]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
IO resources, x86: ioremap sanity check to catch mapping requests exceeding the BAR...
authorSuresh Siddha <suresh.b.siddha@intel.com>
Fri, 26 Sep 2008 01:43:34 +0000 (18:43 -0700)
committerIngo Molnar <mingo@elte.hu>
Fri, 26 Sep 2008 07:42:20 +0000 (09:42 +0200)
Go through the iomem resource tree to check if any of the ioremap()
requests span more than any slot in the iomem resource tree and do
a WARN_ON() if we hit this check.

This will raise a red-flag, if some driver is mapping more than what
is needed. And hopefully identify possible corruptions much earlier.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/mm/ioremap.c
include/linux/ioport.h
kernel/resource.c

index d4b6e6a29ae3597c45071805f734a502a12d6ab2..c818b45bd07d3bade0b48174b0436d39f4134fd2 100644 (file)
@@ -149,6 +149,12 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        if (is_ISA_range(phys_addr, last_addr))
                return (__force void __iomem *)phys_to_virt(phys_addr);
 
+       /*
+        * Check if the request spans more than any BAR in the iomem resource
+        * tree.
+        */
+       WARN_ON(iomem_map_sanity_check(phys_addr, size));
+
        /*
         * Don't allow anybody to remap normal RAM that we're using..
         */
index fded376b94e3fdb53aa532408b63c4059502e24d..01712cf1a38b3b47d5f40f7b7ba145f343f286c5 100644 (file)
@@ -169,6 +169,7 @@ extern struct resource * __devm_request_region(struct device *dev,
 
 extern void __devm_release_region(struct device *dev, struct resource *parent,
                                  resource_size_t start, resource_size_t n);
+extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size);
 
 #endif /* __ASSEMBLY__ */
 #endif /* _LINUX_IOPORT_H */
index fc59dcc4795b772c9aae54f266d50d9a79703db2..1d003a50ee17a1bd6291ba3cd9472ecbeb95ae27 100644 (file)
@@ -827,3 +827,36 @@ static int __init reserve_setup(char *str)
 }
 
 __setup("reserve=", reserve_setup);
+
+/*
+ * Check if the requested addr and size spans more than any slot in the
+ * iomem resource tree.
+ */
+int iomem_map_sanity_check(resource_size_t addr, unsigned long size)
+{
+       struct resource *p = &iomem_resource;
+       int err = 0;
+       loff_t l;
+
+       read_lock(&resource_lock);
+       for (p = p->child; p ; p = r_next(NULL, p, &l)) {
+               /*
+                * We can probably skip the resources without
+                * IORESOURCE_IO attribute?
+                */
+               if (p->start >= addr + size)
+                       continue;
+               if (p->end < addr)
+                       continue;
+               if (p->start <= addr && (p->end >= addr + size - 1))
+                       continue;
+               printk(KERN_WARNING "resource map sanity check conflict: "
+                      "0x%llx 0x%llx 0x%llx 0x%llx %s\n",
+                      addr, addr + size - 1, p->start, p->end, p->name);
+               err = -1;
+               break;
+       }
+       read_unlock(&resource_lock);
+
+       return err;
+}