@@ -286,6 +286,41 @@ static void pasid_flush_caches(struct intel_iommu *iommu,
}
}
+/*
+ * This function is supposed to be used after caller updates the fields
+ * except for the SSADE and P bit of a pasid table entry. It does the
+ * below:
+ * - Flush cacheline if needed
+ * - Flush the caches per the guidance of VT-d spec 5.0 Table 28.
+ * ”Guidance to Software for Invalidations“
+ *
+ * Caller of it should not modify the in-use pasid table entries.
+ */
+static void intel_pasid_flush_present(struct intel_iommu *iommu,
+ struct device *dev,
+ u32 pasid, u16 did,
+ struct pasid_entry *pte)
+{
+ if (!ecap_coherent(iommu->ecap))
+ clflush_cache_range(pte, sizeof(*pte));
+
+ /*
+ * VT-d spec 5.0 table28 states guides for cache invalidation:
+ *
+ * - PASID-selective-within-Domain PASID-cache invalidation
+ * - PASID-selective PASID-based IOTLB invalidation
+ * - If (pasid is RID_PASID)
+ * - Global Device-TLB invalidation to affected functions
+ * Else
+ * - PASID-based Device-TLB invalidation (with S=1 and
+ * Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions
+ */
+ pasid_cache_invalidation_with_pasid(iommu, did, pasid);
+ qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+
+ devtlb_invalidation_with_pasid(iommu, dev, pasid);
+}
+
/*
* Set up the scalable mode pasid table entry for first only
* translation type.
@@ -551,24 +586,7 @@ void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
did = pasid_get_domain_id(pte);
spin_unlock(&iommu->lock);
- if (!ecap_coherent(iommu->ecap))
- clflush_cache_range(pte, sizeof(*pte));
-
- /*
- * VT-d spec 3.4 table23 states guides for cache invalidation:
- *
- * - PASID-selective-within-Domain PASID-cache invalidation
- * - PASID-selective PASID-based IOTLB invalidation
- * - If (pasid is RID_PASID)
- * - Global Device-TLB invalidation to affected functions
- * Else
- * - PASID-based Device-TLB invalidation (with S=1 and
- * Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions
- */
- pasid_cache_invalidation_with_pasid(iommu, did, pasid);
- qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
-
- devtlb_invalidation_with_pasid(iommu, dev, pasid);
+ intel_pasid_flush_present(iommu, dev, pasid, did, pte);
}
/**
There are more paths that need to flush cache for present pasid entry after adding pasid replacement. Hence, add a helper for it. Per the VT-d spec, the changes to the fields other than SSADE and P bit can share the same code. So intel_pasid_setup_page_snoop_control() is the first user of this helper. No functional change is intended. Signed-off-by: Yi Liu <yi.l.liu@intel.com> --- drivers/iommu/intel/pasid.c | 54 ++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 18 deletions(-)