Skip to content

Commit cee6867

Browse files
LuBaoluwilldeacon
authored andcommitted
iommu/vt-d: Make iotlb_sync_map a static property of dmar_domain
Commit 12724ce ("iommu/vt-d: Optimize iotlb_sync_map for non-caching/non-RWBF modes") dynamically set iotlb_sync_map. This causes synchronization issues due to lack of locking on map and attach paths, racing iommufd userspace operations. Invalidation changes must precede device attachment to ensure all flushes complete before hardware walks page tables, preventing coherence issues. Make domain->iotlb_sync_map static, set once during domain allocation. If an IOMMU requires iotlb_sync_map but the domain lacks it, attach is rejected. This won't reduce domain sharing: RWBF and shadowing page table caching are legacy uses with legacy hardware. Mixed configs (some IOMMUs in caching mode, others not) are unlikely in real-world scenarios. Fixes: 12724ce ("iommu/vt-d: Optimize iotlb_sync_map for non-caching/non-RWBF modes") Suggested-by: Jason Gunthorpe <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent e934464 commit cee6867

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
static void __init check_tylersburg_isoch(void);
5858
static int rwbf_quirk;
5959

60+
#define rwbf_required(iommu) (rwbf_quirk || cap_rwbf((iommu)->cap))
61+
6062
/*
6163
* set to 1 to panic kernel if can't successfully enable VT-d
6264
* (used when kernel is launched w/ TXT)
@@ -1780,18 +1782,6 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
17801782
__pa(pgd), flags, old);
17811783
}
17821784

1783-
static bool domain_need_iotlb_sync_map(struct dmar_domain *domain,
1784-
struct intel_iommu *iommu)
1785-
{
1786-
if (cap_caching_mode(iommu->cap) && intel_domain_is_ss_paging(domain))
1787-
return true;
1788-
1789-
if (rwbf_quirk || cap_rwbf(iommu->cap))
1790-
return true;
1791-
1792-
return false;
1793-
}
1794-
17951785
static int dmar_domain_attach_device(struct dmar_domain *domain,
17961786
struct device *dev)
17971787
{
@@ -1831,8 +1821,6 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
18311821
if (ret)
18321822
goto out_block_translation;
18331823

1834-
domain->iotlb_sync_map |= domain_need_iotlb_sync_map(domain, iommu);
1835-
18361824
return 0;
18371825

18381826
out_block_translation:
@@ -3352,6 +3340,14 @@ intel_iommu_domain_alloc_first_stage(struct device *dev,
33523340
return ERR_CAST(dmar_domain);
33533341

33543342
dmar_domain->domain.ops = &intel_fs_paging_domain_ops;
3343+
/*
3344+
* iotlb sync for map is only needed for legacy implementations that
3345+
* explicitly require flushing internal write buffers to ensure memory
3346+
* coherence.
3347+
*/
3348+
if (rwbf_required(iommu))
3349+
dmar_domain->iotlb_sync_map = true;
3350+
33553351
return &dmar_domain->domain;
33563352
}
33573353

@@ -3386,6 +3382,14 @@ intel_iommu_domain_alloc_second_stage(struct device *dev,
33863382
if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING)
33873383
dmar_domain->domain.dirty_ops = &intel_dirty_ops;
33883384

3385+
/*
3386+
* Besides the internal write buffer flush, the caching mode used for
3387+
* legacy nested translation (which utilizes shadowing page tables)
3388+
* also requires iotlb sync on map.
3389+
*/
3390+
if (rwbf_required(iommu) || cap_caching_mode(iommu->cap))
3391+
dmar_domain->iotlb_sync_map = true;
3392+
33893393
return &dmar_domain->domain;
33903394
}
33913395

@@ -3446,6 +3450,11 @@ static int paging_domain_compatible_first_stage(struct dmar_domain *dmar_domain,
34463450
if (!cap_fl1gp_support(iommu->cap) &&
34473451
(dmar_domain->domain.pgsize_bitmap & SZ_1G))
34483452
return -EINVAL;
3453+
3454+
/* iotlb sync on map requirement */
3455+
if ((rwbf_required(iommu)) && !dmar_domain->iotlb_sync_map)
3456+
return -EINVAL;
3457+
34493458
return 0;
34503459
}
34513460

@@ -3469,6 +3478,12 @@ paging_domain_compatible_second_stage(struct dmar_domain *dmar_domain,
34693478
return -EINVAL;
34703479
if (!(sslps & BIT(1)) && (dmar_domain->domain.pgsize_bitmap & SZ_1G))
34713480
return -EINVAL;
3481+
3482+
/* iotlb sync on map requirement */
3483+
if ((rwbf_required(iommu) || cap_caching_mode(iommu->cap)) &&
3484+
!dmar_domain->iotlb_sync_map)
3485+
return -EINVAL;
3486+
34723487
return 0;
34733488
}
34743489

0 commit comments

Comments
 (0)