Skip to content

Commit 65ca7f5

Browse files
Jacob Panjoergroedel
authored andcommitted
iommu/vt-d: Fix pasid table size encoding
Different encodings are used to represent supported PASID bits and number of PASID table entries. The current code assigns ecap_pss directly to extended context table entry PTS which is wrong and could result in writing non-zero bits to the reserved fields. IOMMU fault reason 11 will be reported when reserved bits are nonzero. This patch converts ecap_pss to extend context entry pts encoding based on VT-d spec. Chapter 9.4 as follows: - number of PASID bits = ecap_pss + 1 - number of PASID table entries = 2^(pts + 5) Software assigned limit of pasid_max value is also respected to match the allocation limitation of PASID table. cc: Mika Kuoppala <[email protected]> cc: Ashok Raj <[email protected]> Signed-off-by: Jacob Pan <[email protected]> Tested-by: Mika Kuoppala <[email protected]> Fixes: 2f26e0a ('iommu/vt-d: Add basic SVM PASID support') Signed-off-by: Joerg Roedel <[email protected]>
1 parent aec0e86 commit 65ca7f5

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5204,6 +5204,25 @@ static void intel_iommu_remove_device(struct device *dev)
52045204
}
52055205

52065206
#ifdef CONFIG_INTEL_IOMMU_SVM
5207+
#define MAX_NR_PASID_BITS (20)
5208+
static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu)
5209+
{
5210+
/*
5211+
* Convert ecap_pss to extend context entry pts encoding, also
5212+
* respect the soft pasid_max value set by the iommu.
5213+
* - number of PASID bits = ecap_pss + 1
5214+
* - number of PASID table entries = 2^(pts + 5)
5215+
* Therefore, pts = ecap_pss - 4
5216+
* e.g. KBL ecap_pss = 0x13, PASID has 20 bits, pts = 15
5217+
*/
5218+
if (ecap_pss(iommu->ecap) < 5)
5219+
return 0;
5220+
5221+
/* pasid_max is encoded as actual number of entries not the bits */
5222+
return find_first_bit((unsigned long *)&iommu->pasid_max,
5223+
MAX_NR_PASID_BITS) - 5;
5224+
}
5225+
52075226
int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
52085227
{
52095228
struct device_domain_info *info;
@@ -5236,7 +5255,9 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd
52365255

52375256
if (!(ctx_lo & CONTEXT_PASIDE)) {
52385257
context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
5239-
context[1].lo = (u64)virt_to_phys(iommu->pasid_table) | ecap_pss(iommu->ecap);
5258+
context[1].lo = (u64)virt_to_phys(iommu->pasid_table) |
5259+
intel_iommu_get_pts(iommu);
5260+
52405261
wmb();
52415262
/* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
52425263
* extended to permit requests-with-PASID if the PASIDE bit

0 commit comments

Comments
 (0)