diff options
author | Yong-Xuan Wang <yongxuan.wang@sifive.com> | 2023-07-27 10:24:36 +0000 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2023-09-11 11:45:55 +1000 |
commit | 95a97b3fd25ee1c73a6bbfe0d47ac31864a95a4c (patch) | |
tree | 85a36091eed846591e76d0d8365d99a441d65fe4 /hw/intc/riscv_aplic.c | |
parent | 9634ef7eda5f5b57f03924351a213b776f6b8a23 (diff) |
target/riscv: update APLIC and IMSIC to support KVM AIA
KVM AIA can't emulate APLIC only. When "aia=aplic" parameter is passed,
APLIC devices is emulated by QEMU. For "aia=aplic-imsic", remove the
mmio operations of APLIC when using KVM AIA and send wired interrupt
signal via KVM_IRQ_LINE API.
After KVM AIA enabled, MSI messages are delivered by KVM_SIGNAL_MSI API
when the IMSICs receive mmio write requests.
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Message-ID: <20230727102439.22554-5-yongxuan.wang@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'hw/intc/riscv_aplic.c')
-rw-r--r-- | hw/intc/riscv_aplic.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index 4bdc6a5d1a..592c3ce768 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -31,6 +31,7 @@ #include "hw/irq.h" #include "target/riscv/cpu.h" #include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "migration/vmstate.h" #define APLIC_MAX_IDC (1UL << 14) @@ -148,6 +149,15 @@ #define APLIC_IDC_CLAIMI 0x1c +/* + * KVM AIA only supports APLIC MSI, fallback to QEMU emulation if we want to use + * APLIC Wired. + */ +static bool is_kvm_aia(bool msimode) +{ + return kvm_irqchip_in_kernel() && msimode; +} + static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic, uint32_t word) { @@ -471,6 +481,11 @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc) return topi; } +static void riscv_kvm_aplic_request(void *opaque, int irq, int level) +{ + kvm_set_irq(kvm_state, irq, !!level); +} + static void riscv_aplic_request(void *opaque, int irq, int level) { bool update = false; @@ -801,29 +816,35 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp) uint32_t i; RISCVAPLICState *aplic = RISCV_APLIC(dev); - aplic->bitfield_words = (aplic->num_irqs + 31) >> 5; - aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs); - aplic->state = g_new0(uint32_t, aplic->num_irqs); - aplic->target = g_new0(uint32_t, aplic->num_irqs); - if (!aplic->msimode) { - for (i = 0; i < aplic->num_irqs; i++) { - aplic->target[i] = 1; + if (!is_kvm_aia(aplic->msimode)) { + aplic->bitfield_words = (aplic->num_irqs + 31) >> 5; + aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs); + aplic->state = g_new0(uint32_t, aplic->num_irqs); + aplic->target = g_new0(uint32_t, aplic->num_irqs); + if (!aplic->msimode) { + for (i = 0; i < aplic->num_irqs; i++) { + aplic->target[i] = 1; + } } - } - aplic->idelivery = g_new0(uint32_t, aplic->num_harts); - aplic->iforce = g_new0(uint32_t, aplic->num_harts); - aplic->ithreshold = g_new0(uint32_t, aplic->num_harts); + aplic->idelivery = g_new0(uint32_t, aplic->num_harts); + aplic->iforce = g_new0(uint32_t, aplic->num_harts); + aplic->ithreshold = g_new0(uint32_t, aplic->num_harts); - memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, aplic, - TYPE_RISCV_APLIC, aplic->aperture_size); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio); + memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, + aplic, TYPE_RISCV_APLIC, aplic->aperture_size); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio); + } /* * Only root APLICs have hardware IRQ lines. All non-root APLICs * have IRQ lines delegated by their parent APLIC. */ if (!aplic->parent) { - qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs); + if (is_kvm_aia(aplic->msimode)) { + qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs); + } else { + qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs); + } } /* Create output IRQ lines for non-MSI mode */ @@ -958,7 +979,10 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size, qdev_prop_set_bit(dev, "mmode", mmode); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + if (!is_kvm_aia(msimode)) { + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + } if (parent) { riscv_aplic_add_child(parent, dev); |