Hi Eric,

On 8/31/2026 4:22 PM, Eric Auger wrote:
Hi Tao,

On 8/13/26 6:26 PM, Tao Tang wrote:
Parse each PCI device's sec-sid property during SMMU device initialization
and cache it in SMMUDevice::sec_sid. Support "non-secure" and "secure",
default to non-secure when unspecified, and reject invalid values with an
explicit error. Use sdev->sec_sid in smmuv3_translate() to select the
register bank instead of hardcoding the non-secure context.

Keep sec-sid parsing in smmu-common, and add a SMMUv3-specific validation
hook to enforce architectural constraints: fail fast when sec-sid=secure
while SMMU_S_IDR1.SECURE_IMPL is 0 or secure AS is not available.

Typically, SEC_SID is a system-defined attribute (e.g. sideband or tied-off)
rather than something a PCIe endpoint can freely toggle in pre-RME scenario.
So this PCI sec-sid property is used as a static platform/testing knob to
drive the SMMU bank selection.

For future RME-DA and TDISP support, this static property will need to be
replaced by runtime platform plumbing that derives the effective SEC_SID
from the device security assignment.

Signed-off-by: Tao Tang <[email protected]>
Reviewed-by: Pierrick Bouvier <[email protected]>
---
  hw/arm/smmu-common.c         | 37 ++++++++++++++++++++++
  hw/arm/smmuv3.c              | 61 +++++++++++++++++++++++++++++++++++-
  include/hw/arm/smmu-common.h |  2 ++
  3 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index e8a1ed65c19..4a94799fb0d 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -21,6 +21,7 @@
  #include "exec/target_page.h"
  #include "hw/core/cpu.h"
  #include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_device.h"
  #include "hw/core/qdev-properties.h"
  #include "qapi/error.h"
  #include "qemu/jhash.h"
@@ -1100,14 +1101,50 @@ SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t 
bus_num)
      return NULL;
  }
+static SMMUSecSID smmu_parse_pci_sec_sid(PCIDevice *pdev, int bus_num,
+                                         int devfn)
+{
+    const char *sec_sid;
+
+    if (!pdev || !pdev->sec_sid) {
+        return SMMU_SEC_SID_NS;
+    }
+
+    sec_sid = pdev->sec_sid;
+    if (!strcmp(sec_sid, "non-secure")) {
+        return SMMU_SEC_SID_NS;
+    }
else if?
+    if (!strcmp(sec_sid, "secure")) {
+        return SMMU_SEC_SID_S;
+    }
+
+    error_report("Invalid sec-sid value '%s' for PCI device %02x:%02x.%x; "
+                 "allowed values: non-secure or secure (case-sensitive)",
To me this is not the place where pci property validation should happen.
This should happen in the pcie device instead, on property setting.
I've moved sec-sid value validation to the PCI property setter and simplified the SMMU-side conversion.
+                 sec_sid, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+    exit(EXIT_FAILURE);
+}
+
  void smmu_init_sdev(SMMUState *s, SMMUDevice *sdev, PCIBus *bus, int devfn)
  {
      static unsigned int index;
      g_autofree char *name = g_strdup_printf("%s-%d-%d", s->mrtypename, devfn,
                                              index++);
+    SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(s);
+    PCIDevice *pdev;
+    int bus_num;
+
      sdev->smmu = s;
      sdev->bus = bus;
      sdev->devfn = devfn;
+    sdev->sec_sid = SMMU_SEC_SID_NS;
do we need this init? smmu_parse_pci_sec_sid() already implements the
default.
Yes this should be removed.
+
+    bus_num = pci_bus_num(bus);
+    pdev = pci_find_device(bus, bus_num, devfn);
+    sdev->sec_sid = smmu_parse_pci_sec_sid(pdev, bus_num, devfn);
+    if (sbc->validate_sec_sid &&
+        !sbc->validate_sec_sid(s, sdev, bus_num)) {
+        exit(EXIT_FAILURE);
The problem is any attempt to hotplu a secure device will exit QEMU.
I wonder if we shouldn't implement a PCIIOMMUOps that detects the
incompatibility.
Maybe supports_address_space() could do that. At the moment it is used
to check accel mode only but another implementation could check secure
compatibility I think. The advantage is this callback passes an errp.
Thanks for the advice. I'll add a new smmu_supports_address_space() callback to smmu_ops to check Secure compatibility and propagate errors through errp, so incompatible hotplug requests won't terminate QEMU.

static const PCIIOMMUOps smmu_ops = {
    .supports_address_space = smmu_supports_address_space,
    .get_address_space = smmu_find_add_as,
};
+    }
memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu),
                               s->mrtypename, OBJECT(s), name, UINT64_MAX);
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index e5f0bc18415..a755f1ebd69 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -43,6 +43,12 @@
                                          ((ptw_info).stage == SMMU_STAGE_2 && \
                                          (cfg)->s2cfg.record_faults))
+enum {
+    SMMU_IOMMU_IDX_NS,
+    SMMU_IOMMU_IDX_S,
+    SMMU_IOMMU_IDX_NUM,
+};
why do we need another enum, can't we reuse SMMUSecSID?
......
------------------------------<snip>------------------------------



------------------------------<snip>------------------------------
      object_class_property_set_description(klass, "accel",
          "Enable SMMUv3 accelerator support. Allows host SMMUv3 to be "
@@ -2905,6 +2962,8 @@ static void 
smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
imrc->translate = smmuv3_translate;
      imrc->notify_flag_changed = smmuv3_notify_flag_changed;
+    imrc->attrs_to_index = smmuv3_attrs_to_index;
+    imrc->num_indexes = smmuv3_num_indexes;
Why do we need the above ops? Isn't it generic enough to stay in smmu
base code?

In v6, I'll drop SMMU_IOMMU_IDX_* and reuse the SMMU_SEC_SID_* constants. I'll also move the attrs_to_index() and num_indexes() implementations to smmu-common.c/.h with function renamed to smmu_*.


Best regards,

Tao


Reply via email to