aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Pan <jacob.jun.pan@linux.intel.com>2016-12-06 13:14:23 -0500
committerJoerg Roedel <jroedel@suse.de>2017-01-04 09:18:57 -0500
commit65ca7f5f7d1cdde6c25172fe6107cd16902f826f (patch)
tree6fff0dccb8fcf28797336c23e973f7dfbd8a20a4
parentaec0e86172a79eb5e44aff1055bb953fe4d47c59 (diff)
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 <mika.kuoppala@linux.intel.com> cc: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Tested-by: Mika Kuoppala <mika.kuoppala@intel.com> Fixes: 2f26e0a9c9860 ('iommu/vt-d: Add basic SVM PASID support') Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/intel-iommu.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 8862dc1e88eb..8a185250ae5a 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5204,6 +5204,25 @@ static void intel_iommu_remove_device(struct device *dev)
5204} 5204}
5205 5205
5206#ifdef CONFIG_INTEL_IOMMU_SVM 5206#ifdef CONFIG_INTEL_IOMMU_SVM
5207#define MAX_NR_PASID_BITS (20)
5208static 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
5207int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev) 5226int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
5208{ 5227{
5209 struct device_domain_info *info; 5228 struct device_domain_info *info;
@@ -5236,7 +5255,9 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd
5236 5255
5237 if (!(ctx_lo & CONTEXT_PASIDE)) { 5256 if (!(ctx_lo & CONTEXT_PASIDE)) {
5238 context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table); 5257 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
5240 wmb(); 5261 wmb();
5241 /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both 5262 /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
5242 * extended to permit requests-with-PASID if the PASIDE bit 5263 * extended to permit requests-with-PASID if the PASIDE bit