Intel IOMMU fixes from 2.6.39.2
This commit is contained in:
parent
b67156cd9e
commit
198deb8acf
|
@ -0,0 +1,37 @@
|
|||
From 8519dc4401ddf8a5399f979870bbeeadbc111186 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Habeck <habeck@sgi.com>
|
||||
Date: Sat, 28 May 2011 13:15:07 -0500
|
||||
Subject: intel-iommu: Add domain check in domain_remove_one_dev_info
|
||||
|
||||
From: Mike Habeck <habeck@sgi.com>
|
||||
|
||||
commit 8519dc4401ddf8a5399f979870bbeeadbc111186 upstream.
|
||||
|
||||
The comment in domain_remove_one_dev_info() states "No need to compare
|
||||
PCI domain; it has to be the same". But for the si_domain that isn't
|
||||
going to be true, as it consists of all the PCI devices that are
|
||||
identity mapped thus multiple PCI domains can be in si_domain. The
|
||||
code needs to validate the PCI domain too.
|
||||
|
||||
Signed-off-by: Mike Habeck <habeck@sgi.com>
|
||||
Signed-off-by: Mike Travis <travis@sgi.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -3398,8 +3398,8 @@ static void domain_remove_one_dev_info(s
|
||||
spin_lock_irqsave(&device_domain_lock, flags);
|
||||
list_for_each_safe(entry, tmp, &domain->devices) {
|
||||
info = list_entry(entry, struct device_domain_info, link);
|
||||
- /* No need to compare PCI domain; it has to be the same */
|
||||
- if (info->bus == pdev->bus->number &&
|
||||
+ if (info->segment == pci_domain_nr(pdev->bus) &&
|
||||
+ info->bus == pdev->bus->number &&
|
||||
info->devfn == pdev->devfn) {
|
||||
list_del(&info->link);
|
||||
list_del(&info->global);
|
|
@ -0,0 +1,53 @@
|
|||
From 8fcc5372fbac085199d84a880503ed67aba3fe49 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Wright <chrisw@sous-sol.org>
|
||||
Date: Sat, 28 May 2011 13:15:02 -0500
|
||||
Subject: intel-iommu: Check for identity mapping candidate using
|
||||
system dma mask
|
||||
|
||||
From: Chris Wright <chrisw@sous-sol.org>
|
||||
|
||||
commit 8fcc5372fbac085199d84a880503ed67aba3fe49 upstream.
|
||||
|
||||
The identity mapping code appears to make the assumption that if the
|
||||
devices dma_mask is greater than 32bits the device can use identity
|
||||
mapping. But that is not true: take the case where we have a 40bit
|
||||
device in a 44bit architecture. The device can potentially receive a
|
||||
physical address that it will truncate and cause incorrect addresses
|
||||
to be used.
|
||||
|
||||
Instead check to see if the device's dma_mask is large enough
|
||||
to address the system's dma_mask.
|
||||
|
||||
Signed-off-by: Mike Travis <travis@sgi.com>
|
||||
Reviewed-by: Mike Habeck <habeck@sgi.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 15 +++++++++++++--
|
||||
1 file changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -2190,8 +2190,19 @@ static int iommu_should_identity_map(str
|
||||
* Assume that they will -- if they turn out not to be, then we can
|
||||
* take them out of the 1:1 domain later.
|
||||
*/
|
||||
- if (!startup)
|
||||
- return pdev->dma_mask > DMA_BIT_MASK(32);
|
||||
+ if (!startup) {
|
||||
+ /*
|
||||
+ * If the device's dma_mask is less than the system's memory
|
||||
+ * size then this is not a candidate for identity mapping.
|
||||
+ */
|
||||
+ u64 dma_mask = pdev->dma_mask;
|
||||
+
|
||||
+ if (pdev->dev.coherent_dma_mask &&
|
||||
+ pdev->dev.coherent_dma_mask < dma_mask)
|
||||
+ dma_mask = pdev->dev.coherent_dma_mask;
|
||||
+
|
||||
+ return dma_mask >= dma_get_required_mask(&pdev->dev);
|
||||
+ }
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
From 1c9fc3d11b84fbd0c4f4aa7855702c2a1f098ebb Mon Sep 17 00:00:00 2001
|
||||
From: Chris Wright <chrisw@sous-sol.org>
|
||||
Date: Sat, 28 May 2011 13:15:04 -0500
|
||||
Subject: intel-iommu: Dont cache iova above 32bit
|
||||
|
||||
From: Chris Wright <chrisw@sous-sol.org>
|
||||
|
||||
commit 1c9fc3d11b84fbd0c4f4aa7855702c2a1f098ebb upstream.
|
||||
|
||||
Mike Travis and Mike Habeck reported an issue where iova allocation
|
||||
would return a range that was larger than a device's dma mask.
|
||||
|
||||
https://lkml.org/lkml/2011/3/29/423
|
||||
|
||||
The dmar initialization code will reserve all PCI MMIO regions and copy
|
||||
those reservations into a domain specific iova tree. It is possible for
|
||||
one of those regions to be above the dma mask of a device. It is typical
|
||||
to allocate iovas with a 32bit mask (despite device's dma mask possibly
|
||||
being larger) and cache the result until it exhausts the lower 32bit
|
||||
address space. Freeing the iova range that is >= the last iova in the
|
||||
lower 32bit range when there is still an iova above the 32bit range will
|
||||
corrupt the cached iova by pointing it to a region that is above 32bit.
|
||||
If that region is also larger than the device's dma mask, a subsequent
|
||||
allocation will return an unusable iova and cause dma failure.
|
||||
|
||||
Simply don't cache an iova that is above the 32bit caching boundary.
|
||||
|
||||
Reported-by: Mike Travis <travis@sgi.com>
|
||||
Reported-by: Mike Habeck <habeck@sgi.com>
|
||||
Acked-by: Mike Travis <travis@sgi.com>
|
||||
Tested-by: Mike Habeck <habeck@sgi.com>
|
||||
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/iova.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/iova.c
|
||||
+++ b/drivers/pci/iova.c
|
||||
@@ -63,8 +63,16 @@ __cached_rbnode_delete_update(struct iov
|
||||
curr = iovad->cached32_node;
|
||||
cached_iova = container_of(curr, struct iova, node);
|
||||
|
||||
- if (free->pfn_lo >= cached_iova->pfn_lo)
|
||||
- iovad->cached32_node = rb_next(&free->node);
|
||||
+ if (free->pfn_lo >= cached_iova->pfn_lo) {
|
||||
+ struct rb_node *node = rb_next(&free->node);
|
||||
+ struct iova *iova = container_of(node, struct iova, node);
|
||||
+
|
||||
+ /* only cache if it's below 32bit pfn */
|
||||
+ if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
|
||||
+ iovad->cached32_node = node;
|
||||
+ else
|
||||
+ iovad->cached32_node = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Computes the padding size required, to make the
|
|
@ -0,0 +1,36 @@
|
|||
From 7b668357810ecb5fdda4418689d50f5d95aea6a8 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Williamson <alex.williamson@redhat.com>
|
||||
Date: Tue, 24 May 2011 12:02:41 +0100
|
||||
Subject: intel-iommu: Flush unmaps at domain_exit
|
||||
|
||||
From: Alex Williamson <alex.williamson@redhat.com>
|
||||
|
||||
commit 7b668357810ecb5fdda4418689d50f5d95aea6a8 upstream.
|
||||
|
||||
We typically batch unmaps to be lazily flushed out at
|
||||
regular intervals. When we destroy a domain, we need
|
||||
to force a flush of these lazy unmaps to be sure none
|
||||
reference the domain we're about to free.
|
||||
|
||||
Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=35062
|
||||
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -1416,6 +1416,10 @@ static void domain_exit(struct dmar_doma
|
||||
if (!domain)
|
||||
return;
|
||||
|
||||
+ /* Flush any lazy unmaps that may reference this domain */
|
||||
+ if (!intel_iommu_strict)
|
||||
+ flush_unmaps_timeout(0);
|
||||
+
|
||||
domain_remove_dev_info(domain);
|
||||
/* destroy iovas */
|
||||
put_iova_domain(&domain->iovad);
|
|
@ -0,0 +1,48 @@
|
|||
From 9b4554b21ed07e8556405510638171f0c787742a Mon Sep 17 00:00:00 2001
|
||||
From: Alex Williamson <alex.williamson@redhat.com>
|
||||
Date: Tue, 24 May 2011 12:19:04 -0400
|
||||
Subject: intel-iommu: Only unlink device domains from iommu
|
||||
|
||||
From: Alex Williamson <alex.williamson@redhat.com>
|
||||
|
||||
commit 9b4554b21ed07e8556405510638171f0c787742a upstream.
|
||||
|
||||
Commit a97590e5 added unlinking domains from iommus to reciprocate the
|
||||
iommu from domains unlinking that was already done. We actually want
|
||||
to only do this for device domains and never for the static
|
||||
identity map domain or VM domains. The SI domain is special and
|
||||
never freed, while VM domain->id lives in their own special address
|
||||
space, separate from iommu->domain_ids.
|
||||
|
||||
In the current code, a VM can get domain->id zero, then mark that
|
||||
domain unused when unbound from pci-stub. This leads to DMAR
|
||||
write faults when the device is re-bound to the host driver.
|
||||
|
||||
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -3422,10 +3422,13 @@ static void domain_remove_one_dev_info(s
|
||||
domain_update_iommu_cap(domain);
|
||||
spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
|
||||
|
||||
- spin_lock_irqsave(&iommu->lock, tmp_flags);
|
||||
- clear_bit(domain->id, iommu->domain_ids);
|
||||
- iommu->domains[domain->id] = NULL;
|
||||
- spin_unlock_irqrestore(&iommu->lock, tmp_flags);
|
||||
+ if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
|
||||
+ !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
|
||||
+ spin_lock_irqsave(&iommu->lock, tmp_flags);
|
||||
+ clear_bit(domain->id, iommu->domain_ids);
|
||||
+ iommu->domains[domain->id] = NULL;
|
||||
+ spin_unlock_irqrestore(&iommu->lock, tmp_flags);
|
||||
+ }
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
|
@ -0,0 +1,44 @@
|
|||
From 825507d6d059f1cbe2503e0e5a3926225b983aec Mon Sep 17 00:00:00 2001
|
||||
From: Mike Travis <travis@sgi.com>
|
||||
Date: Sat, 28 May 2011 13:15:06 -0500
|
||||
Subject: intel-iommu: Remove Host Bridge devices from identity
|
||||
mapping
|
||||
|
||||
From: Mike Travis <travis@sgi.com>
|
||||
|
||||
commit 825507d6d059f1cbe2503e0e5a3926225b983aec upstream.
|
||||
|
||||
When using the 1:1 (identity) PCI DMA remapping, PCI Host Bridge devices
|
||||
that do not use the IOMMU causes a kernel panic. Fix that by not
|
||||
inserting those devices into the si_domain.
|
||||
|
||||
Signed-off-by: Mike Travis <travis@sgi.com>
|
||||
Reviewed-by: Mike Habeck <habeck@sgi.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -46,6 +46,8 @@
|
||||
#define ROOT_SIZE VTD_PAGE_SIZE
|
||||
#define CONTEXT_SIZE VTD_PAGE_SIZE
|
||||
|
||||
+#define IS_BRIDGE_HOST_DEVICE(pdev) \
|
||||
+ ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
|
||||
#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
|
||||
#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
|
||||
#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
|
||||
@@ -2217,6 +2219,9 @@ static int __init iommu_prepare_static_i
|
||||
return -EFAULT;
|
||||
|
||||
for_each_pci_dev(pdev) {
|
||||
+ /* Skip Host/PCI Bridge devices */
|
||||
+ if (IS_BRIDGE_HOST_DEVICE(pdev))
|
||||
+ continue;
|
||||
if (iommu_should_identity_map(pdev, 1)) {
|
||||
printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n",
|
||||
hw ? "hardware" : "software", pci_name(pdev));
|
|
@ -0,0 +1,43 @@
|
|||
From cb452a4040bb051d92e85d6e7eb60c11734c1781 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Travis <travis@sgi.com>
|
||||
Date: Sat, 28 May 2011 13:15:03 -0500
|
||||
Subject: intel-iommu: Speed up processing of the identity_mapping
|
||||
function
|
||||
|
||||
From: Mike Travis <travis@sgi.com>
|
||||
|
||||
commit cb452a4040bb051d92e85d6e7eb60c11734c1781 upstream.
|
||||
|
||||
When there are a large count of PCI devices, and the pass through
|
||||
option for iommu is set, much time is spent in the identity_mapping
|
||||
function hunting though the iommu domains to check if a specific
|
||||
device is "identity mapped".
|
||||
|
||||
Speed up the function by checking the cached info to see if
|
||||
it's mapped to the static identity domain.
|
||||
|
||||
Signed-off-by: Mike Travis <travis@sgi.com>
|
||||
Reviewed-by: Mike Habeck <habeck@sgi.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -2109,10 +2109,10 @@ static int identity_mapping(struct pci_d
|
||||
if (likely(!iommu_identity_mapping))
|
||||
return 0;
|
||||
|
||||
+ info = pdev->dev.archdata.iommu;
|
||||
+ if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
|
||||
+ return (info->domain == si_domain);
|
||||
|
||||
- list_for_each_entry(info, &si_domain->devices, link)
|
||||
- if (info->dev == pdev)
|
||||
- return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
From c681d0ba1252954208220ad32248a3e8e2fc98e4 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Travis <travis@sgi.com>
|
||||
Date: Sat, 28 May 2011 13:15:05 -0500
|
||||
Subject: intel-iommu: Use coherent DMA mask when requested
|
||||
|
||||
From: Mike Travis <travis@sgi.com>
|
||||
|
||||
commit c681d0ba1252954208220ad32248a3e8e2fc98e4 upstream.
|
||||
|
||||
The __intel_map_single function is not honoring the passed in DMA mask.
|
||||
This results in not using the coherent DMA mask when called from
|
||||
intel_alloc_coherent().
|
||||
|
||||
Signed-off-by: Mike Travis <travis@sgi.com>
|
||||
Acked-by: Chris Wright <chrisw@sous-sol.org>
|
||||
Reviewed-by: Mike Habeck <habeck@sgi.com>
|
||||
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/pci/intel-iommu.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/intel-iommu.c
|
||||
+++ b/drivers/pci/intel-iommu.c
|
||||
@@ -2606,8 +2606,7 @@ static dma_addr_t __intel_map_single(str
|
||||
iommu = domain_get_iommu(domain);
|
||||
size = aligned_nrpages(paddr, size);
|
||||
|
||||
- iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
|
||||
- pdev->dma_mask);
|
||||
+ iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask);
|
||||
if (!iova)
|
||||
goto error;
|
||||
|
20
kernel.spec
20
kernel.spec
|
@ -708,6 +708,14 @@ Patch1842: drm-radeon-pageflip-oops-fix.patch
|
|||
Patch1843: drm-radeon-update3.patch
|
||||
|
||||
Patch1900: linux-2.6-intel-iommu-igfx.patch
|
||||
Patch1901: intel-iommu-flush-unmaps-at-domain_exit.patch
|
||||
Patch1902: intel-iommu-only-unlink-device-domains-from-iommu.patch
|
||||
Patch1903: intel-iommu-check-for-identity-mapping-candidate-using.patch
|
||||
Patch1904: intel-iommu-speed-up-processing-of-the-identity_mapping.patch
|
||||
Patch1905: intel-iommu-dont-cache-iova-above-32bit.patch
|
||||
Patch1906: intel-iommu-use-coherent-dma-mask-when-requested.patch
|
||||
Patch1907: intel-iommu-remove-host-bridge-devices-from-identity.patch
|
||||
Patch1908: intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch
|
||||
|
||||
# linux1394 git patches
|
||||
Patch2200: linux-2.6-firewire-git-update.patch
|
||||
|
@ -1231,6 +1239,15 @@ ApplyPatch x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available
|
|||
#
|
||||
# Intel IOMMU
|
||||
#
|
||||
# from 2.6.39.2
|
||||
ApplyPatch intel-iommu-flush-unmaps-at-domain_exit.patch
|
||||
ApplyPatch intel-iommu-only-unlink-device-domains-from-iommu.patch
|
||||
ApplyPatch intel-iommu-check-for-identity-mapping-candidate-using.patch
|
||||
ApplyPatch intel-iommu-speed-up-processing-of-the-identity_mapping.patch
|
||||
ApplyPatch intel-iommu-dont-cache-iova-above-32bit.patch
|
||||
ApplyPatch intel-iommu-use-coherent-dma-mask-when-requested.patch
|
||||
ApplyPatch intel-iommu-remove-host-bridge-devices-from-identity.patch
|
||||
ApplyPatch intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch
|
||||
|
||||
#
|
||||
# PowerPC
|
||||
|
@ -2049,6 +2066,9 @@ fi
|
|||
# and build.
|
||||
|
||||
%changelog
|
||||
* Sat Jun 25 2011 Chuck Ebbert <cebbert@redhat.com>
|
||||
- Intel IOMMU fixes from 2.6.39.2
|
||||
|
||||
* Fri Jun 24 2011 Chuck Ebbert <cebbert@redhat.com>
|
||||
- Minor cleanup: use upstream patch to export block_{get,put}_queue
|
||||
- block-blkdev_get-should-access-bd_disk-only-after.patch:
|
||||
|
|
Loading…
Reference in New Issue