[RFC/PATCH] Buggy bios e820 workaround

Marc ZYNGIER (maz@wild-wind.fr.eu.org)
13 Dec 1999 20:38:54 +0100


Hi all,

Having recently got my hands on an old dual P5 (HP XU 5/75, 430NX
chipset), I've been unable to use it reliably with 2.3.x (random
crashes, FS corruption...).

I've narrowed the problem to the following thing :

Dec 12 18:31:10 if kernel: e820: 0009f800 @ 00000000 (usable)
Dec 12 18:31:10 if kernel: e820: 00000800 @ 0009f800 (reserved)
Dec 12 18:31:10 if kernel: e820: 00010000 @ 000e0000 (usable)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dec 12 18:31:10 if kernel: e820: 00010000 @ 000f0000 (reserved)
Dec 12 18:31:10 if kernel: e820: 01f00000 @ 00100000 (usable)
Dec 12 18:31:10 if kernel: e820: 00001000 @ fec00000 (reserved)
Dec 12 18:31:10 if kernel: e820: 00001000 @ fee00000 (reserved)
Dec 12 18:31:10 if kernel: e820: 00010000 @ ffff0000 (reserved)

The bios reports a 64k zone @e000, while it doesn't look there is any
real memory there... Too bad... Digging into lkml archive, I found
that Pavel Machek already reported such a problem with his Toshiba
Satellite 4030CDT.

Since booting with mem=xxM only creates two e820 zones (from 0 to
LOWMEMSIZE, and HIGH_MEMORY to xxM, and thus excluding the 640k-1M
zone), I went ahead and patched my kernel to automagically exclude any
E820_RAM zone that would be between LOWMEMSIZE and HIGH_MEMORY.

With this patch, booting now reports :

e820: 0009f800 @ 00000000 (usable)
e820: 00000800 @ 0009f800 (reserved)
e820: 00010000 @ 000e0000 (was usable, forced to reserved)
e820: 00010000 @ 000f0000 (reserved)
e820: 05f00000 @ 00100000 (usable)
e820: 00001000 @ fec00000 (reserved)
e820: 00001000 @ fee00000 (reserved)
e820: 00010000 @ ffff0000 (reserved)

This workaround works perfectly (at least for me ;-). It is not
currently not a configuration option, but could be easily made so if
necessary. Any comment/{problem,success} report/flame/beer is of
course welcome !

Marc.

--- linux/arch/i386/kernel/setup.c.orig Mon Dec 13 19:22:03 1999
+++ linux/arch/i386/kernel/setup.c Mon Dec 13 19:22:22 1999
@@ -406,9 +406,7 @@
void __init setup_memory_region(void)
{
#define E820_DEBUG 1
-#ifdef E820_DEBUG
int i;
-#endif

/*
* If we're lucky and live on a modern system, the setup code
@@ -421,6 +419,9 @@
* regions: one from 0 to 640k, and one from 1mb up. (The IBM
* thinkpad 560x, for example, does not cooperate with the memory
* detection code.)
+ *
+ * Do not trust e820 maps telling you that there is usable RAM
+ * sitting between 640k and 1MB, this is probably a lie...
*/
if (E820_MAP_NR > 1) {
/* got a memory map; copy it into a safe place.
@@ -429,13 +430,23 @@
if (e820.nr_map > E820MAX)
e820.nr_map = E820MAX;
memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]);
-#ifdef E820_DEBUG
for (i=0; i < e820.nr_map; i++) {
+#ifdef E820_DEBUG
printk("e820: %08x @ %08x ", (int)e820.map[i].size,
(int)e820.map[i].addr);
+#endif
switch (e820.map[i].type) {
- case E820_RAM: printk("(usable)\n");
+ case E820_RAM: if ((int) e820.map[i].addr >= LOWMEMSIZE() &&
+ (int) e820.map[i].addr < HIGH_MEMORY) {
+ e820.map[i].type = E820_RESERVED;
+#ifdef E820_DEBUG
+ printk ("(was usable, forced to reserved)\n");
+ } else {
+ printk("(usable)\n");
+#endif
+ }
break;
+#ifdef E820_DEBUG
case E820_RESERVED:
printk("(reserved)\n");
break;
@@ -447,9 +458,9 @@
break;
default: printk("type %lu\n", e820.map[i].type);
break;
+#endif
}
}
-#endif
}
else {
/* otherwise fake a memory map; one section from 0k->640k,

-- 
Places change, faces change. Life is so very strange.

- 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/