include/hw/arm/smmu-common.h | 4 ++++ include/hw/arm/virt.h | 2 ++ hw/arm/sbsa-ref.c | 16 ++++++++++++---- hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++ hw/arm/virt.c | 13 +++++++++++-- 5 files changed, 54 insertions(+), 6 deletions(-)
This will be used to access non-secure and secure memory. Secure support
and Granule Protection Check (for RME) for SMMU need to access secure
memory.
As well, it allows to remove usage of global address_space_memory,
allowing different SMMU instances to have a specific view of memory.
User creatable SMMU are handled as well for virt machine,
by setting the memory properties when device is plugged in.
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
---
include/hw/arm/smmu-common.h | 4 ++++
include/hw/arm/virt.h | 2 ++
hw/arm/sbsa-ref.c | 16 ++++++++++++----
hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
hw/arm/virt.c | 13 +++++++++++--
5 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index 80d0fecfde8..d9bade3c803 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -162,6 +162,10 @@ struct SMMUState {
uint8_t bus_num;
PCIBus *primary_bus;
bool smmu_per_bus; /* SMMU is specific to the primary_bus */
+ MemoryRegion *memory;
+ AddressSpace memory_as;
+ MemoryRegion *secure_memory;
+ AddressSpace secure_memory_as;
};
struct SMMUBaseClass {
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index c77a33f6df2..d3743810338 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -180,6 +180,8 @@ struct VirtMachineState {
bool ns_el2_virt_timer_irq;
CXLState cxl_devices_state;
bool legacy_smmuv3_present;
+ MemoryRegion *sysmem;
+ MemoryRegion *secure_sysmem;
};
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 2205500a8da..cc9d4385826 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -613,7 +613,9 @@ static void create_xhci(const SBSAMachineState *sms)
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
}
-static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
+static void create_smmu(const SBSAMachineState *sms, PCIBus *bus,
+ MemoryRegion *sysmem,
+ MemoryRegion *secure_sysmem)
{
hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
int irq = sbsa_ref_irqmap[SBSA_SMMU];
@@ -625,6 +627,10 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
object_property_set_str(OBJECT(dev), "stage", "nested", &error_abort);
object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
&error_abort);
+ object_property_set_link(OBJECT(dev), "memory", OBJECT(sysmem),
+ &error_abort);
+ object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(secure_sysmem),
+ &error_abort);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
for (i = 0; i < NUM_SMMU_IRQS; i++) {
@@ -633,7 +639,9 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
}
}
-static void create_pcie(SBSAMachineState *sms)
+static void create_pcie(SBSAMachineState *sms,
+ MemoryRegion *sysmem,
+ MemoryRegion *secure_sysmem)
{
hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
@@ -689,7 +697,7 @@ static void create_pcie(SBSAMachineState *sms)
pci_create_simple(pci->bus, -1, "bochs-display");
- create_smmu(sms, pci->bus);
+ create_smmu(sms, pci->bus, sysmem, secure_sysmem);
}
static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
@@ -825,7 +833,7 @@ static void sbsa_ref_init(MachineState *machine)
create_xhci(sms);
- create_pcie(sms);
+ create_pcie(sms, sysmem, secure_sysmem);
create_secure_ec(secure_sysmem);
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 62a76121841..9a67ce857fe 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
return;
}
+ g_assert(s->memory);
+ address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
+ if (s->secure_memory) {
+ address_space_init(&s->secure_memory_as, s->secure_memory,
+ "smmu-secure-memory-view");
+ }
+
/*
* We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
* root complexes to be associated with SMMU.
@@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
rc->phases.exit = smmu_base_reset_exit;
}
+static void smmu_base_instance_init(Object *obj)
+{
+ SMMUState *s = ARM_SMMU(obj);
+
+ object_property_add_link(obj, "memory",
+ TYPE_MEMORY_REGION,
+ (Object **)&s->memory,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_STRONG);
+
+ object_property_add_link(obj, "secure-memory",
+ TYPE_MEMORY_REGION,
+ (Object **)&s->secure_memory,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_STRONG);
+}
+
static const TypeInfo smmu_base_info = {
.name = TYPE_ARM_SMMU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SMMUState),
+ .instance_init = smmu_base_instance_init,
.class_data = NULL,
.class_size = sizeof(SMMUBaseClass),
.class_init = smmu_base_class_init,
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 25fb2bab568..603f4b6a1d7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1514,8 +1514,7 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms,
0x0, vms->iommu_phandle, 0x0, 0x10000);
}
-static void create_smmu(const VirtMachineState *vms,
- PCIBus *bus)
+static void create_smmu(const VirtMachineState *vms, PCIBus *bus)
{
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
int irq = vms->irqmap[VIRT_SMMU];
@@ -1535,6 +1534,10 @@ static void create_smmu(const VirtMachineState *vms,
}
object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
&error_abort);
+ object_property_set_link(OBJECT(dev), "memory", OBJECT(vms->sysmem),
+ &error_abort);
+ object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(vms->secure_sysmem),
+ &error_abort);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
for (i = 0; i < NUM_SMMU_IRQS; i++) {
@@ -1609,6 +1612,7 @@ static void create_pcie(VirtMachineState *vms)
memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
ecam_reg, 0, size_ecam);
memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
+ vms->sysmem = get_system_memory();
/* Map the MMIO window into system address space so as to expose
* the section of PCI MMIO space which starts at the same base address
@@ -2256,6 +2260,7 @@ static void machvirt_init(MachineState *machine)
* devices go in at higher priority and take precedence.
*/
secure_sysmem = g_new(MemoryRegion, 1);
+ vms->secure_sysmem = secure_sysmem;
memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
UINT64_MAX);
memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
@@ -3051,6 +3056,10 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
} else if (vms->iommu == VIRT_IOMMU_NONE) {
/* The new SMMUv3 device is specific to the PCI bus */
object_property_set_bool(OBJECT(dev), "smmu_per_bus", true, NULL);
+ object_property_set_link(OBJECT(dev), "memory",
+ OBJECT(vms->sysmem), NULL);
+ object_property_set_link(OBJECT(dev), "secure-memory",
+ OBJECT(vms->secure_sysmem), NULL);
}
}
}
--
2.47.3
On 12/16/25 3:57 PM, Pierrick Bouvier wrote: > This will be used to access non-secure and secure memory. Secure support > and Granule Protection Check (for RME) for SMMU need to access secure > memory. > > As well, it allows to remove usage of global address_space_memory, > allowing different SMMU instances to have a specific view of memory. > > User creatable SMMU are handled as well for virt machine, > by setting the memory properties when device is plugged in. > > Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> > --- > include/hw/arm/smmu-common.h | 4 ++++ > include/hw/arm/virt.h | 2 ++ > hw/arm/sbsa-ref.c | 16 ++++++++++++---- > hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++ > hw/arm/virt.c | 13 +++++++++++-- > 5 files changed, 54 insertions(+), 6 deletions(-) > v5 sent: https://lore.kernel.org/qemu-devel/20260108210453.2280733-1-pierrick.bouvier@linaro.org/T/#u
Hi Pierrick,
On 12/17/25 12:57 AM, Pierrick Bouvier wrote:
> This will be used to access non-secure and secure memory. Secure support
> and Granule Protection Check (for RME) for SMMU need to access secure
> memory.
>
> As well, it allows to remove usage of global address_space_memory,
> allowing different SMMU instances to have a specific view of memory.
>
> User creatable SMMU are handled as well for virt machine,
> by setting the memory properties when device is plugged in.
Will Tao's [RFC v3 08/21] hw/arm/smmuv3: Add separate address space for
secure SMMU accesses
be rebased on top of that. How does it cooperate?
Thanks
Eric
>
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> ---
> include/hw/arm/smmu-common.h | 4 ++++
> include/hw/arm/virt.h | 2 ++
> hw/arm/sbsa-ref.c | 16 ++++++++++++----
> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
> hw/arm/virt.c | 13 +++++++++++--
> 5 files changed, 54 insertions(+), 6 deletions(-)
>
> diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
> index 80d0fecfde8..d9bade3c803 100644
> --- a/include/hw/arm/smmu-common.h
> +++ b/include/hw/arm/smmu-common.h
> @@ -162,6 +162,10 @@ struct SMMUState {
> uint8_t bus_num;
> PCIBus *primary_bus;
> bool smmu_per_bus; /* SMMU is specific to the primary_bus */
> + MemoryRegion *memory;
> + AddressSpace memory_as;
> + MemoryRegion *secure_memory;
> + AddressSpace secure_memory_as;
> };
>
> struct SMMUBaseClass {
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index c77a33f6df2..d3743810338 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -180,6 +180,8 @@ struct VirtMachineState {
> bool ns_el2_virt_timer_irq;
> CXLState cxl_devices_state;
> bool legacy_smmuv3_present;
> + MemoryRegion *sysmem;
> + MemoryRegion *secure_sysmem;
> };
>
> #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
> index 2205500a8da..cc9d4385826 100644
> --- a/hw/arm/sbsa-ref.c
> +++ b/hw/arm/sbsa-ref.c
> @@ -613,7 +613,9 @@ static void create_xhci(const SBSAMachineState *sms)
> sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
> }
>
> -static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
> +static void create_smmu(const SBSAMachineState *sms, PCIBus *bus,
> + MemoryRegion *sysmem,
> + MemoryRegion *secure_sysmem)
> {
> hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
> int irq = sbsa_ref_irqmap[SBSA_SMMU];
> @@ -625,6 +627,10 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
> object_property_set_str(OBJECT(dev), "stage", "nested", &error_abort);
> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
> &error_abort);
> + object_property_set_link(OBJECT(dev), "memory", OBJECT(sysmem),
> + &error_abort);
> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(secure_sysmem),
> + &error_abort);
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
> for (i = 0; i < NUM_SMMU_IRQS; i++) {
> @@ -633,7 +639,9 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
> }
> }
>
> -static void create_pcie(SBSAMachineState *sms)
> +static void create_pcie(SBSAMachineState *sms,
> + MemoryRegion *sysmem,
> + MemoryRegion *secure_sysmem)
> {
> hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
> hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
> @@ -689,7 +697,7 @@ static void create_pcie(SBSAMachineState *sms)
>
> pci_create_simple(pci->bus, -1, "bochs-display");
>
> - create_smmu(sms, pci->bus);
> + create_smmu(sms, pci->bus, sysmem, secure_sysmem);
> }
>
> static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
> @@ -825,7 +833,7 @@ static void sbsa_ref_init(MachineState *machine)
>
> create_xhci(sms);
>
> - create_pcie(sms);
> + create_pcie(sms, sysmem, secure_sysmem);
>
> create_secure_ec(secure_sysmem);
>
> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
> index 62a76121841..9a67ce857fe 100644
> --- a/hw/arm/smmu-common.c
> +++ b/hw/arm/smmu-common.c
> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
> return;
> }
>
> + g_assert(s->memory);
> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
> + if (s->secure_memory) {
> + address_space_init(&s->secure_memory_as, s->secure_memory,
> + "smmu-secure-memory-view");
> + }
> +
> /*
> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
> * root complexes to be associated with SMMU.
> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
> rc->phases.exit = smmu_base_reset_exit;
> }
>
> +static void smmu_base_instance_init(Object *obj)
> +{
> + SMMUState *s = ARM_SMMU(obj);
> +
> + object_property_add_link(obj, "memory",
> + TYPE_MEMORY_REGION,
> + (Object **)&s->memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_STRONG);
> +
> + object_property_add_link(obj, "secure-memory",
> + TYPE_MEMORY_REGION,
> + (Object **)&s->secure_memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_STRONG);
> +}
> +
> static const TypeInfo smmu_base_info = {
> .name = TYPE_ARM_SMMU,
> .parent = TYPE_SYS_BUS_DEVICE,
> .instance_size = sizeof(SMMUState),
> + .instance_init = smmu_base_instance_init,
> .class_data = NULL,
> .class_size = sizeof(SMMUBaseClass),
> .class_init = smmu_base_class_init,
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 25fb2bab568..603f4b6a1d7 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1514,8 +1514,7 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms,
> 0x0, vms->iommu_phandle, 0x0, 0x10000);
> }
>
> -static void create_smmu(const VirtMachineState *vms,
> - PCIBus *bus)
> +static void create_smmu(const VirtMachineState *vms, PCIBus *bus)
> {
> VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
> int irq = vms->irqmap[VIRT_SMMU];
> @@ -1535,6 +1534,10 @@ static void create_smmu(const VirtMachineState *vms,
> }
> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
> &error_abort);
> + object_property_set_link(OBJECT(dev), "memory", OBJECT(vms->sysmem),
> + &error_abort);
> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(vms->secure_sysmem),
> + &error_abort);
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
> for (i = 0; i < NUM_SMMU_IRQS; i++) {
> @@ -1609,6 +1612,7 @@ static void create_pcie(VirtMachineState *vms)
> memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
> ecam_reg, 0, size_ecam);
> memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
> + vms->sysmem = get_system_memory();
>
> /* Map the MMIO window into system address space so as to expose
> * the section of PCI MMIO space which starts at the same base address
> @@ -2256,6 +2260,7 @@ static void machvirt_init(MachineState *machine)
> * devices go in at higher priority and take precedence.
> */
> secure_sysmem = g_new(MemoryRegion, 1);
> + vms->secure_sysmem = secure_sysmem;
> memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
> UINT64_MAX);
> memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
> @@ -3051,6 +3056,10 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> } else if (vms->iommu == VIRT_IOMMU_NONE) {
> /* The new SMMUv3 device is specific to the PCI bus */
> object_property_set_bool(OBJECT(dev), "smmu_per_bus", true, NULL);
> + object_property_set_link(OBJECT(dev), "memory",
> + OBJECT(vms->sysmem), NULL);
> + object_property_set_link(OBJECT(dev), "secure-memory",
> + OBJECT(vms->secure_sysmem), NULL);
> }
> }
> }
Hi Eric, On 2026/1/8 02:32, Eric Auger wrote: > Hi Pierrick, > > On 12/17/25 12:57 AM, Pierrick Bouvier wrote: >> This will be used to access non-secure and secure memory. Secure support >> and Granule Protection Check (for RME) for SMMU need to access secure >> memory. >> >> As well, it allows to remove usage of global address_space_memory, >> allowing different SMMU instances to have a specific view of memory. >> >> User creatable SMMU are handled as well for virt machine, >> by setting the memory properties when device is plugged in. > Will Tao's [RFC v3 08/21] hw/arm/smmuv3: Add separate address space for > secure SMMU accesses > be rebased on top of that. How does it cooperate? > > Thanks > > Eric Yes — my latest Secure SMMU V4 will be based on Pierrick’s memory/secure-memory property infrastructure. In my earlier [RFC v3 08/21] implementation, I made the Secure AddressSpace global, which may be a real design problem (notably for multiple SMMU instances). I have already rebased and updated my V4 code on top of Pierrick’s patch; it’s currently under debugging. Thanks, Tao
Hi Pierrick, Tao, On 1/8/26 3:22 AM, Tao Tang wrote: > Hi Eric, > > On 2026/1/8 02:32, Eric Auger wrote: >> Hi Pierrick, >> >> On 12/17/25 12:57 AM, Pierrick Bouvier wrote: >>> This will be used to access non-secure and secure memory. Secure >>> support >>> and Granule Protection Check (for RME) for SMMU need to access secure >>> memory. >>> >>> As well, it allows to remove usage of global address_space_memory, >>> allowing different SMMU instances to have a specific view of memory. >>> >>> User creatable SMMU are handled as well for virt machine, >>> by setting the memory properties when device is plugged in. >> Will Tao's [RFC v3 08/21] hw/arm/smmuv3: Add separate address space for >> secure SMMU accesses >> be rebased on top of that. How does it cooperate? >> >> Thanks >> >> Eric > Yes — my latest Secure SMMU V4 will be based on Pierrick’s > memory/secure-memory property infrastructure. > > In my earlier [RFC v3 08/21] implementation, I made the Secure > AddressSpace global, which may be a real design problem (notably for > multiple SMMU instances). I have already rebased and updated my V4 > code on top of Pierrick’s patch; it’s currently under debugging. OK thank you for the confirmation Eric > > Thanks, > Tao >
On 1/7/26 10:32 AM, Eric Auger wrote:
> Hi Pierrick,
>
> On 12/17/25 12:57 AM, Pierrick Bouvier wrote:
>> This will be used to access non-secure and secure memory. Secure support
>> and Granule Protection Check (for RME) for SMMU need to access secure
>> memory.
>>
>> As well, it allows to remove usage of global address_space_memory,
>> allowing different SMMU instances to have a specific view of memory.
>>
>> User creatable SMMU are handled as well for virt machine,
>> by setting the memory properties when device is plugged in.
>
> Will Tao's [RFC v3 08/21] hw/arm/smmuv3: Add separate address space for
> secure SMMU accesses
> be rebased on top of that. How does it cooperate?
>
Yes, the idea is for him to rebase on top of this series, providing
access to address spaces in a clean way. I felt better pushing it myself
than asking to Tao to integrate it in his series and deal with changes.
As well, we have a wip branch adding root and realm support to smmuv3
that is itself based on current Tao's series and will be published
later. Secure address space is needed to access Granule Protection Table
to implement Granule Protection check. That's how I ended up writing
this series.
> Thanks
>
> Eric
>>
>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>> ---
>> include/hw/arm/smmu-common.h | 4 ++++
>> include/hw/arm/virt.h | 2 ++
>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>> hw/arm/virt.c | 13 +++++++++++--
>> 5 files changed, 54 insertions(+), 6 deletions(-)
>>
>> diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
>> index 80d0fecfde8..d9bade3c803 100644
>> --- a/include/hw/arm/smmu-common.h
>> +++ b/include/hw/arm/smmu-common.h
>> @@ -162,6 +162,10 @@ struct SMMUState {
>> uint8_t bus_num;
>> PCIBus *primary_bus;
>> bool smmu_per_bus; /* SMMU is specific to the primary_bus */
>> + MemoryRegion *memory;
>> + AddressSpace memory_as;
>> + MemoryRegion *secure_memory;
>> + AddressSpace secure_memory_as;
>> };
>>
>> struct SMMUBaseClass {
>> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
>> index c77a33f6df2..d3743810338 100644
>> --- a/include/hw/arm/virt.h
>> +++ b/include/hw/arm/virt.h
>> @@ -180,6 +180,8 @@ struct VirtMachineState {
>> bool ns_el2_virt_timer_irq;
>> CXLState cxl_devices_state;
>> bool legacy_smmuv3_present;
>> + MemoryRegion *sysmem;
>> + MemoryRegion *secure_sysmem;
>> };
>>
>> #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
>> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
>> index 2205500a8da..cc9d4385826 100644
>> --- a/hw/arm/sbsa-ref.c
>> +++ b/hw/arm/sbsa-ref.c
>> @@ -613,7 +613,9 @@ static void create_xhci(const SBSAMachineState *sms)
>> sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
>> }
>>
>> -static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>> +static void create_smmu(const SBSAMachineState *sms, PCIBus *bus,
>> + MemoryRegion *sysmem,
>> + MemoryRegion *secure_sysmem)
>> {
>> hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
>> int irq = sbsa_ref_irqmap[SBSA_SMMU];
>> @@ -625,6 +627,10 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>> object_property_set_str(OBJECT(dev), "stage", "nested", &error_abort);
>> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
>> &error_abort);
>> + object_property_set_link(OBJECT(dev), "memory", OBJECT(sysmem),
>> + &error_abort);
>> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(secure_sysmem),
>> + &error_abort);
>> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
>> for (i = 0; i < NUM_SMMU_IRQS; i++) {
>> @@ -633,7 +639,9 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>> }
>> }
>>
>> -static void create_pcie(SBSAMachineState *sms)
>> +static void create_pcie(SBSAMachineState *sms,
>> + MemoryRegion *sysmem,
>> + MemoryRegion *secure_sysmem)
>> {
>> hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
>> hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
>> @@ -689,7 +697,7 @@ static void create_pcie(SBSAMachineState *sms)
>>
>> pci_create_simple(pci->bus, -1, "bochs-display");
>>
>> - create_smmu(sms, pci->bus);
>> + create_smmu(sms, pci->bus, sysmem, secure_sysmem);
>> }
>>
>> static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
>> @@ -825,7 +833,7 @@ static void sbsa_ref_init(MachineState *machine)
>>
>> create_xhci(sms);
>>
>> - create_pcie(sms);
>> + create_pcie(sms, sysmem, secure_sysmem);
>>
>> create_secure_ec(secure_sysmem);
>>
>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>> index 62a76121841..9a67ce857fe 100644
>> --- a/hw/arm/smmu-common.c
>> +++ b/hw/arm/smmu-common.c
>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
>> return;
>> }
>>
>> + g_assert(s->memory);
>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>> + if (s->secure_memory) {
>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>> + "smmu-secure-memory-view");
>> + }
>> +
>> /*
>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
>> * root complexes to be associated with SMMU.
>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
>> rc->phases.exit = smmu_base_reset_exit;
>> }
>>
>> +static void smmu_base_instance_init(Object *obj)
>> +{
>> + SMMUState *s = ARM_SMMU(obj);
>> +
>> + object_property_add_link(obj, "memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +
>> + object_property_add_link(obj, "secure-memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->secure_memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +}
>> +
>> static const TypeInfo smmu_base_info = {
>> .name = TYPE_ARM_SMMU,
>> .parent = TYPE_SYS_BUS_DEVICE,
>> .instance_size = sizeof(SMMUState),
>> + .instance_init = smmu_base_instance_init,
>> .class_data = NULL,
>> .class_size = sizeof(SMMUBaseClass),
>> .class_init = smmu_base_class_init,
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index 25fb2bab568..603f4b6a1d7 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -1514,8 +1514,7 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms,
>> 0x0, vms->iommu_phandle, 0x0, 0x10000);
>> }
>>
>> -static void create_smmu(const VirtMachineState *vms,
>> - PCIBus *bus)
>> +static void create_smmu(const VirtMachineState *vms, PCIBus *bus)
>> {
>> VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>> int irq = vms->irqmap[VIRT_SMMU];
>> @@ -1535,6 +1534,10 @@ static void create_smmu(const VirtMachineState *vms,
>> }
>> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
>> &error_abort);
>> + object_property_set_link(OBJECT(dev), "memory", OBJECT(vms->sysmem),
>> + &error_abort);
>> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(vms->secure_sysmem),
>> + &error_abort);
>> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
>> for (i = 0; i < NUM_SMMU_IRQS; i++) {
>> @@ -1609,6 +1612,7 @@ static void create_pcie(VirtMachineState *vms)
>> memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
>> ecam_reg, 0, size_ecam);
>> memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
>> + vms->sysmem = get_system_memory();
>>
>> /* Map the MMIO window into system address space so as to expose
>> * the section of PCI MMIO space which starts at the same base address
>> @@ -2256,6 +2260,7 @@ static void machvirt_init(MachineState *machine)
>> * devices go in at higher priority and take precedence.
>> */
>> secure_sysmem = g_new(MemoryRegion, 1);
>> + vms->secure_sysmem = secure_sysmem;
>> memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
>> UINT64_MAX);
>> memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
>> @@ -3051,6 +3056,10 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
>> } else if (vms->iommu == VIRT_IOMMU_NONE) {
>> /* The new SMMUv3 device is specific to the PCI bus */
>> object_property_set_bool(OBJECT(dev), "smmu_per_bus", true, NULL);
>> + object_property_set_link(OBJECT(dev), "memory",
>> + OBJECT(vms->sysmem), NULL);
>> + object_property_set_link(OBJECT(dev), "secure-memory",
>> + OBJECT(vms->secure_sysmem), NULL);
>> }
>> }
>> }
>
On 17/12/25 00:57, Pierrick Bouvier wrote:
> This will be used to access non-secure and secure memory. Secure support
> and Granule Protection Check (for RME) for SMMU need to access secure
> memory.
>
> As well, it allows to remove usage of global address_space_memory,
> allowing different SMMU instances to have a specific view of memory.
>
> User creatable SMMU are handled as well for virt machine,
> by setting the memory properties when device is plugged in.
>
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> ---
> include/hw/arm/smmu-common.h | 4 ++++
> include/hw/arm/virt.h | 2 ++
> hw/arm/sbsa-ref.c | 16 ++++++++++++----
> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
> hw/arm/virt.c | 13 +++++++++++--
> 5 files changed, 54 insertions(+), 6 deletions(-)
> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
> index 62a76121841..9a67ce857fe 100644
> --- a/hw/arm/smmu-common.c
> +++ b/hw/arm/smmu-common.c
> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
> return;
> }
>
> + g_assert(s->memory);
> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
> + if (s->secure_memory) {
> + address_space_init(&s->secure_memory_as, s->secure_memory,
> + "smmu-secure-memory-view");
Else, are we sure the SMMU implementations will behave correctly?
> + }
> +
> /*
> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
> * root complexes to be associated with SMMU.
> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
> rc->phases.exit = smmu_base_reset_exit;
> }
>
> +static void smmu_base_instance_init(Object *obj)
> +{
> + SMMUState *s = ARM_SMMU(obj);
> +
> + object_property_add_link(obj, "memory",
> + TYPE_MEMORY_REGION,
> + (Object **)&s->memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_STRONG);
> +
> + object_property_add_link(obj, "secure-memory",
> + TYPE_MEMORY_REGION,
> + (Object **)&s->secure_memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_STRONG);
Why can't we use device_class_set_props(&static_properties)
in smmu_base_class_init()?
> +}
> +
> static const TypeInfo smmu_base_info = {
> .name = TYPE_ARM_SMMU,
> .parent = TYPE_SYS_BUS_DEVICE,
> .instance_size = sizeof(SMMUState),
> + .instance_init = smmu_base_instance_init,
> .class_data = NULL,
> .class_size = sizeof(SMMUBaseClass),
> .class_init = smmu_base_class_init,
Anyhow this is functional and I suppose this can be improved on top, so:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
On 1/5/26 9:05 PM, Philippe Mathieu-Daudé wrote:
> On 17/12/25 00:57, Pierrick Bouvier wrote:
>> This will be used to access non-secure and secure memory. Secure support
>> and Granule Protection Check (for RME) for SMMU need to access secure
>> memory.
>>
>> As well, it allows to remove usage of global address_space_memory,
>> allowing different SMMU instances to have a specific view of memory.
>>
>> User creatable SMMU are handled as well for virt machine,
>> by setting the memory properties when device is plugged in.
>>
>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>> ---
>> include/hw/arm/smmu-common.h | 4 ++++
>> include/hw/arm/virt.h | 2 ++
>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>> hw/arm/virt.c | 13 +++++++++++--
>> 5 files changed, 54 insertions(+), 6 deletions(-)
>
>
>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>> index 62a76121841..9a67ce857fe 100644
>> --- a/hw/arm/smmu-common.c
>> +++ b/hw/arm/smmu-common.c
>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev,
>> Error **errp)
>> return;
>> }
>> + g_assert(s->memory);
>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>> + if (s->secure_memory) {
>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>> + "smmu-secure-memory-view");
>
> Else, are we sure the SMMU implementations will behave correctly?
>
>> + }
>> +
>> /*
>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie
>> based extra
>> * root complexes to be associated with SMMU.
>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass
>> *klass, const void *data)
>> rc->phases.exit = smmu_base_reset_exit;
>> }
>> +static void smmu_base_instance_init(Object *obj)
>> +{
>> + SMMUState *s = ARM_SMMU(obj);
>> +
>> + object_property_add_link(obj, "memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +
>> + object_property_add_link(obj, "secure-memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->secure_memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>
> Why can't we use device_class_set_props(&static_properties)
> in smmu_base_class_init()?
We have smmu_dev_properties with a DEFINE_PROP_LINK
Couldn't we add the new links there?
Eric
>
>> +}
>> +
>> static const TypeInfo smmu_base_info = {
>> .name = TYPE_ARM_SMMU,
>> .parent = TYPE_SYS_BUS_DEVICE,
>> .instance_size = sizeof(SMMUState),
>> + .instance_init = smmu_base_instance_init,
>> .class_data = NULL,
>> .class_size = sizeof(SMMUBaseClass),
>> .class_init = smmu_base_class_init,
>
> Anyhow this is functional and I suppose this can be improved on top, so:
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
On 1/8/26 1:20 AM, Eric Auger wrote:
>
>
> On 1/5/26 9:05 PM, Philippe Mathieu-Daudé wrote:
>> On 17/12/25 00:57, Pierrick Bouvier wrote:
>>> This will be used to access non-secure and secure memory. Secure support
>>> and Granule Protection Check (for RME) for SMMU need to access secure
>>> memory.
>>>
>>> As well, it allows to remove usage of global address_space_memory,
>>> allowing different SMMU instances to have a specific view of memory.
>>>
>>> User creatable SMMU are handled as well for virt machine,
>>> by setting the memory properties when device is plugged in.
>>>
>>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>>> ---
>>> include/hw/arm/smmu-common.h | 4 ++++
>>> include/hw/arm/virt.h | 2 ++
>>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>>> hw/arm/virt.c | 13 +++++++++++--
>>> 5 files changed, 54 insertions(+), 6 deletions(-)
>>
>>
>>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>>> index 62a76121841..9a67ce857fe 100644
>>> --- a/hw/arm/smmu-common.c
>>> +++ b/hw/arm/smmu-common.c
>>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev,
>>> Error **errp)
>>> return;
>>> }
>>> + g_assert(s->memory);
>>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>>> + if (s->secure_memory) {
>>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>>> + "smmu-secure-memory-view");
>>
>> Else, are we sure the SMMU implementations will behave correctly?
>>
>>> + }
>>> +
>>> /*
>>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie
>>> based extra
>>> * root complexes to be associated with SMMU.
>>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass
>>> *klass, const void *data)
>>> rc->phases.exit = smmu_base_reset_exit;
>>> }
>>> +static void smmu_base_instance_init(Object *obj)
>>> +{
>>> + SMMUState *s = ARM_SMMU(obj);
>>> +
>>> + object_property_add_link(obj, "memory",
>>> + TYPE_MEMORY_REGION,
>>> + (Object **)&s->memory,
>>> + qdev_prop_allow_set_link_before_realize,
>>> + OBJ_PROP_LINK_STRONG);
>>> +
>>> + object_property_add_link(obj, "secure-memory",
>>> + TYPE_MEMORY_REGION,
>>> + (Object **)&s->secure_memory,
>>> + qdev_prop_allow_set_link_before_realize,
>>> + OBJ_PROP_LINK_STRONG);
>>
>> Why can't we use device_class_set_props(&static_properties)
>> in smmu_base_class_init()?
>
> We have smmu_dev_properties with a DEFINE_PROP_LINK
> Couldn't we add the new links there?
>
After checking, yes, DEFINE_PROP_LINK could be used for definition.
The important bit is that DEFINE_PROP_LINK uses create_link_property
which uses qdev_prop_allow_set_link_before_realize, and we really need that.
I'll switch to that in next version, thanks.
Pierrick
> Eric
>>
>>> +}
>>> +
>>> static const TypeInfo smmu_base_info = {
>>> .name = TYPE_ARM_SMMU,
>>> .parent = TYPE_SYS_BUS_DEVICE,
>>> .instance_size = sizeof(SMMUState),
>>> + .instance_init = smmu_base_instance_init,
>>> .class_data = NULL,
>>> .class_size = sizeof(SMMUBaseClass),
>>> .class_init = smmu_base_class_init,
>>
>> Anyhow this is functional and I suppose this can be improved on top, so:
>>
>> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>
>
On 2026-01-05 12:05, Philippe Mathieu-Daudé wrote:
> On 17/12/25 00:57, Pierrick Bouvier wrote:
>> This will be used to access non-secure and secure memory. Secure support
>> and Granule Protection Check (for RME) for SMMU need to access secure
>> memory.
>>
>> As well, it allows to remove usage of global address_space_memory,
>> allowing different SMMU instances to have a specific view of memory.
>>
>> User creatable SMMU are handled as well for virt machine,
>> by setting the memory properties when device is plugged in.
>>
>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>> ---
>> include/hw/arm/smmu-common.h | 4 ++++
>> include/hw/arm/virt.h | 2 ++
>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>> hw/arm/virt.c | 13 +++++++++++--
>> 5 files changed, 54 insertions(+), 6 deletions(-)
>
>
>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>> index 62a76121841..9a67ce857fe 100644
>> --- a/hw/arm/smmu-common.c
>> +++ b/hw/arm/smmu-common.c
>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
>> return;
>> }
>>
>> + g_assert(s->memory);
>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>> + if (s->secure_memory) {
>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>> + "smmu-secure-memory-view");
>
> Else, are we sure the SMMU implementations will behave correctly?
>
>> + }
>> +
>> /*
>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
>> * root complexes to be associated with SMMU.
>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
>> rc->phases.exit = smmu_base_reset_exit;
>> }
>>
>> +static void smmu_base_instance_init(Object *obj)
>> +{
>> + SMMUState *s = ARM_SMMU(obj);
>> +
>> + object_property_add_link(obj, "memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +
>> + object_property_add_link(obj, "secure-memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->secure_memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>
> Why can't we use device_class_set_props(&static_properties)
> in smmu_base_class_init()?
>
To be honest, I simply duplicated what was done on cpu side, without
thinking too much about it.
I thought there was something about passing a memory region that
requires this, compared to having a simple property.
If you think it's important, I can try to use the function you mentioned
above.
>> +}
>> +
>> static const TypeInfo smmu_base_info = {
>> .name = TYPE_ARM_SMMU,
>> .parent = TYPE_SYS_BUS_DEVICE,
>> .instance_size = sizeof(SMMUState),
>> + .instance_init = smmu_base_instance_init,
>> .class_data = NULL,
>> .class_size = sizeof(SMMUBaseClass),
>> .class_init = smmu_base_class_init,
>
> Anyhow this is functional and I suppose this can be improved on top, so:
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
Thanks,
Pierrick
On 5/1/26 21:05, Philippe Mathieu-Daudé wrote:
> On 17/12/25 00:57, Pierrick Bouvier wrote:
>> This will be used to access non-secure and secure memory. Secure support
>> and Granule Protection Check (for RME) for SMMU need to access secure
>> memory.
>>
>> As well, it allows to remove usage of global address_space_memory,
>> allowing different SMMU instances to have a specific view of memory.
>>
>> User creatable SMMU are handled as well for virt machine,
>> by setting the memory properties when device is plugged in.
>>
>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>> ---
>> include/hw/arm/smmu-common.h | 4 ++++
>> include/hw/arm/virt.h | 2 ++
>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>> hw/arm/virt.c | 13 +++++++++++--
>> 5 files changed, 54 insertions(+), 6 deletions(-)
>
>
>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>> index 62a76121841..9a67ce857fe 100644
>> --- a/hw/arm/smmu-common.c
>> +++ b/hw/arm/smmu-common.c
>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev,
>> Error **errp)
>> return;
>> }
>> + g_assert(s->memory);
>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>> + if (s->secure_memory) {
>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>> + "smmu-secure-memory-view");
Preferrably: "smmu-normal-view" and "smmu-secure-view" (IMO 'memory'
is more confusing than helping).
> Else, are we sure the SMMU implementations will behave correctly?
Alternatively, use AddressSpace pointers, then:
} else {
s->secure_memory_as = s->memory_as;
>> + }
>> +
>> /*
>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie
>> based extra
>> * root complexes to be associated with SMMU.
>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass
>> *klass, const void *data)
>> rc->phases.exit = smmu_base_reset_exit;
>> }
>> +static void smmu_base_instance_init(Object *obj)
>> +{
>> + SMMUState *s = ARM_SMMU(obj);
>> +
>> + object_property_add_link(obj, "memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +
>> + object_property_add_link(obj, "secure-memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->secure_memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>
> Why can't we use device_class_set_props(&static_properties)
> in smmu_base_class_init()?
>
>> +}
>> +
>> static const TypeInfo smmu_base_info = {
>> .name = TYPE_ARM_SMMU,
>> .parent = TYPE_SYS_BUS_DEVICE,
>> .instance_size = sizeof(SMMUState),
>> + .instance_init = smmu_base_instance_init,
>> .class_data = NULL,
>> .class_size = sizeof(SMMUBaseClass),
>> .class_init = smmu_base_class_init,
>
> Anyhow this is functional and I suppose this can be improved on top, so:
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
On 1/5/26 12:10 PM, Philippe Mathieu-Daudé wrote:
> On 5/1/26 21:05, Philippe Mathieu-Daudé wrote:
>> On 17/12/25 00:57, Pierrick Bouvier wrote:
>>> This will be used to access non-secure and secure memory. Secure support
>>> and Granule Protection Check (for RME) for SMMU need to access secure
>>> memory.
>>>
>>> As well, it allows to remove usage of global address_space_memory,
>>> allowing different SMMU instances to have a specific view of memory.
>>>
>>> User creatable SMMU are handled as well for virt machine,
>>> by setting the memory properties when device is plugged in.
>>>
>>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>>> ---
>>> include/hw/arm/smmu-common.h | 4 ++++
>>> include/hw/arm/virt.h | 2 ++
>>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>>> hw/arm/virt.c | 13 +++++++++++--
>>> 5 files changed, 54 insertions(+), 6 deletions(-)
>>
>>
>>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>>> index 62a76121841..9a67ce857fe 100644
>>> --- a/hw/arm/smmu-common.c
>>> +++ b/hw/arm/smmu-common.c
>>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev,
>>> Error **errp)
>>> return;
>>> }
>>> + g_assert(s->memory);
>>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>>> + if (s->secure_memory) {
>>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>>> + "smmu-secure-memory-view");
>
> Preferrably: "smmu-normal-view" and "smmu-secure-view" (IMO 'memory'
> is more confusing than helping).
>
A bit of bike shedding, but I'm not sure what "normal" is supposed to
mean. Basically, it's the view of main memory, as opposed to secure
view. Especially, "normal" is used to access realm memory also, so I
would prefer to have something hinting it's global vs secure memory,
thus the names chosen.
>> Else, are we sure the SMMU implementations will behave correctly?
>
> Alternatively, use AddressSpace pointers, then:
>
> } else {
>
> s->secure_memory_as = s->memory_as;
>
>>> + }
>>> +
>>> /*
>>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie
>>> based extra
>>> * root complexes to be associated with SMMU.
>>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass
>>> *klass, const void *data)
>>> rc->phases.exit = smmu_base_reset_exit;
>>> }
>>> +static void smmu_base_instance_init(Object *obj)
>>> +{
>>> + SMMUState *s = ARM_SMMU(obj);
>>> +
>>> + object_property_add_link(obj, "memory",
>>> + TYPE_MEMORY_REGION,
>>> + (Object **)&s->memory,
>>> + qdev_prop_allow_set_link_before_realize,
>>> + OBJ_PROP_LINK_STRONG);
>>> +
>>> + object_property_add_link(obj, "secure-memory",
>>> + TYPE_MEMORY_REGION,
>>> + (Object **)&s->secure_memory,
>>> + qdev_prop_allow_set_link_before_realize,
>>> + OBJ_PROP_LINK_STRONG);
>>
>> Why can't we use device_class_set_props(&static_properties)
>> in smmu_base_class_init()?
>>
>>> +}
>>> +
>>> static const TypeInfo smmu_base_info = {
>>> .name = TYPE_ARM_SMMU,
>>> .parent = TYPE_SYS_BUS_DEVICE,
>>> .instance_size = sizeof(SMMUState),
>>> + .instance_init = smmu_base_instance_init,
>>> .class_data = NULL,
>>> .class_size = sizeof(SMMUBaseClass),
>>> .class_init = smmu_base_class_init,
>>
>> Anyhow this is functional and I suppose this can be improved on top, so:
>>
>> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>
>
On 12/16/25 3:57 PM, Pierrick Bouvier wrote: > This will be used to access non-secure and secure memory. Secure support > and Granule Protection Check (for RME) for SMMU need to access secure > memory. > > As well, it allows to remove usage of global address_space_memory, > allowing different SMMU instances to have a specific view of memory. > > User creatable SMMU are handled as well for virt machine, > by setting the memory properties when device is plugged in. > > Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> > --- > include/hw/arm/smmu-common.h | 4 ++++ > include/hw/arm/virt.h | 2 ++ > hw/arm/sbsa-ref.c | 16 ++++++++++++---- > hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++ > hw/arm/virt.c | 13 +++++++++++-- > 5 files changed, 54 insertions(+), 6 deletions(-) Gentle ping on this patch that was not yet reviewed. Regards, Pierrick
Hi Pierrick,
On 2025/12/17 07:57, Pierrick Bouvier wrote:
> This will be used to access non-secure and secure memory. Secure support
> and Granule Protection Check (for RME) for SMMU need to access secure
> memory.
>
> As well, it allows to remove usage of global address_space_memory,
> allowing different SMMU instances to have a specific view of memory.
>
> User creatable SMMU are handled as well for virt machine,
> by setting the memory properties when device is plugged in.
>
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> ---
> include/hw/arm/smmu-common.h | 4 ++++
> include/hw/arm/virt.h | 2 ++
> hw/arm/sbsa-ref.c | 16 ++++++++++++----
> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
> hw/arm/virt.c | 13 +++++++++++--
> 5 files changed, 54 insertions(+), 6 deletions(-)
>
> diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
> index 80d0fecfde8..d9bade3c803 100644
> --- a/include/hw/arm/smmu-common.h
> +++ b/include/hw/arm/smmu-common.h
> @@ -162,6 +162,10 @@ struct SMMUState {
> uint8_t bus_num;
> PCIBus *primary_bus;
> bool smmu_per_bus; /* SMMU is specific to the primary_bus */
> + MemoryRegion *memory;
> + AddressSpace memory_as;
> + MemoryRegion *secure_memory;
> + AddressSpace secure_memory_as;
> };
>
> struct SMMUBaseClass {
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index c77a33f6df2..d3743810338 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -180,6 +180,8 @@ struct VirtMachineState {
> bool ns_el2_virt_timer_irq;
> CXLState cxl_devices_state;
> bool legacy_smmuv3_present;
> + MemoryRegion *sysmem;
> + MemoryRegion *secure_sysmem;
> };
>
> #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
> index 2205500a8da..cc9d4385826 100644
> --- a/hw/arm/sbsa-ref.c
> +++ b/hw/arm/sbsa-ref.c
> @@ -613,7 +613,9 @@ static void create_xhci(const SBSAMachineState *sms)
> sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
> }
>
> -static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
> +static void create_smmu(const SBSAMachineState *sms, PCIBus *bus,
> + MemoryRegion *sysmem,
> + MemoryRegion *secure_sysmem)
> {
> hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
> int irq = sbsa_ref_irqmap[SBSA_SMMU];
> @@ -625,6 +627,10 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
> object_property_set_str(OBJECT(dev), "stage", "nested", &error_abort);
> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
> &error_abort);
> + object_property_set_link(OBJECT(dev), "memory", OBJECT(sysmem),
> + &error_abort);
> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(secure_sysmem),
......
> + &error_abort);
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
> for (i = 0; i < NUM_SMMU_IRQS; i++) {
> @@ -633,7 +639,9 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
> }
> }
>
> -static void create_pcie(SBSAMachineState *sms)
> +static void create_pcie(SBSAMachineState *sms,
> + MemoryRegion *sysmem,
> + MemoryRegion *secure_sysmem)
> {
> hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
> hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
> @@ -689,7 +697,7 @@ static void create_pcie(SBSAMachineState *sms)
>
> pci_create_simple(pci->bus, -1, "bochs-display");
>
> - create_smmu(sms, pci->bus);
> + create_smmu(sms, pci->bus, sysmem, secure_sysmem);
> }
>
> static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
> @@ -825,7 +833,7 @@ static void sbsa_ref_init(MachineState *machine)
>
> create_xhci(sms);
>
> - create_pcie(sms);
> + create_pcie(sms, sysmem, secure_sysmem);
>
> create_secure_ec(secure_sysmem);
>
> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
> index 62a76121841..9a67ce857fe 100644
> --- a/hw/arm/smmu-common.c
> +++ b/hw/arm/smmu-common.c
> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
> return;
> }
>
> + g_assert(s->memory);
> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
> + if (s->secure_memory) {
> + address_space_init(&s->secure_memory_as, s->secure_memory,
> + "smmu-secure-memory-view");
> + }
> +
> /*
> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
> * root complexes to be associated with SMMU.
> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
> rc->phases.exit = smmu_base_reset_exit;
> }
>
> +static void smmu_base_instance_init(Object *obj)
> +{
> + SMMUState *s = ARM_SMMU(obj);
> +
> + object_property_add_link(obj, "memory",
> + TYPE_MEMORY_REGION,
> + (Object **)&s->memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_STRONG);
> +
> + object_property_add_link(obj, "secure-memory",
> + TYPE_MEMORY_REGION,
> + (Object **)&s->secure_memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_STRONG);
> +}
> +
> static const TypeInfo smmu_base_info = {
> .name = TYPE_ARM_SMMU,
> .parent = TYPE_SYS_BUS_DEVICE,
> .instance_size = sizeof(SMMUState),
> + .instance_init = smmu_base_instance_init,
> .class_data = NULL,
> .class_size = sizeof(SMMUBaseClass),
> .class_init = smmu_base_class_init,
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 25fb2bab568..603f4b6a1d7 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1514,8 +1514,7 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms,
> 0x0, vms->iommu_phandle, 0x0, 0x10000);
> }
>
> -static void create_smmu(const VirtMachineState *vms,
> - PCIBus *bus)
> +static void create_smmu(const VirtMachineState *vms, PCIBus *bus)
> {
> VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
> int irq = vms->irqmap[VIRT_SMMU];
> @@ -1535,6 +1534,10 @@ static void create_smmu(const VirtMachineState *vms,
> }
> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
> &error_abort);
> + object_property_set_link(OBJECT(dev), "memory", OBJECT(vms->sysmem),
> + &error_abort);
> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(vms->secure_sysmem),
> + &error_abort);
I noticed this line is over 80 characters and the corresponding one in
hw/arm/sbsa-ref.c also seems to exceed 80 characters. I’m not fully sure
whether QEMU expects us to strictly keep every line under 80 characters,
but when I ran scripts/checkpatch.pl I did see two warnings.
```
WARNING: line over 80 characters
#47: FILE: hw/arm/sbsa-ref.c:632:
+ object_property_set_link(OBJECT(dev), "secure-memory",
OBJECT(secure_sysmem),
WARNING: line over 80 characters
#148: FILE: hw/arm/virt.c:1539:
+ object_property_set_link(OBJECT(dev), "secure-memory",
OBJECT(vms->secure_sysmem),
total: 0 errors, 2 warnings, 148 lines checked
```
Just flagging this in case you’d like to adjust it before the next revision.
Besides, I tested the SMMU-related MemoryRegion and AddressSpace
instantiation for both user-creatable and machine-wide SMMUv3 devices.
As shown in the info mtree output below, everything looks fine on my side.
```
(QEMU) info mtree
address-space: cpu-secure-memory-0
address-space: smmu-secure-memory-view
0000000000000000-ffffffffffffffff (prio 0, i/o): secure-memory
0000000000000000-0000000003ffffff (prio 0, romd): virt.flash0
....
address-space: cpu-memory-0
address-space: gicv3-its-sysmem
address-space: memory
address-space: smmu-memory-view
0000000000000000-ffffffffffffffff (prio -1, i/o): system
0000000004000000-0000000007ffffff (prio 0, romd): virt.flash1
0000000008000000-000000000800ffff (prio 0, i/o): gicv3_dist
```
Regards,
Tao
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
> for (i = 0; i < NUM_SMMU_IRQS; i++) {
> @@ -1609,6 +1612,7 @@ static void create_pcie(VirtMachineState *vms)
> memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
> ecam_reg, 0, size_ecam);
> memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
> + vms->sysmem = get_system_memory();
>
> /* Map the MMIO window into system address space so as to expose
> * the section of PCI MMIO space which starts at the same base address
> @@ -2256,6 +2260,7 @@ static void machvirt_init(MachineState *machine)
> * devices go in at higher priority and take precedence.
> */
> secure_sysmem = g_new(MemoryRegion, 1);
> + vms->secure_sysmem = secure_sysmem;
> memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
> UINT64_MAX);
> memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
> @@ -3051,6 +3056,10 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> } else if (vms->iommu == VIRT_IOMMU_NONE) {
> /* The new SMMUv3 device is specific to the PCI bus */
> object_property_set_bool(OBJECT(dev), "smmu_per_bus", true, NULL);
> + object_property_set_link(OBJECT(dev), "memory",
> + OBJECT(vms->sysmem), NULL);
> + object_property_set_link(OBJECT(dev), "secure-memory",
> + OBJECT(vms->secure_sysmem), NULL);
> }
> }
> }
On 12/18/25 7:51 AM, Tao Tang wrote:
> Hi Pierrick,
>
> On 2025/12/17 07:57, Pierrick Bouvier wrote:
>> This will be used to access non-secure and secure memory. Secure support
>> and Granule Protection Check (for RME) for SMMU need to access secure
>> memory.
>>
>> As well, it allows to remove usage of global address_space_memory,
>> allowing different SMMU instances to have a specific view of memory.
>>
>> User creatable SMMU are handled as well for virt machine,
>> by setting the memory properties when device is plugged in.
>>
>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>> ---
>> include/hw/arm/smmu-common.h | 4 ++++
>> include/hw/arm/virt.h | 2 ++
>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>> hw/arm/virt.c | 13 +++++++++++--
>> 5 files changed, 54 insertions(+), 6 deletions(-)
>>
>> diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
>> index 80d0fecfde8..d9bade3c803 100644
>> --- a/include/hw/arm/smmu-common.h
>> +++ b/include/hw/arm/smmu-common.h
>> @@ -162,6 +162,10 @@ struct SMMUState {
>> uint8_t bus_num;
>> PCIBus *primary_bus;
>> bool smmu_per_bus; /* SMMU is specific to the primary_bus */
>> + MemoryRegion *memory;
>> + AddressSpace memory_as;
>> + MemoryRegion *secure_memory;
>> + AddressSpace secure_memory_as;
>> };
>>
>> struct SMMUBaseClass {
>> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
>> index c77a33f6df2..d3743810338 100644
>> --- a/include/hw/arm/virt.h
>> +++ b/include/hw/arm/virt.h
>> @@ -180,6 +180,8 @@ struct VirtMachineState {
>> bool ns_el2_virt_timer_irq;
>> CXLState cxl_devices_state;
>> bool legacy_smmuv3_present;
>> + MemoryRegion *sysmem;
>> + MemoryRegion *secure_sysmem;
>> };
>>
>> #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
>> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
>> index 2205500a8da..cc9d4385826 100644
>> --- a/hw/arm/sbsa-ref.c
>> +++ b/hw/arm/sbsa-ref.c
>> @@ -613,7 +613,9 @@ static void create_xhci(const SBSAMachineState *sms)
>> sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
>> }
>>
>> -static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>> +static void create_smmu(const SBSAMachineState *sms, PCIBus *bus,
>> + MemoryRegion *sysmem,
>> + MemoryRegion *secure_sysmem)
>> {
>> hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
>> int irq = sbsa_ref_irqmap[SBSA_SMMU];
>> @@ -625,6 +627,10 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>> object_property_set_str(OBJECT(dev), "stage", "nested", &error_abort);
>> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
>> &error_abort);
>> + object_property_set_link(OBJECT(dev), "memory", OBJECT(sysmem),
>> + &error_abort);
>> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(secure_sysmem),
>
>
> ......
>
>> + &error_abort);
>> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
>> for (i = 0; i < NUM_SMMU_IRQS; i++) {
>> @@ -633,7 +639,9 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>> }
>> }
>>
>> -static void create_pcie(SBSAMachineState *sms)
>> +static void create_pcie(SBSAMachineState *sms,
>> + MemoryRegion *sysmem,
>> + MemoryRegion *secure_sysmem)
>> {
>> hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
>> hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
>> @@ -689,7 +697,7 @@ static void create_pcie(SBSAMachineState *sms)
>>
>> pci_create_simple(pci->bus, -1, "bochs-display");
>>
>> - create_smmu(sms, pci->bus);
>> + create_smmu(sms, pci->bus, sysmem, secure_sysmem);
>> }
>>
>> static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
>> @@ -825,7 +833,7 @@ static void sbsa_ref_init(MachineState *machine)
>>
>> create_xhci(sms);
>>
>> - create_pcie(sms);
>> + create_pcie(sms, sysmem, secure_sysmem);
>>
>> create_secure_ec(secure_sysmem);
>>
>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>> index 62a76121841..9a67ce857fe 100644
>> --- a/hw/arm/smmu-common.c
>> +++ b/hw/arm/smmu-common.c
>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
>> return;
>> }
>>
>> + g_assert(s->memory);
>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>> + if (s->secure_memory) {
>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>> + "smmu-secure-memory-view");
>> + }
>> +
>> /*
>> * We only allow default PCIe Root Complex(pcie.0) or pxb-pcie based extra
>> * root complexes to be associated with SMMU.
>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass *klass, const void *data)
>> rc->phases.exit = smmu_base_reset_exit;
>> }
>>
>> +static void smmu_base_instance_init(Object *obj)
>> +{
>> + SMMUState *s = ARM_SMMU(obj);
>> +
>> + object_property_add_link(obj, "memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +
>> + object_property_add_link(obj, "secure-memory",
>> + TYPE_MEMORY_REGION,
>> + (Object **)&s->secure_memory,
>> + qdev_prop_allow_set_link_before_realize,
>> + OBJ_PROP_LINK_STRONG);
>> +}
>> +
>> static const TypeInfo smmu_base_info = {
>> .name = TYPE_ARM_SMMU,
>> .parent = TYPE_SYS_BUS_DEVICE,
>> .instance_size = sizeof(SMMUState),
>> + .instance_init = smmu_base_instance_init,
>> .class_data = NULL,
>> .class_size = sizeof(SMMUBaseClass),
>> .class_init = smmu_base_class_init,
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index 25fb2bab568..603f4b6a1d7 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -1514,8 +1514,7 @@ static void create_smmuv3_dev_dtb(VirtMachineState *vms,
>> 0x0, vms->iommu_phandle, 0x0, 0x10000);
>> }
>>
>> -static void create_smmu(const VirtMachineState *vms,
>> - PCIBus *bus)
>> +static void create_smmu(const VirtMachineState *vms, PCIBus *bus)
>> {
>> VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>> int irq = vms->irqmap[VIRT_SMMU];
>> @@ -1535,6 +1534,10 @@ static void create_smmu(const VirtMachineState *vms,
>> }
>> object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
>> &error_abort);
>> + object_property_set_link(OBJECT(dev), "memory", OBJECT(vms->sysmem),
>> + &error_abort);
>> + object_property_set_link(OBJECT(dev), "secure-memory", OBJECT(vms->secure_sysmem),
>> + &error_abort);
>
>
> I noticed this line is over 80 characters and the corresponding one in
> hw/arm/sbsa-ref.c also seems to exceed 80 characters. I’m not fully sure
> whether QEMU expects us to strictly keep every line under 80 characters,
> but when I ran scripts/checkpatch.pl I did see two warnings.
>
Thanks for reporting, it's a warning, not a hard error (90 char).
From what I understood, I think it's ok to go over a few characters for
cases like this, to keep code with same layout as lines around.
>
> ```
>
> WARNING: line over 80 characters
> #47: FILE: hw/arm/sbsa-ref.c:632:
> + object_property_set_link(OBJECT(dev), "secure-memory",
> OBJECT(secure_sysmem),
>
> WARNING: line over 80 characters
> #148: FILE: hw/arm/virt.c:1539:
> + object_property_set_link(OBJECT(dev), "secure-memory",
> OBJECT(vms->secure_sysmem),
>
> total: 0 errors, 2 warnings, 148 lines checked
>
> ```
>
>
> Just flagging this in case you’d like to adjust it before the next revision.
>
>
> Besides, I tested the SMMU-related MemoryRegion and AddressSpace
> instantiation for both user-creatable and machine-wide SMMUv3 devices.
> As shown in the info mtree output below, everything looks fine on my side.
>
>
> ```
>
> (QEMU) info mtree
> address-space: cpu-secure-memory-0
> address-space: smmu-secure-memory-view
> 0000000000000000-ffffffffffffffff (prio 0, i/o): secure-memory
> 0000000000000000-0000000003ffffff (prio 0, romd): virt.flash0
>
> ....
>
> address-space: cpu-memory-0
> address-space: gicv3-its-sysmem
> address-space: memory
> address-space: smmu-memory-view
> 0000000000000000-ffffffffffffffff (prio -1, i/o): system
> 0000000004000000-0000000007ffffff (prio 0, romd): virt.flash1
> 0000000008000000-000000000800ffff (prio 0, i/o): gicv3_dist
>
> ```
>
Thanks for testing :)!
>
>
> Regards,
> Tao
>
>> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
>> for (i = 0; i < NUM_SMMU_IRQS; i++) {
>> @@ -1609,6 +1612,7 @@ static void create_pcie(VirtMachineState *vms)
>> memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
>> ecam_reg, 0, size_ecam);
>> memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
>> + vms->sysmem = get_system_memory();
>>
>> /* Map the MMIO window into system address space so as to expose
>> * the section of PCI MMIO space which starts at the same base address
>> @@ -2256,6 +2260,7 @@ static void machvirt_init(MachineState *machine)
>> * devices go in at higher priority and take precedence.
>> */
>> secure_sysmem = g_new(MemoryRegion, 1);
>> + vms->secure_sysmem = secure_sysmem;
>> memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
>> UINT64_MAX);
>> memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
>> @@ -3051,6 +3056,10 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
>> } else if (vms->iommu == VIRT_IOMMU_NONE) {
>> /* The new SMMUv3 device is specific to the PCI bus */
>> object_property_set_bool(OBJECT(dev), "smmu_per_bus", true, NULL);
>> + object_property_set_link(OBJECT(dev), "memory",
>> + OBJECT(vms->sysmem), NULL);
>> + object_property_set_link(OBJECT(dev), "secure-memory",
>> + OBJECT(vms->secure_sysmem), NULL);
>> }
>> }
>> }
>
Cheers,
Pierrick
Hi Pierrick
On 12/18/25 6:51 PM, Pierrick Bouvier wrote:
> On 12/18/25 7:51 AM, Tao Tang wrote:
>> Hi Pierrick,
>>
>> On 2025/12/17 07:57, Pierrick Bouvier wrote:
>>> This will be used to access non-secure and secure memory. Secure
>>> support
>>> and Granule Protection Check (for RME) for SMMU need to access secure
>>> memory.
>>>
>>> As well, it allows to remove usage of global address_space_memory,
>>> allowing different SMMU instances to have a specific view of memory.
>>>
>>> User creatable SMMU are handled as well for virt machine,
>>> by setting the memory properties when device is plugged in.
>>>
>>> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>>> ---
>>> include/hw/arm/smmu-common.h | 4 ++++
>>> include/hw/arm/virt.h | 2 ++
>>> hw/arm/sbsa-ref.c | 16 ++++++++++++----
>>> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
>>> hw/arm/virt.c | 13 +++++++++++--
>>> 5 files changed, 54 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/include/hw/arm/smmu-common.h
>>> b/include/hw/arm/smmu-common.h
>>> index 80d0fecfde8..d9bade3c803 100644
>>> --- a/include/hw/arm/smmu-common.h
>>> +++ b/include/hw/arm/smmu-common.h
>>> @@ -162,6 +162,10 @@ struct SMMUState {
>>> uint8_t bus_num;
>>> PCIBus *primary_bus;
>>> bool smmu_per_bus; /* SMMU is specific to the primary_bus */
>>> + MemoryRegion *memory;
>>> + AddressSpace memory_as;
>>> + MemoryRegion *secure_memory;
>>> + AddressSpace secure_memory_as;
>>> };
>>> struct SMMUBaseClass {
>>> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
>>> index c77a33f6df2..d3743810338 100644
>>> --- a/include/hw/arm/virt.h
>>> +++ b/include/hw/arm/virt.h
>>> @@ -180,6 +180,8 @@ struct VirtMachineState {
>>> bool ns_el2_virt_timer_irq;
>>> CXLState cxl_devices_state;
>>> bool legacy_smmuv3_present;
>>> + MemoryRegion *sysmem;
>>> + MemoryRegion *secure_sysmem;
>>> };
>>> #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM :
>>> VIRT_PCIE_ECAM)
>>> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
>>> index 2205500a8da..cc9d4385826 100644
>>> --- a/hw/arm/sbsa-ref.c
>>> +++ b/hw/arm/sbsa-ref.c
>>> @@ -613,7 +613,9 @@ static void create_xhci(const SBSAMachineState
>>> *sms)
>>> sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
>>> qdev_get_gpio_in(sms->gic, irq));
>>> }
>>> -static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
>>> +static void create_smmu(const SBSAMachineState *sms, PCIBus *bus,
>>> + MemoryRegion *sysmem,
>>> + MemoryRegion *secure_sysmem)
>>> {
>>> hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
>>> int irq = sbsa_ref_irqmap[SBSA_SMMU];
>>> @@ -625,6 +627,10 @@ static void create_smmu(const SBSAMachineState
>>> *sms, PCIBus *bus)
>>> object_property_set_str(OBJECT(dev), "stage", "nested",
>>> &error_abort);
>>> object_property_set_link(OBJECT(dev), "primary-bus",
>>> OBJECT(bus),
>>> &error_abort);
>>> + object_property_set_link(OBJECT(dev), "memory", OBJECT(sysmem),
>>> + &error_abort);
>>> + object_property_set_link(OBJECT(dev), "secure-memory",
>>> OBJECT(secure_sysmem),
>>
>>
>> ......
>>
>>> + &error_abort);
>>> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>>> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
>>> for (i = 0; i < NUM_SMMU_IRQS; i++) {
>>> @@ -633,7 +639,9 @@ static void create_smmu(const SBSAMachineState
>>> *sms, PCIBus *bus)
>>> }
>>> }
>>> -static void create_pcie(SBSAMachineState *sms)
>>> +static void create_pcie(SBSAMachineState *sms,
>>> + MemoryRegion *sysmem,
>>> + MemoryRegion *secure_sysmem)
>>> {
>>> hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
>>> hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
>>> @@ -689,7 +697,7 @@ static void create_pcie(SBSAMachineState *sms)
>>> pci_create_simple(pci->bus, -1, "bochs-display");
>>> - create_smmu(sms, pci->bus);
>>> + create_smmu(sms, pci->bus, sysmem, secure_sysmem);
>>> }
>>> static void *sbsa_ref_dtb(const struct arm_boot_info *binfo,
>>> int *fdt_size)
>>> @@ -825,7 +833,7 @@ static void sbsa_ref_init(MachineState *machine)
>>> create_xhci(sms);
>>> - create_pcie(sms);
>>> + create_pcie(sms, sysmem, secure_sysmem);
>>> create_secure_ec(secure_sysmem);
>>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>>> index 62a76121841..9a67ce857fe 100644
>>> --- a/hw/arm/smmu-common.c
>>> +++ b/hw/arm/smmu-common.c
>>> @@ -944,6 +944,13 @@ static void smmu_base_realize(DeviceState *dev,
>>> Error **errp)
>>> return;
>>> }
>>> + g_assert(s->memory);
>>> + address_space_init(&s->memory_as, s->memory, "smmu-memory-view");
>>> + if (s->secure_memory) {
>>> + address_space_init(&s->secure_memory_as, s->secure_memory,
>>> + "smmu-secure-memory-view");
>>> + }
>>> +
>>> /*
>>> * We only allow default PCIe Root Complex(pcie.0) or
>>> pxb-pcie based extra
>>> * root complexes to be associated with SMMU.
>>> @@ -1008,10 +1015,28 @@ static void smmu_base_class_init(ObjectClass
>>> *klass, const void *data)
>>> rc->phases.exit = smmu_base_reset_exit;
>>> }
>>> +static void smmu_base_instance_init(Object *obj)
>>> +{
>>> + SMMUState *s = ARM_SMMU(obj);
>>> +
>>> + object_property_add_link(obj, "memory",
>>> + TYPE_MEMORY_REGION,
>>> + (Object **)&s->memory,
>>> + qdev_prop_allow_set_link_before_realize,
>>> + OBJ_PROP_LINK_STRONG);
>>> +
>>> + object_property_add_link(obj, "secure-memory",
>>> + TYPE_MEMORY_REGION,
>>> + (Object **)&s->secure_memory,
>>> + qdev_prop_allow_set_link_before_realize,
>>> + OBJ_PROP_LINK_STRONG);
>>> +}
>>> +
>>> static const TypeInfo smmu_base_info = {
>>> .name = TYPE_ARM_SMMU,
>>> .parent = TYPE_SYS_BUS_DEVICE,
>>> .instance_size = sizeof(SMMUState),
>>> + .instance_init = smmu_base_instance_init,
>>> .class_data = NULL,
>>> .class_size = sizeof(SMMUBaseClass),
>>> .class_init = smmu_base_class_init,
>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>> index 25fb2bab568..603f4b6a1d7 100644
>>> --- a/hw/arm/virt.c
>>> +++ b/hw/arm/virt.c
>>> @@ -1514,8 +1514,7 @@ static void
>>> create_smmuv3_dev_dtb(VirtMachineState *vms,
>>> 0x0, vms->iommu_phandle, 0x0, 0x10000);
>>> }
>>> -static void create_smmu(const VirtMachineState *vms,
>>> - PCIBus *bus)
>>> +static void create_smmu(const VirtMachineState *vms, PCIBus *bus)
>>> {
>>> VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>>> int irq = vms->irqmap[VIRT_SMMU];
>>> @@ -1535,6 +1534,10 @@ static void create_smmu(const
>>> VirtMachineState *vms,
>>> }
>>> object_property_set_link(OBJECT(dev), "primary-bus",
>>> OBJECT(bus),
>>> &error_abort);
>>> + object_property_set_link(OBJECT(dev), "memory",
>>> OBJECT(vms->sysmem),
>>> + &error_abort);
>>> + object_property_set_link(OBJECT(dev), "secure-memory",
>>> OBJECT(vms->secure_sysmem),
>>> + &error_abort);
>>
>>
>> I noticed this line is over 80 characters and the corresponding one in
>> hw/arm/sbsa-ref.c also seems to exceed 80 characters. I’m not fully sure
>> whether QEMU expects us to strictly keep every line under 80 characters,
>> but when I ran scripts/checkpatch.pl I did see two warnings.
>>
>
> Thanks for reporting, it's a warning, not a hard error (90 char).
> From what I understood, I think it's ok to go over a few characters
> for cases like this, to keep code with same layout as lines around.
yes as long as it is a warning it is OK
Thanks
Eric
>
>>
>> ```
>>
>> WARNING: line over 80 characters
>> #47: FILE: hw/arm/sbsa-ref.c:632:
>> + object_property_set_link(OBJECT(dev), "secure-memory",
>> OBJECT(secure_sysmem),
>>
>> WARNING: line over 80 characters
>> #148: FILE: hw/arm/virt.c:1539:
>> + object_property_set_link(OBJECT(dev), "secure-memory",
>> OBJECT(vms->secure_sysmem),
>>
>> total: 0 errors, 2 warnings, 148 lines checked
>>
>> ```
>>
>>
>> Just flagging this in case you’d like to adjust it before the next
>> revision.
>>
>>
>> Besides, I tested the SMMU-related MemoryRegion and AddressSpace
>> instantiation for both user-creatable and machine-wide SMMUv3 devices.
>> As shown in the info mtree output below, everything looks fine on my
>> side.
>>
>>
>> ```
>>
>> (QEMU) info mtree
>> address-space: cpu-secure-memory-0
>> address-space: smmu-secure-memory-view
>> 0000000000000000-ffffffffffffffff (prio 0, i/o): secure-memory
>> 0000000000000000-0000000003ffffff (prio 0, romd): virt.flash0
>>
>> ....
>>
>> address-space: cpu-memory-0
>> address-space: gicv3-its-sysmem
>> address-space: memory
>> address-space: smmu-memory-view
>> 0000000000000000-ffffffffffffffff (prio -1, i/o): system
>> 0000000004000000-0000000007ffffff (prio 0, romd): virt.flash1
>> 0000000008000000-000000000800ffff (prio 0, i/o): gicv3_dist
>>
>> ```
>>
>
> Thanks for testing :)!
>
>>
>>
>> Regards,
>> Tao
>>
>>> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>>> sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
>>> for (i = 0; i < NUM_SMMU_IRQS; i++) {
>>> @@ -1609,6 +1612,7 @@ static void create_pcie(VirtMachineState *vms)
>>> memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
>>> ecam_reg, 0, size_ecam);
>>> memory_region_add_subregion(get_system_memory(), base_ecam,
>>> ecam_alias);
>>> + vms->sysmem = get_system_memory();
>>> /* Map the MMIO window into system address space so as to
>>> expose
>>> * the section of PCI MMIO space which starts at the same
>>> base address
>>> @@ -2256,6 +2260,7 @@ static void machvirt_init(MachineState *machine)
>>> * devices go in at higher priority and take precedence.
>>> */
>>> secure_sysmem = g_new(MemoryRegion, 1);
>>> + vms->secure_sysmem = secure_sysmem;
>>> memory_region_init(secure_sysmem, OBJECT(machine),
>>> "secure-memory",
>>> UINT64_MAX);
>>> memory_region_add_subregion_overlap(secure_sysmem, 0,
>>> sysmem, -1);
>>> @@ -3051,6 +3056,10 @@ static void
>>> virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
>>> } else if (vms->iommu == VIRT_IOMMU_NONE) {
>>> /* The new SMMUv3 device is specific to the PCI bus */
>>> object_property_set_bool(OBJECT(dev), "smmu_per_bus",
>>> true, NULL);
>>> + object_property_set_link(OBJECT(dev), "memory",
>>> + OBJECT(vms->sysmem), NULL);
>>> + object_property_set_link(OBJECT(dev), "secure-memory",
>>> + OBJECT(vms->secure_sysmem),
>>> NULL);
>>> }
>>> }
>>> }
>>
>
> Cheers,
> Pierrick
>
On 12/16/25 3:57 PM, Pierrick Bouvier wrote:
> This will be used to access non-secure and secure memory. Secure support
> and Granule Protection Check (for RME) for SMMU need to access secure
> memory.
>
> As well, it allows to remove usage of global address_space_memory,
> allowing different SMMU instances to have a specific view of memory.
>
> User creatable SMMU are handled as well for virt machine,
> by setting the memory properties when device is plugged in.
>
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> ---
> include/hw/arm/smmu-common.h | 4 ++++
> include/hw/arm/virt.h | 2 ++
> hw/arm/sbsa-ref.c | 16 ++++++++++++----
> hw/arm/smmu-common.c | 25 +++++++++++++++++++++++++
> hw/arm/virt.c | 13 +++++++++++--
> 5 files changed, 54 insertions(+), 6 deletions(-)
v4
--
- set smmu->memory property based on plug callback for virt, thus
removing the need to use global get_system_memory on smmu side.
v3
--
- solved issue with user creatable smmuv3 (found with
qtest/bios-tables-test, subtest smmuv3-dev), which is not created by
board file. In this case, smmu->memory is not set, so just use global
get_system_memory() instead.
v2
--
- Fix rebase on top of master
- rename memory and secure-memory address space with
"smmu-memory-view" and "smmu-secure-memory-view".
If someone prefers any other name, I can change it.
© 2016 - 2026 Red Hat, Inc.