* [PATCH v3 00/16] hw/riscv: Socify Atlantis
@ 2026-09-03 5:51 Joel Stanley
2026-09-03 5:51 ` [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices Joel Stanley
` (16 more replies)
0 siblings, 17 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
v2: https://lore.kernel.org/qemu-riscv/20260831021500.82565-1-joel@jms.id.au
Changes in v3:
- Rebase on today's riscv-to-apply.next, fixing conflicts with the
device tree rework
- Take up Phil's suggestion to change @mr to @container in the first
five patches
- Add r-b from Alistair, Daniel, Phil. Thank you!
Original commit message:
This addresses the review given by Cedric on v1 of the Atlantis patches,
where he suggested making the machine a SoC. This is the pattern
followed by the Aspeed ARM machines, where the SoC represents the
modelled hardware, attaching its devices to a memory container, with the
SoC instantiated by a QEMU machine that provides the memory container
and the machine's RAM.
Aside from the clean abstraction that this encourages, this pattern will
be useful in adding other SoCs to the Atlantis machine, such as the RCPU
(boot microcontroller) and CPL (Cluster Power Logic microcontroller).
The series converts the RISC-V interrupt controllers to take a
MemoryRegion for mapping themselves, with no change in behaviour for
existing machines, and then cleans up the CPS device to place its
devices in the memory container provided.
The next few patches clean up the Atlantis machine to make extracting
the SoC device and mapping it in a container relatively straightforward.
Joel Stanley (15):
hw/riscv/aia: Take a MemoryRegion for the created devices
hw/intc/riscv_aclint: Take a MemoryRegion for the created devices
hw/intc/riscv_imsic: Take a MemoryRegion for the created device
hw/intc/riscv_aplic: Take a MemoryRegion for the created device
hw/intc/sifive_plic: Take a MemoryRegion for the created device
hw/riscv/cps: Map interrupt controllers in SoC container
hw/riscv/atlantis: Make UART unimp region a SoC device
hw/riscv/atlantis: Remove unused fdt_size
hw/riscv/atlantis: Rename hart array 'soc' to 'cpus'
hw/riscv/atlantis: Rework device tree creation
hw/riscv/atlantis: Use local reference for system memory
hw/riscv/atlantis: Decouple RAM size from MachineState
hw/riscv/atlantis: Make TTAtlantisState own memory containers
hw/riscv/atlantis: Extract an Atlantis SoC device
hw/riscv/atlantis: Map the SoC through a memory container
Portia Stephens (1):
hw/riscv: Add property to hart array to allow private memory
hw/riscv/aia.h | 3 +-
include/hw/intc/riscv_aclint.h | 7 +-
include/hw/intc/riscv_aplic.h | 7 +-
include/hw/intc/riscv_imsic.h | 3 +-
include/hw/intc/sifive_plic.h | 4 +-
include/hw/riscv/riscv_hart.h | 2 +
include/hw/riscv/tt_atlantis.h | 32 +++-
hw/intc/riscv_aclint.c | 12 +-
hw/intc/riscv_aplic.c | 10 +-
hw/intc/riscv_imsic.c | 6 +-
hw/intc/sifive_plic.c | 7 +-
hw/riscv/aia.c | 17 +-
hw/riscv/cps.c | 12 +-
hw/riscv/k230.c | 9 +-
hw/riscv/microchip_pfsoc.c | 8 +-
hw/riscv/riscv_hart.c | 8 +
hw/riscv/shakti_c.c | 10 +-
hw/riscv/sifive_e.c | 6 +-
hw/riscv/sifive_u.c | 10 +-
hw/riscv/spike.c | 4 +-
hw/riscv/tt_atlantis.c | 280 +++++++++++++++++++++------------
hw/riscv/virt.c | 21 ++-
hw/riscv/xiangshan_kmh.c | 17 +-
23 files changed, 326 insertions(+), 169 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 6:06 ` Chao Liu via qemu development
2026-09-03 5:51 ` [PATCH v3 02/16] hw/intc/riscv_aclint: " Joel Stanley
` (15 subsequent siblings)
16 siblings, 1 reply; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
Add a MemoryRegion parameter to riscv_create_aia(), to be passed on to
the IMSIC and APLIC helpers so a SoC can have the controllers mapped
into its own memory container. Both callers pass system_memory, so there
is no change in behaviour.
As the controllers don't yet take a MemoryRegion the parameter is not
yet passed on. Changing riscv_create_aia first avoids churn in the
intermediate commits.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
hw/riscv/aia.h | 3 ++-
hw/riscv/aia.c | 3 ++-
hw/riscv/tt_atlantis.c | 3 ++-
hw/riscv/virt.c | 3 ++-
4 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h
index 3b6d7f962506..5df3292610e9 100644
--- a/hw/riscv/aia.h
+++ b/hw/riscv/aia.h
@@ -13,7 +13,8 @@
uint32_t imsic_num_bits(uint32_t count);
-DeviceState *riscv_create_aia(bool msimode, int aia_guests,
+DeviceState *riscv_create_aia(MemoryRegion *container,
+ bool msimode, int aia_guests,
uint32_t m_imsic_stride,
uint32_t s_imsic_stride,
uint16_t num_sources,
diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c
index c1a5982856c5..e11382e512da 100644
--- a/hw/riscv/aia.c
+++ b/hw/riscv/aia.c
@@ -24,7 +24,8 @@ uint32_t imsic_num_bits(uint32_t count)
return ret;
}
-DeviceState *riscv_create_aia(bool msimode, int aia_guests,
+DeviceState *riscv_create_aia(MemoryRegion *container,
+ bool msimode, int aia_guests,
uint32_t m_imsic_stride,
uint32_t s_imsic_stride,
uint16_t num_sources,
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 812051a11fd4..f395236d88ab 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -498,7 +498,8 @@ static void tt_atlantis_machine_init(MachineState *machine)
&error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
- s->irqchip = riscv_create_aia(true, TT_IMSIC_GUESTS,
+ s->irqchip = riscv_create_aia(system_memory,
+ true, TT_IMSIC_GUESTS,
TT_IMSIC_STRIDE,
TT_IMSIC_STRIDE,
TT_IRQCHIP_NUM_SOURCES,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index de7b99c6a51e..6480a3f0a9c0 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -809,8 +809,9 @@ static void virt_machine_init(MachineState *machine)
s->irqchip[i] = virt_create_plic(s->memmap, i,
base_hartid, hart_count);
} else {
+ bool msimode = s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
int imsic_bits = imsic_num_bits(s->aia_guests + 1);
- s->irqchip[i] = riscv_create_aia(s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC,
+ s->irqchip[i] = riscv_create_aia(system_memory, msimode,
s->aia_guests,
IMSIC_HART_SIZE(0),
IMSIC_HART_SIZE(imsic_bits),
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 02/16] hw/intc/riscv_aclint: Take a MemoryRegion for the created devices
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
2026-09-03 5:51 ` [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 03/16] hw/intc/riscv_imsic: Take a MemoryRegion for the created device Joel Stanley
` (14 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
The riscv_aclint_mtimer_create() and riscv_aclint_swi_create() helpers
map the device they create into system_memory, which prevents their use
by SoCs that map devices into a memory container of their own.
Add a MemoryRegion parameter and map the device into it instead of
calling sysbus_mmio_map(). All callers pass system_memory, so there is
no change in behaviour.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/intc/riscv_aclint.h | 7 ++++---
hw/intc/riscv_aclint.c | 12 ++++++++----
hw/riscv/cps.c | 6 ++++--
hw/riscv/k230.c | 6 ++++--
hw/riscv/microchip_pfsoc.c | 5 +++--
hw/riscv/shakti_c.c | 7 ++++---
hw/riscv/sifive_e.c | 4 ++--
hw/riscv/sifive_u.c | 7 ++++---
hw/riscv/spike.c | 4 ++--
hw/riscv/tt_atlantis.c | 3 ++-
hw/riscv/virt.c | 17 +++++++++++------
hw/riscv/xiangshan_kmh.c | 6 ++++--
12 files changed, 52 insertions(+), 32 deletions(-)
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
index 0e0b98acb08a..71d1b551a1b2 100644
--- a/include/hw/intc/riscv_aclint.h
+++ b/include/hw/intc/riscv_aclint.h
@@ -46,7 +46,8 @@ typedef struct RISCVAclintMTimerState {
qemu_irq *timer_irqs;
} RISCVAclintMTimerState;
-DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
+DeviceState *riscv_aclint_mtimer_create(MemoryRegion *container,
+ hwaddr addr, hwaddr size,
uint32_t hartid_base, uint32_t num_harts,
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
bool provide_rdtime);
@@ -68,8 +69,8 @@ typedef struct RISCVAclintSwiState {
qemu_irq *soft_irqs;
} RISCVAclintSwiState;
-DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
- uint32_t num_harts, bool sswi);
+DeviceState *riscv_aclint_swi_create(MemoryRegion *container,
+ hwaddr addr, uint32_t hartid_base, uint32_t num_harts, bool sswi);
enum {
RISCV_ACLINT_DEFAULT_MTIMECMP = 0x0,
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 361a8d1bcb45..2d133d0dcf9b 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -371,7 +371,8 @@ static const TypeInfo riscv_aclint_mtimer_info = {
/*
* Create ACLINT MTIMER device.
*/
-DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
+DeviceState *riscv_aclint_mtimer_create(MemoryRegion *container,
+ hwaddr addr, hwaddr size,
uint32_t hartid_base, uint32_t num_harts,
uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
bool provide_rdtime)
@@ -392,7 +393,8 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
qdev_prop_set_uint32(dev, "aperture-size", size);
qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+ memory_region_add_subregion(container, addr,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
for (i = 0; i < num_harts; i++) {
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
@@ -556,7 +558,8 @@ static const TypeInfo riscv_aclint_swi_info = {
/*
* Create ACLINT [M|S]SWI device.
*/
-DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
+DeviceState *riscv_aclint_swi_create(MemoryRegion *container,
+ hwaddr addr, uint32_t hartid_base,
uint32_t num_harts, bool sswi)
{
int i;
@@ -569,7 +572,8 @@ DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
qdev_prop_set_uint32(dev, "num-harts", num_harts);
qdev_prop_set_uint32(dev, "sswi", sswi ? true : false);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+ memory_region_add_subregion(container, addr,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
for (i = 0; i < num_harts; i++) {
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
diff --git a/hw/riscv/cps.c b/hw/riscv/cps.c
index 86172be5b3ca..5cfb54aa27d2 100644
--- a/hw/riscv/cps.c
+++ b/hw/riscv/cps.c
@@ -151,9 +151,11 @@ static void riscv_cps_realize(DeviceState *dev, Error **errp)
false, false, s->aplic);
/* PLIC changes msi_nonbroken to ture. We revert the change. */
msi_nonbroken = false;
- riscv_aclint_swi_create(cm_base + AIA_CLINT_OFFSET,
+ riscv_aclint_swi_create(get_system_memory(),
+ cm_base + AIA_CLINT_OFFSET,
hartid_base, MAX_HARTS, false);
- riscv_aclint_mtimer_create(cm_base + AIA_CLINT_OFFSET +
+ riscv_aclint_mtimer_create(get_system_memory(),
+ cm_base + AIA_CLINT_OFFSET +
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
hartid_base,
diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
index 558f30b97e9d..1ef4260c5391 100644
--- a/hw/riscv/k230.c
+++ b/hw/riscv/k230.c
@@ -196,9 +196,11 @@ static void k230_soc_realize(DeviceState *dev, Error **errp)
s->c908_plic = k230_create_plic(C908_CPU_HARTID, c908_cpus);
/* CLINT */
- riscv_aclint_swi_create(memmap[K230_DEV_CLINT].base,
+ riscv_aclint_swi_create(sys_mem,
+ memmap[K230_DEV_CLINT].base,
C908_CPU_HARTID, c908_cpus, false);
- riscv_aclint_mtimer_create(memmap[K230_DEV_CLINT].base + 0x4000,
+ riscv_aclint_mtimer_create(sys_mem,
+ memmap[K230_DEV_CLINT].base + 0x4000,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
C908_CPU_HARTID, c908_cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP,
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 4017129c8304..a6026776d4de 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -250,9 +250,10 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size);
/* CLINT */
- riscv_aclint_swi_create(memmap[MICROCHIP_PFSOC_CLINT].base,
+ riscv_aclint_swi_create(system_memory,
+ memmap[MICROCHIP_PFSOC_CLINT].base,
0, ms->smp.cpus, false);
- riscv_aclint_mtimer_create(
+ riscv_aclint_mtimer_create(system_memory,
memmap[MICROCHIP_PFSOC_CLINT].base + RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 835b1f879b7f..86ff8f8fcaab 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -127,10 +127,11 @@ static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
SHAKTI_C_PLIC_CONTEXT_STRIDE,
shakti_c_memmap[SHAKTI_C_PLIC].size);
- riscv_aclint_swi_create(shakti_c_memmap[SHAKTI_C_CLINT].base,
+ riscv_aclint_swi_create(system_memory,
+ shakti_c_memmap[SHAKTI_C_CLINT].base,
0, 1, false);
- riscv_aclint_mtimer_create(shakti_c_memmap[SHAKTI_C_CLINT].base +
- RISCV_ACLINT_SWI_SIZE,
+ riscv_aclint_mtimer_create(system_memory,
+ shakti_c_memmap[SHAKTI_C_CLINT].base + RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, 1,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 71925583bd97..0ea444f43bc5 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -225,9 +225,9 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
SIFIVE_E_PLIC_CONTEXT_BASE,
SIFIVE_E_PLIC_CONTEXT_STRIDE,
memmap[SIFIVE_E_DEV_PLIC].size);
- riscv_aclint_swi_create(memmap[SIFIVE_E_DEV_CLINT].base,
+ riscv_aclint_swi_create(sys_mem, memmap[SIFIVE_E_DEV_CLINT].base,
0, ms->smp.cpus, false);
- riscv_aclint_mtimer_create(memmap[SIFIVE_E_DEV_CLINT].base +
+ riscv_aclint_mtimer_create(sys_mem, memmap[SIFIVE_E_DEV_CLINT].base +
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 852c48c056e9..6bbf2c4504d8 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -790,10 +790,11 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ));
sifive_uart_create(system_memory, memmap[SIFIVE_U_DEV_UART1].base,
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
- riscv_aclint_swi_create(memmap[SIFIVE_U_DEV_CLINT].base, 0,
+ riscv_aclint_swi_create(system_memory,
+ memmap[SIFIVE_U_DEV_CLINT].base, 0,
ms->smp.cpus, false);
- riscv_aclint_mtimer_create(memmap[SIFIVE_U_DEV_CLINT].base +
- RISCV_ACLINT_SWI_SIZE,
+ riscv_aclint_mtimer_create(system_memory,
+ memmap[SIFIVE_U_DEV_CLINT].base + RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
CLINT_TIMEBASE_FREQ, false);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 8d7e93807c06..c0c22d639f17 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -167,10 +167,10 @@ static void spike_board_init(MachineState *machine)
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_fatal);
/* Core Local Interruptor (timer and IPI) for each socket */
- riscv_aclint_swi_create(
+ riscv_aclint_swi_create(system_memory,
memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size,
base_hartid, hart_count, false);
- riscv_aclint_mtimer_create(
+ riscv_aclint_mtimer_create(system_memory,
memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size +
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index f395236d88ab..373d4dabf3a4 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -511,7 +511,8 @@ static void tt_atlantis_machine_init(MachineState *machine)
TT_IRQCHIP_NUM_MSIS,
TT_IRQCHIP_NUM_PRIO_BITS);
- riscv_aclint_mtimer_create(s->memmap[TT_ATL_ACLINT].base,
+ riscv_aclint_mtimer_create(system_memory,
+ s->memmap[TT_ATL_ACLINT].base,
TT_ACLINT_MTIME_SIZE,
0, hart_count,
TT_ACLINT_MTIMECMP,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 6480a3f0a9c0..8fd742181e28 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -768,7 +768,8 @@ static void virt_machine_init(MachineState *machine)
if (virt_aclint_allowed() && s->have_aclint) {
if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
/* Per-socket ACLINT MTIMER */
- riscv_aclint_mtimer_create(s->memmap[VIRT_CLINT].base +
+ riscv_aclint_mtimer_create(system_memory,
+ s->memmap[VIRT_CLINT].base +
i * RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
base_hartid, hart_count,
@@ -777,10 +778,12 @@ static void virt_machine_init(MachineState *machine)
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
} else {
/* Per-socket ACLINT MSWI, MTIMER, and SSWI */
- riscv_aclint_swi_create(s->memmap[VIRT_CLINT].base +
+ riscv_aclint_swi_create(system_memory,
+ s->memmap[VIRT_CLINT].base +
i * s->memmap[VIRT_CLINT].size,
base_hartid, hart_count, false);
- riscv_aclint_mtimer_create(s->memmap[VIRT_CLINT].base +
+ riscv_aclint_mtimer_create(system_memory,
+ s->memmap[VIRT_CLINT].base +
i * s->memmap[VIRT_CLINT].size +
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
@@ -788,16 +791,18 @@ static void virt_machine_init(MachineState *machine)
RISCV_ACLINT_DEFAULT_MTIMECMP,
RISCV_ACLINT_DEFAULT_MTIME,
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
- riscv_aclint_swi_create(s->memmap[VIRT_ACLINT_SSWI].base +
+ riscv_aclint_swi_create(system_memory,
+ s->memmap[VIRT_ACLINT_SSWI].base +
i * s->memmap[VIRT_ACLINT_SSWI].size,
base_hartid, hart_count, true);
}
} else if (tcg_enabled()) {
/* Per-socket SiFive CLINT */
- riscv_aclint_swi_create(
+ riscv_aclint_swi_create(system_memory,
s->memmap[VIRT_CLINT].base + i * s->memmap[VIRT_CLINT].size,
base_hartid, hart_count, false);
- riscv_aclint_mtimer_create(s->memmap[VIRT_CLINT].base +
+ riscv_aclint_mtimer_create(system_memory,
+ s->memmap[VIRT_CLINT].base +
i * s->memmap[VIRT_CLINT].size + RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
index 384624d69ad5..94f9d02a00b9 100644
--- a/hw/riscv/xiangshan_kmh.c
+++ b/hw/riscv/xiangshan_kmh.c
@@ -116,9 +116,11 @@ static void xiangshan_kmh_soc_realize(DeviceState *dev, Error **errp)
115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
/* CLINT */
- riscv_aclint_swi_create(memmap[XIANGSHAN_KMH_CLINT].base,
+ riscv_aclint_swi_create(system_memory,
+ memmap[XIANGSHAN_KMH_CLINT].base,
0, num_harts, false);
- riscv_aclint_mtimer_create(memmap[XIANGSHAN_KMH_CLINT].base +
+ riscv_aclint_mtimer_create(system_memory,
+ memmap[XIANGSHAN_KMH_CLINT].base +
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
0, num_harts, RISCV_ACLINT_DEFAULT_MTIMECMP,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 03/16] hw/intc/riscv_imsic: Take a MemoryRegion for the created device
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
2026-09-03 5:51 ` [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices Joel Stanley
2026-09-03 5:51 ` [PATCH v3 02/16] hw/intc/riscv_aclint: " Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 04/16] hw/intc/riscv_aplic: " Joel Stanley
` (13 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
riscv_imsic_create() maps the device it creates into system_memory,
which prevents its use by SoCs that map devices into their own memory
container.
Add a MemoryRegion parameter and map the device into it instead of
calling sysbus_mmio_map(). All callers pass system_memory, so there is
no change in behaviour.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/intc/riscv_imsic.h | 3 ++-
hw/intc/riscv_imsic.c | 6 ++++--
hw/riscv/aia.c | 6 ++++--
hw/riscv/xiangshan_kmh.c | 5 +++--
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/include/hw/intc/riscv_imsic.h b/include/hw/intc/riscv_imsic.h
index fae999731dff..0a1df1c2f8d6 100644
--- a/include/hw/intc/riscv_imsic.h
+++ b/include/hw/intc/riscv_imsic.h
@@ -62,7 +62,8 @@ struct RISCVIMSICState {
uint32_t num_irqs;
};
-DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
+DeviceState *riscv_imsic_create(MemoryRegion *container, hwaddr addr,
+ uint32_t hartid, bool mmode,
uint32_t num_pages, uint32_t num_ids);
#endif
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index d6b46cdca220..cb9ce9612cff 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -495,7 +495,8 @@ type_init(riscv_imsic_register_types)
/*
* Create IMSIC device.
*/
-DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
+DeviceState *riscv_imsic_create(MemoryRegion *container, hwaddr addr,
+ uint32_t hartid, bool mmode,
uint32_t num_pages, uint32_t num_ids)
{
DeviceState *dev = qdev_new(TYPE_RISCV_IMSIC);
@@ -518,7 +519,8 @@ DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
qdev_prop_set_uint32(dev, "num-irqs", num_ids + 1);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+ memory_region_add_subregion(container, addr,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
if (!kvm_irqchip_in_kernel()) {
for (i = 0; i < num_pages; i++) {
diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c
index e11382e512da..eae7638f972b 100644
--- a/hw/riscv/aia.c
+++ b/hw/riscv/aia.c
@@ -53,7 +53,8 @@ DeviceState *riscv_create_aia(MemoryRegion *container,
/* 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 * m_imsic_stride,
+ riscv_imsic_create(container,
+ addr + i * m_imsic_stride,
base_hartid + i, true, 1,
num_msis);
}
@@ -62,7 +63,8 @@ DeviceState *riscv_create_aia(MemoryRegion *container,
/* Per-socket S-level IMSICs */
addr = imsic_s->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT);
for (i = 0; i < hart_count; i++) {
- riscv_imsic_create(addr + i * s_imsic_stride,
+ riscv_imsic_create(container,
+ addr + i * s_imsic_stride,
base_hartid + i, false, 1 + aia_guests,
num_msis);
}
diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
index 94f9d02a00b9..9eb608f8c578 100644
--- a/hw/riscv/xiangshan_kmh.c
+++ b/hw/riscv/xiangshan_kmh.c
@@ -65,14 +65,15 @@ static DeviceState *xiangshan_kmh_create_aia(uint32_t num_harts)
/* M-level IMSICs */
addr = memmap[XIANGSHAN_KMH_IMSIC_M].base;
for (i = 0; i < num_harts; i++) {
- riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0), i, true,
+ riscv_imsic_create(get_system_memory(),
+ addr + i * IMSIC_HART_SIZE(0), i, true,
1, XIANGSHAN_KMH_IMSIC_NUM_IDS);
}
/* S-level IMSICs */
addr = memmap[XIANGSHAN_KMH_IMSIC_S].base;
for (i = 0; i < num_harts; i++) {
- riscv_imsic_create(addr +
+ riscv_imsic_create(get_system_memory(), addr +
i * IMSIC_HART_SIZE(XIANGSHAN_KMH_IMSIC_GUEST_BITS),
i, false, 1 + XIANGSHAN_KMH_IMSIC_GUEST_BITS,
XIANGSHAN_KMH_IMSIC_NUM_IDS);
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 04/16] hw/intc/riscv_aplic: Take a MemoryRegion for the created device
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (2 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 03/16] hw/intc/riscv_imsic: Take a MemoryRegion for the created device Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 05/16] hw/intc/sifive_plic: " Joel Stanley
` (12 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
riscv_aplic_create() maps the device it creates into system_memory,
which prevents its use by SoCs that map devices into their own memory
container.
Add a MemoryRegion parameter and map the device into it instead of
calling sysbus_mmio_map(). The mapping still only happens when the
APLIC is emulated. All callers pass system_memory, so there is no
change in behaviour.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/intc/riscv_aplic.h | 7 ++++---
hw/intc/riscv_aplic.c | 10 ++++++----
hw/riscv/aia.c | 8 ++++----
hw/riscv/cps.c | 6 ++++--
hw/riscv/xiangshan_kmh.c | 6 ++++--
5 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/include/hw/intc/riscv_aplic.h b/include/hw/intc/riscv_aplic.h
index c7a4d4ad0172..62d2b33ade61 100644
--- a/include/hw/intc/riscv_aplic.h
+++ b/include/hw/intc/riscv_aplic.h
@@ -80,8 +80,9 @@ bool riscv_is_kvm_aia_aplic_imsic(bool msimode);
bool riscv_use_emulated_aplic(bool msimode);
void riscv_aplic_set_kvm_msicfgaddr(RISCVAPLICState *aplic, hwaddr addr);
-DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
- uint32_t hartid_base, uint32_t num_harts, uint32_t num_sources,
- uint32_t iprio_bits, bool msimode, bool mmode, DeviceState *parent);
+DeviceState *riscv_aplic_create(MemoryRegion *container,
+ hwaddr addr, hwaddr size, uint32_t hartid_base, uint32_t num_harts,
+ uint32_t num_sources, uint32_t iprio_bits, bool msimode, bool mmode,
+ DeviceState *parent);
#endif
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index 84606e9f3d88..d8e25bfda14b 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -1109,9 +1109,10 @@ void riscv_aplic_add_child(DeviceState *parent, DeviceState *child)
/*
* Create APLIC device.
*/
-DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
- uint32_t hartid_base, uint32_t num_harts, uint32_t num_sources,
- uint32_t iprio_bits, bool msimode, bool mmode, DeviceState *parent)
+DeviceState *riscv_aplic_create(MemoryRegion *container,
+ hwaddr addr, hwaddr size, uint32_t hartid_base, uint32_t num_harts,
+ uint32_t num_sources, uint32_t iprio_bits, bool msimode, bool mmode,
+ DeviceState *parent)
{
DeviceState *dev = qdev_new(TYPE_RISCV_APLIC);
uint32_t i;
@@ -1137,7 +1138,8 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
if (riscv_use_emulated_aplic(msimode)) {
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+ memory_region_add_subregion(container, addr,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
if (!msimode) {
for (i = 0; i < num_harts; i++) {
diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c
index eae7638f972b..56fc06453321 100644
--- a/hw/riscv/aia.c
+++ b/hw/riscv/aia.c
@@ -72,8 +72,8 @@ DeviceState *riscv_create_aia(MemoryRegion *container,
if (!kvm_enabled()) {
/* Per-socket M-level APLIC */
- aplic_m_dev = riscv_aplic_create(aplic_m->base +
- socket * aplic_m->size,
+ aplic_m_dev = riscv_aplic_create(container,
+ aplic_m->base + socket * aplic_m->size,
aplic_m->size,
(msimode) ? 0 : base_hartid,
(msimode) ? 0 : hart_count,
@@ -83,8 +83,8 @@ DeviceState *riscv_create_aia(MemoryRegion *container,
}
/* Per-socket S-level APLIC */
- aplic_s_dev = riscv_aplic_create(aplic_s->base +
- socket * aplic_s->size,
+ aplic_s_dev = riscv_aplic_create(container,
+ aplic_s->base + socket * aplic_s->size,
aplic_s->size,
(msimode) ? 0 : base_hartid,
(msimode) ? 0 : hart_count,
diff --git a/hw/riscv/cps.c b/hw/riscv/cps.c
index 5cfb54aa27d2..d2fd9638a08d 100644
--- a/hw/riscv/cps.c
+++ b/hw/riscv/cps.c
@@ -135,14 +135,16 @@ static void riscv_cps_realize(DeviceState *dev, Error **errp)
for (i = 0; i < num_of_clusters; i++) {
uint64_t cm_base = GLOBAL_CM_BASE + (CM_SIZE * i);
uint32_t hartid_base = i << MHARTID_CLUSTER_SHIFT;
- s->aplic = riscv_aplic_create(cm_base + AIA_PLIC_M_OFFSET,
+ s->aplic = riscv_aplic_create(get_system_memory(),
+ cm_base + AIA_PLIC_M_OFFSET,
AIA_PLIC_M_SIZE,
hartid_base, /* hartid_base */
MAX_HARTS, /* num_harts */
APLIC_NUM_SOURCES,
APLIC_NUM_PRIO_BITS,
false, true, NULL);
- riscv_aplic_create(cm_base + AIA_PLIC_S_OFFSET,
+ riscv_aplic_create(get_system_memory(),
+ cm_base + AIA_PLIC_S_OFFSET,
AIA_PLIC_S_SIZE,
hartid_base, /* hartid_base */
MAX_HARTS, /* num_harts */
diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
index 9eb608f8c578..c5a654ab417d 100644
--- a/hw/riscv/xiangshan_kmh.c
+++ b/hw/riscv/xiangshan_kmh.c
@@ -80,13 +80,15 @@ static DeviceState *xiangshan_kmh_create_aia(uint32_t num_harts)
}
/* M-level APLIC */
- aplic_m = riscv_aplic_create(memmap[XIANGSHAN_KMH_APLIC_M].base,
+ aplic_m = riscv_aplic_create(get_system_memory(),
+ memmap[XIANGSHAN_KMH_APLIC_M].base,
memmap[XIANGSHAN_KMH_APLIC_M].size,
0, 0, XIANGSHAN_KMH_APLIC_NUM_SOURCES,
1, true, true, NULL);
/* S-level APLIC */
- riscv_aplic_create(memmap[XIANGSHAN_KMH_APLIC_S].base,
+ riscv_aplic_create(get_system_memory(),
+ memmap[XIANGSHAN_KMH_APLIC_S].base,
memmap[XIANGSHAN_KMH_APLIC_S].size,
0, 0, XIANGSHAN_KMH_APLIC_NUM_SOURCES,
1, true, false, aplic_m);
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 05/16] hw/intc/sifive_plic: Take a MemoryRegion for the created device
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (3 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 04/16] hw/intc/riscv_aplic: " Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 6:07 ` Chao Liu via
2026-09-03 5:51 ` [PATCH v3 06/16] hw/riscv/cps: Map interrupt controllers in SoC container Joel Stanley
` (11 subsequent siblings)
16 siblings, 1 reply; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
sifive_plic_create() maps the device it creates into system_memory,
which prevents its use by SoCs that map devices into their own memory
container.
Add a MemoryRegion parameter and map the device into it instead of
calling sysbus_mmio_map(). All callers pass system_memory, so there is
no change in behaviour.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/intc/sifive_plic.h | 4 ++--
hw/intc/sifive_plic.c | 7 ++++---
hw/riscv/k230.c | 3 ++-
hw/riscv/microchip_pfsoc.c | 3 ++-
hw/riscv/shakti_c.c | 3 ++-
hw/riscv/sifive_e.c | 2 +-
hw/riscv/sifive_u.c | 3 ++-
hw/riscv/virt.c | 1 +
8 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
index 32973dbf281e..064754c3f628 100644
--- a/include/hw/intc/sifive_plic.h
+++ b/include/hw/intc/sifive_plic.h
@@ -76,8 +76,8 @@ struct SiFivePLICState {
qemu_irq *s_external_irqs;
};
-DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
- uint32_t num_harts,
+DeviceState *sifive_plic_create(MemoryRegion *container,
+ hwaddr addr, char *hart_config, uint32_t num_harts,
uint32_t hartid_base, uint32_t num_sources,
uint32_t num_priorities, uint32_t priority_base,
uint32_t pending_base, uint32_t enable_base,
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index 9c84ff06a9fd..90f17e6ee724 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -473,8 +473,8 @@ type_init(sifive_plic_register_types)
/*
* Create PLIC device.
*/
-DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
- uint32_t num_harts,
+DeviceState *sifive_plic_create(MemoryRegion *container,
+ hwaddr addr, char *hart_config, uint32_t num_harts,
uint32_t hartid_base, uint32_t num_sources,
uint32_t num_priorities, uint32_t priority_base,
uint32_t pending_base, uint32_t enable_base,
@@ -499,7 +499,8 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
qdev_prop_set_uint32(dev, "context-stride", context_stride);
qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+ memory_region_add_subregion(container, addr,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
plic = SIFIVE_PLIC(dev);
diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
index 1ef4260c5391..6b0f0453c80b 100644
--- a/hw/riscv/k230.c
+++ b/hw/riscv/k230.c
@@ -134,7 +134,8 @@ static DeviceState *k230_create_plic(int base_hartid, int hartid_count)
plic_hart_config = riscv_plic_hart_config_string(hartid_count);
/* Per-socket PLIC */
- return sifive_plic_create(memmap[K230_DEV_PLIC].base,
+ return sifive_plic_create(get_system_memory(),
+ memmap[K230_DEV_PLIC].base,
plic_hart_config, hartid_count, base_hartid,
K230_PLIC_NUM_SOURCES,
K230_PLIC_NUM_PRIORITIES,
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index a6026776d4de..1f6d9f5ae1ed 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -282,7 +282,8 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
/* PLIC */
- s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
+ s->plic = sifive_plic_create(system_memory,
+ memmap[MICROCHIP_PFSOC_PLIC].base,
plic_hart_config, ms->smp.cpus, 0,
MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 86ff8f8fcaab..62052bf7c61e 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -115,7 +115,8 @@ static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
- sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
+ sss->plic = sifive_plic_create(system_memory,
+ shakti_c_memmap[SHAKTI_C_PLIC].base,
(char *)SHAKTI_C_PLIC_HART_CONFIG, ms->smp.cpus, 0,
SHAKTI_C_PLIC_NUM_SOURCES,
SHAKTI_C_PLIC_NUM_PRIORITIES,
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 0ea444f43bc5..81d7995ddcfb 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -214,7 +214,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
memmap[SIFIVE_E_DEV_MROM].base, &s->mask_rom);
/* MMIO */
- s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
+ s->plic = sifive_plic_create(sys_mem, memmap[SIFIVE_E_DEV_PLIC].base,
(char *)SIFIVE_E_PLIC_HART_CONFIG, ms->smp.cpus, 0,
SIFIVE_E_PLIC_NUM_SOURCES,
SIFIVE_E_PLIC_NUM_PRIORITIES,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 6bbf2c4504d8..632194a06ea1 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -774,7 +774,8 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
/* MMIO */
- s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
+ s->plic = sifive_plic_create(system_memory,
+ memmap[SIFIVE_U_DEV_PLIC].base,
plic_hart_config, ms->smp.cpus, 0,
SIFIVE_U_PLIC_NUM_SOURCES,
SIFIVE_U_PLIC_NUM_PRIORITIES,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 8fd742181e28..a7b5af4e4c88 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -561,6 +561,7 @@ static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
/* Per-socket PLIC */
return sifive_plic_create(
+ get_system_memory(),
memmap[VIRT_PLIC].base + socket * memmap[VIRT_PLIC].size,
plic_hart_config, hart_count, base_hartid,
VIRT_IRQCHIP_NUM_SOURCES,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 06/16] hw/riscv/cps: Map interrupt controllers in SoC container
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (4 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 05/16] hw/intc/sifive_plic: " Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 07/16] hw/riscv/atlantis: Make UART unimp region a SoC device Joel Stanley
` (10 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
The CPS device maps some devices into a container region, but the
ACLINT and APLIC were mapped directly to system_memory.
Pass the container memory region to the interrupt controller helpers so
all CPS devices live in the container. The location of devices in memory
for the boston-aia machine is unchanged.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
hw/riscv/cps.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/riscv/cps.c b/hw/riscv/cps.c
index d2fd9638a08d..21daaf4943d8 100644
--- a/hw/riscv/cps.c
+++ b/hw/riscv/cps.c
@@ -135,7 +135,7 @@ static void riscv_cps_realize(DeviceState *dev, Error **errp)
for (i = 0; i < num_of_clusters; i++) {
uint64_t cm_base = GLOBAL_CM_BASE + (CM_SIZE * i);
uint32_t hartid_base = i << MHARTID_CLUSTER_SHIFT;
- s->aplic = riscv_aplic_create(get_system_memory(),
+ s->aplic = riscv_aplic_create(&s->container,
cm_base + AIA_PLIC_M_OFFSET,
AIA_PLIC_M_SIZE,
hartid_base, /* hartid_base */
@@ -143,7 +143,7 @@ static void riscv_cps_realize(DeviceState *dev, Error **errp)
APLIC_NUM_SOURCES,
APLIC_NUM_PRIO_BITS,
false, true, NULL);
- riscv_aplic_create(get_system_memory(),
+ riscv_aplic_create(&s->container,
cm_base + AIA_PLIC_S_OFFSET,
AIA_PLIC_S_SIZE,
hartid_base, /* hartid_base */
@@ -153,10 +153,10 @@ static void riscv_cps_realize(DeviceState *dev, Error **errp)
false, false, s->aplic);
/* PLIC changes msi_nonbroken to ture. We revert the change. */
msi_nonbroken = false;
- riscv_aclint_swi_create(get_system_memory(),
+ riscv_aclint_swi_create(&s->container,
cm_base + AIA_CLINT_OFFSET,
hartid_base, MAX_HARTS, false);
- riscv_aclint_mtimer_create(get_system_memory(),
+ riscv_aclint_mtimer_create(&s->container,
cm_base + AIA_CLINT_OFFSET +
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 07/16] hw/riscv/atlantis: Make UART unimp region a SoC device
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (5 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 06/16] hw/riscv/cps: Map interrupt controllers in SoC container Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 08/16] hw/riscv/atlantis: Remove unused fdt_size Joel Stanley
` (9 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
Make the unimplemented region covering the remainder of the console
UART's register space a SoC child device, mapped using a helper. This
makes it easier to map it into the SoC's memory container along with
the other devices in the future.
While here, rename the region from uart0 to uart1. The uart0 name was
a leftover from an earlier revision that used a different device for
the console.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 2 ++
hw/riscv/tt_atlantis.c | 19 ++++++++++++++++---
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 7f7d4a5a5905..c9308aa57017 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -13,6 +13,7 @@
#include "hw/core/sysbus.h"
#include "hw/i2c/designware_i2c.h"
#include "hw/intc/riscv_imsic.h"
+#include "hw/misc/unimp.h"
#include "hw/riscv/riscv_hart.h"
#define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME("tt-atlantis")
@@ -31,6 +32,7 @@ struct TTAtlantisState {
RISCVHartArrayState soc;
DeviceState *irqchip;
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
+ UnimplementedDeviceState uart1;
int fdt_size;
};
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 373d4dabf3a4..a2fb83aab78e 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -411,6 +411,17 @@ static void load_fdt(TTAtlantisState *s)
create_fdt_memory(s);
}
+static void mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev,
+ const char *name, hwaddr addr, uint64_t size)
+{
+ qdev_prop_set_string(DEVICE(dev), "name", name);
+ qdev_prop_set_uint64(DEVICE(dev), "size", size);
+ sysbus_realize(dev, &error_abort);
+
+ memory_region_add_subregion_overlap(memory, addr,
+ sysbus_mmio_get_region(dev, 0), -1000);
+}
+
static void tt_atlantis_machine_done(Notifier *notifier, void *data)
{
TTAtlantisState *s = container_of(notifier, TTAtlantisState, machine_done);
@@ -562,9 +573,11 @@ static void tt_atlantis_machine_init(MachineState *machine)
* Create an unimplemented device region so writes don't fault
* and reads return zero, which keeps Linux happy.
*/
- create_unimplemented_device("tt-atlantis.uart0",
- s->memmap[TT_ATL_UART1].base,
- s->memmap[TT_ATL_UART1].size);
+ object_initialize_child(OBJECT(s), "uart1", &s->uart1,
+ TYPE_UNIMPLEMENTED_DEVICE);
+ mmio_map_unimplemented(system_memory, SYS_BUS_DEVICE(&s->uart1),
+ "tt-atlantis.uart1", s->memmap[TT_ATL_UART1].base,
+ s->memmap[TT_ATL_UART1].size);
/* I2C */
for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 08/16] hw/riscv/atlantis: Remove unused fdt_size
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (6 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 07/16] hw/riscv/atlantis: Make UART unimp region a SoC device Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 09/16] hw/riscv/atlantis: Rename hart array 'soc' to 'cpus' Joel Stanley
` (8 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
The machine state carries around the FDT size which isn't used by
anything.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 2 --
hw/riscv/tt_atlantis.c | 9 +++++----
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index c9308aa57017..d0cca3b02424 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -33,8 +33,6 @@ struct TTAtlantisState {
DeviceState *irqchip;
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
UnimplementedDeviceState uart1;
-
- int fdt_size;
};
enum {
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index a2fb83aab78e..7d31294ea1fb 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -367,10 +367,10 @@ static void finalize_fdt(TTAtlantisState *s)
static void create_fdt(TTAtlantisState *s)
{
MachineState *ms = MACHINE(s);
+ int fdt_size = 0;
- ms->fdt = riscv_create_board_device_tree(
- "Tenstorrent Atlantis RISC-V Machine",
- "tenstorrent,atlantis", &s->fdt_size);
+ ms->fdt = riscv_create_board_device_tree("Tenstorrent Atlantis RISC-V Machine",
+ "tenstorrent,atlantis", &fdt_size);
qemu_fdt_add_subnode(ms->fdt, "/chosen");
@@ -386,8 +386,9 @@ static void load_fdt(TTAtlantisState *s)
MachineState *ms = MACHINE(s);
char **node_path;
Error *err = NULL;
+ int fdt_size = 0;
- ms->fdt = load_device_tree(ms->dtb, &s->fdt_size);
+ ms->fdt = load_device_tree(ms->dtb, &fdt_size);
if (!ms->fdt) {
error_report("load_device_tree() failed");
exit(1);
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 09/16] hw/riscv/atlantis: Rename hart array 'soc' to 'cpus'
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (7 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 08/16] hw/riscv/atlantis: Remove unused fdt_size Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 10/16] hw/riscv/atlantis: Rework device tree creation Joel Stanley
` (7 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
The RISCVHartArrayState member is named soc, but it's an array of cpus,
not the entire SoC. Use cpus instead as an accurate description of the
hart array.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 2 +-
hw/riscv/tt_atlantis.c | 34 +++++++++++++++++-----------------
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index d0cca3b02424..642490d21743 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -29,7 +29,7 @@ struct TTAtlantisState {
Notifier machine_done;
const MemMapEntry *memmap;
- RISCVHartArrayState soc;
+ RISCVHartArrayState cpus;
DeviceState *irqchip;
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
UnimplementedDeviceState uart1;
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 7d31294ea1fb..80300a18a4ab 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -113,13 +113,13 @@ static void create_fdt_aclint(TTAtlantisState *s, uint32_t *intc_phandles)
uint32_t aclint_cells_size;
hwaddr addr;
- aclint_mtimer_cells = g_new0(uint32_t, s->soc.num_harts * 2);
+ aclint_mtimer_cells = g_new0(uint32_t, s->cpus.num_harts * 2);
- for (int cpu = 0; cpu < s->soc.num_harts; cpu++) {
+ for (int cpu = 0; cpu < s->cpus.num_harts; cpu++) {
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_cells_size = s->soc.num_harts * sizeof(uint32_t) * 2;
+ aclint_cells_size = s->cpus.num_harts * sizeof(uint32_t) * 2;
addr = s->memmap[TT_ATL_ACLINT].base;
@@ -211,7 +211,7 @@ static void create_fdt_pmu(TTAtlantisState *s)
{
char pmu_name[] = "/pmu";
void *fdt = MACHINE(s)->fdt;
- RISCVCPU *hart = &s->soc.harts[0];
+ RISCVCPU *hart = &s->cpus.harts[0];
qemu_fdt_add_subnode(fdt, pmu_name);
qemu_fdt_setprop_string(fdt, pmu_name, "compatible", "riscv,pmu");
@@ -228,8 +228,8 @@ static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap,
riscv_fdt_create_cpu_socket_subnode(fdt, TT_ACLINT_TIMEBASE_FREQ);
- riscv_create_fdt_socket_cpus(fdt, s->soc.harts, 0, s->soc.num_harts,
- s->soc.hartid_base, &fdt_phandle,
+ riscv_create_fdt_socket_cpus(fdt, s->cpus.harts, 0, s->cpus.num_harts,
+ s->cpus.hartid_base, &fdt_phandle,
intc_phandles, false, false);
create_fdt_memory(s);
@@ -253,13 +253,13 @@ static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap,
create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_MAPLIC],
msi_m_phandle, intc_phandles,
aplic_m_phandle, aplic_s_phandle,
- IRQ_M_EXT, s->soc.num_harts);
+ IRQ_M_EXT, s->cpus.num_harts);
/* S-level APLIC node */
create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_SAPLIC],
imsic_s_phandle, intc_phandles,
aplic_s_phandle, 0,
- IRQ_S_EXT, s->soc.num_harts);
+ IRQ_S_EXT, s->cpus.num_harts);
}
static void create_fdt_uart(void *fdt, const MemMapEntry *mem, int irq,
@@ -430,7 +430,7 @@ static void tt_atlantis_machine_done(Notifier *notifier, void *data)
hwaddr start_addr = s->memmap[TT_ATL_DDR_LO].base;
hwaddr mem_size;
target_ulong firmware_end_addr, kernel_start_addr;
- const char *firmware_name = riscv_default_firmware_name(&s->soc);
+ const char *firmware_name = riscv_default_firmware_name(&s->cpus);
uint64_t fdt_load_addr;
uint64_t kernel_entry;
RISCVBootInfo boot_info;
@@ -447,7 +447,7 @@ static void tt_atlantis_machine_done(Notifier *notifier, void *data)
if (mem_size > s->memmap[TT_ATL_DDR_LO].size) {
mem_size = s->memmap[TT_ATL_DDR_LO].size;
}
- riscv_boot_info_init_discontig_mem(&boot_info, &s->soc,
+ riscv_boot_info_init_discontig_mem(&boot_info, &s->cpus,
s->memmap[TT_ATL_DDR_LO].base,
mem_size);
@@ -477,7 +477,7 @@ static void tt_atlantis_machine_done(Notifier *notifier, void *data)
riscv_load_fdt(fdt_load_addr, machine->fdt);
/* load the reset vector */
- riscv_setup_rom_reset_vec(machine, &s->soc, start_addr,
+ riscv_setup_rom_reset_vec(machine, &s->cpus, start_addr,
s->memmap[TT_ATL_BOOTROM].base,
s->memmap[TT_ATL_BOOTROM].size,
kernel_entry,
@@ -497,18 +497,18 @@ static void tt_atlantis_machine_init(MachineState *machine)
s->memmap = tt_atlantis_memmap;
- object_initialize_child(OBJECT(machine), "soc", &s->soc,
+ object_initialize_child(OBJECT(machine), "soc", &s->cpus,
TYPE_RISCV_HART_ARRAY);
- object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type,
+ object_property_set_str(OBJECT(&s->cpus), "cpu-type", machine->cpu_type,
&error_abort);
- object_property_set_int(OBJECT(&s->soc), "hartid-base", 0,
+ object_property_set_int(OBJECT(&s->cpus), "hartid-base", 0,
&error_abort);
- object_property_set_int(OBJECT(&s->soc), "num-harts", hart_count,
+ object_property_set_int(OBJECT(&s->cpus), "num-harts", hart_count,
&error_abort);
- object_property_set_int(OBJECT(&s->soc), "resetvec",
+ object_property_set_int(OBJECT(&s->cpus), "resetvec",
s->memmap[TT_ATL_BOOTROM].base,
&error_abort);
- sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
+ sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal);
s->irqchip = riscv_create_aia(system_memory,
true, TT_IMSIC_GUESTS,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 10/16] hw/riscv/atlantis: Rework device tree creation
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (8 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 09/16] hw/riscv/atlantis: Rename hart array 'soc' to 'cpus' Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 11/16] hw/riscv/atlantis: Use local reference for system memory Joel Stanley
` (6 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
Remove the direct use of MachineState from the device tree creation to
allow separation between the SoC (TTAtlantisState) and the QEMU
MachineState.
Fix this for the device tree pointer by passing it directly to the
functions that use it, instead of casting the TTAtlantisState to a
MachineState.
MachineState::smp.cpus is replaced with TTAtlantisState::cpus.num_harts,
as these are equivalent after tt_atlantis_machine_init.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
hw/riscv/tt_atlantis.c | 51 +++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 28 deletions(-)
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 80300a18a4ab..f2a4a051d1f6 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -80,9 +80,8 @@ static uint32_t next_phandle(void)
return fdt_phandle++;
}
-static void create_fdt_memory(TTAtlantisState *s)
+static void create_fdt_memory(void *fdt, TTAtlantisState *s)
{
- void *fdt = MACHINE(s)->fdt;
hwaddr size_lo = MACHINE(s)->ram_size;
hwaddr size_hi = 0;
@@ -105,9 +104,9 @@ static void create_fdt_memory(TTAtlantisState *s)
}
}
-static void create_fdt_aclint(TTAtlantisState *s, uint32_t *intc_phandles)
+static void create_fdt_aclint(void *fdt, TTAtlantisState *s,
+ uint32_t *intc_phandles)
{
- void *fdt = MACHINE(s)->fdt;
g_autofree char *name = NULL;
g_autofree uint32_t *aclint_mtimer_cells = NULL;
uint32_t aclint_cells_size;
@@ -207,10 +206,9 @@ static void create_fdt_one_aplic(void *fdt,
qemu_fdt_setprop_cell(fdt, name, "phandle", aplic_phandle);
}
-static void create_fdt_pmu(TTAtlantisState *s)
+static void create_fdt_pmu(void *fdt, TTAtlantisState *s)
{
char pmu_name[] = "/pmu";
- void *fdt = MACHINE(s)->fdt;
RISCVCPU *hart = &s->cpus.harts[0];
qemu_fdt_add_subnode(fdt, pmu_name);
@@ -218,32 +216,29 @@ static void create_fdt_pmu(TTAtlantisState *s)
riscv_pmu_generate_fdt_node(fdt, hart->pmu_avail_ctrs, pmu_name);
}
-static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap,
+static void create_fdt_cpu(void *fdt, TTAtlantisState *s,
uint32_t aplic_s_phandle,
uint32_t imsic_s_phandle)
{
- MachineState *ms = MACHINE(s);
- void *fdt = MACHINE(s)->fdt;
- g_autofree uint32_t *intc_phandles = g_new0(uint32_t, ms->smp.cpus);
+ g_autofree uint32_t *intc_phandles = g_new0(uint32_t, s->cpus.num_harts);
+ int num_harts = s->cpus.num_harts;
riscv_fdt_create_cpu_socket_subnode(fdt, TT_ACLINT_TIMEBASE_FREQ);
- riscv_create_fdt_socket_cpus(fdt, s->cpus.harts, 0, s->cpus.num_harts,
+ riscv_create_fdt_socket_cpus(fdt, s->cpus.harts, 0, num_harts,
s->cpus.hartid_base, &fdt_phandle,
intc_phandles, false, false);
- create_fdt_memory(s);
-
- create_fdt_aclint(s, intc_phandles);
+ create_fdt_aclint(fdt, s, intc_phandles);
/* M-level IMSIC node */
uint32_t msi_m_phandle = next_phandle();
- create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_MIMSIC], ms->smp.cpus,
+ create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_MIMSIC], num_harts,
intc_phandles, msi_m_phandle,
IRQ_M_EXT, TT_IMSIC_GUEST_BITS);
/* S-level IMSIC node */
- create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_SIMSIC], ms->smp.cpus,
+ create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_SIMSIC], num_harts,
intc_phandles, imsic_s_phandle,
IRQ_S_EXT, TT_IMSIC_GUEST_BITS);
@@ -253,13 +248,13 @@ static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap,
create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_MAPLIC],
msi_m_phandle, intc_phandles,
aplic_m_phandle, aplic_s_phandle,
- IRQ_M_EXT, s->cpus.num_harts);
+ IRQ_M_EXT, num_harts);
/* S-level APLIC node */
create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_SAPLIC],
imsic_s_phandle, intc_phandles,
aplic_s_phandle, 0,
- IRQ_S_EXT, s->cpus.num_harts);
+ IRQ_S_EXT, num_harts);
}
static void create_fdt_uart(void *fdt, const MemMapEntry *mem, int irq,
@@ -318,10 +313,9 @@ static void create_fdt_i2c(void *fdt, const MemMapEntry *mem, uint32_t irq,
qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0);
}
-static void create_fdt_i2c_device(TTAtlantisState *s, int bus,
+static void create_fdt_i2c_device(void *fdt, TTAtlantisState *s, int bus,
const char *compat, int addr)
{
- void *fdt = MACHINE(s)->fdt;
hwaddr base = s->memmap[TT_ATL_I2C0 + bus].base;
g_autofree char *name = g_strdup_printf("/soc/i2c@%"HWADDR_PRIX"/sensor@%x",
base, addr);
@@ -331,14 +325,15 @@ static void create_fdt_i2c_device(TTAtlantisState *s, int bus,
qemu_fdt_setprop_cell(fdt, name, "reg", addr);
}
-static void finalize_fdt(TTAtlantisState *s)
+static void finalize_fdt(void *fdt, TTAtlantisState *s)
{
uint32_t aplic_s_phandle = next_phandle();
uint32_t imsic_s_phandle = next_phandle();
uint32_t periph_clk_phandle = next_phandle();
- void *fdt = MACHINE(s)->fdt;
- create_fdt_cpu(s, s->memmap, aplic_s_phandle, imsic_s_phandle);
+ create_fdt_cpu(fdt, s, aplic_s_phandle, imsic_s_phandle);
+
+ create_fdt_memory(fdt, s);
/*
* We want to do this, but the Linux aplic driver was broken before v6.16
@@ -360,8 +355,8 @@ static void finalize_fdt(TTAtlantisState *s)
}
/* I2C peripherals: qemu specific */
- create_fdt_i2c_device(s, 0, "dallas,ds1338", 0x6f);
- create_fdt_i2c_device(s, 4, "ti,tmp105", 0x48);
+ create_fdt_i2c_device(fdt, s, 0, "dallas,ds1338", 0x6f);
+ create_fdt_i2c_device(fdt, s, 4, "ti,tmp105", 0x48);
}
static void create_fdt(TTAtlantisState *s)
@@ -378,7 +373,7 @@ static void create_fdt(TTAtlantisState *s)
qemu_fdt_add_subnode(ms->fdt, "/aliases");
- create_fdt_pmu(s);
+ create_fdt_pmu(ms->fdt, s);
}
static void load_fdt(TTAtlantisState *s)
@@ -409,7 +404,7 @@ static void load_fdt(TTAtlantisState *s)
g_strfreev(node_path);
}
- create_fdt_memory(s);
+ create_fdt_memory(ms->fdt, s);
}
static void mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev,
@@ -440,7 +435,7 @@ static void tt_atlantis_machine_done(Notifier *notifier, void *data)
* dynamic sysbus devices. Our FDT needs to be finalized.
*/
if (machine->dtb == NULL) {
- finalize_fdt(s);
+ finalize_fdt(machine->fdt, s);
}
mem_size = machine->ram_size;
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 11/16] hw/riscv/atlantis: Use local reference for system memory
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (9 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 10/16] hw/riscv/atlantis: Rework device tree creation Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 12/16] hw/riscv/atlantis: Decouple RAM size from MachineState Joel Stanley
` (5 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
Instead of system_memory, attach devices to TTAtlantisState::memory in
preparation for the ->memory becoming a container.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 1 +
hw/riscv/tt_atlantis.c | 19 ++++++++++---------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 642490d21743..a29c67c1cfcf 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -29,6 +29,7 @@ struct TTAtlantisState {
Notifier machine_done;
const MemMapEntry *memmap;
+ MemoryRegion *memory;
RISCVHartArrayState cpus;
DeviceState *irqchip;
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index f2a4a051d1f6..2a70119c2c6b 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -483,13 +483,14 @@ static void tt_atlantis_machine_init(MachineState *machine)
{
TTAtlantisState *s = TT_ATLANTIS_MACHINE(machine);
- MemoryRegion *system_memory = get_system_memory();
MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
MemoryRegion *bootrom = g_new(MemoryRegion, 1);
ram_addr_t lo_ram_size;
int hart_count = machine->smp.cpus;
+ s->memory = get_system_memory();
+
s->memmap = tt_atlantis_memmap;
object_initialize_child(OBJECT(machine), "soc", &s->cpus,
@@ -505,7 +506,7 @@ static void tt_atlantis_machine_init(MachineState *machine)
&error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal);
- s->irqchip = riscv_create_aia(system_memory,
+ s->irqchip = riscv_create_aia(s->memory,
true, TT_IMSIC_GUESTS,
TT_IMSIC_STRIDE,
TT_IMSIC_STRIDE,
@@ -518,7 +519,7 @@ static void tt_atlantis_machine_init(MachineState *machine)
TT_IRQCHIP_NUM_MSIS,
TT_IRQCHIP_NUM_PRIO_BITS);
- riscv_aclint_mtimer_create(system_memory,
+ riscv_aclint_mtimer_create(s->memory,
s->memmap[TT_ATL_ACLINT].base,
TT_ACLINT_MTIME_SIZE,
0, hart_count,
@@ -541,23 +542,23 @@ static void tt_atlantis_machine_init(MachineState *machine)
memory_region_init_alias(ram_hi, OBJECT(machine), "ram.high", machine->ram,
0, machine->ram_size);
- memory_region_add_subregion(system_memory,
+ memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_DDR_HI].base, ram_hi);
lo_ram_size = MIN(machine->ram_size, s->memmap[TT_ATL_DDR_LO].size);
memory_region_init_alias(ram_lo, OBJECT(machine), "ram.low", machine->ram,
0, lo_ram_size);
- memory_region_add_subregion(system_memory,
+ memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_DDR_LO].base, ram_lo);
/* Boot ROM */
memory_region_init_rom(bootrom, NULL, "tt-atlantis.bootrom",
s->memmap[TT_ATL_BOOTROM].size, &error_fatal);
- memory_region_add_subregion(system_memory, s->memmap[TT_ATL_BOOTROM].base,
+ memory_region_add_subregion(s->memory, s->memmap[TT_ATL_BOOTROM].base,
bootrom);
/* UART1, the soc console (UART0 is for the boot microcontroller) */
- serial_mm_init(system_memory, s->memmap[TT_ATL_UART1].base, 2,
+ serial_mm_init(s->memory, s->memmap[TT_ATL_UART1].base, 2,
qdev_get_gpio_in(s->irqchip, TT_ATL_UART1_IRQ),
115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
/*
@@ -571,7 +572,7 @@ static void tt_atlantis_machine_init(MachineState *machine)
*/
object_initialize_child(OBJECT(s), "uart1", &s->uart1,
TYPE_UNIMPLEMENTED_DEVICE);
- mmio_map_unimplemented(system_memory, SYS_BUS_DEVICE(&s->uart1),
+ mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->uart1),
"tt-atlantis.uart1", s->memmap[TT_ATL_UART1].base,
s->memmap[TT_ATL_UART1].size);
@@ -583,7 +584,7 @@ static void tt_atlantis_machine_init(MachineState *machine)
TYPE_DESIGNWARE_I2C);
sbd = SYS_BUS_DEVICE(&s->i2c[i]);
sysbus_realize(sbd, &error_fatal);
- memory_region_add_subregion(system_memory,
+ memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_I2C0 + i].base,
sysbus_mmio_get_region(sbd, 0));
sysbus_connect_irq(sbd, 0,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 12/16] hw/riscv/atlantis: Decouple RAM size from MachineState
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (10 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 11/16] hw/riscv/atlantis: Use local reference for system memory Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 13/16] hw/riscv/atlantis: Make TTAtlantisState own memory containers Joel Stanley
` (4 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
Keep a reference to the machine's RAM MemoryRegion in TTAtlantisState,
and get the MemoryRegion's size where the configured RAM size is
required.
This allows reading the RAM size without needing a pointer to
MachineState, decoupling the memory layout setup from the machine.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 1 +
hw/riscv/tt_atlantis.c | 20 ++++++++++++--------
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index a29c67c1cfcf..2ec283d0fd7b 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -30,6 +30,7 @@ struct TTAtlantisState {
const MemMapEntry *memmap;
MemoryRegion *memory;
+ MemoryRegion *dram;
RISCVHartArrayState cpus;
DeviceState *irqchip;
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 2a70119c2c6b..90b8e1bc904a 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -82,12 +82,13 @@ static uint32_t next_phandle(void)
static void create_fdt_memory(void *fdt, TTAtlantisState *s)
{
- hwaddr size_lo = MACHINE(s)->ram_size;
+ hwaddr ram_size = memory_region_size(s->dram);
+ hwaddr size_lo = ram_size;
hwaddr size_hi = 0;
if (size_lo > s->memmap[TT_ATL_DDR_LO].size) {
size_lo = s->memmap[TT_ATL_DDR_LO].size;
- size_hi = MACHINE(s)->ram_size - size_lo;
+ size_hi = ram_size - size_lo;
}
riscv_create_fdt_socket_memory(fdt, s->memmap[TT_ATL_DDR_LO].base,
@@ -486,11 +487,14 @@ static void tt_atlantis_machine_init(MachineState *machine)
MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
MemoryRegion *bootrom = g_new(MemoryRegion, 1);
- ram_addr_t lo_ram_size;
+ ram_addr_t lo_ram_size, ram_size;
int hart_count = machine->smp.cpus;
s->memory = get_system_memory();
+ s->dram = machine->ram;
+ ram_size = memory_region_size(s->dram);
+
s->memmap = tt_atlantis_memmap;
object_initialize_child(OBJECT(machine), "soc", &s->cpus,
@@ -533,20 +537,20 @@ static void tt_atlantis_machine_init(MachineState *machine)
* The high address is where RAM lives. It is always present and may be
* up to 64GB. The low address is an alias of the first 2GB of that RAM.
*/
- if (machine->ram_size > s->memmap[TT_ATL_DDR_HI].size) {
+ if (ram_size > s->memmap[TT_ATL_DDR_HI].size) {
char *sz = size_to_str(s->memmap[TT_ATL_DDR_HI].size);
error_report("RAM size is too large, maximum is %s", sz);
g_free(sz);
exit(EXIT_FAILURE);
}
- memory_region_init_alias(ram_hi, OBJECT(machine), "ram.high", machine->ram,
- 0, machine->ram_size);
+ memory_region_init_alias(ram_hi, OBJECT(machine), "ram.high", s->dram,
+ 0, ram_size);
memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_DDR_HI].base, ram_hi);
- lo_ram_size = MIN(machine->ram_size, s->memmap[TT_ATL_DDR_LO].size);
- memory_region_init_alias(ram_lo, OBJECT(machine), "ram.low", machine->ram,
+ lo_ram_size = MIN(ram_size, s->memmap[TT_ATL_DDR_LO].size);
+ memory_region_init_alias(ram_lo, OBJECT(machine), "ram.low", s->dram,
0, lo_ram_size);
memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_DDR_LO].base, ram_lo);
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 13/16] hw/riscv/atlantis: Make TTAtlantisState own memory containers
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (11 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 12/16] hw/riscv/atlantis: Decouple RAM size from MachineState Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory Joel Stanley
` (3 subsequent siblings)
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
The DRAM hi, DRAM low and bootrom memory containers can be owned by the
TTAtlantisState.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 4 ++++
hw/riscv/tt_atlantis.c | 15 ++++++---------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 2ec283d0fd7b..9ca98bfb8478 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -31,10 +31,14 @@ struct TTAtlantisState {
MemoryRegion *memory;
MemoryRegion *dram;
+ MemoryRegion ram_hi;
+ MemoryRegion ram_lo;
+
RISCVHartArrayState cpus;
DeviceState *irqchip;
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
UnimplementedDeviceState uart1;
+ MemoryRegion bootrom;
};
enum {
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 90b8e1bc904a..d4fe505fe033 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -484,9 +484,6 @@ static void tt_atlantis_machine_init(MachineState *machine)
{
TTAtlantisState *s = TT_ATLANTIS_MACHINE(machine);
- MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
- MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
- MemoryRegion *bootrom = g_new(MemoryRegion, 1);
ram_addr_t lo_ram_size, ram_size;
int hart_count = machine->smp.cpus;
@@ -544,22 +541,22 @@ static void tt_atlantis_machine_init(MachineState *machine)
exit(EXIT_FAILURE);
}
- memory_region_init_alias(ram_hi, OBJECT(machine), "ram.high", s->dram,
+ memory_region_init_alias(&s->ram_hi, OBJECT(machine), "ram.high", s->dram,
0, ram_size);
memory_region_add_subregion(s->memory,
- s->memmap[TT_ATL_DDR_HI].base, ram_hi);
+ s->memmap[TT_ATL_DDR_HI].base, &s->ram_hi);
lo_ram_size = MIN(ram_size, s->memmap[TT_ATL_DDR_LO].size);
- memory_region_init_alias(ram_lo, OBJECT(machine), "ram.low", s->dram,
+ memory_region_init_alias(&s->ram_lo, OBJECT(machine), "ram.low", s->dram,
0, lo_ram_size);
memory_region_add_subregion(s->memory,
- s->memmap[TT_ATL_DDR_LO].base, ram_lo);
+ s->memmap[TT_ATL_DDR_LO].base, &s->ram_lo);
/* Boot ROM */
- memory_region_init_rom(bootrom, NULL, "tt-atlantis.bootrom",
+ memory_region_init_rom(&s->bootrom, NULL, "tt-atlantis.bootrom",
s->memmap[TT_ATL_BOOTROM].size, &error_fatal);
memory_region_add_subregion(s->memory, s->memmap[TT_ATL_BOOTROM].base,
- bootrom);
+ &s->bootrom);
/* UART1, the soc console (UART0 is for the boot microcontroller) */
serial_mm_init(s->memory, s->memmap[TT_ATL_UART1].base, 2,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (12 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 13/16] hw/riscv/atlantis: Make TTAtlantisState own memory containers Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-04 10:42 ` Philippe Mathieu-Daudé
2026-09-03 5:51 ` [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device Joel Stanley
` (2 subsequent siblings)
16 siblings, 1 reply; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Portia Stephens, Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Cédric Le Goater,
qemu-riscv, qemu-devel
From: Portia Stephens <portias@oss.tenstorrent.com>
There are platforms where CPUs have different mapping of system memory.
The global system memory does not allow for this. This adds an optional
property on the hart array to assign a specific memory region. The array
passes the region to each hart it creates, so a machine can alias the
harts' memory to system memory, while the harts view memory from their
own memory region.
Signed-off-by: Portia Stephens <portias@oss.tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/riscv_hart.h | 2 ++
hw/riscv/riscv_hart.c | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
index 197fa1623115..c3cd05a2c877 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -42,6 +42,8 @@ struct RISCVHartArrayState {
uint64_t *rnmi_irqvec;
uint32_t num_rnmi_excpvec;
uint64_t *rnmi_excpvec;
+ /* Optional private memory region for use instead of system memory */
+ MemoryRegion *memory;
RISCVCPU *harts;
};
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index 747754be6158..32fd39737ff6 100644
--- a/hw/riscv/riscv_hart.c
+++ b/hw/riscv/riscv_hart.c
@@ -53,6 +53,8 @@ static const Property riscv_harts_props[] = {
DEFINE_PROP_ARRAY("rnmi-exception-vector", RISCVHartArrayState,
num_rnmi_excpvec, rnmi_excpvec, qdev_prop_uint64,
uint64_t),
+ DEFINE_PROP_LINK("memory", RISCVHartArrayState, memory,
+ TYPE_MEMORY_REGION, MemoryRegion *),
};
static void riscv_harts_cpu_reset(void *opaque)
@@ -117,6 +119,12 @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
+ /* Use private memory instead of system_memory if provided */
+ if (s->memory) {
+ object_property_set_link(OBJECT(&s->harts[idx]), "memory",
+ OBJECT(s->memory), &error_abort);
+ }
+
if (s->harts[idx].cfg.ext_smrnmi) {
if (idx < s->num_rnmi_irqvec) {
qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (13 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-04 10:47 ` Philippe Mathieu-Daudé
2026-09-03 5:51 ` [PATCH v3 16/16] hw/riscv/atlantis: Map the SoC through a memory container Joel Stanley
2026-09-03 23:35 ` [PATCH v3 00/16] hw/riscv: Socify Atlantis Alistair Francis
16 siblings, 1 reply; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
Introduce TYPE_TT_ATLANTIS_SOC and move the hart array, AIA, ACLINT,
boot ROM, UART and I2C controllers into the new TTAtlantisSoCState. The
machine keeps ownership of RAM, device tree generation, firmware
loading, and the board-level I2C slaves.
This makes it easier to compose the SoC into a more complex machine in
the future.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 21 ++++-
hw/riscv/tt_atlantis.c | 144 +++++++++++++++++++++++----------
2 files changed, 119 insertions(+), 46 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 9ca98bfb8478..5d4e4d133bd9 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -19,14 +19,16 @@
#define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME("tt-atlantis")
OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, TT_ATLANTIS_MACHINE)
+#define TYPE_TT_ATLANTIS_SOC "tt-atlantis-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisSoCState, TT_ATLANTIS_SOC)
+
#define TT_ATL_NUM_I2C 5
-struct TTAtlantisState {
+struct TTAtlantisSoCState {
/*< private >*/
- MachineState parent;
+ DeviceState parent;
/*< public >*/
- Notifier machine_done;
const MemMapEntry *memmap;
MemoryRegion *memory;
@@ -39,6 +41,19 @@ struct TTAtlantisState {
DesignWareI2CState i2c[TT_ATL_NUM_I2C];
UnimplementedDeviceState uart1;
MemoryRegion bootrom;
+
+ uint32_t num_harts;
+ char *cpu_type;
+};
+
+struct TTAtlantisState {
+ /*< private >*/
+ MachineState parent;
+
+ /*< public >*/
+ Notifier machine_done;
+
+ TTAtlantisSoCState soc;
};
enum {
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index d4fe505fe033..6c46121287c7 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -7,6 +7,7 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/guest-random.h"
@@ -14,6 +15,7 @@
#include "hw/core/boards.h"
#include "hw/core/loader.h"
+#include "hw/core/qdev-properties.h"
#include "hw/core/sysbus.h"
#include "target/riscv/cpu.h"
@@ -67,7 +69,7 @@ static const MemMapEntry tt_atlantis_memmap[] = {
[TT_ATL_DDR_HI] = { 0x100000000, 0x1000000000 },
};
-static I2CBus *i2c_get_bus(TTAtlantisState *s, unsigned busnr)
+static I2CBus *i2c_get_bus(TTAtlantisSoCState *s, unsigned busnr)
{
assert(busnr < TT_ATL_NUM_I2C);
@@ -80,7 +82,7 @@ static uint32_t next_phandle(void)
return fdt_phandle++;
}
-static void create_fdt_memory(void *fdt, TTAtlantisState *s)
+static void create_fdt_memory(void *fdt, TTAtlantisSoCState *s)
{
hwaddr ram_size = memory_region_size(s->dram);
hwaddr size_lo = ram_size;
@@ -105,7 +107,7 @@ static void create_fdt_memory(void *fdt, TTAtlantisState *s)
}
}
-static void create_fdt_aclint(void *fdt, TTAtlantisState *s,
+static void create_fdt_aclint(void *fdt, TTAtlantisSoCState *s,
uint32_t *intc_phandles)
{
g_autofree char *name = NULL;
@@ -207,7 +209,7 @@ static void create_fdt_one_aplic(void *fdt,
qemu_fdt_setprop_cell(fdt, name, "phandle", aplic_phandle);
}
-static void create_fdt_pmu(void *fdt, TTAtlantisState *s)
+static void create_fdt_pmu(void *fdt, TTAtlantisSoCState *s)
{
char pmu_name[] = "/pmu";
RISCVCPU *hart = &s->cpus.harts[0];
@@ -217,7 +219,7 @@ static void create_fdt_pmu(void *fdt, TTAtlantisState *s)
riscv_pmu_generate_fdt_node(fdt, hart->pmu_avail_ctrs, pmu_name);
}
-static void create_fdt_cpu(void *fdt, TTAtlantisState *s,
+static void create_fdt_cpu(void *fdt, TTAtlantisSoCState *s,
uint32_t aplic_s_phandle,
uint32_t imsic_s_phandle)
{
@@ -314,7 +316,7 @@ static void create_fdt_i2c(void *fdt, const MemMapEntry *mem, uint32_t irq,
qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0);
}
-static void create_fdt_i2c_device(void *fdt, TTAtlantisState *s, int bus,
+static void create_fdt_i2c_device(void *fdt, TTAtlantisSoCState *s, int bus,
const char *compat, int addr)
{
hwaddr base = s->memmap[TT_ATL_I2C0 + bus].base;
@@ -326,7 +328,7 @@ static void create_fdt_i2c_device(void *fdt, TTAtlantisState *s, int bus,
qemu_fdt_setprop_cell(fdt, name, "reg", addr);
}
-static void finalize_fdt(void *fdt, TTAtlantisState *s)
+static void finalize_fdt(void *fdt, TTAtlantisSoCState *s)
{
uint32_t aplic_s_phandle = next_phandle();
uint32_t imsic_s_phandle = next_phandle();
@@ -360,9 +362,9 @@ static void finalize_fdt(void *fdt, TTAtlantisState *s)
create_fdt_i2c_device(fdt, s, 4, "ti,tmp105", 0x48);
}
-static void create_fdt(TTAtlantisState *s)
+static void create_fdt(TTAtlantisState *ams)
{
- MachineState *ms = MACHINE(s);
+ MachineState *ms = MACHINE(ams);
int fdt_size = 0;
ms->fdt = riscv_create_board_device_tree("Tenstorrent Atlantis RISC-V Machine",
@@ -374,12 +376,12 @@ static void create_fdt(TTAtlantisState *s)
qemu_fdt_add_subnode(ms->fdt, "/aliases");
- create_fdt_pmu(ms->fdt, s);
+ create_fdt_pmu(ms->fdt, &ams->soc);
}
-static void load_fdt(TTAtlantisState *s)
+static void load_fdt(TTAtlantisState *ams)
{
- MachineState *ms = MACHINE(s);
+ MachineState *ms = MACHINE(ams);
char **node_path;
Error *err = NULL;
int fdt_size = 0;
@@ -405,7 +407,7 @@ static void load_fdt(TTAtlantisState *s)
g_strfreev(node_path);
}
- create_fdt_memory(ms->fdt, s);
+ create_fdt_memory(ms->fdt, &ams->soc);
}
static void mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev,
@@ -419,10 +421,11 @@ static void mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev,
sysbus_mmio_get_region(dev, 0), -1000);
}
-static void tt_atlantis_machine_done(Notifier *notifier, void *data)
+static void tt_atlantis_machine_done(Notifier *n, void *data)
{
- TTAtlantisState *s = container_of(notifier, TTAtlantisState, machine_done);
- MachineState *machine = MACHINE(s);
+ TTAtlantisState *ams = container_of(n, TTAtlantisState, machine_done);
+ TTAtlantisSoCState *s = &ams->soc;
+ MachineState *machine = MACHINE(ams);
hwaddr start_addr = s->memmap[TT_ATL_DDR_LO].base;
hwaddr mem_size;
target_ulong firmware_end_addr, kernel_start_addr;
@@ -480,23 +483,39 @@ static void tt_atlantis_machine_done(Notifier *notifier, void *data)
fdt_load_addr);
}
-static void tt_atlantis_machine_init(MachineState *machine)
+static void tt_atlantis_soc_init(Object *obj)
{
- TTAtlantisState *s = TT_ATLANTIS_MACHINE(machine);
+ TTAtlantisSoCState *s = TT_ATLANTIS_SOC(obj);
+
+ object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY);
+
+ object_initialize_child(obj, "uart1", &s->uart1,
+ TYPE_UNIMPLEMENTED_DEVICE);
+ for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
+ object_initialize_child(obj, "i2c[*]", &s->i2c[i],
+ TYPE_DESIGNWARE_I2C);
+ }
+}
+
+static void tt_atlantis_soc_realize(DeviceState *dev, Error **errp)
+{
+ TTAtlantisSoCState *s = TT_ATLANTIS_SOC(dev);
ram_addr_t lo_ram_size, ram_size;
- int hart_count = machine->smp.cpus;
+ int hart_count = s->num_harts;
s->memory = get_system_memory();
- s->dram = machine->ram;
+ if (!s->dram) {
+ error_setg(errp, "'dram' link is not set");
+ return;
+ }
ram_size = memory_region_size(s->dram);
s->memmap = tt_atlantis_memmap;
- object_initialize_child(OBJECT(machine), "soc", &s->cpus,
- TYPE_RISCV_HART_ARRAY);
- object_property_set_str(OBJECT(&s->cpus), "cpu-type", machine->cpu_type,
+ /* CPUs */
+ object_property_set_str(OBJECT(&s->cpus), "cpu-type", s->cpu_type,
&error_abort);
object_property_set_int(OBJECT(&s->cpus), "hartid-base", 0,
&error_abort);
@@ -505,7 +524,9 @@ static void tt_atlantis_machine_init(MachineState *machine)
object_property_set_int(OBJECT(&s->cpus), "resetvec",
s->memmap[TT_ATL_BOOTROM].base,
&error_abort);
- sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpus), errp)) {
+ return;
+ }
s->irqchip = riscv_create_aia(s->memory,
true, TT_IMSIC_GUESTS,
@@ -535,26 +556,27 @@ static void tt_atlantis_machine_init(MachineState *machine)
* up to 64GB. The low address is an alias of the first 2GB of that RAM.
*/
if (ram_size > s->memmap[TT_ATL_DDR_HI].size) {
- char *sz = size_to_str(s->memmap[TT_ATL_DDR_HI].size);
- error_report("RAM size is too large, maximum is %s", sz);
- g_free(sz);
- exit(EXIT_FAILURE);
+ g_autofree char *sz = size_to_str(s->memmap[TT_ATL_DDR_HI].size);
+ error_setg(errp, "RAM size is too large, maximum is %s", sz);
+ return;
}
- memory_region_init_alias(&s->ram_hi, OBJECT(machine), "ram.high", s->dram,
+ memory_region_init_alias(&s->ram_hi, OBJECT(s), "ram.high", s->dram,
0, ram_size);
memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_DDR_HI].base, &s->ram_hi);
lo_ram_size = MIN(ram_size, s->memmap[TT_ATL_DDR_LO].size);
- memory_region_init_alias(&s->ram_lo, OBJECT(machine), "ram.low", s->dram,
+ memory_region_init_alias(&s->ram_lo, OBJECT(s), "ram.low", s->dram,
0, lo_ram_size);
memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_DDR_LO].base, &s->ram_lo);
/* Boot ROM */
- memory_region_init_rom(&s->bootrom, NULL, "tt-atlantis.bootrom",
- s->memmap[TT_ATL_BOOTROM].size, &error_fatal);
+ if (!memory_region_init_rom(&s->bootrom, OBJECT(s), "tt-atlantis.bootrom",
+ s->memmap[TT_ATL_BOOTROM].size, errp)) {
+ return;
+ }
memory_region_add_subregion(s->memory, s->memmap[TT_ATL_BOOTROM].base,
&s->bootrom);
@@ -571,26 +593,56 @@ static void tt_atlantis_machine_init(MachineState *machine)
* Create an unimplemented device region so writes don't fault
* and reads return zero, which keeps Linux happy.
*/
- object_initialize_child(OBJECT(s), "uart1", &s->uart1,
- TYPE_UNIMPLEMENTED_DEVICE);
mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->uart1),
"tt-atlantis.uart1", s->memmap[TT_ATL_UART1].base,
s->memmap[TT_ATL_UART1].size);
/* I2C */
for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
- SysBusDevice *sbd;
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->i2c[i]);
- object_initialize_child(OBJECT(s), "i2c[*]", &s->i2c[i],
- TYPE_DESIGNWARE_I2C);
- sbd = SYS_BUS_DEVICE(&s->i2c[i]);
- sysbus_realize(sbd, &error_fatal);
+ if (!sysbus_realize(sbd, errp)) {
+ return;
+ }
memory_region_add_subregion(s->memory,
s->memmap[TT_ATL_I2C0 + i].base,
sysbus_mmio_get_region(sbd, 0));
sysbus_connect_irq(sbd, 0,
qdev_get_gpio_in(s->irqchip, TT_ATL_I2C0_IRQ + i));
}
+}
+
+static const Property tt_atlantis_soc_props[] = {
+ DEFINE_PROP_STRING("cpu-type", TTAtlantisSoCState, cpu_type),
+ DEFINE_PROP_UINT32("num-harts", TTAtlantisSoCState, num_harts, 8),
+ DEFINE_PROP_LINK("dram", TTAtlantisSoCState, dram,
+ TYPE_MEMORY_REGION, MemoryRegion *),
+};
+
+static void tt_atlantis_soc_class_init(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = tt_atlantis_soc_realize;
+ device_class_set_props(dc, tt_atlantis_soc_props);
+ /* The SoC can only be instantiated from the machine */
+ dc->user_creatable = false;
+}
+
+static void tt_atlantis_machine_init(MachineState *machine)
+{
+ TTAtlantisState *ams = TT_ATLANTIS_MACHINE(machine);
+ TTAtlantisSoCState *s = &ams->soc;
+
+ object_initialize_child(OBJECT(machine), "soc", &ams->soc,
+ TYPE_TT_ATLANTIS_SOC);
+ object_property_set_str(OBJECT(&ams->soc), "cpu-type", machine->cpu_type,
+ &error_abort);
+ object_property_set_int(OBJECT(&ams->soc), "num-harts", machine->smp.cpus,
+ &error_abort);
+ object_property_set_link(OBJECT(&ams->soc), "dram", OBJECT(machine->ram),
+ &error_abort);
+ qdev_realize(DEVICE(&ams->soc), NULL, &error_fatal);
/* I2C peripherals: qemu specific */
i2c_slave_create_simple(i2c_get_bus(s, 0), "ds1338", 0x6f);
@@ -598,13 +650,13 @@ static void tt_atlantis_machine_init(MachineState *machine)
/* Load or create device tree */
if (machine->dtb) {
- load_fdt(s);
+ load_fdt(ams);
} else {
- create_fdt(s);
+ create_fdt(ams);
}
- s->machine_done.notify = tt_atlantis_machine_done;
- qemu_add_machine_init_done_notifier(&s->machine_done);
+ ams->machine_done.notify = tt_atlantis_machine_done;
+ qemu_add_machine_init_done_notifier(&ams->machine_done);
}
static void tt_atlantis_machine_class_init(ObjectClass *oc, const void *data)
@@ -624,6 +676,12 @@ static void tt_atlantis_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo tt_atlantis_types[] = {
{
+ .name = TYPE_TT_ATLANTIS_SOC,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(TTAtlantisSoCState),
+ .instance_init = tt_atlantis_soc_init,
+ .class_init = tt_atlantis_soc_class_init,
+ }, {
.name = MACHINE_TYPE_NAME("tt-atlantis"),
.parent = TYPE_MACHINE,
.class_init = tt_atlantis_machine_class_init,
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v3 16/16] hw/riscv/atlantis: Map the SoC through a memory container
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (14 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device Joel Stanley
@ 2026-09-03 5:51 ` Joel Stanley
2026-09-03 23:35 ` [PATCH v3 00/16] hw/riscv: Socify Atlantis Alistair Francis
16 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-03 5:51 UTC (permalink / raw)
To: Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
Give the Atlantis SoC a 'memory' link property. The machine creates a
container MemoryRegion, maps it at address 0 of system memory, and
passes it to the SoC together with the machine RAM. The SoC maps devices
into the 'memory' container instead of system memory, allowing
TTAtlantisSoCState to be composed together with other SoCs in the
future.
This prepares the machine for adding other microcontrollers that share
the memory bus with the Ascalon complex (aka the Atlantis SoC), but with
their own view of the address map.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
include/hw/riscv/tt_atlantis.h | 1 +
hw/riscv/tt_atlantis.c | 17 +++++++++++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 5d4e4d133bd9..3923308b7c89 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -53,6 +53,7 @@ struct TTAtlantisState {
/*< public >*/
Notifier machine_done;
+ MemoryRegion soc_memory;
TTAtlantisSoCState soc;
};
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index 6c46121287c7..c6f235a7eac0 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -504,8 +504,10 @@ static void tt_atlantis_soc_realize(DeviceState *dev, Error **errp)
ram_addr_t lo_ram_size, ram_size;
int hart_count = s->num_harts;
- s->memory = get_system_memory();
-
+ if (!s->memory) {
+ error_setg(errp, "'memory' link is not set");
+ return;
+ }
if (!s->dram) {
error_setg(errp, "'dram' link is not set");
return;
@@ -524,6 +526,8 @@ static void tt_atlantis_soc_realize(DeviceState *dev, Error **errp)
object_property_set_int(OBJECT(&s->cpus), "resetvec",
s->memmap[TT_ATL_BOOTROM].base,
&error_abort);
+ object_property_set_link(OBJECT(&s->cpus), "memory", OBJECT(s->memory),
+ &error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpus), errp)) {
return;
}
@@ -615,6 +619,8 @@ static void tt_atlantis_soc_realize(DeviceState *dev, Error **errp)
static const Property tt_atlantis_soc_props[] = {
DEFINE_PROP_STRING("cpu-type", TTAtlantisSoCState, cpu_type),
DEFINE_PROP_UINT32("num-harts", TTAtlantisSoCState, num_harts, 8),
+ DEFINE_PROP_LINK("memory", TTAtlantisSoCState, memory,
+ TYPE_MEMORY_REGION, MemoryRegion *),
DEFINE_PROP_LINK("dram", TTAtlantisSoCState, dram,
TYPE_MEMORY_REGION, MemoryRegion *),
};
@@ -634,12 +640,19 @@ static void tt_atlantis_machine_init(MachineState *machine)
TTAtlantisState *ams = TT_ATLANTIS_MACHINE(machine);
TTAtlantisSoCState *s = &ams->soc;
+ memory_region_init(&ams->soc_memory, OBJECT(machine),
+ "tt-atlantis.soc-memory", UINT64_MAX);
+ memory_region_add_subregion(get_system_memory(), 0, &ams->soc_memory);
+
object_initialize_child(OBJECT(machine), "soc", &ams->soc,
TYPE_TT_ATLANTIS_SOC);
object_property_set_str(OBJECT(&ams->soc), "cpu-type", machine->cpu_type,
&error_abort);
object_property_set_int(OBJECT(&ams->soc), "num-harts", machine->smp.cpus,
&error_abort);
+
+ object_property_set_link(OBJECT(&ams->soc), "memory",
+ OBJECT(&ams->soc_memory), &error_abort);
object_property_set_link(OBJECT(&ams->soc), "dram", OBJECT(machine->ram),
&error_abort);
qdev_realize(DEVICE(&ams->soc), NULL, &error_fatal);
--
2.47.3
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices
2026-09-03 5:51 ` [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices Joel Stanley
@ 2026-09-03 6:06 ` Chao Liu via qemu development
0 siblings, 0 replies; 28+ messages in thread
From: Chao Liu via @ 2026-09-03 6:06 UTC (permalink / raw)
To: Joel Stanley
Cc: Alistair Francis, Daniel Henrique Barboza, Weiwei Li, Liu Zhiwei,
Nicholas Piggin, Anirudh Srinivasan, Michael Ellerman,
Portia Stephens, Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
On Thu, Sep 03, 2026 at 03:21:15PM +0800, Joel Stanley wrote:
> Add a MemoryRegion parameter to riscv_create_aia(), to be passed on to
> the IMSIC and APLIC helpers so a SoC can have the controllers mapped
> into its own memory container. Both callers pass system_memory, so there
> is no change in behaviour.
>
> As the controllers don't yet take a MemoryRegion the parameter is not
> yet passed on. Changing riscv_create_aia first avoids churn in the
> intermediate commits.
>
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Thanks,
Chao
> ---
> hw/riscv/aia.h | 3 ++-
> hw/riscv/aia.c | 3 ++-
> hw/riscv/tt_atlantis.c | 3 ++-
> hw/riscv/virt.c | 3 ++-
> 4 files changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h
> index 3b6d7f962506..5df3292610e9 100644
> --- a/hw/riscv/aia.h
> +++ b/hw/riscv/aia.h
> @@ -13,7 +13,8 @@
>
> uint32_t imsic_num_bits(uint32_t count);
>
> -DeviceState *riscv_create_aia(bool msimode, int aia_guests,
> +DeviceState *riscv_create_aia(MemoryRegion *container,
> + bool msimode, int aia_guests,
> uint32_t m_imsic_stride,
> uint32_t s_imsic_stride,
> uint16_t num_sources,
> diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c
> index c1a5982856c5..e11382e512da 100644
> --- a/hw/riscv/aia.c
> +++ b/hw/riscv/aia.c
> @@ -24,7 +24,8 @@ uint32_t imsic_num_bits(uint32_t count)
> return ret;
> }
>
> -DeviceState *riscv_create_aia(bool msimode, int aia_guests,
> +DeviceState *riscv_create_aia(MemoryRegion *container,
> + bool msimode, int aia_guests,
> uint32_t m_imsic_stride,
> uint32_t s_imsic_stride,
> uint16_t num_sources,
> diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
> index 812051a11fd4..f395236d88ab 100644
> --- a/hw/riscv/tt_atlantis.c
> +++ b/hw/riscv/tt_atlantis.c
> @@ -498,7 +498,8 @@ static void tt_atlantis_machine_init(MachineState *machine)
> &error_abort);
> sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
>
> - s->irqchip = riscv_create_aia(true, TT_IMSIC_GUESTS,
> + s->irqchip = riscv_create_aia(system_memory,
> + true, TT_IMSIC_GUESTS,
> TT_IMSIC_STRIDE,
> TT_IMSIC_STRIDE,
> TT_IRQCHIP_NUM_SOURCES,
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index de7b99c6a51e..6480a3f0a9c0 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -809,8 +809,9 @@ static void virt_machine_init(MachineState *machine)
> s->irqchip[i] = virt_create_plic(s->memmap, i,
> base_hartid, hart_count);
> } else {
> + bool msimode = s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
> int imsic_bits = imsic_num_bits(s->aia_guests + 1);
> - s->irqchip[i] = riscv_create_aia(s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC,
> + s->irqchip[i] = riscv_create_aia(system_memory, msimode,
> s->aia_guests,
> IMSIC_HART_SIZE(0),
> IMSIC_HART_SIZE(imsic_bits),
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices
@ 2026-09-03 6:06 ` Chao Liu via qemu development
0 siblings, 0 replies; 28+ messages in thread
From: Chao Liu via qemu development @ 2026-09-03 6:06 UTC (permalink / raw)
To: Joel Stanley
Cc: Alistair Francis, Daniel Henrique Barboza, Weiwei Li, Liu Zhiwei,
Nicholas Piggin, Anirudh Srinivasan, Michael Ellerman,
Portia Stephens, Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
On Thu, Sep 03, 2026 at 03:21:15PM +0800, Joel Stanley wrote:
> Add a MemoryRegion parameter to riscv_create_aia(), to be passed on to
> the IMSIC and APLIC helpers so a SoC can have the controllers mapped
> into its own memory container. Both callers pass system_memory, so there
> is no change in behaviour.
>
> As the controllers don't yet take a MemoryRegion the parameter is not
> yet passed on. Changing riscv_create_aia first avoids churn in the
> intermediate commits.
>
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Thanks,
Chao
> ---
> hw/riscv/aia.h | 3 ++-
> hw/riscv/aia.c | 3 ++-
> hw/riscv/tt_atlantis.c | 3 ++-
> hw/riscv/virt.c | 3 ++-
> 4 files changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h
> index 3b6d7f962506..5df3292610e9 100644
> --- a/hw/riscv/aia.h
> +++ b/hw/riscv/aia.h
> @@ -13,7 +13,8 @@
>
> uint32_t imsic_num_bits(uint32_t count);
>
> -DeviceState *riscv_create_aia(bool msimode, int aia_guests,
> +DeviceState *riscv_create_aia(MemoryRegion *container,
> + bool msimode, int aia_guests,
> uint32_t m_imsic_stride,
> uint32_t s_imsic_stride,
> uint16_t num_sources,
> diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c
> index c1a5982856c5..e11382e512da 100644
> --- a/hw/riscv/aia.c
> +++ b/hw/riscv/aia.c
> @@ -24,7 +24,8 @@ uint32_t imsic_num_bits(uint32_t count)
> return ret;
> }
>
> -DeviceState *riscv_create_aia(bool msimode, int aia_guests,
> +DeviceState *riscv_create_aia(MemoryRegion *container,
> + bool msimode, int aia_guests,
> uint32_t m_imsic_stride,
> uint32_t s_imsic_stride,
> uint16_t num_sources,
> diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
> index 812051a11fd4..f395236d88ab 100644
> --- a/hw/riscv/tt_atlantis.c
> +++ b/hw/riscv/tt_atlantis.c
> @@ -498,7 +498,8 @@ static void tt_atlantis_machine_init(MachineState *machine)
> &error_abort);
> sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
>
> - s->irqchip = riscv_create_aia(true, TT_IMSIC_GUESTS,
> + s->irqchip = riscv_create_aia(system_memory,
> + true, TT_IMSIC_GUESTS,
> TT_IMSIC_STRIDE,
> TT_IMSIC_STRIDE,
> TT_IRQCHIP_NUM_SOURCES,
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index de7b99c6a51e..6480a3f0a9c0 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -809,8 +809,9 @@ static void virt_machine_init(MachineState *machine)
> s->irqchip[i] = virt_create_plic(s->memmap, i,
> base_hartid, hart_count);
> } else {
> + bool msimode = s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
> int imsic_bits = imsic_num_bits(s->aia_guests + 1);
> - s->irqchip[i] = riscv_create_aia(s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC,
> + s->irqchip[i] = riscv_create_aia(system_memory, msimode,
> s->aia_guests,
> IMSIC_HART_SIZE(0),
> IMSIC_HART_SIZE(imsic_bits),
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 05/16] hw/intc/sifive_plic: Take a MemoryRegion for the created device
2026-09-03 5:51 ` [PATCH v3 05/16] hw/intc/sifive_plic: " Joel Stanley
@ 2026-09-03 6:07 ` Chao Liu via
0 siblings, 0 replies; 28+ messages in thread
From: Chao Liu via qemu development @ 2026-09-03 6:07 UTC (permalink / raw)
To: Joel Stanley
Cc: Alistair Francis, Daniel Henrique Barboza, Weiwei Li, Liu Zhiwei,
Nicholas Piggin, Anirudh Srinivasan, Michael Ellerman,
Portia Stephens, Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
On Thu, Sep 03, 2026 at 03:21:19PM +0800, Joel Stanley wrote:
> sifive_plic_create() maps the device it creates into system_memory,
> which prevents its use by SoCs that map devices into their own memory
> container.
>
> Add a MemoryRegion parameter and map the device into it instead of
> calling sysbus_mmio_map(). All callers pass system_memory, so there is
> no change in behaviour.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Thanks,
Chao
> ---
> include/hw/intc/sifive_plic.h | 4 ++--
> hw/intc/sifive_plic.c | 7 ++++---
> hw/riscv/k230.c | 3 ++-
> hw/riscv/microchip_pfsoc.c | 3 ++-
> hw/riscv/shakti_c.c | 3 ++-
> hw/riscv/sifive_e.c | 2 +-
> hw/riscv/sifive_u.c | 3 ++-
> hw/riscv/virt.c | 1 +
> 8 files changed, 16 insertions(+), 10 deletions(-)
>
> diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
> index 32973dbf281e..064754c3f628 100644
> --- a/include/hw/intc/sifive_plic.h
> +++ b/include/hw/intc/sifive_plic.h
> @@ -76,8 +76,8 @@ struct SiFivePLICState {
> qemu_irq *s_external_irqs;
> };
>
> -DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
> - uint32_t num_harts,
> +DeviceState *sifive_plic_create(MemoryRegion *container,
> + hwaddr addr, char *hart_config, uint32_t num_harts,
> uint32_t hartid_base, uint32_t num_sources,
> uint32_t num_priorities, uint32_t priority_base,
> uint32_t pending_base, uint32_t enable_base,
> diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
> index 9c84ff06a9fd..90f17e6ee724 100644
> --- a/hw/intc/sifive_plic.c
> +++ b/hw/intc/sifive_plic.c
> @@ -473,8 +473,8 @@ type_init(sifive_plic_register_types)
> /*
> * Create PLIC device.
> */
> -DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
> - uint32_t num_harts,
> +DeviceState *sifive_plic_create(MemoryRegion *container,
> + hwaddr addr, char *hart_config, uint32_t num_harts,
> uint32_t hartid_base, uint32_t num_sources,
> uint32_t num_priorities, uint32_t priority_base,
> uint32_t pending_base, uint32_t enable_base,
> @@ -499,7 +499,8 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
> qdev_prop_set_uint32(dev, "context-stride", context_stride);
> qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
> + memory_region_add_subregion(container, addr,
> + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
>
> plic = SIFIVE_PLIC(dev);
>
> diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
> index 1ef4260c5391..6b0f0453c80b 100644
> --- a/hw/riscv/k230.c
> +++ b/hw/riscv/k230.c
> @@ -134,7 +134,8 @@ static DeviceState *k230_create_plic(int base_hartid, int hartid_count)
> plic_hart_config = riscv_plic_hart_config_string(hartid_count);
>
> /* Per-socket PLIC */
> - return sifive_plic_create(memmap[K230_DEV_PLIC].base,
> + return sifive_plic_create(get_system_memory(),
> + memmap[K230_DEV_PLIC].base,
> plic_hart_config, hartid_count, base_hartid,
> K230_PLIC_NUM_SOURCES,
> K230_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
> index a6026776d4de..1f6d9f5ae1ed 100644
> --- a/hw/riscv/microchip_pfsoc.c
> +++ b/hw/riscv/microchip_pfsoc.c
> @@ -282,7 +282,8 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
> plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
>
> /* PLIC */
> - s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
> + s->plic = sifive_plic_create(system_memory,
> + memmap[MICROCHIP_PFSOC_PLIC].base,
> plic_hart_config, ms->smp.cpus, 0,
> MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
> MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
> index 86ff8f8fcaab..62052bf7c61e 100644
> --- a/hw/riscv/shakti_c.c
> +++ b/hw/riscv/shakti_c.c
> @@ -115,7 +115,8 @@ static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
>
> sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
>
> - sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
> + sss->plic = sifive_plic_create(system_memory,
> + shakti_c_memmap[SHAKTI_C_PLIC].base,
> (char *)SHAKTI_C_PLIC_HART_CONFIG, ms->smp.cpus, 0,
> SHAKTI_C_PLIC_NUM_SOURCES,
> SHAKTI_C_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index 0ea444f43bc5..81d7995ddcfb 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -214,7 +214,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
> memmap[SIFIVE_E_DEV_MROM].base, &s->mask_rom);
>
> /* MMIO */
> - s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
> + s->plic = sifive_plic_create(sys_mem, memmap[SIFIVE_E_DEV_PLIC].base,
> (char *)SIFIVE_E_PLIC_HART_CONFIG, ms->smp.cpus, 0,
> SIFIVE_E_PLIC_NUM_SOURCES,
> SIFIVE_E_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 6bbf2c4504d8..632194a06ea1 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -774,7 +774,8 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
> plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
>
> /* MMIO */
> - s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
> + s->plic = sifive_plic_create(system_memory,
> + memmap[SIFIVE_U_DEV_PLIC].base,
> plic_hart_config, ms->smp.cpus, 0,
> SIFIVE_U_PLIC_NUM_SOURCES,
> SIFIVE_U_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 8fd742181e28..a7b5af4e4c88 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -561,6 +561,7 @@ static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
>
> /* Per-socket PLIC */
> return sifive_plic_create(
> + get_system_memory(),
> memmap[VIRT_PLIC].base + socket * memmap[VIRT_PLIC].size,
> plic_hart_config, hart_count, base_hartid,
> VIRT_IRQCHIP_NUM_SOURCES,
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 05/16] hw/intc/sifive_plic: Take a MemoryRegion for the created device
@ 2026-09-03 6:07 ` Chao Liu via
0 siblings, 0 replies; 28+ messages in thread
From: Chao Liu via @ 2026-09-03 6:07 UTC (permalink / raw)
To: Joel Stanley
Cc: Alistair Francis, Daniel Henrique Barboza, Weiwei Li, Liu Zhiwei,
Nicholas Piggin, Anirudh Srinivasan, Michael Ellerman,
Portia Stephens, Cédric Le Goater, qemu-riscv, qemu-devel,
Philippe Mathieu-Daudé
On Thu, Sep 03, 2026 at 03:21:19PM +0800, Joel Stanley wrote:
> sifive_plic_create() maps the device it creates into system_memory,
> which prevents its use by SoCs that map devices into their own memory
> container.
>
> Add a MemoryRegion parameter and map the device into it instead of
> calling sysbus_mmio_map(). All callers pass system_memory, so there is
> no change in behaviour.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Thanks,
Chao
> ---
> include/hw/intc/sifive_plic.h | 4 ++--
> hw/intc/sifive_plic.c | 7 ++++---
> hw/riscv/k230.c | 3 ++-
> hw/riscv/microchip_pfsoc.c | 3 ++-
> hw/riscv/shakti_c.c | 3 ++-
> hw/riscv/sifive_e.c | 2 +-
> hw/riscv/sifive_u.c | 3 ++-
> hw/riscv/virt.c | 1 +
> 8 files changed, 16 insertions(+), 10 deletions(-)
>
> diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
> index 32973dbf281e..064754c3f628 100644
> --- a/include/hw/intc/sifive_plic.h
> +++ b/include/hw/intc/sifive_plic.h
> @@ -76,8 +76,8 @@ struct SiFivePLICState {
> qemu_irq *s_external_irqs;
> };
>
> -DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
> - uint32_t num_harts,
> +DeviceState *sifive_plic_create(MemoryRegion *container,
> + hwaddr addr, char *hart_config, uint32_t num_harts,
> uint32_t hartid_base, uint32_t num_sources,
> uint32_t num_priorities, uint32_t priority_base,
> uint32_t pending_base, uint32_t enable_base,
> diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
> index 9c84ff06a9fd..90f17e6ee724 100644
> --- a/hw/intc/sifive_plic.c
> +++ b/hw/intc/sifive_plic.c
> @@ -473,8 +473,8 @@ type_init(sifive_plic_register_types)
> /*
> * Create PLIC device.
> */
> -DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
> - uint32_t num_harts,
> +DeviceState *sifive_plic_create(MemoryRegion *container,
> + hwaddr addr, char *hart_config, uint32_t num_harts,
> uint32_t hartid_base, uint32_t num_sources,
> uint32_t num_priorities, uint32_t priority_base,
> uint32_t pending_base, uint32_t enable_base,
> @@ -499,7 +499,8 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
> qdev_prop_set_uint32(dev, "context-stride", context_stride);
> qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
> + memory_region_add_subregion(container, addr,
> + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
>
> plic = SIFIVE_PLIC(dev);
>
> diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
> index 1ef4260c5391..6b0f0453c80b 100644
> --- a/hw/riscv/k230.c
> +++ b/hw/riscv/k230.c
> @@ -134,7 +134,8 @@ static DeviceState *k230_create_plic(int base_hartid, int hartid_count)
> plic_hart_config = riscv_plic_hart_config_string(hartid_count);
>
> /* Per-socket PLIC */
> - return sifive_plic_create(memmap[K230_DEV_PLIC].base,
> + return sifive_plic_create(get_system_memory(),
> + memmap[K230_DEV_PLIC].base,
> plic_hart_config, hartid_count, base_hartid,
> K230_PLIC_NUM_SOURCES,
> K230_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
> index a6026776d4de..1f6d9f5ae1ed 100644
> --- a/hw/riscv/microchip_pfsoc.c
> +++ b/hw/riscv/microchip_pfsoc.c
> @@ -282,7 +282,8 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
> plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
>
> /* PLIC */
> - s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
> + s->plic = sifive_plic_create(system_memory,
> + memmap[MICROCHIP_PFSOC_PLIC].base,
> plic_hart_config, ms->smp.cpus, 0,
> MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
> MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
> index 86ff8f8fcaab..62052bf7c61e 100644
> --- a/hw/riscv/shakti_c.c
> +++ b/hw/riscv/shakti_c.c
> @@ -115,7 +115,8 @@ static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
>
> sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
>
> - sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
> + sss->plic = sifive_plic_create(system_memory,
> + shakti_c_memmap[SHAKTI_C_PLIC].base,
> (char *)SHAKTI_C_PLIC_HART_CONFIG, ms->smp.cpus, 0,
> SHAKTI_C_PLIC_NUM_SOURCES,
> SHAKTI_C_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index 0ea444f43bc5..81d7995ddcfb 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -214,7 +214,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
> memmap[SIFIVE_E_DEV_MROM].base, &s->mask_rom);
>
> /* MMIO */
> - s->plic = sifive_plic_create(memmap[SIFIVE_E_DEV_PLIC].base,
> + s->plic = sifive_plic_create(sys_mem, memmap[SIFIVE_E_DEV_PLIC].base,
> (char *)SIFIVE_E_PLIC_HART_CONFIG, ms->smp.cpus, 0,
> SIFIVE_E_PLIC_NUM_SOURCES,
> SIFIVE_E_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 6bbf2c4504d8..632194a06ea1 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -774,7 +774,8 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
> plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
>
> /* MMIO */
> - s->plic = sifive_plic_create(memmap[SIFIVE_U_DEV_PLIC].base,
> + s->plic = sifive_plic_create(system_memory,
> + memmap[SIFIVE_U_DEV_PLIC].base,
> plic_hart_config, ms->smp.cpus, 0,
> SIFIVE_U_PLIC_NUM_SOURCES,
> SIFIVE_U_PLIC_NUM_PRIORITIES,
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 8fd742181e28..a7b5af4e4c88 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -561,6 +561,7 @@ static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
>
> /* Per-socket PLIC */
> return sifive_plic_create(
> + get_system_memory(),
> memmap[VIRT_PLIC].base + socket * memmap[VIRT_PLIC].size,
> plic_hart_config, hart_count, base_hartid,
> VIRT_IRQCHIP_NUM_SOURCES,
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 00/16] hw/riscv: Socify Atlantis
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
` (15 preceding siblings ...)
2026-09-03 5:51 ` [PATCH v3 16/16] hw/riscv/atlantis: Map the SoC through a memory container Joel Stanley
@ 2026-09-03 23:35 ` Alistair Francis
2026-09-04 10:49 ` Philippe Mathieu-Daudé
16 siblings, 1 reply; 28+ messages in thread
From: Alistair Francis @ 2026-09-03 23:35 UTC (permalink / raw)
To: daniel.barboza@oss.qualcomm.com, joel@jms.id.au
Cc: npiggin@gmail.com, mpe@kernel.org, portias@oss.tenstorrent.com,
qemu-devel@nongnu.org, clg@kaod.org, chao.liu@processmission.com,
zhiwei_liu@linux.alibaba.com, asrinivasan@oss.tenstorrent.com,
liwei1518@gmail.com, qemu-riscv@nongnu.org
On Thu, 2026-09-03 at 15:21 +0930, Joel Stanley wrote:
> v2:
> https://lore.kernel.org/qemu-riscv/20260831021500.82565-1-joel@jms.id.au
>
> Changes in v3:
>
> - Rebase on today's riscv-to-apply.next, fixing conflicts with the
> device tree rework
> - Take up Phil's suggestion to change @mr to @container in the first
> five patches
> - Add r-b from Alistair, Daniel, Phil. Thank you!
>
> Original commit message:
>
> This addresses the review given by Cedric on v1 of the Atlantis
> patches,
> where he suggested making the machine a SoC. This is the pattern
> followed by the Aspeed ARM machines, where the SoC represents the
> modelled hardware, attaching its devices to a memory container, with
> the
> SoC instantiated by a QEMU machine that provides the memory container
> and the machine's RAM.
>
> Aside from the clean abstraction that this encourages, this pattern
> will
> be useful in adding other SoCs to the Atlantis machine, such as the
> RCPU
> (boot microcontroller) and CPL (Cluster Power Logic microcontroller).
>
> The series converts the RISC-V interrupt controllers to take a
> MemoryRegion for mapping themselves, with no change in behaviour for
> existing machines, and then cleans up the CPS device to place its
> devices in the memory container provided.
>
> The next few patches clean up the Atlantis machine to make extracting
> the SoC device and mapping it in a container relatively
> straightforward.
>
> Joel Stanley (15):
> hw/riscv/aia: Take a MemoryRegion for the created devices
> hw/intc/riscv_aclint: Take a MemoryRegion for the created devices
> hw/intc/riscv_imsic: Take a MemoryRegion for the created device
> hw/intc/riscv_aplic: Take a MemoryRegion for the created device
> hw/intc/sifive_plic: Take a MemoryRegion for the created device
> hw/riscv/cps: Map interrupt controllers in SoC container
> hw/riscv/atlantis: Make UART unimp region a SoC device
> hw/riscv/atlantis: Remove unused fdt_size
> hw/riscv/atlantis: Rename hart array 'soc' to 'cpus'
> hw/riscv/atlantis: Rework device tree creation
> hw/riscv/atlantis: Use local reference for system memory
> hw/riscv/atlantis: Decouple RAM size from MachineState
> hw/riscv/atlantis: Make TTAtlantisState own memory containers
> hw/riscv/atlantis: Extract an Atlantis SoC device
> hw/riscv/atlantis: Map the SoC through a memory container
>
> Portia Stephens (1):
> hw/riscv: Add property to hart array to allow private memory
Thanks!
Applied to riscv-to-apply.next
Alistair
>
> hw/riscv/aia.h | 3 +-
> include/hw/intc/riscv_aclint.h | 7 +-
> include/hw/intc/riscv_aplic.h | 7 +-
> include/hw/intc/riscv_imsic.h | 3 +-
> include/hw/intc/sifive_plic.h | 4 +-
> include/hw/riscv/riscv_hart.h | 2 +
> include/hw/riscv/tt_atlantis.h | 32 +++-
> hw/intc/riscv_aclint.c | 12 +-
> hw/intc/riscv_aplic.c | 10 +-
> hw/intc/riscv_imsic.c | 6 +-
> hw/intc/sifive_plic.c | 7 +-
> hw/riscv/aia.c | 17 +-
> hw/riscv/cps.c | 12 +-
> hw/riscv/k230.c | 9 +-
> hw/riscv/microchip_pfsoc.c | 8 +-
> hw/riscv/riscv_hart.c | 8 +
> hw/riscv/shakti_c.c | 10 +-
> hw/riscv/sifive_e.c | 6 +-
> hw/riscv/sifive_u.c | 10 +-
> hw/riscv/spike.c | 4 +-
> hw/riscv/tt_atlantis.c | 280 +++++++++++++++++++++----------
> --
> hw/riscv/virt.c | 21 ++-
> hw/riscv/xiangshan_kmh.c | 17 +-
> 23 files changed, 326 insertions(+), 169 deletions(-)
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory
2026-09-03 5:51 ` [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory Joel Stanley
@ 2026-09-04 10:42 ` Philippe Mathieu-Daudé
2026-09-07 7:27 ` Joel Stanley
0 siblings, 1 reply; 28+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-09-04 10:42 UTC (permalink / raw)
To: Joel Stanley, Alistair Francis, Daniel Henrique Barboza
Cc: Portia Stephens, Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Cédric Le Goater,
qemu-riscv, qemu-devel
On 3/9/26 07:51, Joel Stanley wrote:
> From: Portia Stephens <portias@oss.tenstorrent.com>
>
> There are platforms where CPUs have different mapping of system memory.
> The global system memory does not allow for this. This adds an optional
> property on the hart array to assign a specific memory region. The array
> passes the region to each hart it creates, so a machine can alias the
> harts' memory to system memory, while the harts view memory from their
> own memory region.
>
> Signed-off-by: Portia Stephens <portias@oss.tenstorrent.com>
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> include/hw/riscv/riscv_hart.h | 2 ++
> hw/riscv/riscv_hart.c | 8 ++++++++
> 2 files changed, 10 insertions(+)
>
> diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
> index 197fa1623115..c3cd05a2c877 100644
> --- a/include/hw/riscv/riscv_hart.h
> +++ b/include/hw/riscv/riscv_hart.h
> @@ -42,6 +42,8 @@ struct RISCVHartArrayState {
> uint64_t *rnmi_irqvec;
> uint32_t num_rnmi_excpvec;
> uint64_t *rnmi_excpvec;
> + /* Optional private memory region for use instead of system memory */
> + MemoryRegion *memory;
> RISCVCPU *harts;
> };
>
> diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
> index 747754be6158..32fd39737ff6 100644
> --- a/hw/riscv/riscv_hart.c
> +++ b/hw/riscv/riscv_hart.c
> @@ -53,6 +53,8 @@ static const Property riscv_harts_props[] = {
> DEFINE_PROP_ARRAY("rnmi-exception-vector", RISCVHartArrayState,
> num_rnmi_excpvec, rnmi_excpvec, qdev_prop_uint64,
> uint64_t),
> + DEFINE_PROP_LINK("memory", RISCVHartArrayState, memory,
> + TYPE_MEMORY_REGION, MemoryRegion *),
> };
>
> static void riscv_harts_cpu_reset(void *opaque)
> @@ -117,6 +119,12 @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
> object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
> qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
>
> + /* Use private memory instead of system_memory if provided */
> + if (s->memory) {
> + object_property_set_link(OBJECT(&s->harts[idx]), "memory",
> + OBJECT(s->memory), &error_abort);
IMHO this logic should be inverted: we want explicit memory bus mapping
by default, and if not set then take the global memory. Personally I'd
even go further and assert it is set (otherwise programming error), with
a preliminary patch setting global system memory to current machines.
> + }
> +
> if (s->harts[idx].cfg.ext_smrnmi) {
> if (idx < s->num_rnmi_irqvec) {
> qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device
2026-09-03 5:51 ` [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device Joel Stanley
@ 2026-09-04 10:47 ` Philippe Mathieu-Daudé
2026-09-04 10:48 ` Philippe Mathieu-Daudé
2026-09-07 7:16 ` Joel Stanley
0 siblings, 2 replies; 28+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-09-04 10:47 UTC (permalink / raw)
To: Joel Stanley, Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
On 3/9/26 07:51, Joel Stanley wrote:
> Introduce TYPE_TT_ATLANTIS_SOC and move the hart array, AIA, ACLINT,
> boot ROM, UART and I2C controllers into the new TTAtlantisSoCState. The
> machine keeps ownership of RAM, device tree generation, firmware
> loading, and the board-level I2C slaves.
>
> This makes it easier to compose the SoC into a more complex machine in
> the future.
>
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> include/hw/riscv/tt_atlantis.h | 21 ++++-
> hw/riscv/tt_atlantis.c | 144 +++++++++++++++++++++++----------
> 2 files changed, 119 insertions(+), 46 deletions(-)
> -struct TTAtlantisState {
> +struct TTAtlantisSoCState {
> /*< private >*/
While here please drop these legacy private/public comments (QOM
style doesn't want them anymore).
> - MachineState parent;
> + DeviceState parent;
>
> /*< public >*/
> - Notifier machine_done;
> const MemMapEntry *memmap;
>
> MemoryRegion *memory;
> @@ -39,6 +41,19 @@ struct TTAtlantisState {
> DesignWareI2CState i2c[TT_ATL_NUM_I2C];
> UnimplementedDeviceState uart1;
> MemoryRegion bootrom;
> +
> + uint32_t num_harts;
> + char *cpu_type;
> +};
> +
> +struct TTAtlantisState {
> + /*< private >*/
> + MachineState parent;
> +
> + /*< public >*/
(Ditto).
> + Notifier machine_done;
> +
> + TTAtlantisSoCState soc;
> };
> +static void tt_atlantis_soc_realize(DeviceState *dev, Error **errp)
> +{
> + TTAtlantisSoCState *s = TT_ATLANTIS_SOC(dev);
> ram_addr_t lo_ram_size, ram_size;
> - int hart_count = machine->smp.cpus;
> + int hart_count = s->num_harts;
>
> s->memory = get_system_memory();
For machine layer this was OK but now this is SOC layer and might be
provided by machine layer via linked property. IOW this should be
handled like s->dram below.
>
> - s->dram = machine->ram;
> + if (!s->dram) {
> + error_setg(errp, "'dram' link is not set");
> + return;
> + }
> ram_size = memory_region_size(s->dram);
>
> s->memmap = tt_atlantis_memmap;
>
> - object_initialize_child(OBJECT(machine), "soc", &s->cpus,
> - TYPE_RISCV_HART_ARRAY);
> - object_property_set_str(OBJECT(&s->cpus), "cpu-type", machine->cpu_type,
> + /* CPUs */
> + object_property_set_str(OBJECT(&s->cpus), "cpu-type", s->cpu_type,
> &error_abort);
> object_property_set_int(OBJECT(&s->cpus), "hartid-base", 0,
> &error_abort);
> @@ -505,7 +524,9 @@ static void tt_atlantis_machine_init(MachineState *machine)
> object_property_set_int(OBJECT(&s->cpus), "resetvec",
> s->memmap[TT_ATL_BOOTROM].base,
> &error_abort);
> - sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal);
> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpus), errp)) {
> + return;
> + }
Patch LGTM otherwise, thanks!
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device
2026-09-04 10:47 ` Philippe Mathieu-Daudé
@ 2026-09-04 10:48 ` Philippe Mathieu-Daudé
2026-09-07 7:16 ` Joel Stanley
1 sibling, 0 replies; 28+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-09-04 10:48 UTC (permalink / raw)
To: Joel Stanley, Alistair Francis, Daniel Henrique Barboza
Cc: Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Portia Stephens,
Cédric Le Goater, qemu-riscv, qemu-devel
On 4/9/26 12:47, Philippe Mathieu-Daudé wrote:
> On 3/9/26 07:51, Joel Stanley wrote:
>> Introduce TYPE_TT_ATLANTIS_SOC and move the hart array, AIA, ACLINT,
>> boot ROM, UART and I2C controllers into the new TTAtlantisSoCState. The
>> machine keeps ownership of RAM, device tree generation, firmware
>> loading, and the board-level I2C slaves.
>>
>> This makes it easier to compose the SoC into a more complex machine in
>> the future.
>>
>> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
>> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
>> Signed-off-by: Joel Stanley <joel@jms.id.au>
>> ---
>> include/hw/riscv/tt_atlantis.h | 21 ++++-
>> hw/riscv/tt_atlantis.c | 144 +++++++++++++++++++++++----------
>> 2 files changed, 119 insertions(+), 46 deletions(-)
>
>
>> -struct TTAtlantisState {
>> +struct TTAtlantisSoCState {
>> /*< private >*/
>
> While here please drop these legacy private/public comments (QOM
> style doesn't want them anymore).
>
>> - MachineState parent;
>> + DeviceState parent;
>> /*< public >*/
>> - Notifier machine_done;
>> const MemMapEntry *memmap;
>> MemoryRegion *memory;
>> @@ -39,6 +41,19 @@ struct TTAtlantisState {
>> DesignWareI2CState i2c[TT_ATL_NUM_I2C];
>> UnimplementedDeviceState uart1;
>> MemoryRegion bootrom;
>> +
>> + uint32_t num_harts;
>> + char *cpu_type;
>> +};
>> +
>> +struct TTAtlantisState {
>> + /*< private >*/
>> + MachineState parent;
>> +
>> + /*< public >*/
>
> (Ditto).
>
>> + Notifier machine_done;
>> +
>> + TTAtlantisSoCState soc;
>> };
>
>
>> +static void tt_atlantis_soc_realize(DeviceState *dev, Error **errp)
>> +{
>> + TTAtlantisSoCState *s = TT_ATLANTIS_SOC(dev);
>> ram_addr_t lo_ram_size, ram_size;
>> - int hart_count = machine->smp.cpus;
>> + int hart_count = s->num_harts;
>> s->memory = get_system_memory();
>
> For machine layer this was OK but now this is SOC layer and might be
> provided by machine layer via linked property. IOW this should be
> handled like s->dram below.
(Sorry I'm just noticing the next patch exactly addresses that).
>> - s->dram = machine->ram;
>> + if (!s->dram) {
>> + error_setg(errp, "'dram' link is not set");
>> + return;
>> + }
>> ram_size = memory_region_size(s->dram);
>> s->memmap = tt_atlantis_memmap;
>> - object_initialize_child(OBJECT(machine), "soc", &s->cpus,
>> - TYPE_RISCV_HART_ARRAY);
>> - object_property_set_str(OBJECT(&s->cpus), "cpu-type", machine-
>> >cpu_type,
>> + /* CPUs */
>> + object_property_set_str(OBJECT(&s->cpus), "cpu-type", s->cpu_type,
>> &error_abort);
>> object_property_set_int(OBJECT(&s->cpus), "hartid-base", 0,
>> &error_abort);
>> @@ -505,7 +524,9 @@ static void tt_atlantis_machine_init(MachineState
>> *machine)
>> object_property_set_int(OBJECT(&s->cpus), "resetvec",
>> s->memmap[TT_ATL_BOOTROM].base,
>> &error_abort);
>> - sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal);
>> + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpus), errp)) {
>> + return;
>> + }
>
> Patch LGTM otherwise, thanks!
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 00/16] hw/riscv: Socify Atlantis
2026-09-03 23:35 ` [PATCH v3 00/16] hw/riscv: Socify Atlantis Alistair Francis
@ 2026-09-04 10:49 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 28+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-09-04 10:49 UTC (permalink / raw)
To: Alistair Francis, daniel.barboza@oss.qualcomm.com, joel@jms.id.au
Cc: npiggin@gmail.com, mpe@kernel.org, portias@oss.tenstorrent.com,
qemu-devel@nongnu.org, clg@kaod.org, chao.liu@processmission.com,
zhiwei_liu@linux.alibaba.com, asrinivasan@oss.tenstorrent.com,
liwei1518@gmail.com, qemu-riscv@nongnu.org
On 4/9/26 01:35, Alistair Francis wrote:
> Applied to riscv-to-apply.next
Great! I made a comment on patch #14 which can be addressed later:
https://lore.kernel.org/qemu-devel/a4b3c4a2-e359-4952-8b1a-34db4e2b3c9a@oss.qualcomm.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device
2026-09-04 10:47 ` Philippe Mathieu-Daudé
2026-09-04 10:48 ` Philippe Mathieu-Daudé
@ 2026-09-07 7:16 ` Joel Stanley
1 sibling, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-07 7:16 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Alistair Francis, Daniel Henrique Barboza, Weiwei Li, Liu Zhiwei,
Chao Liu, Nicholas Piggin, Anirudh Srinivasan, Michael Ellerman,
Portia Stephens, Cédric Le Goater, qemu-riscv, qemu-devel
On Fri, 4 Sept 2026 at 20:17, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> On 3/9/26 07:51, Joel Stanley wrote:
> > Introduce TYPE_TT_ATLANTIS_SOC and move the hart array, AIA, ACLINT,
> > boot ROM, UART and I2C controllers into the new TTAtlantisSoCState. The
> > machine keeps ownership of RAM, device tree generation, firmware
> > loading, and the board-level I2C slaves.
> >
> > This makes it easier to compose the SoC into a more complex machine in
> > the future.
> >
> > Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> > Signed-off-by: Joel Stanley <joel@jms.id.au>
> > ---
> > include/hw/riscv/tt_atlantis.h | 21 ++++-
> > hw/riscv/tt_atlantis.c | 144 +++++++++++++++++++++++----------
> > 2 files changed, 119 insertions(+), 46 deletions(-)
>
>
> > -struct TTAtlantisState {
> > +struct TTAtlantisSoCState {
> > /*< private >*/
>
> While here please drop these legacy private/public comments (QOM
> style doesn't want them anymore).
Thanks, TIL. I might send a cleanup for the risc-v tree to set an
example for new code.
Cheers,
Joel
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory
2026-09-04 10:42 ` Philippe Mathieu-Daudé
@ 2026-09-07 7:27 ` Joel Stanley
0 siblings, 0 replies; 28+ messages in thread
From: Joel Stanley @ 2026-09-07 7:27 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Alistair Francis, Daniel Henrique Barboza, Portia Stephens,
Weiwei Li, Liu Zhiwei, Chao Liu, Nicholas Piggin,
Anirudh Srinivasan, Michael Ellerman, Cédric Le Goater,
qemu-riscv, qemu-devel
On Fri, 4 Sept 2026 at 20:13, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
> > @@ -117,6 +119,12 @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
> > object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
> > qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
> >
> > + /* Use private memory instead of system_memory if provided */
> > + if (s->memory) {
> > + object_property_set_link(OBJECT(&s->harts[idx]), "memory",
> > + OBJECT(s->memory), &error_abort);
>
> IMHO this logic should be inverted: we want explicit memory bus mapping
> by default, and if not set then take the global memory. Personally I'd
> even go further and assert it is set (otherwise programming error), with
> a preliminary patch setting global system memory to current machines.
I'm on board with this idea, but I couldn't follow what you meant by
"if not set then take the global memory"? That's what happens
currently?
Are you saying always set the memory link to the provided MemoryRegion
(with a fallback to system_memory, or in the stronger case with an
assert if not set)?
Then we could drop cpu_exec_init.
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2026-09-07 7:27 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 5:51 [PATCH v3 00/16] hw/riscv: Socify Atlantis Joel Stanley
2026-09-03 5:51 ` [PATCH v3 01/16] hw/riscv/aia: Take a MemoryRegion for the created devices Joel Stanley
2026-09-03 6:06 ` Chao Liu via
2026-09-03 6:06 ` Chao Liu via qemu development
2026-09-03 5:51 ` [PATCH v3 02/16] hw/intc/riscv_aclint: " Joel Stanley
2026-09-03 5:51 ` [PATCH v3 03/16] hw/intc/riscv_imsic: Take a MemoryRegion for the created device Joel Stanley
2026-09-03 5:51 ` [PATCH v3 04/16] hw/intc/riscv_aplic: " Joel Stanley
2026-09-03 5:51 ` [PATCH v3 05/16] hw/intc/sifive_plic: " Joel Stanley
2026-09-03 6:07 ` Chao Liu via qemu development
2026-09-03 6:07 ` Chao Liu via
2026-09-03 5:51 ` [PATCH v3 06/16] hw/riscv/cps: Map interrupt controllers in SoC container Joel Stanley
2026-09-03 5:51 ` [PATCH v3 07/16] hw/riscv/atlantis: Make UART unimp region a SoC device Joel Stanley
2026-09-03 5:51 ` [PATCH v3 08/16] hw/riscv/atlantis: Remove unused fdt_size Joel Stanley
2026-09-03 5:51 ` [PATCH v3 09/16] hw/riscv/atlantis: Rename hart array 'soc' to 'cpus' Joel Stanley
2026-09-03 5:51 ` [PATCH v3 10/16] hw/riscv/atlantis: Rework device tree creation Joel Stanley
2026-09-03 5:51 ` [PATCH v3 11/16] hw/riscv/atlantis: Use local reference for system memory Joel Stanley
2026-09-03 5:51 ` [PATCH v3 12/16] hw/riscv/atlantis: Decouple RAM size from MachineState Joel Stanley
2026-09-03 5:51 ` [PATCH v3 13/16] hw/riscv/atlantis: Make TTAtlantisState own memory containers Joel Stanley
2026-09-03 5:51 ` [PATCH v3 14/16] hw/riscv: Add property to hart array to allow private memory Joel Stanley
2026-09-04 10:42 ` Philippe Mathieu-Daudé
2026-09-07 7:27 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 15/16] hw/riscv/atlantis: Extract an Atlantis SoC device Joel Stanley
2026-09-04 10:47 ` Philippe Mathieu-Daudé
2026-09-04 10:48 ` Philippe Mathieu-Daudé
2026-09-07 7:16 ` Joel Stanley
2026-09-03 5:51 ` [PATCH v3 16/16] hw/riscv/atlantis: Map the SoC through a memory container Joel Stanley
2026-09-03 23:35 ` [PATCH v3 00/16] hw/riscv: Socify Atlantis Alistair Francis
2026-09-04 10:49 ` Philippe Mathieu-Daudé
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.