Skip to content

Commit

Permalink
hw/loongarch/virt: CPU irq line connection improvement
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Bibo Mao <[email protected]>
  • Loading branch information
bibo-mao committed Feb 12, 2025
1 parent 2d2c37c commit 456739c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 24 deletions.
60 changes: 36 additions & 24 deletions hw/loongarch/virt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 */
Expand All @@ -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);
}
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions include/hw/loongarch/virt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down

0 comments on commit 456739c

Please sign in to comment.