Skip to content

Commit e645c20

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Support enforce_cache_coherency only for empty domains
The enforce_cache_coherency callback ensures DMA cache coherency for devices attached to the domain. Intel IOMMU supports enforced DMA cache coherency when the Snoop Control bit in the IOMMU's extended capability register is set. Supporting it differs between legacy and scalable modes. In legacy mode, it's supported page-level by setting the SNP field in second-stage page-table entries. In scalable mode, it's supported in PASID-table granularity by setting the PGSNP field in PASID-table entries. In legacy mode, mappings before attaching to a device have SNP fields cleared, while mappings after the callback have them set. This means partial DMAs are cache coherent while others are not. One possible fix is replaying mappings and flipping SNP bits when attaching a domain to a device. But this seems to be over-engineered, given that all real use cases just attach an empty domain to a device. To meet practical needs while reducing mode differences, only support enforce_cache_coherency on a domain without mappings if SNP field is used. Fixes: fc0051c ("iommu/vt-d: Check domain force_snooping against attached devices") 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 a2e7e59 commit e645c20

File tree

2 files changed

+7
-1
lines changed

2 files changed

+7
-1
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,8 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
22072207
attr |= DMA_FL_PTE_DIRTY;
22082208
}
22092209

2210+
domain->has_mappings = true;
2211+
22102212
pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | attr;
22112213

22122214
while (nr_pages > 0) {
@@ -4360,7 +4362,8 @@ static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domain)
43604362
return true;
43614363

43624364
spin_lock_irqsave(&dmar_domain->lock, flags);
4363-
if (!domain_support_force_snooping(dmar_domain)) {
4365+
if (!domain_support_force_snooping(dmar_domain) ||
4366+
(!dmar_domain->use_first_level && dmar_domain->has_mappings)) {
43644367
spin_unlock_irqrestore(&dmar_domain->lock, flags);
43654368
return false;
43664369
}

drivers/iommu/intel/iommu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,9 @@ struct dmar_domain {
602602
*/
603603
u8 dirty_tracking:1; /* Dirty tracking is enabled */
604604
u8 nested_parent:1; /* Has other domains nested on it */
605+
u8 has_mappings:1; /* Has mappings configured through
606+
* iommu_map() interface.
607+
*/
605608

606609
spinlock_t lock; /* Protect device tracking lists */
607610
struct list_head devices; /* all devices' list */

0 commit comments

Comments
 (0)