On Wed, Jun 3, 2026 at 5:03 PM Joel Stanley <[email protected]> wrote: > > The AIA init will be used by any server class riscv machine. Separate it > out in order to share code with such systems. > > The virt machine keeps machine specific #defines such as > VIRT_IRQCHIP_NUM_MSIS, VIRT_IRQCHIP_NUM_PRIO_BITS. > > Reviewed-by: Daniel Henrique Barboza <[email protected]> > Reviewed-by: Nutty Liu <[email protected]> > Reviewed-by: Philippe Mathieu-Daudé <[email protected]> > Signed-off-by: Nicholas Piggin <[email protected]> > Signed-off-by: Joel Stanley <[email protected]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > hw/riscv/aia.h | 26 +++++++++++ > include/hw/riscv/virt.h | 1 - > hw/riscv/aia.c | 89 ++++++++++++++++++++++++++++++++++++++ > hw/riscv/virt-acpi-build.c | 2 + > hw/riscv/virt.c | 87 +++++-------------------------------- > hw/riscv/meson.build | 2 +- > 6 files changed, 129 insertions(+), 78 deletions(-) > create mode 100644 hw/riscv/aia.h > create mode 100644 hw/riscv/aia.c > > diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h > new file mode 100644 > index 000000000000..dbb833340276 > --- /dev/null > +++ b/hw/riscv/aia.h > @@ -0,0 +1,26 @@ > +/* > + * QEMU RISC-V Advanced Interrupt Architecture (AIA) > + * > + * Copyright (C) 2019 Western Digital Corporation or its affiliates. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#ifndef HW_RISCV_AIA_H > +#define HW_RISCV_AIA_H > + > +#include "exec/hwaddr.h" > + > +#define VIRT_IRQCHIP_NUM_SOURCES 96 > + > +uint32_t imsic_num_bits(uint32_t count); > + > +DeviceState *riscv_create_aia(bool msimode, int aia_guests, > + const MemMapEntry *aplic_m, > + const MemMapEntry *aplic_s, > + const MemMapEntry *imsic_m, > + const MemMapEntry *imsic_s, > + int socket, int base_hartid, int hart_count, > + uint32_t num_msis, uint32_t num_prio_bits); > + > +#endif > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h > index 18a2a323a344..ad858deb76ad 100644 > --- a/include/hw/riscv/virt.h > +++ b/include/hw/riscv/virt.h > @@ -135,7 +135,6 @@ enum { > bool virt_is_acpi_enabled(RISCVVirtState *s); > bool virt_is_iommu_sys_enabled(RISCVVirtState *s); > void virt_acpi_setup(RISCVVirtState *vms); > -uint32_t imsic_num_bits(uint32_t count); > > /* > * The virt machine physical address space used by some of the devices > diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c > new file mode 100644 > index 000000000000..c724612a50a5 > --- /dev/null > +++ b/hw/riscv/aia.c > @@ -0,0 +1,89 @@ > +/* > + * QEMU RISC-V Advanced Interrupt Architecture (AIA) > + * > + * Copyright (C) 2019 Western Digital Corporation or its affiliates. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "system/kvm.h" > +#include "hw/intc/riscv_aplic.h" > +#include "hw/intc/riscv_imsic.h" > + > +#include "aia.h" > + > +uint32_t imsic_num_bits(uint32_t count) > +{ > + uint32_t ret = 0; > + > + while (BIT(ret) < count) { > + ret++; > + } > + > + return ret; > +} > + > +DeviceState *riscv_create_aia(bool msimode, int aia_guests, > + const MemMapEntry *aplic_m, > + const MemMapEntry *aplic_s, > + const MemMapEntry *imsic_m, > + const MemMapEntry *imsic_s, > + int socket, int base_hartid, int hart_count, > + uint32_t num_msis, uint32_t num_prio_bits) > +{ > + int i; > + hwaddr addr = 0; > + uint32_t guest_bits; > + DeviceState *aplic_s_dev = NULL; > + DeviceState *aplic_m_dev = NULL; > + > + if (msimode) { > + if (!kvm_enabled()) { > + /* Per-socket M-level IMSICs */ > + addr = imsic_m->base + socket * (1U << > IMSIC_MMIO_GROUP_MIN_SHIFT); > + for (i = 0; i < hart_count; i++) { > + riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0), > + base_hartid + i, true, 1, > + num_msis); > + } > + } > + > + /* Per-socket S-level IMSICs */ > + guest_bits = imsic_num_bits(aia_guests + 1); > + addr = imsic_s->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT); > + for (i = 0; i < hart_count; i++) { > + riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits), > + base_hartid + i, false, 1 + aia_guests, > + num_msis); > + } > + } > + > + if (!kvm_enabled()) { > + /* Per-socket M-level APLIC */ > + aplic_m_dev = riscv_aplic_create(aplic_m->base + > + socket * aplic_m->size, > + aplic_m->size, > + (msimode) ? 0 : base_hartid, > + (msimode) ? 0 : hart_count, > + VIRT_IRQCHIP_NUM_SOURCES, > + num_prio_bits, > + msimode, true, NULL); > + } > + > + /* Per-socket S-level APLIC */ > + aplic_s_dev = riscv_aplic_create(aplic_s->base + > + socket * aplic_s->size, > + aplic_s->size, > + (msimode) ? 0 : base_hartid, > + (msimode) ? 0 : hart_count, > + VIRT_IRQCHIP_NUM_SOURCES, > + num_prio_bits, > + msimode, false, aplic_m_dev); > + > + if (kvm_enabled() && msimode) { > + riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s_dev), addr); > + } > + > + return kvm_enabled() ? aplic_s_dev : aplic_m_dev; > +} > diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c > index 413d47d70ef1..e3da87492408 100644 > --- a/hw/riscv/virt-acpi-build.c > +++ b/hw/riscv/virt-acpi-build.c > @@ -42,6 +42,8 @@ > #include "system/kvm.h" > #include "system/reset.h" > > +#include "aia.h" > + > #define ACPI_BUILD_TABLE_SIZE 0x20000 > #define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index)) > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > index febf49d5f149..614220a0ce66 100644 > --- a/hw/riscv/virt.c > +++ b/hw/riscv/virt.c > @@ -60,6 +60,8 @@ > #include "hw/virtio/virtio-iommu.h" > #include "hw/uefi/var-service-api.h" > > +#include "aia.h" > + > /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. > */ > static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type) > { > @@ -510,17 +512,6 @@ static void create_fdt_socket_plic(RISCVVirtState *s, > } > } > > -uint32_t imsic_num_bits(uint32_t count) > -{ > - uint32_t ret = 0; > - > - while (BIT(ret) < count) { > - ret++; > - } > - > - return ret; > -} > - > static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr base_addr, > uint32_t *intc_phandles, uint32_t > msi_phandle, > bool m_mode, uint32_t imsic_guest_bits) > @@ -1294,68 +1285,6 @@ static DeviceState *virt_create_plic(const MemMapEntry > *memmap, int socket, > memmap[VIRT_PLIC].size); > } > > -static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int > aia_guests, > - const MemMapEntry *memmap, int socket, > - int base_hartid, int hart_count) > -{ > - int i; > - hwaddr addr = 0; > - uint32_t guest_bits; > - DeviceState *aplic_s = NULL; > - DeviceState *aplic_m = NULL; > - bool msimode = aia_type == VIRT_AIA_TYPE_APLIC_IMSIC; > - > - if (msimode) { > - if (!kvm_enabled()) { > - /* Per-socket M-level IMSICs */ > - addr = memmap[VIRT_IMSIC_M].base + > - socket * VIRT_IMSIC_GROUP_MAX_SIZE; > - for (i = 0; i < hart_count; i++) { > - riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0), > - base_hartid + i, true, 1, > - VIRT_IRQCHIP_NUM_MSIS); > - } > - } > - > - /* Per-socket S-level IMSICs */ > - guest_bits = imsic_num_bits(aia_guests + 1); > - addr = memmap[VIRT_IMSIC_S].base + socket * > VIRT_IMSIC_GROUP_MAX_SIZE; > - for (i = 0; i < hart_count; i++) { > - riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits), > - base_hartid + i, false, 1 + aia_guests, > - VIRT_IRQCHIP_NUM_MSIS); > - } > - } > - > - if (!kvm_enabled()) { > - /* Per-socket M-level APLIC */ > - aplic_m = riscv_aplic_create(memmap[VIRT_APLIC_M].base + > - socket * memmap[VIRT_APLIC_M].size, > - memmap[VIRT_APLIC_M].size, > - (msimode) ? 0 : base_hartid, > - (msimode) ? 0 : hart_count, > - VIRT_IRQCHIP_NUM_SOURCES, > - VIRT_IRQCHIP_NUM_PRIO_BITS, > - msimode, true, NULL); > - } > - > - /* Per-socket S-level APLIC */ > - aplic_s = riscv_aplic_create(memmap[VIRT_APLIC_S].base + > - socket * memmap[VIRT_APLIC_S].size, > - memmap[VIRT_APLIC_S].size, > - (msimode) ? 0 : base_hartid, > - (msimode) ? 0 : hart_count, > - VIRT_IRQCHIP_NUM_SOURCES, > - VIRT_IRQCHIP_NUM_PRIO_BITS, > - msimode, false, aplic_m); > - > - if (kvm_enabled() && msimode) { > - riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s), addr); > - } > - > - return kvm_enabled() ? aplic_s : aplic_m; > -} > - > static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip) > { > DeviceState *dev; > @@ -1618,9 +1547,15 @@ static void virt_machine_init(MachineState *machine) > s->irqchip[i] = virt_create_plic(s->memmap, i, > base_hartid, hart_count); > } else { > - s->irqchip[i] = virt_create_aia(s->aia_type, s->aia_guests, > - s->memmap, i, base_hartid, > - hart_count); > + s->irqchip[i] = riscv_create_aia(s->aia_type == > VIRT_AIA_TYPE_APLIC_IMSIC, > + s->aia_guests, > + &s->memmap[VIRT_APLIC_M], > + &s->memmap[VIRT_APLIC_S], > + &s->memmap[VIRT_IMSIC_M], > + &s->memmap[VIRT_IMSIC_S], > + i, base_hartid, hart_count, > + VIRT_IRQCHIP_NUM_MSIS, > + VIRT_IRQCHIP_NUM_PRIO_BITS); > } > > /* Try to use different IRQCHIP instance based device type */ > diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build > index 533472e22aef..e53c180d0d10 100644 > --- a/hw/riscv/meson.build > +++ b/hw/riscv/meson.build > @@ -1,5 +1,5 @@ > riscv_ss = ss.source_set() > -riscv_ss.add(files('boot.c')) > +riscv_ss.add(files('boot.c', 'aia.c')) > riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) > riscv_ss.add(files('riscv_hart.c')) > riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) > -- > 2.47.3 > >
