diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-06 13:49:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-06 13:49:36 -0500 |
commit | 65cdc405b37a0f43af9c0fb6cf011304b3959ef8 (patch) | |
tree | 4becabf9b9ccf4695c0ea3d452d99b10cca5ade6 | |
parent | 7397e1e838228a0957043613c265a611e09c05f3 (diff) | |
parent | 432abf68a79332282329286d190e21fe3ac02a31 (diff) |
Merge tag 'iommu-fixes-v4.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU fixes from Joerg Roedel:
"Three fixes queued up:
- fix an issue with command buffer overflow handling in the AMD IOMMU
driver
- add an additional context entry flush to the Intel VT-d driver to
make sure any old context entry from kdump copying is flushed out
of the cache
- correct the encoding of the PASID table size in the Intel VT-d
driver"
* tag 'iommu-fixes-v4.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
iommu/amd: Fix the left value check of cmd buffer
iommu/vt-d: Fix pasid table size encoding
iommu/vt-d: Flush old iommu caches for kdump when the device gets context mapped
-rw-r--r-- | drivers/iommu/amd_iommu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 42 |
2 files changed, 42 insertions, 2 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 019e02707cd5..3ef0f42984f2 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -1023,7 +1023,7 @@ again: | |||
1023 | next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE; | 1023 | next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE; |
1024 | left = (head - next_tail) % CMD_BUFFER_SIZE; | 1024 | left = (head - next_tail) % CMD_BUFFER_SIZE; |
1025 | 1025 | ||
1026 | if (left <= 2) { | 1026 | if (left <= 0x20) { |
1027 | struct iommu_cmd sync_cmd; | 1027 | struct iommu_cmd sync_cmd; |
1028 | int ret; | 1028 | int ret; |
1029 | 1029 | ||
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c66c273dfd8a..8a185250ae5a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -2037,6 +2037,25 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
2037 | if (context_present(context)) | 2037 | if (context_present(context)) |
2038 | goto out_unlock; | 2038 | goto out_unlock; |
2039 | 2039 | ||
2040 | /* | ||
2041 | * For kdump cases, old valid entries may be cached due to the | ||
2042 | * in-flight DMA and copied pgtable, but there is no unmapping | ||
2043 | * behaviour for them, thus we need an explicit cache flush for | ||
2044 | * the newly-mapped device. For kdump, at this point, the device | ||
2045 | * is supposed to finish reset at its driver probe stage, so no | ||
2046 | * in-flight DMA will exist, and we don't need to worry anymore | ||
2047 | * hereafter. | ||
2048 | */ | ||
2049 | if (context_copied(context)) { | ||
2050 | u16 did_old = context_domain_id(context); | ||
2051 | |||
2052 | if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) | ||
2053 | iommu->flush.flush_context(iommu, did_old, | ||
2054 | (((u16)bus) << 8) | devfn, | ||
2055 | DMA_CCMD_MASK_NOBIT, | ||
2056 | DMA_CCMD_DEVICE_INVL); | ||
2057 | } | ||
2058 | |||
2040 | pgd = domain->pgd; | 2059 | pgd = domain->pgd; |
2041 | 2060 | ||
2042 | context_clear_entry(context); | 2061 | context_clear_entry(context); |
@@ -5185,6 +5204,25 @@ static void intel_iommu_remove_device(struct device *dev) | |||
5185 | } | 5204 | } |
5186 | 5205 | ||
5187 | #ifdef CONFIG_INTEL_IOMMU_SVM | 5206 | #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 | |||
5188 | int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev) | 5226 | int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev) |
5189 | { | 5227 | { |
5190 | struct device_domain_info *info; | 5228 | struct device_domain_info *info; |
@@ -5217,7 +5255,9 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd | |||
5217 | 5255 | ||
5218 | if (!(ctx_lo & CONTEXT_PASIDE)) { | 5256 | if (!(ctx_lo & CONTEXT_PASIDE)) { |
5219 | context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table); | 5257 | context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table); |
5220 | 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 | |||
5221 | wmb(); | 5261 | wmb(); |
5222 | /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both | 5262 | /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both |
5223 | * extended to permit requests-with-PASID if the PASIDE bit | 5263 | * extended to permit requests-with-PASID if the PASIDE bit |