hw/riscv/virt: Move AIA initialisation to helper file
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 <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Joel Stanley <joel@jms.id.au> Message-ID: <20260630024952.1520546-4-joel@jms.id.au> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Joel Stanley committed
Jun 30, 2026 at 12:19 UTC
698205820e015cce9ce18dddd592d6b810a9de44
6 files changed
+129
-77
hw/riscv/aia.c
new
+89
@@ -0,0 +1,89 @@
1
+/*
2
+ * QEMU RISC-V Advanced Interrupt Architecture (AIA)
3
+ *
4
+ * Copyright (C) 2019 Western Digital Corporation or its affiliates.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#include "qemu/osdep.h"
10
+#include "system/kvm.h"
11
+#include "hw/intc/riscv_aplic.h"
12
+#include "hw/intc/riscv_imsic.h"
13
+
14
+#include "aia.h"
15
+
16
+uint32_t imsic_num_bits(uint32_t count)
17
+{
18
+ uint32_t ret = 0;
19
+
20
+ while (BIT(ret) < count) {
21
+ ret++;
22
+ }
23
+
24
+ return ret;
25
+}
26
+
27
+DeviceState *riscv_create_aia(bool msimode, int aia_guests,
28
+ const MemMapEntry *aplic_m,
29
+ const MemMapEntry *aplic_s,
30
+ const MemMapEntry *imsic_m,
31
+ const MemMapEntry *imsic_s,
32
+ int socket, int base_hartid, int hart_count,
33
+ uint32_t num_msis, uint32_t num_prio_bits)
34
+{
35
+ int i;
36
+ hwaddr addr = 0;
37
+ uint32_t guest_bits;
38
+ DeviceState *aplic_s_dev = NULL;
39
+ DeviceState *aplic_m_dev = NULL;
40
+
41
+ if (msimode) {
42
+ if (!kvm_enabled()) {
43
+ /* Per-socket M-level IMSICs */
44
+ addr = imsic_m->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT);
45
+ for (i = 0; i < hart_count; i++) {
46
+ riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
47
+ base_hartid + i, true, 1,
48
+ num_msis);
49
+ }
50
+ }
51
+
52
+ /* Per-socket S-level IMSICs */
53
+ guest_bits = imsic_num_bits(aia_guests + 1);
54
+ addr = imsic_s->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT);
55
+ for (i = 0; i < hart_count; i++) {
56
+ riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits),
57
+ base_hartid + i, false, 1 + aia_guests,
58
+ num_msis);
59
+ }
60
+ }
61
+
62
+ if (!kvm_enabled()) {
63
+ /* Per-socket M-level APLIC */
64
+ aplic_m_dev = riscv_aplic_create(aplic_m->base +
65
+ socket * aplic_m->size,
66
+ aplic_m->size,
67
+ (msimode) ? 0 : base_hartid,
68
+ (msimode) ? 0 : hart_count,
69
+ VIRT_IRQCHIP_NUM_SOURCES,
70
+ num_prio_bits,
71
+ msimode, true, NULL);
72
+ }
73
+
74
+ /* Per-socket S-level APLIC */
75
+ aplic_s_dev = riscv_aplic_create(aplic_s->base +
76
+ socket * aplic_s->size,
77
+ aplic_s->size,
78
+ (msimode) ? 0 : base_hartid,
79
+ (msimode) ? 0 : hart_count,
80
+ VIRT_IRQCHIP_NUM_SOURCES,
81
+ num_prio_bits,
82
+ msimode, false, aplic_m_dev);
83
+
84
+ if (kvm_enabled() && msimode) {
85
+ riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s_dev), addr);
86
+ }
87
+
88
+ return kvm_enabled() ? aplic_s_dev : aplic_m_dev;
89
+}
hw/riscv/aia.h
new
+26
@@ -0,0 +1,26 @@
1
+/*
2
+ * QEMU RISC-V Advanced Interrupt Architecture (AIA)
3
+ *
4
+ * Copyright (C) 2019 Western Digital Corporation or its affiliates.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#ifndef HW_RISCV_AIA_H
10
+#define HW_RISCV_AIA_H
11
+
12
+#include "exec/hwaddr.h"
13
+
14
+#define VIRT_IRQCHIP_NUM_SOURCES 96
15
+
16
+uint32_t imsic_num_bits(uint32_t count);
17
+
18
+DeviceState *riscv_create_aia(bool msimode, int aia_guests,
19
+ const MemMapEntry *aplic_m,
20
+ const MemMapEntry *aplic_s,
21
+ const MemMapEntry *imsic_m,
22
+ const MemMapEntry *imsic_s,
23
+ int socket, int base_hartid, int hart_count,
24
+ uint32_t num_msis, uint32_t num_prio_bits);
25
+
26
+#endif
hw/riscv/meson.build
+1
@@ -1,4 +1,5 @@
1
riscv_ss = ss.source_set()
2
+riscv_ss.add(files('aia.c'))
3
riscv_ss.add(files('boot.c'))
4
riscv_ss.add(files('fdt-common.c'))
5
riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c'))
hw/riscv/virt-acpi-build.c
+2
@@ -42,6 +42,8 @@
42
#include "system/kvm.h"
43
#include "system/reset.h"
44
45
+#include "aia.h"
46
+
47
#define ACPI_BUILD_TABLE_SIZE 0x20000
48
#define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index))
49
hw/riscv/virt.c
+11
-76
@@ -61,6 +61,8 @@
61
#include "hw/virtio/virtio-iommu.h"
62
#include "hw/uefi/var-service-api.h"
63
64
+#include "aia.h"
65
+
66
/* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */
67
static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type)
68
{
@@ -371,17 +373,6 @@ static void create_fdt_socket_plic(RISCVVirtState *s,
373
}
374
}
375
374
-uint32_t imsic_num_bits(uint32_t count)
375
-{
376
- uint32_t ret = 0;
377
-
378
- while (BIT(ret) < count) {
379
- ret++;
380
- }
381
-
382
- return ret;
383
-}
384
-
376
static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr base_addr,
377
uint32_t *intc_phandles, uint32_t msi_phandle,
378
bool m_mode, uint32_t imsic_guest_bits)
@@ -1146,68 +1137,6 @@ static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
1137
memmap[VIRT_PLIC].size);
1138
}
1139
1149
-static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
1150
- const MemMapEntry *memmap, int socket,
1151
- int base_hartid, int hart_count)
1152
-{
1153
- int i;
1154
- hwaddr addr = 0;
1155
- uint32_t guest_bits;
1156
- DeviceState *aplic_s = NULL;
1157
- DeviceState *aplic_m = NULL;
1158
- bool msimode = aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
1159
-
1160
- if (msimode) {
1161
- if (!kvm_enabled()) {
1162
- /* Per-socket M-level IMSICs */
1163
- addr = memmap[VIRT_IMSIC_M].base +
1164
- socket * VIRT_IMSIC_GROUP_MAX_SIZE;
1165
- for (i = 0; i < hart_count; i++) {
1166
- riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
1167
- base_hartid + i, true, 1,
1168
- VIRT_IRQCHIP_NUM_MSIS);
1169
- }
1170
- }
1171
-
1172
- /* Per-socket S-level IMSICs */
1173
- guest_bits = imsic_num_bits(aia_guests + 1);
1174
- addr = memmap[VIRT_IMSIC_S].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
1175
- for (i = 0; i < hart_count; i++) {
1176
- riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits),
1177
- base_hartid + i, false, 1 + aia_guests,
1178
- VIRT_IRQCHIP_NUM_MSIS);
1179
- }
1180
- }
1181
-
1182
- if (!kvm_enabled()) {
1183
- /* Per-socket M-level APLIC */
1184
- aplic_m = riscv_aplic_create(memmap[VIRT_APLIC_M].base +
1185
- socket * memmap[VIRT_APLIC_M].size,
1186
- memmap[VIRT_APLIC_M].size,
1187
- (msimode) ? 0 : base_hartid,
1188
- (msimode) ? 0 : hart_count,
1189
- VIRT_IRQCHIP_NUM_SOURCES,
1190
- VIRT_IRQCHIP_NUM_PRIO_BITS,
1191
- msimode, true, NULL);
1192
- }
1193
-
1194
- /* Per-socket S-level APLIC */
1195
- aplic_s = riscv_aplic_create(memmap[VIRT_APLIC_S].base +
1196
- socket * memmap[VIRT_APLIC_S].size,
1197
- memmap[VIRT_APLIC_S].size,
1198
- (msimode) ? 0 : base_hartid,
1199
- (msimode) ? 0 : hart_count,
1200
- VIRT_IRQCHIP_NUM_SOURCES,
1201
- VIRT_IRQCHIP_NUM_PRIO_BITS,
1202
- msimode, false, aplic_m);
1203
-
1204
- if (kvm_enabled() && msimode) {
1205
- riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s), addr);
1206
- }
1207
-
1208
- return kvm_enabled() ? aplic_s : aplic_m;
1209
-}
1210
-
1140
static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip)
1141
{
1142
DeviceState *dev;
@@ -1470,9 +1399,15 @@ static void virt_machine_init(MachineState *machine)
1399
s->irqchip[i] = virt_create_plic(s->memmap, i,
1400
base_hartid, hart_count);
1401
} else {
1473
- s->irqchip[i] = virt_create_aia(s->aia_type, s->aia_guests,
1474
- s->memmap, i, base_hartid,
1475
- hart_count);
1402
+ s->irqchip[i] = riscv_create_aia(s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC,
1403
+ s->aia_guests,
1404
+ &s->memmap[VIRT_APLIC_M],
1405
+ &s->memmap[VIRT_APLIC_S],
1406
+ &s->memmap[VIRT_IMSIC_M],
1407
+ &s->memmap[VIRT_IMSIC_S],
1408
+ i, base_hartid, hart_count,
1409
+ VIRT_IRQCHIP_NUM_MSIS,
1410
+ VIRT_IRQCHIP_NUM_PRIO_BITS);
1411
}
1412
1413
/* Try to use different IRQCHIP instance based device type */
include/hw/riscv/virt.h
-1
@@ -135,7 +135,6 @@ enum {
135
bool virt_is_acpi_enabled(RISCVVirtState *s);
136
bool virt_is_iommu_sys_enabled(RISCVVirtState *s);
137
void virt_acpi_setup(RISCVVirtState *vms);
138
-uint32_t imsic_num_bits(uint32_t count);
138
139
/*
140
* The virt machine physical address space used by some of the devices