aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-10-22 22:55:31 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 14:12:32 -0500
commite8de1481fd7126ee9e93d6889da6f00c05e1e019 (patch)
tree3e0e564f6aff2f8f0f66bdf37dc2eb87d6e17cde /drivers
parent23616941914917cf25b94789856b5326b68d8ee8 (diff)
resource: allow MMIO exclusivity for device drivers
Device drivers that use pci_request_regions() (and similar APIs) have a reasonable expectation that they are the only ones accessing their device. As part of the e1000e hunt, we were afraid that some userland (X or some bootsplash stuff) was mapping the MMIO region that the driver thought it had exclusively via /dev/mem or via various sysfs resource mappings. This patch adds the option for device drivers to cause their reserved regions to the "banned from /dev/mem use" list, so now both kernel memory and device-exclusive MMIO regions are banned. NOTE: This is only active when CONFIG_STRICT_DEVMEM is set. In addition to the config option, a kernel parameter iomem=relaxed is provided for the cases where developers want to diagnose, in the field, drivers issues from userspace. Reviewed-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/pci/pci-sysfs.c3
-rw-r--r--drivers/pci/pci.c107
3 files changed, 99 insertions, 13 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index d4639facd1bd..91817d0afcaf 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4807,7 +4807,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
4807 } 4807 }
4808 } 4808 }
4809 4809
4810 err = pci_request_selected_regions(pdev, 4810 err = pci_request_selected_regions_exclusive(pdev,
4811 pci_select_bars(pdev, IORESOURCE_MEM), 4811 pci_select_bars(pdev, IORESOURCE_MEM),
4812 e1000e_driver_name); 4812 e1000e_driver_name);
4813 if (err) 4813 if (err)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 388440e0d222..d5cdccf27a69 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -620,6 +620,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
620 vma->vm_pgoff += start >> PAGE_SHIFT; 620 vma->vm_pgoff += start >> PAGE_SHIFT;
621 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; 621 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
622 622
623 if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(start))
624 return -EINVAL;
625
623 return pci_mmap_page_range(pdev, vma, mmap_type, write_combine); 626 return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
624} 627}
625 628
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2cfa41e367a7..47663dc0daf7 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1395,7 +1395,8 @@ void pci_release_region(struct pci_dev *pdev, int bar)
1395 * Returns 0 on success, or %EBUSY on error. A warning 1395 * Returns 0 on success, or %EBUSY on error. A warning
1396 * message is also printed on failure. 1396 * message is also printed on failure.
1397 */ 1397 */
1398int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) 1398static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_name,
1399 int exclusive)
1399{ 1400{
1400 struct pci_devres *dr; 1401 struct pci_devres *dr;
1401 1402
@@ -1408,8 +1409,9 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
1408 goto err_out; 1409 goto err_out;
1409 } 1410 }
1410 else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { 1411 else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
1411 if (!request_mem_region(pci_resource_start(pdev, bar), 1412 if (!__request_mem_region(pci_resource_start(pdev, bar),
1412 pci_resource_len(pdev, bar), res_name)) 1413 pci_resource_len(pdev, bar), res_name,
1414 exclusive))
1413 goto err_out; 1415 goto err_out;
1414 } 1416 }
1415 1417
@@ -1428,6 +1430,47 @@ err_out:
1428} 1430}
1429 1431
1430/** 1432/**
1433 * pci_request_region - Reserved PCI I/O and memory resource
1434 * @pdev: PCI device whose resources are to be reserved
1435 * @bar: BAR to be reserved
1436 * @res_name: Name to be associated with resource.
1437 *
1438 * Mark the PCI region associated with PCI device @pdev BR @bar as
1439 * being reserved by owner @res_name. Do not access any
1440 * address inside the PCI regions unless this call returns
1441 * successfully.
1442 *
1443 * Returns 0 on success, or %EBUSY on error. A warning
1444 * message is also printed on failure.
1445 */
1446int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
1447{
1448 return __pci_request_region(pdev, bar, res_name, 0);
1449}
1450
1451/**
1452 * pci_request_region_exclusive - Reserved PCI I/O and memory resource
1453 * @pdev: PCI device whose resources are to be reserved
1454 * @bar: BAR to be reserved
1455 * @res_name: Name to be associated with resource.
1456 *
1457 * Mark the PCI region associated with PCI device @pdev BR @bar as
1458 * being reserved by owner @res_name. Do not access any
1459 * address inside the PCI regions unless this call returns
1460 * successfully.
1461 *
1462 * Returns 0 on success, or %EBUSY on error. A warning
1463 * message is also printed on failure.
1464 *
1465 * The key difference that _exclusive makes it that userspace is
1466 * explicitly not allowed to map the resource via /dev/mem or
1467 * sysfs.
1468 */
1469int pci_request_region_exclusive(struct pci_dev *pdev, int bar, const char *res_name)
1470{
1471 return __pci_request_region(pdev, bar, res_name, IORESOURCE_EXCLUSIVE);
1472}
1473/**
1431 * pci_release_selected_regions - Release selected PCI I/O and memory resources 1474 * pci_release_selected_regions - Release selected PCI I/O and memory resources
1432 * @pdev: PCI device whose resources were previously reserved 1475 * @pdev: PCI device whose resources were previously reserved
1433 * @bars: Bitmask of BARs to be released 1476 * @bars: Bitmask of BARs to be released
@@ -1444,20 +1487,14 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars)
1444 pci_release_region(pdev, i); 1487 pci_release_region(pdev, i);
1445} 1488}
1446 1489
1447/** 1490int __pci_request_selected_regions(struct pci_dev *pdev, int bars,
1448 * pci_request_selected_regions - Reserve selected PCI I/O and memory resources 1491 const char *res_name, int excl)
1449 * @pdev: PCI device whose resources are to be reserved
1450 * @bars: Bitmask of BARs to be requested
1451 * @res_name: Name to be associated with resource
1452 */
1453int pci_request_selected_regions(struct pci_dev *pdev, int bars,
1454 const char *res_name)
1455{ 1492{
1456 int i; 1493 int i;
1457 1494
1458 for (i = 0; i < 6; i++) 1495 for (i = 0; i < 6; i++)
1459 if (bars & (1 << i)) 1496 if (bars & (1 << i))
1460 if(pci_request_region(pdev, i, res_name)) 1497 if (__pci_request_region(pdev, i, res_name, excl))
1461 goto err_out; 1498 goto err_out;
1462 return 0; 1499 return 0;
1463 1500
@@ -1469,6 +1506,26 @@ err_out:
1469 return -EBUSY; 1506 return -EBUSY;
1470} 1507}
1471 1508
1509
1510/**
1511 * pci_request_selected_regions - Reserve selected PCI I/O and memory resources
1512 * @pdev: PCI device whose resources are to be reserved
1513 * @bars: Bitmask of BARs to be requested
1514 * @res_name: Name to be associated with resource
1515 */
1516int pci_request_selected_regions(struct pci_dev *pdev, int bars,
1517 const char *res_name)
1518{
1519 return __pci_request_selected_regions(pdev, bars, res_name, 0);
1520}
1521
1522int pci_request_selected_regions_exclusive(struct pci_dev *pdev,
1523 int bars, const char *res_name)
1524{
1525 return __pci_request_selected_regions(pdev, bars, res_name,
1526 IORESOURCE_EXCLUSIVE);
1527}
1528
1472/** 1529/**
1473 * pci_release_regions - Release reserved PCI I/O and memory resources 1530 * pci_release_regions - Release reserved PCI I/O and memory resources
1474 * @pdev: PCI device whose resources were previously reserved by pci_request_regions 1531 * @pdev: PCI device whose resources were previously reserved by pci_request_regions
@@ -1502,6 +1559,29 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)
1502} 1559}
1503 1560
1504/** 1561/**
1562 * pci_request_regions_exclusive - Reserved PCI I/O and memory resources
1563 * @pdev: PCI device whose resources are to be reserved
1564 * @res_name: Name to be associated with resource.
1565 *
1566 * Mark all PCI regions associated with PCI device @pdev as
1567 * being reserved by owner @res_name. Do not access any
1568 * address inside the PCI regions unless this call returns
1569 * successfully.
1570 *
1571 * pci_request_regions_exclusive() will mark the region so that
1572 * /dev/mem and the sysfs MMIO access will not be allowed.
1573 *
1574 * Returns 0 on success, or %EBUSY on error. A warning
1575 * message is also printed on failure.
1576 */
1577int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
1578{
1579 return pci_request_selected_regions_exclusive(pdev,
1580 ((1 << 6) - 1), res_name);
1581}
1582
1583
1584/**
1505 * pci_set_master - enables bus-mastering for device dev 1585 * pci_set_master - enables bus-mastering for device dev
1506 * @dev: the PCI device to enable 1586 * @dev: the PCI device to enable
1507 * 1587 *
@@ -2149,10 +2229,13 @@ EXPORT_SYMBOL(pci_find_capability);
2149EXPORT_SYMBOL(pci_bus_find_capability); 2229EXPORT_SYMBOL(pci_bus_find_capability);
2150EXPORT_SYMBOL(pci_release_regions); 2230EXPORT_SYMBOL(pci_release_regions);
2151EXPORT_SYMBOL(pci_request_regions); 2231EXPORT_SYMBOL(pci_request_regions);
2232EXPORT_SYMBOL(pci_request_regions_exclusive);
2152EXPORT_SYMBOL(pci_release_region); 2233EXPORT_SYMBOL(pci_release_region);
2153EXPORT_SYMBOL(pci_request_region); 2234EXPORT_SYMBOL(pci_request_region);
2235EXPORT_SYMBOL(pci_request_region_exclusive);
2154EXPORT_SYMBOL(pci_release_selected_regions); 2236EXPORT_SYMBOL(pci_release_selected_regions);
2155EXPORT_SYMBOL(pci_request_selected_regions); 2237EXPORT_SYMBOL(pci_request_selected_regions);
2238EXPORT_SYMBOL(pci_request_selected_regions_exclusive);
2156EXPORT_SYMBOL(pci_set_master); 2239EXPORT_SYMBOL(pci_set_master);
2157EXPORT_SYMBOL(pci_set_mwi); 2240EXPORT_SYMBOL(pci_set_mwi);
2158EXPORT_SYMBOL(pci_try_set_mwi); 2241EXPORT_SYMBOL(pci_try_set_mwi);