Hi Shameer,
On 10/31/25 11:50 AM, 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.
>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
> ---
> hw/arm/smmuv3-accel.c | 23 ++++++++++++++++++++++-
> hw/arm/smmuv3-internal.h | 1 +
> hw/arm/smmuv3.c | 10 +++++++++-
> include/hw/arm/smmuv3.h | 1 +
> 4 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c
> index caa4a1d82d..1f206be8e4 100644
> --- a/hw/arm/smmuv3-accel.c
> +++ b/hw/arm/smmuv3-accel.c
> @@ -68,6 +68,12 @@ smmuv3_accel_check_hw_compatible(SMMUv3State *s,
> error_setg(errp, "Host SMMUv3 SIDSIZE not compatible");
> return false;
> }
> + /* If user enables PASID support(pasid=on), QEMU sets SSIDSIZE to 16 */
> + if (FIELD_EX32(info->idr[1], IDR1, SSIDSIZE) <
> + FIELD_EX32(s->idr[1], IDR1, SSIDSIZE)) {
> + error_setg(errp, "Host SMMUv3 SSIDSIZE not compatible");
> + return false;
> + }
>
> /* User can disable QEMU SMMUv3 Range Invalidation support */
> if (FIELD_EX32(info->idr[3], IDR3, RIL) !=
> @@ -642,7 +648,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 = {
> @@ -672,6 +685,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);
> + }
> }
>
> /* Based on SMUUv3 GBPA configuration, attach a corresponding HWPT */
> diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
> index cfc5897569..2e0d8d538b 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 c4d28a3786..e1140fe087 100644
> --- a/hw/arm/smmuv3.c
> +++ b/hw/arm/smmuv3.c
> @@ -611,7 +611,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) {
can't you directly check s->pasid instead of decoding the IDR1?
> qemu_log_mask(LOG_UNIMP,
> "SMMUv3 does not support multiple context descriptors yet\n");
you may suggest to add pasid= option then.
> goto bad_ste;
> @@ -1966,6 +1967,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 false;
> }
>
> @@ -2098,6 +2103,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)
> @@ -2133,6 +2139,8 @@ static void smmuv3_class_init(ObjectClass *klass, const void *data)
> object_class_property_set_description(klass, "oas",
> "Specify Output Address Size (for accel =on). Supported values "
> "are 44 or 48 bits. Defaults to 44 bits");
> + object_class_property_set_description(klass, "pasid",
> + "Enable/disable PASID support (for accel=on)");
> }
>
> static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
> diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
> index e4226b66f3..ee0b5ed74f 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 {
Otherwise looks good to me
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric