iommu/vt-d: Fixes for v5.16-rc3
Subsystems (2)
Lu Baolu
maintainerv2 cover iommu/vt-d: Fixes for v5.16-rc3
Hi Joerg,
Update this series with a fix for an issue reported by Intel 0-day robot. Sorry for the inconvenience.
Best regards,
baolu
change log:
v1:
https://lore.kernel.org/all/[email protected]/
v2: For the patch titled "iommu/vt-d: Fix unmap_pages support",
fixed below issue reported by Intel 0-day robot.
"drivers/iommu/intel/iommu.c:1344:7: warning: variable 'level_pfn' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
"
Alex Williamson (1):
iommu/vt-d: Fix unmap_pages support
Christophe JAILLET (1):
iommu/vt-d: Fix an unbalanced rcu_read_lock/rcu_read_unlock()
drivers/iommu/intel/cap_audit.c | 5 +++-- drivers/iommu/intel/iommu.c | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-)
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerPATCH v2 1/2 iommu/vt-d: Fix an unbalanced rcu_read_lock/rcu_read_unlock()
From: Christophe JAILLET <[email protected]>
If we return -EOPNOTSUPP, the rcu lock remains lock. This is spurious. Go through the end of the function instead. This way, the missing 'rcu_read_unlock()' is called.
--- drivers/iommu/intel/cap_audit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/iommu/intel/cap_audit.c +3 -2
@@ -144,6 +144,7 @@ static int cap_audit_static(struct intel_iommu *iommu, enum cap_audit_type type) {struct dmar_drhd_unit *d;struct intel_iommu *i; +int rc =0 ;rcu_read_lock ();if (list_empty (&dmar_drhd_units))
@@ -169,11 +170,11 @@ static int cap_audit_static(struct intel_iommu *iommu, enum cap_audit_type type)*/ if (intel_cap_smts_sanity () && !intel_cap_flts_sanity () && !intel_cap_slts_sanity ()) -return -EOPNOTSUPP ; + rc = -EOPNOTSUPP ; out:rcu_read_unlock (); -return 0 ; +return rc; }int intel_cap_audit (enum cap_audit_type type,struct intel_iommu *iommu)
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerPATCH v2 2/2 iommu/vt-d: Fix unmap_pages support
In reply to Lu BaoluFrom: Alex Williamson <[email protected]>
When supporting only the .map and .unmap callbacks of iommu_ops, the IOMMU driver can make assumptions about the size and alignment used for mappings based on the driver provided pgsize_bitmap. VT-d previously used essentially PAGE_MASK for this bitmap as any power of two mapping was acceptably filled by native page sizes.
However, with the .map_pages and .unmap_pages interface we're now getting page-size and count arguments. If we simply combine these as (page-size * count) and make use of the previous map/unmap functions internally, any size and alignment assumptions are very different.
As an example, a given vfio device assignment VM will often create a 4MB mapping at IOVA pfn [0x3fe00 - 0x401ff]. On a system that does not support IOMMU super pages, the unmap_pages interface will ask to unmap 1024 4KB pages at the base IOVA. dma_pte_clear_level() will recurse down to level 2 of the page table where the first half of the pfn range exactly matches the entire pte level. We clear the pte, increment the pfn by the level size, but (oops) the next pte is on a new page, so we exit the loop an pop back up a level. When we then update the pfn based on that higher level, we seem to assume that the previous pfn value was at the start of the level. In this case the level size is 256K pfns, which we add to the base pfn and get a results of 0x7fe00, which is clearly greater than 0x401ff, so we're done. Meanwhile we never cleared the ptes for the remainder of the range. When the VM remaps this range, we're overwriting valid ptes and the VT-d driver complains loudly, as reported by the user report linked below.
The fix for this seems relatively simple, if each iteration of the loop in dma_pte_clear_level() is assumed to clear to the end of the level pte page, then our next pfn should be calculated from level_pfn rather than our working pfn.
--- drivers/iommu/intel/iommu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/iommu/intel/iommu.c +2 -4
@@ -1339,13 +1339,11 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level, pte = &pte[pfn_level_offset (pfn, level)]; do { - unsigned long level_pfn; + unsigned long level_pfn = pfn & level_mask(level); if (!dma_pte_present(pte)) goto next; - level_pfn = pfn & level_mask(level); - /* If range covers entire pagetable, free it */ if (start_pfn <= level_pfn && last_pfn >= level_pfn + level_size(level) - 1) {
@@ -1366,7 +1364,7 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level, freelist); } next: - pfn +=level_size (level); + pfn = level_pfn +level_size (level); }while (!first_pte_in_page (++pte) && pfn <= last_pfn);if (first_pte)
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Joerg Roedel
maintainerQuoted 2 lines · Lu Baolu
Update this series with a fix for an issue reported by Intel 0-day robot. Sorry for the inconvenience.
Replaced those with the previous fixes, thanks. Please just send a fix on-top next time. This was already in the published fixes branch, which I had to rebase now.
Thanks,
Joerg
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerQuoted 7 lines · Joerg Roedel
Quoted 2 lines · Lu Baolu
Update this series with a fix for an issue reported by Intel 0-day robot. Sorry for the inconvenience.
Replaced those with the previous fixes, thanks. Please just send a fix on-top next time. This was already in the published fixes branch, which I had to rebase now.
Sure.
Best regards,
baolu
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu