Interrupt controller extioi and ipi connect to CPU with irq line method. With command -smp x, -device la464-loongarch-cpu, smp.cpus is not accurate for all possible CPU objects, possible_cpu_arch_ids() is used.
Signed-off-by: Bibo Mao <maob...@loongson.cn> Reviewed-by: Bibo Mao <maob...@loongson.cn> --- hw/loongarch/virt.c | 60 ++++++++++++++++++++++--------------- include/hw/loongarch/virt.h | 2 ++ 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index da98b21c58..f2aa0a9782 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -318,14 +318,43 @@ static void virt_devices_init(DeviceState *pch_pic, lvms->platform_bus_dev = create_platform_bus(pch_pic); } -static void virt_irq_init(LoongArchVirtMachineState *lvms) +static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms) { + int num, pin; MachineState *ms = MACHINE(lvms); - DeviceState *pch_pic, *pch_msi, *cpudev; + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus; + CPUState *cs; + + /* cpu nodes */ + possible_cpus = mc->possible_cpu_arch_ids(ms); + for (num = 0; num < possible_cpus->len; num++) { + cs = possible_cpus->cpus[num].cpu; + if (cs == NULL) { + continue; + } + + /* connect ipi irq to cpu irq */ + qdev_connect_gpio_out(lvms->ipi, num, + qdev_get_gpio_in(DEVICE(cs), IRQ_IPI)); + + /* + * connect ext irq to the cpu irq + * cpu_pin[9:2] <= intc_pin[7:0] + */ + for (pin = 0; pin < LS3A_INTC_IP; pin++) { + qdev_connect_gpio_out(lvms->extioi, (num * LS3A_INTC_IP + pin), + qdev_get_gpio_in(DEVICE(cs), pin + 2)); + } + } +} + +static void virt_irq_init(LoongArchVirtMachineState *lvms) +{ + DeviceState *pch_pic, *pch_msi; DeviceState *ipi, *extioi; SysBusDevice *d; - CPUState *cpu_state; - int cpu, pin, i, start, num; + int i, start, num; /* * Extended IRQ model. @@ -373,6 +402,7 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) /* Create IPI device */ ipi = qdev_new(TYPE_LOONGARCH_IPI); + lvms->ipi = ipi; sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal); /* IPI iocsr memory region */ @@ -381,16 +411,9 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR, sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1)); - for (cpu = 0; cpu < ms->smp.cpus; cpu++) { - cpu_state = qemu_get_cpu(cpu); - cpudev = DEVICE(cpu_state); - - /* connect ipi irq to cpu irq */ - qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI)); - } - /* Create EXTIOI device */ extioi = qdev_new(TYPE_LOONGARCH_EXTIOI); + lvms->extioi = extioi; if (virt_is_veiointc_enabled(lvms)) { qdev_prop_set_bit(extioi, "has-virtualization-extension", true); } @@ -402,18 +425,7 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1)); } - /* - * connect ext irq to the cpu irq - * cpu_pin[9:2] <= intc_pin[7:0] - */ - for (cpu = 0; cpu < ms->smp.cpus; cpu++) { - cpudev = DEVICE(qemu_get_cpu(cpu)); - for (pin = 0; pin < LS3A_INTC_IP; pin++) { - qdev_connect_gpio_out(extioi, (cpu * 8 + pin), - qdev_get_gpio_in(cpudev, pin + 2)); - } - } - + virt_cpu_irq_init(lvms); pch_pic = qdev_new(TYPE_LOONGARCH_PIC); num = VIRT_PCH_PIC_IRQ_NUM; qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num); diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index f01350017b..661efae61d 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -60,6 +60,8 @@ struct LoongArchVirtMachineState { MemoryRegion iocsr_mem; AddressSpace as_iocsr; struct loongarch_boot_info bootinfo; + DeviceState *ipi; + DeviceState *extioi; }; #define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt") -- 2.43.5