iommu/vt-d: Fixes for v5.14-rc7
Subsystems (2)
Lu Baolu
maintainerHi Joerg,
Two small fixes are queued for v5.14. They aim to fix:
- PASID reference leakage in intel_svm_unbind_mm();
- An improper iotlb invalidation in intel_pasid_tear_down_entry().
Please consider it for your iommu/fix branch.
Best regards,
Lu Baolu
Fenghua Yu (1):
iommu/vt-d: Fix PASID reference leak
Liu Yi L (1):
iommu/vt-d: Fix incomplete cache flush in
intel_pasid_tear_down_entry()
drivers/iommu/intel/pasid.h | 6 ++++++ drivers/iommu/intel/pasid.c | 10 ++++++++-- drivers/iommu/intel/svm.c | 3 ++- 3 files changed, 16 insertions(+), 3 deletions(-)
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerPATCH 1/2 iommu/vt-d: Fix PASID reference leak
From: Fenghua Yu <[email protected]>
A PASID reference is increased whenever a device is bound to an mm (and its PASID) successfully (i.e. the device's sdev user count is increased). But the reference is not dropped every time the device is unbound successfully from the mm (i.e. the device's sdev user count is decreased). The reference is dropped only once by calling intel_svm_free_pasid() when there isn't any device bound to the mm. intel_svm_free_pasid() drops the reference and only frees the PASID on zero reference.
Fix the issue by dropping the PASID reference and freeing the PASID when no reference on successful unbinding the device by calling intel_svm_free_pasid() .
--- drivers/iommu/intel/svm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/iommu/intel/svm.c +2 -1
@@ -675,7 +675,6 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)kfree_rcu (sdev, rcu);if (list_empty (&svm->devs)) { -intel_svm_free_pasid (mm);if (svm->notifier.ops) {mmu_notifier_unregister (&svm->notifier, mm);/* Clear mm's pasid. */
@@ -690,6 +689,8 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)kfree (svm); } } +/* Drop a PASID reference and free it if no reference. */ +intel_svm_free_pasid (mm); } out:return ret;
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerPATCH 2/2 iommu/vt-d: Fix incomplete cache flush in intel_pasid_tear_down_entry()
In reply to Lu BaoluFrom: Liu Yi L <[email protected]>
This fixes improper iotlb invalidation in intel_pasid_tear_down_entry(). When a PASID was used as nested mode, released and reused, the following error message will appear:
[ 180.187556] Unexpected page request in Privilege Mode [ 180.187565] Unexpected page request in Privilege Mode [ 180.279933] Unexpected page request in Privilege Mode [ 180.279937] Unexpected page request in Privilege Mode
Per chapter 6.5.3.3 of VT-d spec 3.3, when tear down a pasid entry, the software should use Domain selective IOTLB flush if the PGTT of the pasid entry is SL only or Nested, while for the pasid entries whose PGTT is FL only or PT using PASID-based IOTLB flush is enough.
--- drivers/iommu/intel/pasid.h | 6 ++++++ drivers/iommu/intel/pasid.c | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-)
drivers/iommu/intel/pasid.h +6 -0
@@ -99,6 +99,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)return READ_ONCE (pte->val[0 ]) &PASID_PTE_PRESENT ; } +/* Get PGTT field of a PASID table entry */ +static inline u16 pasid_pte_get_pgtt (struct pasid_entry *pte) +{ +return (u16)((READ_ONCE (pte->val[0 ]) >>6 ) &0x7 ); +} +extern unsigned int intel_pasid_max_id;int intel_pasid_alloc_table (struct device *dev);void intel_pasid_free_table (struct device *dev);
drivers/iommu/intel/pasid.c +8 -2
@@ -511,7 +511,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev, u32 pasid, bool fault_ignore) {struct pasid_entry *pte; -u16 did; +u16 did, pgtt; pte =intel_pasid_get_entry (dev, pasid);if (WARN_ON (!pte))
@@ -521,13 +521,19 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,return ; did =pasid_get_domain_id (pte); + pgtt =pasid_pte_get_pgtt (pte); +intel_pasid_clear_entry (dev, pasid, fault_ignore);if (!ecap_coherent (iommu->ecap))clflush_cache_range (pte,sizeof (*pte));pasid_cache_invalidation_with_pasid (iommu, did, pasid); -qi_flush_piotlb (iommu, did, pasid,0 ,-1 ,0 ); + +if (pgtt ==PASID_ENTRY_PGTT_PT || pgtt ==PASID_ENTRY_PGTT_FL_ONLY ) +qi_flush_piotlb (iommu, did, pasid,0 ,-1 ,0 ); +else + iommu->flush.flush_iotlb (iommu, did,0 ,0 ,DMA_TLB_DSI_FLUSH );/* Device IOTLB doesn't need to be flushed in caching mode. */ if (!cap_caching_mode (iommu->cap))
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Quoted 6 lines · Lu Baolu
Fenghua Yu (1):
iommu/vt-d: Fix PASID reference leakLiu Yi L (1):
iommu/vt-d: Fix incomplete cache flush in
intel_pasid_tear_down_entry()
Applied both, thanks.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu