| From 4ed6a540fab8ea4388c1703b73ecfed68a2009d1 Mon Sep 17 00:00:00 2001 |
| From: David Woodhouse <David.Woodhouse@intel.com> |
| Date: Mon, 11 May 2015 14:59:20 +0100 |
| Subject: iommu/vt-d: Fix passthrough mode with translation-disabled devices |
| |
| From: David Woodhouse <David.Woodhouse@intel.com> |
| |
| commit 4ed6a540fab8ea4388c1703b73ecfed68a2009d1 upstream. |
| |
| When we use 'intel_iommu=igfx_off' to disable translation for the |
| graphics, and when we discover that the BIOS has misconfigured the DMAR |
| setup for I/OAT, we use a special DUMMY_DEVICE_DOMAIN_INFO value in |
| dev->archdata.iommu to indicate that translation is disabled. |
| |
| With passthrough mode, we were attempting to dereference that as a |
| normal pointer to a struct device_domain_info when setting up an |
| identity mapping for the affected device. |
| |
| This fixes the problem by making device_to_iommu() explicitly check for |
| the special value and indicate that no IOMMU was found to handle the |
| devices in question. |
| |
| Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/iommu/intel-iommu.c | 13 ++++++++----- |
| 1 file changed, 8 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/iommu/intel-iommu.c |
| +++ b/drivers/iommu/intel-iommu.c |
| @@ -673,6 +673,11 @@ static void domain_update_iommu_cap(stru |
| domain->iommu_superpage = domain_update_iommu_superpage(NULL); |
| } |
| |
| +static int iommu_dummy(struct device *dev) |
| +{ |
| + return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; |
| +} |
| + |
| static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn) |
| { |
| struct dmar_drhd_unit *drhd = NULL; |
| @@ -682,6 +687,9 @@ static struct intel_iommu *device_to_iom |
| u16 segment = 0; |
| int i; |
| |
| + if (iommu_dummy(dev)) |
| + return NULL; |
| + |
| if (dev_is_pci(dev)) { |
| pdev = to_pci_dev(dev); |
| segment = pci_domain_nr(pdev->bus); |
| @@ -2974,11 +2982,6 @@ static inline struct dmar_domain *get_va |
| return __get_valid_domain_for_dev(dev); |
| } |
| |
| -static int iommu_dummy(struct device *dev) |
| -{ |
| - return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; |
| -} |
| - |
| /* Check if the dev needs to go through non-identity map and unmap process.*/ |
| static int iommu_no_mapping(struct device *dev) |
| { |