lkml.org 
[lkml]   [1999]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subjectioremap() bugs + patch
Date
Note: this _has_ been reported before, by David Howells and Molnar Ingo,
but no fixes have made it into the kernel, and all of the patches I've
seen
miss one or two of the problems I describe below.

I was writing a driver here the other day and discovered a bug which
prevents attempts to ioremap() the top of physical space on i386. I was
able to fix it and I am now able to do things like

ioremap(0xFFF00000,0x100000);

which grabs the top 1MB of physical space. (hint: this is where the bios
flash chip might live on a system with an Intel chipset). These accesses
fail on both 2.2.1 and 2.0.36 currently due to little bugs in __ioremap().

The problem is that __ioremap() does this:

101 if (phys_addr >= 0xA0000 && (phys_addr+size) <= 0x100000)
102 return phys_to_virt(phys_addr);


and this:

120 if (!size || size > phys_addr + size)
121 return NULL;

Problem #1:
You can see that first of all, the first test will (incorrectly) think
I'm within the range 0xA0000 - 0x100000 because phys_addr+size will
wrap to 0. This should be phys_addr - 1 + size.

Problem #2:
The second test will fail because phys_addr+size, again, is 0. This
should also be phys_addr - 1 + size to work properly.

Problem #3: (need help here)
The test on line 120 (checking for a range that will go past the end
of memory) should really be first, as the call

ioremap(0xFFF00000, 0x1B0000)

will be seen not as an illegal request, but as a request for the area
between 0xA0000 and 0x100000. I'm thinking that this test should move
to the beginning of the function. Are there any reasons why this would
be a bad idea? (note I've done it in my patch below)

Thanks...

Eric Seppanen / sepp@primenet.com

PS I'd appreciate a CC if anyone replies.
PPS this patch fixes it and I've been running with it for a few days
now, no problems.

--- linux-2.2.1/arch/i386/mm/ioremap.c Fri Nov 27 17:03:14 1998
+++ linux/arch/i386/mm/ioremap.c Thu Feb 18 17:01:45 1999
@@ -96,9 +96,15 @@
unsigned long offset;

/*
+ * Don't allow mappings that wrap..
+ */
+ if (!size || size > phys_addr-1+size)
+ return NULL;
+
+ /*
* Don't remap the low PCI/ISA area, it's always mapped..
*/
- if (phys_addr >= 0xA0000 && (phys_addr+size) <= 0x100000)
+ if (phys_addr >= 0xA0000 && (phys_addr-1+size) <= 0x100000)
return phys_to_virt(phys_addr);

/*
@@ -113,12 +119,6 @@
offset = phys_addr & ~PAGE_MASK;
phys_addr &= PAGE_MASK;
size = PAGE_ALIGN(size + offset);
-
- /*
- * Don't allow mappings that wrap..
- */
- if (!size || size > phys_addr + size)
- return NULL;

/*
* Ok, go for it..

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:50    [W:0.040 / U:0.364 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site