Skip to contentSkip to conversation

Fix remaining RMRR issues

PATCH New Joerg Roedel 2 participants 4 messages Oct 1, 2015 IOMMU

lore
Share & tools
lore

Joerg Roedel

author maintainer
#0 lore raw

cover Fix remaining RMRR issues

Hi,

here is a patch-set to fix a remaining RMRR issue in the VT-d driver. The problem was that RMRR mappings are only created for boot-time (or hotplug-time) allocated domains.

Domains allocated on demand don't get RMRR mappings, which is bad for the kdump case, for example. With this patch-set the on-demand domains also get RMRR mappings.

Regards,

Joerg

Joerg Roedel (2):
iommu/vt-d: Split iommu_prepare_identity_map iommu/vt-d: Create RMRR mappings in newly allocated domains

 drivers/iommu/intel-iommu.c | 60 +++++++++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 18 deletions(-)
Signature · 1 line
1.9.1
author maintainer
#1 lore raw

PATCH 1/2 iommu/vt-d: Split iommu_prepare_identity_map

From: Joerg Roedel <[email protected]>

Split the part of the function that fetches the domain out and put the rest into into a domain_prepare_identity_map, so that the code can also be used with when the domain is already known.

---
 drivers/iommu/intel-iommu.c | 40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)
drivers/iommu/intel-iommu.c +22 -18
index 2d7349a..e182d81 100644
@@ -2429,17 +2429,13 @@ static int iommu_domain_identity_map(struct dmar_domain *domain,
 				  DMA_PTE_READ|DMA_PTE_WRITE);
 }
 
-static int iommu_prepare_identity_map(struct device *dev,
-				      unsigned long long start,
-				      unsigned long long end)
+static int domain_prepare_identity_map(struct device *dev,
+				       struct dmar_domain *domain,
+				       unsigned long long start,
+				       unsigned long long end)
 {
-	struct dmar_domain *domain;
 	int ret;
 
-	domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
-	if (!domain)
-		return -ENOMEM;
-
 	/* For _hardware_ passthrough, don't bother. But for software
 	   passthrough, we do it anyway -- it may indicate a memory
 	   range which is reserved in E820, so which didn't get set
@@ -2459,8 +2455,7 @@ static int iommu_prepare_identity_map(struct device *dev,
 			dmi_get_system_info(DMI_BIOS_VENDOR),
 			dmi_get_system_info(DMI_BIOS_VERSION),
 		     dmi_get_system_info(DMI_PRODUCT_VERSION));
-		ret = -EIO;
-		goto error;
+		return -EIO;
 	}
 
 	if (end >> agaw_to_width(domain->agaw)) {
@@ -2470,18 +2465,27 @@ static int iommu_prepare_identity_map(struct device *dev,
 		     dmi_get_system_info(DMI_BIOS_VENDOR),
 		     dmi_get_system_info(DMI_BIOS_VERSION),
 		     dmi_get_system_info(DMI_PRODUCT_VERSION));
-		ret = -EIO;
-		goto error;
+		return -EIO;
 	}
 
-	ret = iommu_domain_identity_map(domain, start, end);
-	if (ret)
-		goto error;
+	return iommu_domain_identity_map(domain, start, end);
+}
 
-	return 0;
+static int iommu_prepare_identity_map(struct device *dev,
+				      unsigned long long start,
+				      unsigned long long end)
+{
+	struct dmar_domain *domain;
+	int ret;
+
+	domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	if (!domain)
+		return -ENOMEM;
+
+	ret = domain_prepare_identity_map(dev, domain, start, end);
+	if (ret)
+		domain_exit(domain);
 
- error:
-	domain_exit(domain);
 	return ret;
 }
 
Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH 1/2] iommu/vt-d: Split iommu_prepare_identity_map

config: ia64-allyesconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git…

Hi Joerg,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please ignore]

config: ia64-allyesconfig (attached as .config)
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
git checkout 75170658f4350889e0d0d404c5bb17179797bd47
# save the attached .config to linux build tree
make.cross ARCH=ia64

All warnings (new ones prefixed by >>):

drivers/iommu/intel-iommu.c: In function 'domain_prepare_identity_map':

>> drivers/iommu/intel-iommu.c:2437:6: warning: unused variable 'ret' [-Wunused-variable]
     int ret;
         ^

vim +/ret +2437 drivers/iommu/intel-iommu.c

ba395927 drivers/pci/intel-iommu.c   Keshavamurthy, Anil S 2007-10-21  2421  	/*
ba395927 drivers/pci/intel-iommu.c   Keshavamurthy, Anil S 2007-10-21  2422  	 * RMRR range might have overlap with physical memory range,
ba395927 drivers/pci/intel-iommu.c   Keshavamurthy, Anil S 2007-10-21  2423  	 * clear it first
ba395927 drivers/pci/intel-iommu.c   Keshavamurthy, Anil S 2007-10-21  2424  	 */
c5395d5c drivers/pci/intel-iommu.c   David Woodhouse       2009-06-28  2425  	dma_pte_clear_range(domain, first_vpfn, last_vpfn);
ba395927 drivers/pci/intel-iommu.c   Keshavamurthy, Anil S 2007-10-21  2426  
c5395d5c drivers/pci/intel-iommu.c   David Woodhouse       2009-06-28  2427  	return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
c5395d5c drivers/pci/intel-iommu.c   David Woodhouse       2009-06-28  2428  				  last_vpfn - first_vpfn + 1,
ba395927 drivers/pci/intel-iommu.c   Keshavamurthy, Anil S 2007-10-21  2429  				  DMA_PTE_READ|DMA_PTE_WRITE);
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26  2430  }
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26  2431  
75170658 drivers/iommu/intel-iommu.c Joerg Roedel          2015-10-01  2432  static int domain_prepare_identity_map(struct device *dev,
75170658 drivers/iommu/intel-iommu.c Joerg Roedel          2015-10-01  2433  				       struct dmar_domain *domain,
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26  2434  				       unsigned long long start,
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26  2435  				       unsigned long long end)
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26  2436  {
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26 @2437  	int ret;
b213203e drivers/pci/intel-iommu.c   David Woodhouse       2009-06-26  2438  
19943b0e drivers/pci/intel-iommu.c   David Woodhouse       2009-08-04  2439  	/* For _hardware_ passthrough, don't bother. But for software
19943b0e drivers/pci/intel-iommu.c   David Woodhouse       2009-08-04  2440  	   passthrough, we do it anyway -- it may indicate a memory
19943b0e drivers/pci/intel-iommu.c   David Woodhouse       2009-08-04  2441  	   range which is reserved in E820, so which didn't get set
19943b0e drivers/pci/intel-iommu.c   David Woodhouse       2009-08-04  2442  	   up to start with in si_domain */
19943b0e drivers/pci/intel-iommu.c   David Woodhouse       2009-08-04  2443  	if (domain == si_domain && hw_pass_through) {
9f10e5bf drivers/iommu/intel-iommu.c Joerg Roedel          2015-06-12  2444  		pr_warn("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
0b9d9753 drivers/iommu/intel-iommu.c David Woodhouse       2014-03-09  2445  			dev_name(dev), start, end);

:::::: The code at line 2437 was first introduced by commit
:::::: b213203e475212a69ad6fedfb73464087e317148 intel-iommu: Create new iommu_domain_identity_map() function

:::::: TO: David Woodhouse <[email protected]> :::::: CC: David Woodhouse <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

author maintainer
#3 lore raw

PATCH 2/2 iommu/vt-d: Create RMRR mappings in newly allocated domains

In reply to Joerg Roedel

From: Joerg Roedel <[email protected]>

Currently the RMRR entries are created only at boot time. This means they will vanish when the domain allocated at boot time is destroyed.
This patch makes sure that also newly allocated domains will get RMRR mappings.

---
 drivers/iommu/intel-iommu.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
drivers/iommu/intel-iommu.c +20 -0
index e182d81..e9ace17 100644
@@ -3243,7 +3243,10 @@ static struct iova *intel_alloc_iova(struct device *dev,
 
 static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
 {
+	struct dmar_rmrr_unit *rmrr;
 	struct dmar_domain *domain;
+	struct device *i_dev;
+	int i, ret;
 
 	domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 	if (!domain) {
@@ -3252,6 +3255,23 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
 		return NULL;
 	}
 
+	/* We have a new domain - setup possible RMRRs for the device */
+	rcu_read_lock();
+	for_each_rmrr_units(rmrr) {
+		for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
+					  i, i_dev) {
+			if (i_dev != dev)
+				continue;
+
+			ret = domain_prepare_identity_map(dev, domain,
+							  rmrr->base_address,
+							  rmrr->end_address);
+			if (ret)
+				dev_err(dev, "Mapping reserved region failed\n");
+		}
+	}
+	rcu_read_unlock();
+
 	return domain;
 }
 
Signature · 1 line
1.9.1