aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/amd_iommu.c110
1 files changed, 49 insertions, 61 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 405f8dad7c77..d10195b685a7 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -111,6 +111,33 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
111 return ret; 111 return ret;
112} 112}
113 113
114/*
115 * This function checks if the driver got a valid device from the caller to
116 * avoid dereferencing invalid pointers.
117 */
118static bool check_device(struct device *dev)
119{
120 u16 devid;
121
122 if (!dev || !dev->dma_mask)
123 return false;
124
125 /* No device or no PCI device */
126 if (!dev || dev->bus != &pci_bus_type)
127 return false;
128
129 devid = get_device_id(dev);
130
131 /* Out of our scope? */
132 if (devid > amd_iommu_last_bdf)
133 return false;
134
135 if (amd_iommu_rlookup_table[devid] == NULL)
136 return false;
137
138 return true;
139}
140
114#ifdef CONFIG_AMD_IOMMU_STATS 141#ifdef CONFIG_AMD_IOMMU_STATS
115 142
116/* 143/*
@@ -1386,22 +1413,17 @@ static int device_change_notifier(struct notifier_block *nb,
1386 unsigned long action, void *data) 1413 unsigned long action, void *data)
1387{ 1414{
1388 struct device *dev = data; 1415 struct device *dev = data;
1389 struct pci_dev *pdev = to_pci_dev(dev); 1416 u16 devid;
1390 u16 devid = calc_devid(pdev->bus->number, pdev->devfn);
1391 struct protection_domain *domain; 1417 struct protection_domain *domain;
1392 struct dma_ops_domain *dma_domain; 1418 struct dma_ops_domain *dma_domain;
1393 struct amd_iommu *iommu; 1419 struct amd_iommu *iommu;
1394 unsigned long flags; 1420 unsigned long flags;
1395 1421
1396 if (devid > amd_iommu_last_bdf) 1422 if (!check_device(dev))
1397 goto out; 1423 return 0;
1398
1399 devid = amd_iommu_alias_table[devid];
1400
1401 iommu = amd_iommu_rlookup_table[devid];
1402 if (iommu == NULL)
1403 goto out;
1404 1424
1425 devid = get_device_id(dev);
1426 iommu = amd_iommu_rlookup_table[devid];
1405 domain = domain_for_device(dev); 1427 domain = domain_for_device(dev);
1406 1428
1407 if (domain && !dma_ops_domain(domain)) 1429 if (domain && !dma_ops_domain(domain))
@@ -1453,36 +1475,6 @@ static struct notifier_block device_nb = {
1453 *****************************************************************************/ 1475 *****************************************************************************/
1454 1476
1455/* 1477/*
1456 * This function checks if the driver got a valid device from the caller to
1457 * avoid dereferencing invalid pointers.
1458 */
1459static bool check_device(struct device *dev)
1460{
1461 u16 bdf;
1462 struct pci_dev *pcidev;
1463
1464 if (!dev || !dev->dma_mask)
1465 return false;
1466
1467 /* No device or no PCI device */
1468 if (!dev || dev->bus != &pci_bus_type)
1469 return false;
1470
1471 pcidev = to_pci_dev(dev);
1472
1473 bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
1474
1475 /* Out of our scope? */
1476 if (bdf > amd_iommu_last_bdf)
1477 return false;
1478
1479 if (amd_iommu_rlookup_table[bdf] == NULL)
1480 return false;
1481
1482 return true;
1483}
1484
1485/*
1486 * In the dma_ops path we only have the struct device. This function 1478 * In the dma_ops path we only have the struct device. This function
1487 * finds the corresponding IOMMU, the protection domain and the 1479 * finds the corresponding IOMMU, the protection domain and the
1488 * requestor id for a given device. 1480 * requestor id for a given device.
@@ -2094,15 +2086,20 @@ static void prealloc_protection_domains(void)
2094 struct pci_dev *dev = NULL; 2086 struct pci_dev *dev = NULL;
2095 struct dma_ops_domain *dma_dom; 2087 struct dma_ops_domain *dma_dom;
2096 struct amd_iommu *iommu; 2088 struct amd_iommu *iommu;
2097 u16 devid, __devid; 2089 u16 devid;
2098 2090
2099 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 2091 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
2100 __devid = devid = calc_devid(dev->bus->number, dev->devfn); 2092
2101 if (devid > amd_iommu_last_bdf) 2093 /* Do we handle this device? */
2094 if (!check_device(&dev->dev))
2102 continue; 2095 continue;
2103 devid = amd_iommu_alias_table[devid]; 2096
2097 /* Is there already any domain for it? */
2104 if (domain_for_device(&dev->dev)) 2098 if (domain_for_device(&dev->dev))
2105 continue; 2099 continue;
2100
2101 devid = get_device_id(&dev->dev);
2102
2106 iommu = amd_iommu_rlookup_table[devid]; 2103 iommu = amd_iommu_rlookup_table[devid];
2107 if (!iommu) 2104 if (!iommu)
2108 continue; 2105 continue;
@@ -2294,17 +2291,14 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
2294 struct device *dev) 2291 struct device *dev)
2295{ 2292{
2296 struct amd_iommu *iommu; 2293 struct amd_iommu *iommu;
2297 struct pci_dev *pdev;
2298 u16 devid; 2294 u16 devid;
2299 2295
2300 if (dev->bus != &pci_bus_type) 2296 if (!check_device(dev))
2301 return; 2297 return;
2302 2298
2303 pdev = to_pci_dev(dev); 2299 devid = get_device_id(dev);
2304
2305 devid = calc_devid(pdev->bus->number, pdev->devfn);
2306 2300
2307 if (devid > 0) 2301 if (amd_iommu_pd_table[devid] != NULL)
2308 detach_device(dev); 2302 detach_device(dev);
2309 2303
2310 iommu = amd_iommu_rlookup_table[devid]; 2304 iommu = amd_iommu_rlookup_table[devid];
@@ -2321,20 +2315,13 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
2321 struct protection_domain *domain = dom->priv; 2315 struct protection_domain *domain = dom->priv;
2322 struct protection_domain *old_domain; 2316 struct protection_domain *old_domain;
2323 struct amd_iommu *iommu; 2317 struct amd_iommu *iommu;
2324 struct pci_dev *pdev;
2325 int ret; 2318 int ret;
2326 u16 devid; 2319 u16 devid;
2327 2320
2328 if (dev->bus != &pci_bus_type) 2321 if (!check_device(dev))
2329 return -EINVAL; 2322 return -EINVAL;
2330 2323
2331 pdev = to_pci_dev(dev); 2324 devid = get_device_id(dev);
2332
2333 devid = calc_devid(pdev->bus->number, pdev->devfn);
2334
2335 if (devid >= amd_iommu_last_bdf ||
2336 devid != amd_iommu_alias_table[devid])
2337 return -EINVAL;
2338 2325
2339 iommu = amd_iommu_rlookup_table[devid]; 2326 iommu = amd_iommu_rlookup_table[devid];
2340 if (!iommu) 2327 if (!iommu)
@@ -2458,10 +2445,11 @@ int __init amd_iommu_init_passthrough(void)
2458 2445
2459 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 2446 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
2460 2447
2461 devid = calc_devid(dev->bus->number, dev->devfn); 2448 if (!check_device(&dev->dev))
2462 if (devid > amd_iommu_last_bdf)
2463 continue; 2449 continue;
2464 2450
2451 devid = get_device_id(&dev->dev);
2452
2465 iommu = amd_iommu_rlookup_table[devid]; 2453 iommu = amd_iommu_rlookup_table[devid];
2466 if (!iommu) 2454 if (!iommu)
2467 continue; 2455 continue;