[PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID enable

Shameer Kolothum posted 27 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID enable
Posted by Shameer Kolothum 1 month, 2 weeks ago
QEMU SMMUv3 currently forces SSID (Substream ID) to zero. One key use case
for accelerated mode is Shared Virtual Addressing (SVA), which requires
SSID support so the guest can maintain multiple context descriptors per
substream ID.

Provide an option for user to enable PASID support. A SSIDSIZE of 16
is currently used as default.

Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
 hw/arm/smmuv3-accel.c    | 24 +++++++++++++++++++++++-
 hw/arm/smmuv3-internal.h |  1 +
 hw/arm/smmuv3.c          |  8 +++++++-
 include/hw/arm/smmuv3.h  |  1 +
 4 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
index 283d36e6cd..0de9598dcb 100644
--- a/hw/arm/smmuv3-accel.c
+++ b/hw/arm/smmuv3-accel.c
@@ -79,6 +79,13 @@ smmuv3_accel_check_hw_compatible(SMMUv3State *s,
         return false;
     }
 
+    /* If user enables PASID support(pasid=on), QEMU sets SSIDSIZE to 16 */
+    val = FIELD_EX32(info->idr[1], IDR1, SSIDSIZE);
+    if (val < FIELD_EX32(s->idr[1], IDR1, SSIDSIZE)) {
+        error_setg(errp, "Host SUMMUv3 SSIDSIZE not compatible");
+        return false;
+    }
+
     /* User can override QEMU SMMUv3 Range Invalidation support */
     val = FIELD_EX32(info->idr[3], IDR3, RIL);
     if (val != FIELD_EX32(s->idr[3], IDR3, RIL)) {
@@ -635,7 +642,14 @@ static uint64_t smmuv3_accel_get_viommu_flags(void *opaque)
      * The real HW nested support should be reported from host SMMUv3 and if
      * it doesn't, the nesting parent allocation will fail anyway in VFIO core.
      */
-    return VIOMMU_FLAG_WANT_NESTING_PARENT;
+    uint64_t flags = VIOMMU_FLAG_WANT_NESTING_PARENT;
+    SMMUState *bs = opaque;
+    SMMUv3State *s = ARM_SMMUV3(bs);
+
+    if (s->pasid) {
+        flags |= VIOMMU_FLAG_PASID_SUPPORTED;
+    }
+    return flags;
 }
 
 static const PCIIOMMUOps smmuv3_accel_ops = {
@@ -664,6 +678,14 @@ void smmuv3_accel_idr_override(SMMUv3State *s)
     if (s->oas == 48) {
         s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS_48);
     }
+
+    /*
+     * By default QEMU SMMUv3 has no PASID(SSID) support. Update IDR1 if user
+     * has enabled it.
+     */
+    if (s->pasid) {
+        s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SSIDSIZE, SMMU_IDR1_SSIDSIZE);
+    }
 }
 
 /*
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index 910a34e05b..38e9da245b 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -81,6 +81,7 @@ REG32(IDR1,                0x4)
     FIELD(IDR1, ECMDQ,        31, 1)
 
 #define SMMU_IDR1_SIDSIZE 16
+#define SMMU_IDR1_SSIDSIZE 16
 #define SMMU_CMDQS   19
 #define SMMU_EVENTQS 19
 
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 7c391ab711..f7a1635ec7 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -604,7 +604,8 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
         }
     }
 
-    if (STE_S1CDMAX(ste) != 0) {
+    /* If pasid enabled, we report SSIDSIZE = 16 */
+    if (!FIELD_EX32(s->idr[1], IDR1, SSIDSIZE) && STE_S1CDMAX(ste) != 0) {
         qemu_log_mask(LOG_UNIMP,
                       "SMMUv3 does not support multiple context descriptors yet\n");
         goto bad_ste;
@@ -1962,6 +1963,10 @@ static bool smmu_validate_property(SMMUv3State *s, Error **errp)
         error_setg(errp, "oas can only be set to 44 bits if accel=off");
         return false;
     }
+    if (s->pasid) {
+        error_setg(errp, "pasid can only be enabled if accel=on");
+        return false;
+    }
     return true;
 }
 
@@ -2088,6 +2093,7 @@ static const Property smmuv3_properties[] = {
     DEFINE_PROP_BOOL("ril", SMMUv3State, ril, true),
     DEFINE_PROP_BOOL("ats", SMMUv3State, ats, false),
     DEFINE_PROP_UINT8("oas", SMMUv3State, oas, 44),
+    DEFINE_PROP_BOOL("pasid", SMMUv3State, pasid, false),
 };
 
 static void smmuv3_instance_init(Object *obj)
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
index d3788b2d85..3781b79fc8 100644
--- a/include/hw/arm/smmuv3.h
+++ b/include/hw/arm/smmuv3.h
@@ -71,6 +71,7 @@ struct SMMUv3State {
     bool ril;
     bool ats;
     uint8_t oas;
+    bool pasid;
 };
 
 typedef enum {
-- 
2.43.0
Re: [PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID enable
Posted by Eric Auger 2 weeks, 4 days ago
Hi Shameer,

On 9/29/25 3:36 PM, Shameer Kolothum wrote:
> QEMU SMMUv3 currently forces SSID (Substream ID) to zero. One key use case
> for accelerated mode is Shared Virtual Addressing (SVA), which requires
> SSID support so the guest can maintain multiple context descriptors per
> substream ID.
>
> Provide an option for user to enable PASID support. A SSIDSIZE of 16
> is currently used as default.
>
> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
> ---
>  hw/arm/smmuv3-accel.c    | 24 +++++++++++++++++++++++-
>  hw/arm/smmuv3-internal.h |  1 +
>  hw/arm/smmuv3.c          |  8 +++++++-
>  include/hw/arm/smmuv3.h  |  1 +
>  4 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
> index 283d36e6cd..0de9598dcb 100644
> --- a/hw/arm/smmuv3-accel.c
> +++ b/hw/arm/smmuv3-accel.c
> @@ -79,6 +79,13 @@ smmuv3_accel_check_hw_compatible(SMMUv3State *s,
>          return false;
>      }
>  
> +    /* If user enables PASID support(pasid=on), QEMU sets SSIDSIZE to 16 */
> +    val = FIELD_EX32(info->idr[1], IDR1, SSIDSIZE);
> +    if (val < FIELD_EX32(s->idr[1], IDR1, SSIDSIZE)) {
> +        error_setg(errp, "Host SUMMUv3 SSIDSIZE not compatible");
> +        return false;
> +    }
> +
>      /* User can override QEMU SMMUv3 Range Invalidation support */
>      val = FIELD_EX32(info->idr[3], IDR3, RIL);
>      if (val != FIELD_EX32(s->idr[3], IDR3, RIL)) {
> @@ -635,7 +642,14 @@ static uint64_t smmuv3_accel_get_viommu_flags(void *opaque)
>       * The real HW nested support should be reported from host SMMUv3 and if
>       * it doesn't, the nesting parent allocation will fail anyway in VFIO core.
>       */
> -    return VIOMMU_FLAG_WANT_NESTING_PARENT;
> +    uint64_t flags = VIOMMU_FLAG_WANT_NESTING_PARENT;
> +    SMMUState *bs = opaque;
> +    SMMUv3State *s = ARM_SMMUV3(bs);
> +
> +    if (s->pasid) {
> +        flags |= VIOMMU_FLAG_PASID_SUPPORTED;
> +    }
> +    return flags;
>  }
>  
>  static const PCIIOMMUOps smmuv3_accel_ops = {
> @@ -664,6 +678,14 @@ void smmuv3_accel_idr_override(SMMUv3State *s)
>      if (s->oas == 48) {
>          s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS_48);
>      }
> +
> +    /*
> +     * By default QEMU SMMUv3 has no PASID(SSID) support. Update IDR1 if user
> +     * has enabled it.
> +     */
> +    if (s->pasid) {
> +        s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SSIDSIZE, SMMU_IDR1_SSIDSIZE);
> +    }
>  }
>  
>  /*
> diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
> index 910a34e05b..38e9da245b 100644
> --- a/hw/arm/smmuv3-internal.h
> +++ b/hw/arm/smmuv3-internal.h
> @@ -81,6 +81,7 @@ REG32(IDR1,                0x4)
>      FIELD(IDR1, ECMDQ,        31, 1)
>  
>  #define SMMU_IDR1_SIDSIZE 16
> +#define SMMU_IDR1_SSIDSIZE 16
>  #define SMMU_CMDQS   19
>  #define SMMU_EVENTQS 19
>  
> diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> index 7c391ab711..f7a1635ec7 100644
> --- a/hw/arm/smmuv3.c
> +++ b/hw/arm/smmuv3.c
> @@ -604,7 +604,8 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
>          }
>      }
>  
> -    if (STE_S1CDMAX(ste) != 0) {
> +    /* If pasid enabled, we report SSIDSIZE = 16 */
why do we chose 16 and not a bigger value to avoid incompatibility?
worth a comment
> +    if (!FIELD_EX32(s->idr[1], IDR1, SSIDSIZE) && STE_S1CDMAX(ste) != 0) {
>          qemu_log_mask(LOG_UNIMP,
>                        "SMMUv3 does not support multiple context descriptors yet\n");
>          goto bad_ste;
> @@ -1962,6 +1963,10 @@ static bool smmu_validate_property(SMMUv3State *s, Error **errp)
>          error_setg(errp, "oas can only be set to 44 bits if accel=off");
>          return false;
>      }
> +    if (s->pasid) {
> +        error_setg(errp, "pasid can only be enabled if accel=on");
> +        return false;
> +    }
>      return true;
>  }
Just skimming though the SMMU spec, I don't see any handling for
STE.S1DSS anywhere
Also I would expect some C_BAD_SUBSTREAMID likely to be emitted?

Thanks

Eric
>  
> @@ -2088,6 +2093,7 @@ static const Property smmuv3_properties[] = {
>      DEFINE_PROP_BOOL("ril", SMMUv3State, ril, true),
>      DEFINE_PROP_BOOL("ats", SMMUv3State, ats, false),
>      DEFINE_PROP_UINT8("oas", SMMUv3State, oas, 44),
> +    DEFINE_PROP_BOOL("pasid", SMMUv3State, pasid, false),
>  };
>  
>  static void smmuv3_instance_init(Object *obj)
> diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
> index d3788b2d85..3781b79fc8 100644
> --- a/include/hw/arm/smmuv3.h
> +++ b/include/hw/arm/smmuv3.h
> @@ -71,6 +71,7 @@ struct SMMUv3State {
>      bool ril;
>      bool ats;
>      uint8_t oas;
> +    bool pasid;
>  };
>  
>  typedef enum {
RE: [PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID enable
Posted by Shameer Kolothum 2 weeks, 4 days ago
Hi Eric,

> -----Original Message-----
> From: Eric Auger <eric.auger@redhat.com>
> Sent: 27 October 2025 18:15
> To: Shameer Kolothum <skolothumtho@nvidia.com>; qemu-
> arm@nongnu.org; qemu-devel@nongnu.org
> Cc: peter.maydell@linaro.org; Jason Gunthorpe <jgg@nvidia.com>; Nicolin
> Chen <nicolinc@nvidia.com>; ddutile@redhat.com; berrange@redhat.com;
> Nathan Chen <nathanc@nvidia.com>; Matt Ochs <mochs@nvidia.com>;
> smostafa@google.com; wangzhou1@hisilicon.com;
> jiangkunkun@huawei.com; jonathan.cameron@huawei.com;
> zhangfei.gao@linaro.org; zhenzhong.duan@intel.com; yi.l.liu@intel.com;
> shameerkolothum@gmail.com
> Subject: Re: [PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID
> enable
> 
> External email: Use caution opening links or attachments
> 
> 
> Hi Shameer,

[..]

> > -    if (STE_S1CDMAX(ste) != 0) {
> > +    /* If pasid enabled, we report SSIDSIZE = 16 */
> why do we chose 16 and not a bigger value to avoid incompatibility?
> worth a comment

I am not sure what a good value here to support most hardware out there.
If we select a bigger value, anything less can't be supported.

> > +    if (!FIELD_EX32(s->idr[1], IDR1, SSIDSIZE) && STE_S1CDMAX(ste) !=
> > + 0) {
> >          qemu_log_mask(LOG_UNIMP,
> >                        "SMMUv3 does not support multiple context descriptors
> yet\n");
> >          goto bad_ste;
> > @@ -1962,6 +1963,10 @@ static bool
> smmu_validate_property(SMMUv3State *s, Error **errp)
> >          error_setg(errp, "oas can only be set to 44 bits if accel=off");
> >          return false;
> >      }
> > +    if (s->pasid) {
> > +        error_setg(errp, "pasid can only be enabled if accel=on");
> > +        return false;
> > +    }
> >      return true;
> >  }
> Just skimming though the SMMU spec, I don't see any handling for STE.S1DSS
> anywhere Also I would expect some C_BAD_SUBSTREAMID likely to be
> emitted?

S1DSS is passed down to host kernel during S1 translate HWPT install. And if
anything is mis configured w.r.t CD by Guest, the host SMMUv3 will generate
the events.

Do we need to check S1DSS in here?

Thanks,
Shameer

Re: [PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID enable
Posted by Eric Auger 2 weeks, 3 days ago
Hi Shameer,

On 10/27/25 7:40 PM, Shameer Kolothum wrote:
> Hi Eric,
>
>> -----Original Message-----
>> From: Eric Auger <eric.auger@redhat.com>
>> Sent: 27 October 2025 18:15
>> To: Shameer Kolothum <skolothumtho@nvidia.com>; qemu-
>> arm@nongnu.org; qemu-devel@nongnu.org
>> Cc: peter.maydell@linaro.org; Jason Gunthorpe <jgg@nvidia.com>; Nicolin
>> Chen <nicolinc@nvidia.com>; ddutile@redhat.com; berrange@redhat.com;
>> Nathan Chen <nathanc@nvidia.com>; Matt Ochs <mochs@nvidia.com>;
>> smostafa@google.com; wangzhou1@hisilicon.com;
>> jiangkunkun@huawei.com; jonathan.cameron@huawei.com;
>> zhangfei.gao@linaro.org; zhenzhong.duan@intel.com; yi.l.liu@intel.com;
>> shameerkolothum@gmail.com
>> Subject: Re: [PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID
>> enable
>>
>> External email: Use caution opening links or attachments
>>
>>
>> Hi Shameer,
> [..]
>
>>> -    if (STE_S1CDMAX(ste) != 0) {
>>> +    /* If pasid enabled, we report SSIDSIZE = 16 */
>> why do we chose 16 and not a bigger value to avoid incompatibility?
>> worth a comment
> I am not sure what a good value here to support most hardware out there.
> If we select a bigger value, anything less can't be supported.
ah yes you're right, that's the opposite. this is aligned with sid size
anyway so let's keep it as is.
>
>>> +    if (!FIELD_EX32(s->idr[1], IDR1, SSIDSIZE) && STE_S1CDMAX(ste) !=
>>> + 0) {
>>>          qemu_log_mask(LOG_UNIMP,
>>>                        "SMMUv3 does not support multiple context descriptors
>> yet\n");
>>>          goto bad_ste;
>>> @@ -1962,6 +1963,10 @@ static bool
>> smmu_validate_property(SMMUv3State *s, Error **errp)
>>>          error_setg(errp, "oas can only be set to 44 bits if accel=off");
>>>          return false;
>>>      }
>>> +    if (s->pasid) {
>>> +        error_setg(errp, "pasid can only be enabled if accel=on");
>>> +        return false;
>>> +    }
>>>      return true;
>>>  }
>> Just skimming though the SMMU spec, I don't see any handling for STE.S1DSS
>> anywhere Also I would expect some C_BAD_SUBSTREAMID likely to be
>> emitted?
> S1DSS is passed down to host kernel during S1 translate HWPT install. And if
> anything is mis configured w.r.t CD by Guest, the host SMMUv3 will generate
> the events.
OK
>
> Do we need to check S1DSS in here?

about C_BAD_SUBSTREAMID it is likely to be returned through events by
the host. I see it handled in smmuv3_record_event() so maybe that's
enough with accel.

Eric
>
> Thanks,
> Shameer
>
Re: [PATCH v4 27/27] hw.arm/smmuv3: Add support for PASID enable
Posted by Jonathan Cameron via 1 month, 2 weeks ago
On Mon, 29 Sep 2025 14:36:43 +0100
Shameer Kolothum <skolothumtho@nvidia.com> wrote:

> QEMU SMMUv3 currently forces SSID (Substream ID) to zero. One key use case
> for accelerated mode is Shared Virtual Addressing (SVA), which requires
> SSID support so the guest can maintain multiple context descriptors per
> substream ID.
> 
> Provide an option for user to enable PASID support. A SSIDSIZE of 16
> is currently used as default.
> 
> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>

Some follow through from comments in earlier patches, but in general LGTM
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>