diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2008-09-25 18:43:34 -0700 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-26 09:42:20 +0200 |
commit | 379daf6290814e41f14880094b7b773640df2461 (patch) | |
tree | e9b016fd4b8dcb0e4fbe39af75db84f313b6fd75 /kernel/resource.c | |
parent | 9a22b6e76ba75fa0f3963cdec7829156d00a7173 (diff) | |
download | op-kernel-dev-379daf6290814e41f14880094b7b773640df2461.zip op-kernel-dev-379daf6290814e41f14880094b7b773640df2461.tar.gz |
IO resources, x86: ioremap sanity check to catch mapping requests exceeding the BAR sizes
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>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index fc59dcc..1d003a5 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -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; +} |