| From 68fbed3bf41b19b4787b828fcf8a77ff9ef1aba0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 13 Dec 2024 09:17:52 +0800 |
| Subject: iommu/vt-d: Avoid draining PRQ in sva mm release path |
| |
| From: Lu Baolu <baolu.lu@linux.intel.com> |
| |
| [ Upstream commit dda2b8c3c6ccc50deae65cc75f246577348e2ec5 ] |
| |
| When a PASID is used for SVA by a device, it's possible that the PASID |
| entry is cleared 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. |
| |
| Unfortunately, commit c43e1ccdebf2 ("iommu/vt-d: Drain PRQs when domain |
| removed from RID") changed this behavior by unconditionally draining the |
| PRQ in intel_pasid_tear_down_entry(). This can lead to a potential |
| sleeping-in-atomic-context issue. |
| |
| Smatch static checker warning: |
| |
| drivers/iommu/intel/prq.c:95 intel_iommu_drain_pasid_prq() |
| warn: sleeping in atomic context |
| |
| To avoid this issue, prevent draining the PRQ in the SVA mm release path |
| and restore the previous behavior. |
| |
| Fixes: c43e1ccdebf2 ("iommu/vt-d: Drain PRQs when domain removed from RID") |
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org> |
| Closes: https://lore.kernel.org/linux-iommu/c5187676-2fa2-4e29-94e0-4a279dc88b49@stanley.mountain/ |
| Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> |
| Reviewed-by: Kevin Tian <kevin.tian@intel.com> |
| Link: https://lore.kernel.org/r/20241212021529.1104745-1-baolu.lu@linux.intel.com |
| Signed-off-by: Joerg Roedel <jroedel@suse.de> |
| Stable-dep-of: 75ed00055c05 ("iommu/vt-d: Clear Present bit before tearing down PASID entry") |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/iommu/intel/pasid.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c |
| index 4e4d167720ba8..57969ba2d3975 100644 |
| --- a/drivers/iommu/intel/pasid.c |
| +++ b/drivers/iommu/intel/pasid.c |
| @@ -266,7 +266,8 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev, |
| iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH); |
| |
| devtlb_invalidation_with_pasid(iommu, dev, pasid); |
| - intel_iommu_drain_pasid_prq(dev, pasid); |
| + if (!fault_ignore) |
| + intel_iommu_drain_pasid_prq(dev, pasid); |
| } |
| |
| /* |
| -- |
| 2.51.0 |
| |