]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.4.36/iommu-vt-d-fix-pasid-table-allocation.patch
Fix up backported ptrace patch
[thirdparty/kernel/stable-queue.git] / releases / 4.4.36 / iommu-vt-d-fix-pasid-table-allocation.patch
CommitLineData
9c6fd700
GKH
1From 910170442944e1f8674fd5ddbeeb8ccd1877ea98 Mon Sep 17 00:00:00 2001
2From: David Woodhouse <dwmw2@infradead.org>
3Date: Mon, 12 Sep 2016 10:49:11 +0800
4Subject: iommu/vt-d: Fix PASID table allocation
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: David Woodhouse <dwmw2@infradead.org>
10
11commit 910170442944e1f8674fd5ddbeeb8ccd1877ea98 upstream.
12
13Somehow I ended up with an off-by-three error in calculating the size of
14the PASID and PASID State tables, which triggers allocations failures as
15those tables unfortunately have to be physically contiguous.
16
17In fact, even the *correct* maximum size of 8MiB is problematic and is
18wont to lead to allocation failures. Since I have extracted a promise
19that this *will* be fixed in hardware, I'm happy to limit it on the
20current hardware to a maximum of 0x20000 PASIDs, which gives us 1MiB
21tables — still not ideal, but better than before.
22
23Reported by Mika Kuoppala <mika.kuoppala@linux.intel.com> and also by
24Xunlei Pang <xlpang@redhat.com> who submitted a simpler patch to fix
25only the allocation (and not the free) to the "correct" limit... which
26was still problematic.
27
28Signed-off-by: David Woodhouse <dwmw2@infradead.org>
29Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30
31---
32 drivers/iommu/intel-svm.c | 26 ++++++++++++++++----------
33 include/linux/intel-iommu.h | 1 +
34 2 files changed, 17 insertions(+), 10 deletions(-)
35
36--- a/drivers/iommu/intel-svm.c
37+++ b/drivers/iommu/intel-svm.c
38@@ -39,10 +39,18 @@ int intel_svm_alloc_pasid_tables(struct
39 struct page *pages;
40 int order;
41
42- order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT;
43- if (order < 0)
44- order = 0;
45+ /* Start at 2 because it's defined as 2^(1+PSS) */
46+ iommu->pasid_max = 2 << ecap_pss(iommu->ecap);
47
48+ /* Eventually I'm promised we will get a multi-level PASID table
49+ * and it won't have to be physically contiguous. Until then,
50+ * limit the size because 8MiB contiguous allocations can be hard
51+ * to come by. The limit of 0x20000, which is 1MiB for each of
52+ * the PASID and PASID-state tables, is somewhat arbitrary. */
53+ if (iommu->pasid_max > 0x20000)
54+ iommu->pasid_max = 0x20000;
55+
56+ order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max);
57 pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
58 if (!pages) {
59 pr_warn("IOMMU: %s: Failed to allocate PASID table\n",
60@@ -53,6 +61,8 @@ int intel_svm_alloc_pasid_tables(struct
61 pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order);
62
63 if (ecap_dis(iommu->ecap)) {
64+ /* Just making it explicit... */
65+ BUILD_BUG_ON(sizeof(struct pasid_entry) != sizeof(struct pasid_state_entry));
66 pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
67 if (pages)
68 iommu->pasid_state_table = page_address(pages);
69@@ -68,11 +78,7 @@ int intel_svm_alloc_pasid_tables(struct
70
71 int intel_svm_free_pasid_tables(struct intel_iommu *iommu)
72 {
73- int order;
74-
75- order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT;
76- if (order < 0)
77- order = 0;
78+ int order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max);
79
80 if (iommu->pasid_table) {
81 free_pages((unsigned long)iommu->pasid_table, order);
82@@ -371,8 +377,8 @@ int intel_svm_bind_mm(struct device *dev
83 }
84 svm->iommu = iommu;
85
86- if (pasid_max > 2 << ecap_pss(iommu->ecap))
87- pasid_max = 2 << ecap_pss(iommu->ecap);
88+ if (pasid_max > iommu->pasid_max)
89+ pasid_max = iommu->pasid_max;
90
91 /* Do not use PASID 0 in caching mode (virtualised IOMMU) */
92 ret = idr_alloc(&iommu->pasid_idr, svm,
93--- a/include/linux/intel-iommu.h
94+++ b/include/linux/intel-iommu.h
95@@ -429,6 +429,7 @@ struct intel_iommu {
96 struct page_req_dsc *prq;
97 unsigned char prq_name[16]; /* Name for PRQ interrupt */
98 struct idr pasid_idr;
99+ u32 pasid_max;
100 #endif
101 struct q_inval *qi; /* Queued invalidation info */
102 u32 *iommu_state; /* Store iommu states between suspend and resume.*/