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 <[email protected]> Reviewed-by: Eric Auger <[email protected]> Signed-off-by: Shameer Kolothum <[email protected]> --- hw/arm/smmuv3-accel.c | 23 ++++++++++++++++++++++- hw/arm/smmuv3-internal.h | 1 + hw/arm/smmuv3.c | 13 +++++++++++-- include/hw/arm/smmuv3.h | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c index 254d29ee2d..dc0f61e841 100644 --- a/hw/arm/smmuv3-accel.c +++ b/hw/arm/smmuv3-accel.c @@ -67,6 +67,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) > @@ -643,7 +649,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 = { @@ -671,6 +684,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 GPBA.ABORT configuration, attach a corresponding HWPT */ diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 0f44a4e1d3..e45aad27f7 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 a7bd4eeb77..763f069a35 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -611,9 +611,11 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg, } } - if (STE_S1CDMAX(ste) != 0) { + /* If pasid not enabled, can't support multiple CDs */ + if (!s->pasid && STE_S1CDMAX(ste) != 0) { qemu_log_mask(LOG_UNIMP, - "SMMUv3 does not support multiple context descriptors yet\n"); + "SMMUv3: multiple S1 context descriptors require PASID support. " + "Enable PASID with pasid=on (supported only with accel=on)\n"); goto bad_ste; } @@ -1950,6 +1952,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; } @@ -2084,6 +2090,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) @@ -2117,6 +2124,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 d488a39cd0..2d4970fe19 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -72,6 +72,7 @@ struct SMMUv3State { bool ril; bool ats; uint8_t oas; + bool pasid; }; typedef enum { -- 2.43.0
