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
>
>

Reply via email to