aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--arch/x86/mm/init_32.c2
-rw-r--r--arch/x86/mm/init_64.c2
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/pci/pci-sysfs.c3
-rw-r--r--drivers/pci/pci.c107
-rw-r--r--include/linux/ioport.h11
-rw-r--r--include/linux/pci.h3
-rw-r--r--kernel/resource.c61
9 files changed, 176 insertions, 19 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 0b3f6711d2f1..0072fabb1dd1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -918,6 +918,10 @@ and is between 256 and 4096 characters. It is defined in the file
918 918
919 inttest= [IA64] 919 inttest= [IA64]
920 920
921 iomem= Disable strict checking of access to MMIO memory
922 strict regions from userspace.
923 relaxed
924
921 iommu= [x86] 925 iommu= [x86]
922 off 926 off
923 force 927 force
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 544d724caeee..88f1b10de3be 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -328,6 +328,8 @@ int devmem_is_allowed(unsigned long pagenr)
328{ 328{
329 if (pagenr <= 256) 329 if (pagenr <= 256)
330 return 1; 330 return 1;
331 if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
332 return 0;
331 if (!page_is_ram(pagenr)) 333 if (!page_is_ram(pagenr))
332 return 1; 334 return 1;
333 return 0; 335 return 0;
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 54c437e96541..23f68e77ad1f 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -888,6 +888,8 @@ int devmem_is_allowed(unsigned long pagenr)
888{ 888{
889 if (pagenr <= 256) 889 if (pagenr <= 256)
890 return 1; 890 return 1;
891 if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
892 return 0;
891 if (!page_is_ram(pagenr)) 893 if (!page_is_ram(pagenr))
892 return 1; 894 return 1;
893 return 0; 895 return 0;
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);
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 041e95aac2bf..f6bb2ca8e3ba 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -49,6 +49,7 @@ struct resource_list {
49#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */ 49#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */
50#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */ 50#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */
51 51
52#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
52#define IORESOURCE_DISABLED 0x10000000 53#define IORESOURCE_DISABLED 0x10000000
53#define IORESOURCE_UNSET 0x20000000 54#define IORESOURCE_UNSET 0x20000000
54#define IORESOURCE_AUTO 0x40000000 55#define IORESOURCE_AUTO 0x40000000
@@ -133,13 +134,16 @@ static inline unsigned long resource_type(struct resource *res)
133} 134}
134 135
135/* Convenience shorthand with allocation */ 136/* Convenience shorthand with allocation */
136#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name)) 137#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)
137#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name)) 138#define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl)
139#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
140#define request_mem_region_exclusive(start,n,name) \
141 __request_region(&iomem_resource, (start), (n), (name), IORESOURCE_EXCLUSIVE)
138#define rename_region(region, newname) do { (region)->name = (newname); } while (0) 142#define rename_region(region, newname) do { (region)->name = (newname); } while (0)
139 143
140extern struct resource * __request_region(struct resource *, 144extern struct resource * __request_region(struct resource *,
141 resource_size_t start, 145 resource_size_t start,
142 resource_size_t n, const char *name); 146 resource_size_t n, const char *name, int relaxed);
143 147
144/* Compatibility cruft */ 148/* Compatibility cruft */
145#define release_region(start,n) __release_region(&ioport_resource, (start), (n)) 149#define release_region(start,n) __release_region(&ioport_resource, (start), (n))
@@ -175,6 +179,7 @@ extern struct resource * __devm_request_region(struct device *dev,
175extern void __devm_release_region(struct device *dev, struct resource *parent, 179extern void __devm_release_region(struct device *dev, struct resource *parent,
176 resource_size_t start, resource_size_t n); 180 resource_size_t start, resource_size_t n);
177extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size); 181extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size);
182extern int iomem_is_exclusive(u64 addr);
178 183
179#endif /* __ASSEMBLY__ */ 184#endif /* __ASSEMBLY__ */
180#endif /* _LINUX_IOPORT_H */ 185#endif /* _LINUX_IOPORT_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 59a3dc2059d3..bfcb39ca8879 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -686,10 +686,13 @@ void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
686 int (*)(struct pci_dev *, u8, u8)); 686 int (*)(struct pci_dev *, u8, u8));
687#define HAVE_PCI_REQ_REGIONS 2 687#define HAVE_PCI_REQ_REGIONS 2
688int __must_check pci_request_regions(struct pci_dev *, const char *); 688int __must_check pci_request_regions(struct pci_dev *, const char *);
689int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);
689void pci_release_regions(struct pci_dev *); 690void pci_release_regions(struct pci_dev *);
690int __must_check pci_request_region(struct pci_dev *, int, const char *); 691int __must_check pci_request_region(struct pci_dev *, int, const char *);
692int __must_check pci_request_region_exclusive(struct pci_dev *, int, const char *);
691void pci_release_region(struct pci_dev *, int); 693void pci_release_region(struct pci_dev *, int);
692int pci_request_selected_regions(struct pci_dev *, int, const char *); 694int pci_request_selected_regions(struct pci_dev *, int, const char *);
695int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *);
693void pci_release_selected_regions(struct pci_dev *, int); 696void pci_release_selected_regions(struct pci_dev *, int);
694 697
695/* drivers/pci/bus.c */ 698/* drivers/pci/bus.c */
diff --git a/kernel/resource.c b/kernel/resource.c
index e633106b12f6..ca6a1536b205 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -623,7 +623,7 @@ resource_size_t resource_alignment(struct resource *res)
623 */ 623 */
624struct resource * __request_region(struct resource *parent, 624struct resource * __request_region(struct resource *parent,
625 resource_size_t start, resource_size_t n, 625 resource_size_t start, resource_size_t n,
626 const char *name) 626 const char *name, int flags)
627{ 627{
628 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); 628 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
629 629
@@ -634,6 +634,7 @@ struct resource * __request_region(struct resource *parent,
634 res->start = start; 634 res->start = start;
635 res->end = start + n - 1; 635 res->end = start + n - 1;
636 res->flags = IORESOURCE_BUSY; 636 res->flags = IORESOURCE_BUSY;
637 res->flags |= flags;
637 638
638 write_lock(&resource_lock); 639 write_lock(&resource_lock);
639 640
@@ -679,7 +680,7 @@ int __check_region(struct resource *parent, resource_size_t start,
679{ 680{
680 struct resource * res; 681 struct resource * res;
681 682
682 res = __request_region(parent, start, n, "check-region"); 683 res = __request_region(parent, start, n, "check-region", 0);
683 if (!res) 684 if (!res)
684 return -EBUSY; 685 return -EBUSY;
685 686
@@ -776,7 +777,7 @@ struct resource * __devm_request_region(struct device *dev,
776 dr->start = start; 777 dr->start = start;
777 dr->n = n; 778 dr->n = n;
778 779
779 res = __request_region(parent, start, n, name); 780 res = __request_region(parent, start, n, name, 0);
780 if (res) 781 if (res)
781 devres_add(dev, dr); 782 devres_add(dev, dr);
782 else 783 else
@@ -876,3 +877,57 @@ int iomem_map_sanity_check(resource_size_t addr, unsigned long size)
876 877
877 return err; 878 return err;
878} 879}
880
881#ifdef CONFIG_STRICT_DEVMEM
882static int strict_iomem_checks = 1;
883#else
884static int strict_iomem_checks;
885#endif
886
887/*
888 * check if an address is reserved in the iomem resource tree
889 * returns 1 if reserved, 0 if not reserved.
890 */
891int iomem_is_exclusive(u64 addr)
892{
893 struct resource *p = &iomem_resource;
894 int err = 0;
895 loff_t l;
896 int size = PAGE_SIZE;
897
898 if (!strict_iomem_checks)
899 return 0;
900
901 addr = addr & PAGE_MASK;
902
903 read_lock(&resource_lock);
904 for (p = p->child; p ; p = r_next(NULL, p, &l)) {
905 /*
906 * We can probably skip the resources without
907 * IORESOURCE_IO attribute?
908 */
909 if (p->start >= addr + size)
910 break;
911 if (p->end < addr)
912 continue;
913 if (p->flags & IORESOURCE_BUSY &&
914 p->flags & IORESOURCE_EXCLUSIVE) {
915 err = 1;
916 break;
917 }
918 }
919 read_unlock(&resource_lock);
920
921 return err;
922}
923
924static int __init strict_iomem(char *str)
925{
926 if (strstr(str, "relaxed"))
927 strict_iomem_checks = 0;
928 if (strstr(str, "strict"))
929 strict_iomem_checks = 1;
930 return 1;
931}
932
933__setup("iomem=", strict_iomem);