| From e933b920015284a9a4199a22c0d0eaf24ec37ea9 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 2e5fa0a232999..2ec76333b6973 100644 |
| --- a/drivers/iommu/intel/pasid.c |
| +++ b/drivers/iommu/intel/pasid.c |
| @@ -152,6 +152,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 |
| @@ -164,10 +167,8 @@ static struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid) |
| iommu_free_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 |
| |