hw/intc/aplic: refine the APLIC realize

When the APLIC is emulated in the kernel, the GPIO output lines to CPUs
can be remove. In this case the APLIC trigger CPU interrupts by KVM APIs.

This patch also move the code that claim the CPU interrupts to the
beginning of APLIC realization. This can avoid the unnecessary resource
allocation before checking failed.

Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Message-ID: <20250224025722.3999-3-yongxuan.wang@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Yong-Xuan Wang 2025-02-24 10:57:19 +08:00 committed by Alistair Francis
parent afd4f4aa7f
commit 489840a012

View File

@ -893,6 +893,26 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
RISCVAPLICState *aplic = RISCV_APLIC(dev); RISCVAPLICState *aplic = RISCV_APLIC(dev);
if (riscv_use_emulated_aplic(aplic->msimode)) { if (riscv_use_emulated_aplic(aplic->msimode)) {
/* Create output IRQ lines for non-MSI mode */
if (!aplic->msimode) {
/* Claim the CPU interrupt to be triggered by this APLIC */
for (i = 0; i < aplic->num_harts; i++) {
RISCVCPU *cpu;
cpu = RISCV_CPU(cpu_by_arch_id(aplic->hartid_base + i));
if (riscv_cpu_claim_interrupts(cpu,
(aplic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
error_report("%s already claimed",
(aplic->mmode) ? "MEIP" : "SEIP");
exit(1);
}
}
aplic->external_irqs = g_malloc(sizeof(qemu_irq) *
aplic->num_harts);
qdev_init_gpio_out(dev, aplic->external_irqs, aplic->num_harts);
}
aplic->bitfield_words = (aplic->num_irqs + 31) >> 5; aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs); aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
aplic->state = g_new0(uint32_t, aplic->num_irqs); aplic->state = g_new0(uint32_t, aplic->num_irqs);
@ -927,23 +947,6 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
} }
} }
/* Create output IRQ lines for non-MSI mode */
if (!aplic->msimode) {
aplic->external_irqs = g_malloc(sizeof(qemu_irq) * aplic->num_harts);
qdev_init_gpio_out(dev, aplic->external_irqs, aplic->num_harts);
/* Claim the CPU interrupt to be triggered by this APLIC */
for (i = 0; i < aplic->num_harts; i++) {
RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(aplic->hartid_base + i));
if (riscv_cpu_claim_interrupts(cpu,
(aplic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
error_report("%s already claimed",
(aplic->mmode) ? "MEIP" : "SEIP");
exit(1);
}
}
}
msi_nonbroken = true; msi_nonbroken = true;
} }
@ -1067,15 +1070,15 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
if (riscv_use_emulated_aplic(msimode)) { if (riscv_use_emulated_aplic(msimode)) {
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
}
if (!msimode) { if (!msimode) {
for (i = 0; i < num_harts; i++) { for (i = 0; i < num_harts; i++) {
CPUState *cpu = cpu_by_arch_id(hartid_base + i); CPUState *cpu = cpu_by_arch_id(hartid_base + i);
qdev_connect_gpio_out_named(dev, NULL, i, qdev_connect_gpio_out_named(dev, NULL, i,
qdev_get_gpio_in(DEVICE(cpu), qdev_get_gpio_in(DEVICE(cpu),
(mmode) ? IRQ_M_EXT : IRQ_S_EXT)); (mmode) ? IRQ_M_EXT : IRQ_S_EXT));
}
} }
} }