Patch "iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set" has been added to the 6.13-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set

to the 6.13-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     iommu-vt-d-draining-prq-in-sva-unbind-path-when-fpd-.patch
and it can be found in the queue-6.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit dca815c360437f9fae5ce11fa32421e9d09e6aa5
Author: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
Date:   Tue Jan 7 10:17:45 2025 +0800

    iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set
    
    [ Upstream commit cf08ca81d08a04b3b304e8fb4e052f323a09783d ]
    
    When a device uses a PASID for SVA (Shared Virtual Address), it's possible
    that the PASID entry is marked as non-present and FPD bit set before the
    device flushes all ongoing DMA requests and removes the SVA domain. This
    can occur when an exception happens and the process terminates before the
    device driver stops DMA and calls the iommu driver to unbind the PASID.
    
    There's no need to drain the PRQ in the mm release path. Instead, the PRQ
    will be drained in the SVA unbind path. But in such case,
    intel_pasid_tear_down_entry() only checks the presence of the pasid entry
    and returns directly.
    
    Add the code to clear the FPD bit and drain the PRQ.
    
    Fixes: c43e1ccdebf2 ("iommu/vt-d: Drain PRQs when domain removed from RID")
    Suggested-by: Kevin Tian <kevin.tian@xxxxxxxxx>
    Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
    Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx>
    Link: https://lore.kernel.org/r/20241217024240.139615-1-baolu.lu@xxxxxxxxxxxxxxx
    Signed-off-by: Joerg Roedel <jroedel@xxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index 5b7d85f1e143c..fb59a7d35958f 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -244,11 +244,31 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
 
 	spin_lock(&iommu->lock);
 	pte = intel_pasid_get_entry(dev, pasid);
-	if (WARN_ON(!pte) || !pasid_pte_is_present(pte)) {
+	if (WARN_ON(!pte)) {
 		spin_unlock(&iommu->lock);
 		return;
 	}
 
+	if (!pasid_pte_is_present(pte)) {
+		if (!pasid_pte_is_fault_disabled(pte)) {
+			WARN_ON(READ_ONCE(pte->val[0]) != 0);
+			spin_unlock(&iommu->lock);
+			return;
+		}
+
+		/*
+		 * When a PASID is used for SVA by a device, it's possible
+		 * that the pasid entry is non-present with the Fault
+		 * Processing Disabled bit set. Clear the pasid entry and
+		 * drain the PRQ for the PASID before return.
+		 */
+		pasid_clear_entry(pte);
+		spin_unlock(&iommu->lock);
+		intel_iommu_drain_pasid_prq(dev, pasid);
+
+		return;
+	}
+
 	did = pasid_get_domain_id(pte);
 	pgtt = pasid_pte_get_pgtt(pte);
 	intel_pasid_clear_entry(dev, pasid, fault_ignore);
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index 082f4fe20216a..668d8ece6b143 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -73,6 +73,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)
 	return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
 }
 
+/* Get FPD(Fault Processing Disable) bit of a PASID table entry */
+static inline bool pasid_pte_is_fault_disabled(struct pasid_entry *pte)
+{
+	return READ_ONCE(pte->val[0]) & PASID_PTE_FPD;
+}
+
 /* Get PGTT field of a PASID table entry */
 static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
 {




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux