IOMMU Fixes for Linux v4.7-rc5

Three fixes:
 
 	* Fix use of smp_processor_id() in preemptible code in the IOVA
 	  allocation code. This got introduced with the scalability
 	  improvements in this release cycle.
 
 	* A VT-d fix for out-of-bounds access of the iommu->domains
 	  array. The bug showed during suspend/resume.
 
 	* AMD IOMMU fix to print the correct device id in the ACPI
 	  parsing code.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJXdoyGAAoJECvwRC2XARrj4s4QANfX5U108HnHvSNZL7dOhQlQ
 RkghYuAgK3Bzgo89WNoNOVat+Q0t+sdqz+4aktbEydrHXgn+8EOLfId1ixzBb0+O
 SWQ1myTtfCMM0quQTG8KMPZli18aEFyWY0P+K/OGZd8YXU9u6xoKArlz8AyBxfIF
 DBuHbYdc646aO763MpkX1WSjnagBEBT/bp90k26smHGoqJNBroXXAo5KEhFdXxNB
 CARM99R9PjatnggU/xSXaUXv3oC+J2Qo1MgWxrARQOIJPkIXuAzS8fgItvUgcxnx
 NZeUpSRBRRe+za0H3vFC7K6D8HlTQ7lhlODzP82gTzzRyG7N5A4+n7zu9p1qeT8w
 fi7Hak7tjp+xQsYp2xDVcKsL3ghLVjqmDrjCBLKGRX/7CeEOIG7eTKV9hsxVUO+q
 Bvjx+Lc+XKuDdLJmhGCueFxZDfBJJBLDSP7HBFRHdhVuovvhxvALik5Hd3pgC+iz
 08zcHzyiLVYKI58t3K3q1OTKo0cIlsk6SWPJHFUR/B3ghcGT9eLgQjXVQIC+jaAD
 RK2/6yl/zfg1mZv5tyX7kGBGB2FfUXQ48eCR/TZnzh2AmEK1P10kc6XJUXfj/hrV
 eJkKnuh1FaRG/PnHzxic/T20aAYhFjp8fmKDqUgoJla8q6h73LZSOfRqgoAknDTa
 0+EASaDbIsU9nHtHxEz8
 =ogRx
 -----END PGP SIGNATURE-----

Merge tag 'iommu-fixes-v4.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull IOMMU fixes from Joerg Roedel:
 "Three fixes:

   - Fix use of smp_processor_id() in preemptible code in the IOVA
     allocation code.  This got introduced with the scalability
     improvements in this release cycle.

   - A VT-d fix for out-of-bounds access of the iommu->domains array.
     The bug showed during suspend/resume.

   - AMD IOMMU fix to print the correct device id in the ACPI parsing
     code"

* tag 'iommu-fixes-v4.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu/amd: Initialize devid variable before using it
  iommu/vt-d: Fix overflow of iommu->domains array
  iommu/iova: Disable preemption around use of this_cpu_ptr()
This commit is contained in:
Linus Torvalds 2016-07-01 09:13:31 -07:00
commit aa7a6c8e52
3 changed files with 8 additions and 4 deletions

View File

@ -1107,13 +1107,13 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
break; break;
} }
devid = e->devid;
DUMP_printk(" DEV_ACPI_HID(%s[%s])\t\tdevid: %02x:%02x.%x\n", DUMP_printk(" DEV_ACPI_HID(%s[%s])\t\tdevid: %02x:%02x.%x\n",
hid, uid, hid, uid,
PCI_BUS_NUM(devid), PCI_BUS_NUM(devid),
PCI_SLOT(devid), PCI_SLOT(devid),
PCI_FUNC(devid)); PCI_FUNC(devid));
devid = e->devid;
flags = e->flags; flags = e->flags;
ret = add_acpi_hid_device(hid, uid, &devid, false); ret = add_acpi_hid_device(hid, uid, &devid, false);

View File

@ -4607,7 +4607,7 @@ static void free_all_cpu_cached_iovas(unsigned int cpu)
if (!iommu) if (!iommu)
continue; continue;
for (did = 0; did < 0xffff; did++) { for (did = 0; did < cap_ndoms(iommu->cap); did++) {
domain = get_iommu_domain(iommu, did); domain = get_iommu_domain(iommu, did);
if (!domain) if (!domain)

View File

@ -420,8 +420,10 @@ retry:
/* Try replenishing IOVAs by flushing rcache. */ /* Try replenishing IOVAs by flushing rcache. */
flushed_rcache = true; flushed_rcache = true;
preempt_disable();
for_each_online_cpu(cpu) for_each_online_cpu(cpu)
free_cpu_cached_iovas(cpu, iovad); free_cpu_cached_iovas(cpu, iovad);
preempt_enable();
goto retry; goto retry;
} }
@ -749,7 +751,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
bool can_insert = false; bool can_insert = false;
unsigned long flags; unsigned long flags;
cpu_rcache = this_cpu_ptr(rcache->cpu_rcaches); cpu_rcache = get_cpu_ptr(rcache->cpu_rcaches);
spin_lock_irqsave(&cpu_rcache->lock, flags); spin_lock_irqsave(&cpu_rcache->lock, flags);
if (!iova_magazine_full(cpu_rcache->loaded)) { if (!iova_magazine_full(cpu_rcache->loaded)) {
@ -779,6 +781,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
iova_magazine_push(cpu_rcache->loaded, iova_pfn); iova_magazine_push(cpu_rcache->loaded, iova_pfn);
spin_unlock_irqrestore(&cpu_rcache->lock, flags); spin_unlock_irqrestore(&cpu_rcache->lock, flags);
put_cpu_ptr(rcache->cpu_rcaches);
if (mag_to_free) { if (mag_to_free) {
iova_magazine_free_pfns(mag_to_free, iovad); iova_magazine_free_pfns(mag_to_free, iovad);
@ -812,7 +815,7 @@ static unsigned long __iova_rcache_get(struct iova_rcache *rcache,
bool has_pfn = false; bool has_pfn = false;
unsigned long flags; unsigned long flags;
cpu_rcache = this_cpu_ptr(rcache->cpu_rcaches); cpu_rcache = get_cpu_ptr(rcache->cpu_rcaches);
spin_lock_irqsave(&cpu_rcache->lock, flags); spin_lock_irqsave(&cpu_rcache->lock, flags);
if (!iova_magazine_empty(cpu_rcache->loaded)) { if (!iova_magazine_empty(cpu_rcache->loaded)) {
@ -834,6 +837,7 @@ static unsigned long __iova_rcache_get(struct iova_rcache *rcache,
iova_pfn = iova_magazine_pop(cpu_rcache->loaded, limit_pfn); iova_pfn = iova_magazine_pop(cpu_rcache->loaded, limit_pfn);
spin_unlock_irqrestore(&cpu_rcache->lock, flags); spin_unlock_irqrestore(&cpu_rcache->lock, flags);
put_cpu_ptr(rcache->cpu_rcaches);
return iova_pfn; return iova_pfn;
} }