Skip to content

Commit cf08ca8

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set
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: c43e1cc ("iommu/vt-d: Drain PRQs when domain removed from RID") Suggested-by: Kevin Tian <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent c220629 commit cf08ca8

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

drivers/iommu/intel/pasid.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,31 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
244244

245245
spin_lock(&iommu->lock);
246246
pte = intel_pasid_get_entry(dev, pasid);
247-
if (WARN_ON(!pte) || !pasid_pte_is_present(pte)) {
247+
if (WARN_ON(!pte)) {
248248
spin_unlock(&iommu->lock);
249249
return;
250250
}
251251

252+
if (!pasid_pte_is_present(pte)) {
253+
if (!pasid_pte_is_fault_disabled(pte)) {
254+
WARN_ON(READ_ONCE(pte->val[0]) != 0);
255+
spin_unlock(&iommu->lock);
256+
return;
257+
}
258+
259+
/*
260+
* When a PASID is used for SVA by a device, it's possible
261+
* that the pasid entry is non-present with the Fault
262+
* Processing Disabled bit set. Clear the pasid entry and
263+
* drain the PRQ for the PASID before return.
264+
*/
265+
pasid_clear_entry(pte);
266+
spin_unlock(&iommu->lock);
267+
intel_iommu_drain_pasid_prq(dev, pasid);
268+
269+
return;
270+
}
271+
252272
did = pasid_get_domain_id(pte);
253273
pgtt = pasid_pte_get_pgtt(pte);
254274
intel_pasid_clear_entry(dev, pasid, fault_ignore);

drivers/iommu/intel/pasid.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)
7373
return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
7474
}
7575

76+
/* Get FPD(Fault Processing Disable) bit of a PASID table entry */
77+
static inline bool pasid_pte_is_fault_disabled(struct pasid_entry *pte)
78+
{
79+
return READ_ONCE(pte->val[0]) & PASID_PTE_FPD;
80+
}
81+
7682
/* Get PGTT field of a PASID table entry */
7783
static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
7884
{

0 commit comments

Comments
 (0)