qemu-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Why my interrupt is not connected? qemu_irq_is_connected( ) returns fals


From: Chan Kim
Subject: Why my interrupt is not connected? qemu_irq_is_connected( ) returns false.
Date: Fri, 1 Apr 2022 18:17:52 +0900

Hello all,

I'm trying to make interrupt work for a device in qemu. The machnie name is
ab21q, a modified version of arm64 virt machine, and the device name is
ab21q_axpu.  
Here are some relevant codes. I referenced pl011.c. (I switched temporarily
back to qemu-5.1.0 for this test.)  

**==== hw/arm/ab21q.c**

    machab21q_init(MachineState *machine)
    {
    .... skip .... 
    create_ab21q_axpu_device(vms, sysmem); // ab21q-axpu test
    ....
    }

    static void create_ab21q_axpu_device(const Ab21qMachineState *vms,
MemoryRegion *mem)
    {
        char *nodename;
        hwaddr base = vms->memmap[AB21Q_AXPU].base;
        hwaddr size = vms->memmap[AB21Q_AXPU].size;
        int irq = vms->irqmap[AB21Q_AXPU];
        const char compat[] = "ab21q-axpu";
        DeviceState *dev = qdev_new(TYPE_AB21Q_AXPU);
        SysBusDevice *s = SYS_BUS_DEVICE(dev);
    
        //sysbus_create_simple("ab21q-axpu", base,
qdev_get_gpio_in(vms->gic, irq));
        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
        memory_region_add_subregion(mem, base,
                                    sysbus_mmio_get_region(s, 0));
        sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
    
        nodename = g_strdup_printf("/ab21q_axpu@%" PRIx64, base);
        qemu_fdt_add_subnode(vms->fdt, nodename);
        qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat,
sizeof(compat));
        qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2,
size);
        qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
                               GIC_FDT_IRQ_TYPE_SPI, irq,
                               GIC_FDT_IRQ_FLAGS_LEVEL_HI);
        qemu_fdt_setprop_cell(vms->fdt, nodename, "interrupt-parent",
vms->gic_phandle);
    
        g_free(nodename);
    }


**==== hw/misc/ab21q_axpu.c**

    static void ab21q_axpu_init(Object *obj)
    {
        Ab21qAxpuState *s = AB21Q_AXPU(obj);
        SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
        int i;
    
        memory_region_init_io(&s->iomem, OBJECT(s), &ab21q_axpu_ops, s,
                                TYPE_AB21Q_AXPU, 0x200000*64);
        sysbus_init_mmio(sbd, &s->iomem);
        sysbus_init_irq(sbd, &s->irq);
    
        s->init = 0;
        s->int_flag = 0;
        s->status = 0;
    
        s->id = CHIP_ID;
    }
    
    static void ab21q_axpu_realize(DeviceState *d, Error **errp)
    {
        Ab21qAxpuState *s = AB21Q_AXPU(d);
        SysBusDevice *sbd = SYS_BUS_DEVICE(d);
    
        if (qemu_irq_is_connected(s->irq)) {printf("axpu irq
connected!\n");}
        else { printf("axpu irq not connected!\n");}
    }
    
    static void ab21q_axpu_class_init(ObjectClass *klass, void *data)
    {
        DeviceClass *dc = DEVICE_CLASS(klass);
    
        dc->realize = ab21q_axpu_realize;
    }


    static void ab21q_axpu_set_irq(Ab21qAxpuState *s, int irq)
    {
        s->status = irq;
        qemu_set_irq(s->irq, 1);
    }

    static void ab21q_axpu_write(void *opaque, hwaddr offset, uint64_t
value,
                              unsigned size)
    {
    Ab21qAxpuState *s = (Ab21qAxpuState *)opaque;

    .... skip ... 
    switch (offset) {

    case TRIGGER_RUN:
    .... 
            if (((uint64_t *)(s->ioctl_arg + *host_virt_offset_p))[0] ==
0x1604) {
                s->int_flag = 1;
                ab21q_axpu_set_irq(s, INT_AXPU_RUN_FINISHED);
            }

The machine and the device works. (actually the device is a shared library
that qemu links to) except the interrupt doesn't work even though qemu does
set_irq.  I checked with `qemu_irq_is_connected` in realize function. The
pl011 case says `pl011 irq connected!`, but in my device I see `axpu irq not
connected!`.  So it's not related to device driver but qemu model itself. 
Could anyone find what is missing in the above code?  Should I add something
to acpi table(in ab21q-build-acpi.c)?

I tried adding in hw/arm/ab21q-build-acpi.c these lines.  In function
build_dsdt,

    acpi_dsdt_add_axpu(scope, &memmap[AB21Q_AXPU],
                           (irqmap[AB21Q_AXPU] + ARM_SPI_BASE));

The acpi_dsdt_add_axpu function being

    static void acpi_dsdt_add_axpu(Aml *scope, const MemMapEntry
*uart_memmap,
                                               uint32_t irq)
    {
        Aml *dev = aml_device("AXPU");
        aml_append(dev, aml_name_decl("_HID", aml_string("AXPU0011")));
        aml_append(dev, aml_name_decl("_UID", aml_int(0)));
    
        Aml *crs = aml_resource_template();
        aml_append(crs, aml_memory32_fixed(uart_memmap->base,
                                           uart_memmap->size,
AML_READ_WRITE));
        aml_append(crs,
                   aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
                                 AML_EXCLUSIVE, &irq, 1));
        aml_append(dev, aml_name_decl("_CRS", crs));
    
        aml_append(scope, dev);
    }

Inside the virtual machine (ubuntu 20.04), I did acpidump and converted it
to .dsl files. The dsdt.dsl contains this entry.

Device (AXPU)
        {
            Name (_HID, "AXPU0011")  // _HID: Hardware ID
            Name (_UID, Zero)  // _UID: Unique ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource
Settings
            {
                Memory32Fixed (ReadWrite,
                    0x09100000,         // Address Base
                    0x00080000,         // Address Length
                    )
                Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive,
,, )
                {
                    0x000000D0,
                }
            })
        }

I'm not sure what I should fix in acpi table.
Any comment or advice will be deeply appreciated.

Thank you!

Chan Kim
p.s. I put the same question on the stackoverflow :
https://stackoverflow.com/questions/71702591/qemu-interrupt-not-connected. 
Answering there is also good because more people could get help using
search.







reply via email to

[Prev in Thread] Current Thread [Next in Thread]