On 3/10/2026 12:42 AM, Cédric Le Goater wrote:

Subsequent patches will make use of this helper to set the
values when we convert the values to OnOffAuto. New auto_mode
and auto_finalised bool members are added to SMMUv3AccelState.
smmuv3_accel_init() will set auto_mode to true when 'auto' is
detected for the accel SMMUv3 properties.
smmuv3_accel_auto_finalise() will set auto_finalised to true
after all 'auto' properties are resolved, and subsequent
calls to this function will return early if auto_finalised is
set to true.

Suggested-by: Shameer Kolothum <[email protected]>
Signed-off-by: Nathan Chen <[email protected]>
---
  hw/arm/smmuv3-accel.c | 38 +++++++++++++++++++++++++++++++++-----
  hw/arm/smmuv3-accel.h |  2 ++
  2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
index 17306cd04b..617629bacd 100644
--- a/hw/arm/smmuv3-accel.c
+++ b/hw/arm/smmuv3-accel.c
@@ -35,11 +35,34 @@ static int smmuv3_oas_bits(uint32_t oas)
      return map[oas];
  }
+static void smmuv3_accel_auto_finalise(SMMUv3State *s, PCIDevice *pdev,
+                                       struct iommu_hw_info_arm_smmuv3 *info) {
+    SMMUv3AccelState *accel = s->s_accel;
+
+    /* Return if no auto for any or finalised already */
+    if (!accel->auto_mode || accel->auto_finalised) {
+        return;
+    }
+
+    /* We can't update if device is hotplugged */
+    if (DEVICE(pdev)->hotplugged) {
+        warn_report("arm-smmuv3: 'auto' feature property detected, but host " +                    "value cannot be applied for hot-plugged device; using "
+                    "existing value");

Please add an 'Error **' parameter instead.

Ok, if we decide to keep this hotplug check I will use the 'Error **' parameter instead here in the next revision. Per Shameer's reply to Markus on this patch, we may end up removing this check as we plan to fail boot if auto_mode is set but auto_finalised is still false from the lack of a cold-plugged device.


+        return;
+    }
+
+    accel->auto_finalised = true;
+}
+
  static bool
  smmuv3_accel_check_hw_compatible(SMMUv3State *s,
                                   struct iommu_hw_info_arm_smmuv3 *info,
+                                 PCIDevice *pdev,
                                   Error **errp)
  {
+    smmuv3_accel_auto_finalise(s, pdev, info);
+
      /* QEMU SMMUv3 supports both linear and 2-level stream tables */
      if (FIELD_EX32(info->idr[0], IDR0, STLEVEL) !=
                  FIELD_EX32(s->idr[0], IDR0, STLEVEL)) {
@@ -124,7 +147,7 @@ smmuv3_accel_check_hw_compatible(SMMUv3State *s,
  static bool
  smmuv3_accel_hw_compatible(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev,
-                           Error **errp)
+                           PCIDevice *pdev, Error **errp)
  {
      struct iommu_hw_info_arm_smmuv3 info;
      uint32_t data_type;
@@ -142,7 +165,7 @@ smmuv3_accel_hw_compatible(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev,
          return false;
      }
-    if (!smmuv3_accel_check_hw_compatible(s, &info, errp)) {
+    if (!smmuv3_accel_check_hw_compatible(s, &info, pdev, errp)) {
          return false;
      }
      return true;
@@ -595,6 +618,7 @@ static bool smmuv3_accel_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
      SMMUv3State *s = ARM_SMMUV3(bs);
      SMMUPciBus *sbus = smmu_get_sbus(bs, bus);
      SMMUv3AccelDevice *accel_dev = smmuv3_accel_get_dev(bs, sbus, bus, devfn);
+    PCIDevice *pdev = pci_find_device(bus, pci_bus_num(bus), devfn);
      if (!idev) {
          return true;
@@ -613,7 +637,7 @@ static bool smmuv3_accel_set_iommu_device(PCIBus *bus, void *opaque, int devfn,        * Check the host SMMUv3 associated with the dev is compatible with the
       * QEMU SMMUv3 accel.
       */
-    if (!smmuv3_accel_hw_compatible(s, idev, errp)) {
+    if (!smmuv3_accel_hw_compatible(s, idev, pdev, errp)) {
          return false;
      }
@@ -867,8 +891,12 @@ bool smmuv3_accel_attach_gbpa_hwpt(SMMUv3State *s, Error **errp)
  void smmuv3_accel_reset(SMMUv3State *s)
  {
-     /* Attach a HWPT based on GBPA reset value */
-     smmuv3_accel_attach_gbpa_hwpt(s, NULL);
+    if (s->s_accel && s->s_accel->auto_mode && !s->s_accel- >auto_finalised) { +        error_report("AUTO mode specified but properties not finalised.");

This is not a very friendly message for the user.

Agreed, instead of 'properties not finalised' we will note that the properties were not introspected from host IDR registers, and that a cold-plugged device attached to the SMMUv3 must be present to do so.

Thanks,
Nathan

Reply via email to