Patch "iommu/vt-d: Fix PASID table allocation" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
iommu/vt-d: Fix PASID table allocation
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
iommu-vt-d-fix-pasid-table-allocation.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
910170442944e1f8674fd5ddbeeb8ccd1877ea98Mon Sep 17 00:00:00 2001
From: David Woodhouse <[email protected]>
Date: Mon, 12 Sep 2016 10:49:11 +0800
Subject: iommu/vt-d: Fix PASID table allocation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: David Woodhouse <[email protected]>
commit 910170442944e1f8674fd5ddbeeb8ccd1877ea98 upstream.
Somehow I ended up with an off-by-three error in calculating the size of the PASID and PASID State tables, which triggers allocations failures as those tables unfortunately have to be physically contiguous.
In fact, even the *correct* maximum size of 8MiB is problematic and is wont to lead to allocation failures. Since I have extracted a promise that this *will* be fixed in hardware, I'm happy to limit it on the current hardware to a maximum of 0x20000 PASIDs, which gives us 1MiB tables — still not ideal, but better than before.
Reported by Mika Kuoppala <[email protected]> and also by Xunlei Pang <[email protected]> who submitted a simpler patch to fix only the allocation (and not the free) to the "correct" limit... which was still problematic.
--- drivers/iommu/intel-svm.c | 26 ++++++++++++++++---------- include/linux/intel-iommu.h | 1 + 2 files changed, 17 insertions(+), 10 deletions(-)
drivers/iommu/intel-svm.c +16 -10
@@ -39,10 +39,18 @@ int intel_svm_alloc_pasid_tables(structstruct page *pages;int order; - order =ecap_pss (iommu->ecap) +7 -PAGE_SHIFT ; -if (order <0 ) - order =0 ; +/* Start at 2 because it's defined as 2^(1+PSS) */ + iommu->pasid_max =2 <<ecap_pss (iommu->ecap); +/* Eventually I'm promised we will get a multi-level PASID table +* and it won't have to be physically contiguous. Until then, +* limit the size because 8MiB contiguous allocations can be hard +* to come by. The limit of 0x20000, which is 1MiB for each of +* the PASID and PASID-state tables, is somewhat arbitrary. */ +if (iommu->pasid_max >0x20000 ) + iommu->pasid_max =0x20000 ; + + order =get_order (sizeof (struct pasid_entry ) * iommu->pasid_max); pages =alloc_pages (GFP_KERNEL | __GFP_ZERO, order);if (!pages) { pr_warn("IOMMU: %s: Failed to allocate PASID table\n",
@@ -53,6 +61,8 @@ int intel_svm_alloc_pasid_tables(structpr_info ("%s: Allocated order %d PASID table.\n" , iommu->name, order);if (ecap_dis (iommu->ecap)) { +/* Just making it explicit... */ +BUILD_BUG_ON (sizeof (struct pasid_entry ) !=sizeof (struct pasid_state_entry )); pages =alloc_pages (GFP_KERNEL | __GFP_ZERO, order);if (pages) iommu->pasid_state_table =page_address (pages);
@@ -68,11 +78,7 @@ int intel_svm_alloc_pasid_tables(structint intel_svm_free_pasid_tables (struct intel_iommu *iommu) { -int order; - - order =ecap_pss (iommu->ecap) +7 -PAGE_SHIFT ; -if (order <0 ) - order =0 ; +int order =get_order (sizeof (struct pasid_entry ) * iommu->pasid_max);if (iommu->pasid_table) {free_pages ((unsigned long )iommu->pasid_table, order);
@@ -371,8 +377,8 @@ int intel_svm_bind_mm(struct device *dev } svm->iommu = iommu; -if (pasid_max >2 <<ecap_pss (iommu->ecap)) - pasid_max =2 <<ecap_pss (iommu->ecap); +if (pasid_max > iommu->pasid_max) + pasid_max = iommu->pasid_max;/* Do not use PASID 0 in caching mode (virtualised IOMMU) */ ret = idr_alloc(&iommu->pasid_idr, svm,
include/linux/intel-iommu.h +1 -0
@@ -429,6 +429,7 @@ struct intel_iommu {struct page_req_dsc *prq;unsigned char prq_name[16 ];/* Name for PRQ interrupt */ struct idr pasid_idr; +u32 pasid_max;#endif struct q_inval *qi;/* Queued invalidation info */ u32 *iommu_state;/* Store iommu states between suspend and resume.*/
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/iommu-vt-d-fix-iommu-lookup-for-sr-iov-virtual-functions.patch queue-4.4/iommu-vt-d-fix-pasid-table-allocation.patch