Commit e6ea6bec5a for qemu.org
commit e6ea6bec5a324b63ec000bc55e28d3b1c37a13ea
Author: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Date: Fri Aug 28 17:39:11 2026 -0300
hw/riscv/fdt-common, virt.c: add riscv_create_fdt_socket_aclint()
Yet another FDT that we want to move to a helper to avoid copy/pasting
code to other boards that will use a mtimer. In particular the future
'riscv-server-ref' board.
No FDT changes made.
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Message-ID: <20260828203918.350131-10-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c
index d815c5adff..d2ce93ad28 100644
--- a/hw/riscv/fdt-common.c
+++ b/hw/riscv/fdt-common.c
@@ -16,6 +16,7 @@
#include "target/riscv/cpu_bits.h"
#include "hw/riscv/riscv-iommu-bits.h"
#include "hw/riscv/iommu.h"
+#include "hw/intc/riscv_aclint.h"
#include "hw/intc/riscv_imsic.h"
#include "hw/pci/pci.h"
#include "hw/pci/pcie_host.h"
@@ -702,3 +703,99 @@ void riscv_create_fdt_socket_aplic(void *fdt, APLICFdtProps *props,
aplic_phandles[props->socket] = aplic_s_phandle;
}
+
+void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props,
+ uint32_t *intc_phandles)
+{
+ uint32_t aclint_cells_size = props->num_harts * sizeof(uint32_t) * 2;
+ g_autofree uint32_t *aclint_mswi_cells = NULL;
+ g_autofree uint32_t *aclint_sswi_cells = NULL;
+ g_autofree uint32_t *aclint_mtimer_cells = NULL;
+ hwaddr addr, size;
+ char *name;
+ int cpu;
+
+ aclint_mswi_cells = g_new0(uint32_t, props->num_harts * 2);
+ aclint_mtimer_cells = g_new0(uint32_t, props->num_harts * 2);
+ aclint_sswi_cells = g_new0(uint32_t, props->num_harts * 2);
+
+ for (cpu = 0; cpu < props->num_harts; cpu++) {
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
+ aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
+ }
+
+ if (props->aia_type != AIA_TYPE_APLIC_IMSIC) {
+ addr = props->clint->base + (props->clint->size * props->socket);
+ name = g_strdup_printf("/soc/mswi@%"HWADDR_PRIx, addr);
+
+ qemu_fdt_add_subnode(fdt, name);
+ qemu_fdt_setprop_string(fdt, name, "compatible", "riscv,aclint-mswi");
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
+ 2, addr, 2, RISCV_ACLINT_SWI_SIZE);
+ qemu_fdt_setprop(fdt, name, "interrupts-extended",
+ aclint_mswi_cells, aclint_cells_size);
+ qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0);
+ qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 0);
+
+ if (props->numa_enabled) {
+ qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket);
+ }
+
+ g_free(name);
+ }
+
+ if (props->aia_type == AIA_TYPE_APLIC_IMSIC) {
+ addr = props->clint->base +
+ (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * props->socket);
+ size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE;
+ } else {
+ addr = props->clint->base + RISCV_ACLINT_SWI_SIZE +
+ (props->clint->size * props->socket);
+ size = props->clint->size - RISCV_ACLINT_SWI_SIZE;
+ }
+
+ name = g_strdup_printf("/soc/mtimer@%"HWADDR_PRIx,
+ addr + RISCV_ACLINT_DEFAULT_MTIME);
+ qemu_fdt_add_subnode(fdt, name);
+ qemu_fdt_setprop_string(fdt, name, "compatible",
+ "riscv,aclint-mtimer");
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
+ 2, addr + RISCV_ACLINT_DEFAULT_MTIME,
+ 2, size - RISCV_ACLINT_DEFAULT_MTIME,
+ 2, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
+ 2, RISCV_ACLINT_DEFAULT_MTIME);
+ qemu_fdt_setprop(fdt, name, "interrupts-extended",
+ aclint_mtimer_cells, aclint_cells_size);
+
+ if (props->numa_enabled) {
+ qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket);
+ }
+
+ g_free(name);
+
+ if (props->aia_type != AIA_TYPE_APLIC_IMSIC) {
+ addr = props->aclint_sswi->base
+ + (props->aclint_sswi->size * props->socket);
+
+ name = g_strdup_printf("/soc/sswi@%"HWADDR_PRIx, addr);
+ qemu_fdt_add_subnode(fdt, name);
+ qemu_fdt_setprop_string(fdt, name, "compatible",
+ "riscv,aclint-sswi");
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
+ 2, addr, 2, props->aclint_sswi->size);
+ qemu_fdt_setprop(fdt, name, "interrupts-extended",
+ aclint_sswi_cells, aclint_cells_size);
+ qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0);
+ qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 0);
+
+ if (props->numa_enabled) {
+ qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket);
+ }
+
+ g_free(name);
+ }
+}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 840dd0e075..c9b1a669a5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -179,94 +179,6 @@ static void virt_flash_map(RISCVVirtState *s,
sysmem);
}
-static void create_fdt_socket_aclint(RISCVVirtState *s,
- int socket,
- uint32_t *intc_phandles)
-{
- int cpu;
- char *name;
- unsigned long addr, size;
- uint32_t aclint_cells_size;
- g_autofree uint32_t *aclint_mswi_cells = NULL;
- g_autofree uint32_t *aclint_sswi_cells = NULL;
- g_autofree uint32_t *aclint_mtimer_cells = NULL;
- MachineState *ms = MACHINE(s);
-
- aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
- aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
- aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
-
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
- aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
- aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
- aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
- aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
- aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
- aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
- }
- aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
-
- if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) {
- addr = s->memmap[VIRT_CLINT].base +
- (s->memmap[VIRT_CLINT].size * socket);
- name = g_strdup_printf("/soc/mswi@%lx", addr);
-
- qemu_fdt_add_subnode(ms->fdt, name);
- qemu_fdt_setprop_string(ms->fdt, name, "compatible",
- "riscv,aclint-mswi");
- qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg",
- 2, addr, 2, RISCV_ACLINT_SWI_SIZE);
- qemu_fdt_setprop(ms->fdt, name, "interrupts-extended",
- aclint_mswi_cells, aclint_cells_size);
- qemu_fdt_setprop(ms->fdt, name, "interrupt-controller", NULL, 0);
- qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells", 0);
- riscv_socket_fdt_write_id(ms, name, socket);
- g_free(name);
- }
-
- if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
- addr = s->memmap[VIRT_CLINT].base +
- (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * socket);
- size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE;
- } else {
- addr = s->memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
- (s->memmap[VIRT_CLINT].size * socket);
- size = s->memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE;
- }
- name = g_strdup_printf("/soc/mtimer@%"HWADDR_PRIx,
- addr + RISCV_ACLINT_DEFAULT_MTIME);
- qemu_fdt_add_subnode(ms->fdt, name);
- qemu_fdt_setprop_string(ms->fdt, name, "compatible",
- "riscv,aclint-mtimer");
- qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg",
- 2, addr + RISCV_ACLINT_DEFAULT_MTIME,
- 2, size - RISCV_ACLINT_DEFAULT_MTIME,
- 2, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
- 2, RISCV_ACLINT_DEFAULT_MTIME);
- qemu_fdt_setprop(ms->fdt, name, "interrupts-extended",
- aclint_mtimer_cells, aclint_cells_size);
- riscv_socket_fdt_write_id(ms, name, socket);
- g_free(name);
-
- if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) {
- addr = s->memmap[VIRT_ACLINT_SSWI].base +
- (s->memmap[VIRT_ACLINT_SSWI].size * socket);
-
- name = g_strdup_printf("/soc/sswi@%lx", addr);
- qemu_fdt_add_subnode(ms->fdt, name);
- qemu_fdt_setprop_string(ms->fdt, name, "compatible",
- "riscv,aclint-sswi");
- qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg",
- 2, addr, 2, s->memmap[VIRT_ACLINT_SSWI].size);
- qemu_fdt_setprop(ms->fdt, name, "interrupts-extended",
- aclint_sswi_cells, aclint_cells_size);
- qemu_fdt_setprop(ms->fdt, name, "interrupt-controller", NULL, 0);
- qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells", 0);
- riscv_socket_fdt_write_id(ms, name, socket);
- g_free(name);
- }
-}
-
static void create_fdt_socket_plic(RISCVVirtState *s,
int socket,
uint32_t *phandle, uint32_t *intc_phandles,
@@ -347,6 +259,7 @@ static void create_fdt_sockets(RISCVVirtState *s,
bool numa_enabled = riscv_numa_enabled(ms);
bool is_32_bit = riscv_is_32bit(&s->soc[0]);
APLICFdtProps aplic_props;
+ ACLINTFdtProps aclint_props;
riscv_fdt_create_cpu_socket_subnode(ms->fdt,
kvm_enabled() ? kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) :
@@ -354,6 +267,13 @@ static void create_fdt_sockets(RISCVVirtState *s,
intc_phandles = g_new0(uint32_t, ms->smp.cpus);
+ if (virt_aclint_allowed() && s->have_aclint) {
+ aclint_props.clint = &s->memmap[VIRT_CLINT];
+ aclint_props.aclint_sswi = &s->memmap[VIRT_ACLINT_SSWI];
+ aclint_props.aia_type = s->aia_type;
+ aclint_props.numa_enabled = numa_enabled;
+ }
+
phandle_pos = ms->smp.cpus;
for (socket = (socket_count - 1); socket >= 0; socket--) {
hwaddr memaddr = s->memmap[VIRT_DRAM].base +
@@ -372,8 +292,10 @@ static void create_fdt_sockets(RISCVVirtState *s,
socket, riscv_numa_enabled(ms));
if (virt_aclint_allowed() && s->have_aclint) {
- create_fdt_socket_aclint(s, socket,
- &intc_phandles[phandle_pos]);
+ aclint_props.socket = socket;
+ aclint_props.num_harts = s->soc[socket].num_harts;
+ riscv_create_fdt_socket_aclint(ms->fdt, &aclint_props,
+ &intc_phandles[phandle_pos]);
} else if (tcg_enabled()) {
hwaddr clintaddr = s->memmap[VIRT_CLINT].base +
s->memmap[VIRT_CLINT].size * socket;
diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h
index 8207cfee7b..a45b063f66 100644
--- a/include/hw/riscv/fdt-common.h
+++ b/include/hw/riscv/fdt-common.h
@@ -63,6 +63,15 @@ typedef struct APLICFdtProps {
int aia_type;
} APLICFdtProps;
+typedef struct ACLINTFdtProps {
+ const MemMapEntry *clint;
+ const MemMapEntry *aclint_sswi;
+ int socket;
+ int num_harts;
+ int aia_type;
+ bool numa_enabled;
+} ACLINTFdtProps;
+
void *riscv_create_board_device_tree(const char *model, const char *compatible,
int *fdt_size);
void riscv_create_fdt_socket_memory(void *fdt, hwaddr addr, uint64_t size,
@@ -117,4 +126,6 @@ void riscv_create_fdt_socket_aplic(void *fdt, APLICFdtProps *props,
uint32_t *next_phandle,
uint32_t *intc_phandles,
uint32_t *aplic_phandles);
+void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props,
+ uint32_t *intc_phandles);
#endif