| From 79d7b0a23f25bbc258fe6f02e26016e72574d2f4 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 22 Jan 2026 09:48:52 +0800 |
| Subject: iommu/vt-d: Flush cache for PASID table before using it |
| |
| From: Dmytro Maluka <dmaluka@chromium.org> |
| |
| [ Upstream commit 22d169bdd2849fe6bd18c2643742e1c02be6451c ] |
| |
| When writing the address of a freshly allocated zero-initialized PASID |
| table to a PASID directory entry, do that after the CPU cache flush for |
| this PASID table, not before it, to avoid the time window when this |
| PASID table may be already used by non-coherent IOMMU hardware while |
| its contents in RAM is still some random old data, not zero-initialized. |
| |
| Fixes: 194b3348bdbb ("iommu/vt-d: Fix PASID directory pointer coherency") |
| Signed-off-by: Dmytro Maluka <dmaluka@chromium.org> |
| Reviewed-by: Kevin Tian <kevin.tian@intel.com> |
| Link: https://lore.kernel.org/r/20251221123508.37495-1-dmaluka@chromium.org |
| Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> |
| Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/iommu/intel/pasid.c | 7 ++++--- |
| 1 file changed, 4 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c |
| index 8faa93cffac45..07c8b0df8e2a8 100644 |
| --- a/drivers/iommu/intel/pasid.c |
| +++ b/drivers/iommu/intel/pasid.c |
| @@ -207,6 +207,9 @@ static struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid) |
| if (!entries) |
| return NULL; |
| |
| + if (!ecap_coherent(info->iommu->ecap)) |
| + clflush_cache_range(entries, VTD_PAGE_SIZE); |
| + |
| /* |
| * The pasid directory table entry won't be freed after |
| * allocation. No worry about the race with free and |
| @@ -218,10 +221,8 @@ static struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid) |
| free_pgtable_page(entries); |
| goto retry; |
| } |
| - if (!ecap_coherent(info->iommu->ecap)) { |
| - clflush_cache_range(entries, VTD_PAGE_SIZE); |
| + if (!ecap_coherent(info->iommu->ecap)) |
| clflush_cache_range(&dir[dir_index].val, sizeof(*dir)); |
| - } |
| } |
| |
| return &entries[index]; |
| -- |
| 2.51.0 |
| |