Skip to content

Commit 6c00612

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Report right snoop capability when using FL for IOVA
The Intel VT-d driver checks wrong register to report snoop capablility when using first level page table for GPA to HPA translation. This might lead the IOMMU driver to say that it supports snooping control, but in reality, it does not. Fix this by always setting PASID-table-entry.PGSNP whenever a pasid entry is setting up for GPA to HPA translation so that the IOMMU driver could report snoop capability as long as it runs in the scalable mode. Fixes: b802d07 ("iommu/vt-d: Use iova over first level") Suggested-by: Rajesh Sankaran <rajesh.sankaran@intel.com> Suggested-by: Kevin Tian <kevin.tian@intel.com> Suggested-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Link: https://lore.kernel.org/r/20210330021145.13824-1-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 442b818 commit 6c00612

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,14 @@ static int domain_update_iommu_snooping(struct intel_iommu *skip)
658658
rcu_read_lock();
659659
for_each_active_iommu(iommu, drhd) {
660660
if (iommu != skip) {
661-
if (!ecap_sc_support(iommu->ecap)) {
661+
/*
662+
* If the hardware is operating in the scalable mode,
663+
* the snooping control is always supported since we
664+
* always set PASID-table-entry.PGSNP bit if the domain
665+
* is managed outside (UNMANAGED).
666+
*/
667+
if (!sm_supported(iommu) &&
668+
!ecap_sc_support(iommu->ecap)) {
662669
ret = 0;
663670
break;
664671
}
@@ -2505,6 +2512,9 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
25052512

25062513
flags |= (level == 5) ? PASID_FLAG_FL5LP : 0;
25072514

2515+
if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED)
2516+
flags |= PASID_FLAG_PAGE_SNOOP;
2517+
25082518
return intel_pasid_setup_first_level(iommu, dev, (pgd_t *)pgd, pasid,
25092519
domain->iommu_did[iommu->seq_id],
25102520
flags);

drivers/iommu/intel/pasid.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,16 @@ static inline void pasid_set_page_snoop(struct pasid_entry *pe, bool value)
425425
pasid_set_bits(&pe->val[1], 1 << 23, value << 23);
426426
}
427427

428+
/*
429+
* Setup the Page Snoop (PGSNP) field (Bit 88) of a scalable mode
430+
* PASID entry.
431+
*/
432+
static inline void
433+
pasid_set_pgsnp(struct pasid_entry *pe)
434+
{
435+
pasid_set_bits(&pe->val[1], 1ULL << 24, 1ULL << 24);
436+
}
437+
428438
/*
429439
* Setup the First Level Page table Pointer field (Bit 140~191)
430440
* of a scalable mode PASID entry.
@@ -596,6 +606,9 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
596606
}
597607
}
598608

609+
if (flags & PASID_FLAG_PAGE_SNOOP)
610+
pasid_set_pgsnp(pte);
611+
599612
pasid_set_domain_id(pte, did);
600613
pasid_set_address_width(pte, iommu->agaw);
601614
pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
@@ -674,6 +687,9 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
674687
pasid_set_fault_enable(pte);
675688
pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
676689

690+
if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED)
691+
pasid_set_pgsnp(pte);
692+
677693
/*
678694
* Since it is a second level only translation setup, we should
679695
* set SRE bit as well (addresses are expected to be GPAs).

drivers/iommu/intel/pasid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
*/
4949
#define PASID_FLAG_SUPERVISOR_MODE BIT(0)
5050
#define PASID_FLAG_NESTED BIT(1)
51+
#define PASID_FLAG_PAGE_SNOOP BIT(2)
5152

5253
/*
5354
* The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-

0 commit comments

Comments
 (0)