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 d4b6e6a..c818b45 100644 (file)
@@ -150,6 +150,12 @@ static void __iomem *__ioremap_caller(resource_size_t phys_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..
         */
        for (pfn = phys_addr >> PAGE_SHIFT;
index fded376..01712cf 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 fc59dcc..1d003a5 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;
+}