aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndres Salomon <dilinger@queued.net>2008-04-30 11:30:24 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-30 17:15:35 -0400
commitcb8ab687c32331fb548c613ae74df574bb0908c1 (patch)
tree7b6f4258984e7e95dc584de3baf9894429de6acb
parent5f464707c8c18fccd3c6278ad46ac94b5cf15a98 (diff)
x86: ioremap ram check fix
bdd3cee2e4b7279457139058615ced6c2b41e7de (x86: ioremap(), extend check to all RAM pages) breaks OLPC's ioremap call. The ioremap that OLPC uses is: romsig = ioremap(0xffffffc0, 16); The commit that breaks it is basically: - for (pfn = phys_addr >> PAGE_SHIFT; pfn < max_pfn_mapped && - (pfn << PAGE_SHIFT) < last_addr; pfn++) { + for (pfn = phys_addr >> PAGE_SHIFT; + (pfn << PAGE_SHIFT) < last_addr; pfn++) { + Previously, the 'pfn < max_pfn_mapped' check would've caused us to not enter the loop. Removing that check means we loop infinitely. The reason for that is because pfn is 0xfffff, and last_addr is 0xffffffcf. The remaining check that is used to exit the loop is not sufficient; when pfn<<PAGE_SHIFT is 0xfffff000, that is less than 0xffffffcf; when we increment pfn and it overflows (pfn == 0x100000), pfn<<PAGE_SHIFT ends up being 0. That, of course, is less than last_addr. In effect, pfn<<PAGE_SHIFT is never lower than last_addr. The simple fix for this is to limit the last_addr check to the PAGE_MASK; a patch is below. Signed-off-by: Andres Salomon <dilinger@debian.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/mm/ioremap.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 6d02a36e5e49..71bb3159031a 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -148,8 +148,9 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
148 /* 148 /*
149 * Don't allow anybody to remap normal RAM that we're using.. 149 * Don't allow anybody to remap normal RAM that we're using..
150 */ 150 */
151 for (pfn = phys_addr >> PAGE_SHIFT; pfn < max_pfn_mapped && 151 for (pfn = phys_addr >> PAGE_SHIFT;
152 (pfn << PAGE_SHIFT) < last_addr; pfn++) { 152 (pfn << PAGE_SHIFT) < (last_addr & PAGE_MASK);
153 pfn++) {
153 154
154 int is_ram = page_is_ram(pfn); 155 int is_ram = page_is_ram(pfn);
155 156