[patch] endbase patch in 2.2.12-final3 may lose 640k of ram

Andrea Arcangeli (andrea@suse.de)
Tue, 24 Aug 1999 18:40:49 +0200 (CEST)


Some time ago I written this proggy to check the endbase value from lots
of BIOSes:

#include <fcntl.h>
#include <unistd.h>

main()
{
unsigned long bios_base_mem_limit_addr;
unsigned short bios_base_mem_limit;
unsigned long value;
int mem;

bios_base_mem_limit_addr = 0x413;
mem = open("/dev/mem", O_RDONLY);
if (mem < 0)
perror("open"), exit(1);
if (lseek(mem, bios_base_mem_limit_addr, SEEK_SET) < 0)
perror("lseek"), exit(1);
if (read(mem, &bios_base_mem_limit, 2) < 2)
perror("read"), exit(1);

value = ((unsigned long) bios_base_mem_limit) << 10;
printf("high limit of low memory: decimal %lu, hex %lx\n",
value, value);
}

and I had report about some motherbard that was reading zero from the
endbase address. This mean that 2.2.12-final3 will lose around 640k of ram
in such _real-world_ motherboards. Also the endbios code completly depends
on the presence of a bios.

Due these issues I rewritten the endbase patch to allow the end user to
override the endbase address. I also noticed an error in smp_alloc_memory
and I fixed it as well.

Patch against 2.2.12-final3:

diff -urN 2.2.12-final3/Documentation/memory.txt 2.2.12-final3-endbase/Documentation/memory.txt
--- 2.2.12-final3/Documentation/memory.txt Mon Jan 18 02:29:29 1999
+++ 2.2.12-final3-endbase/Documentation/memory.txt Tue Aug 24 18:13:59 1999
@@ -54,3 +54,11 @@

* Try passing the "no-hlt" option to disable the potentially
buggy HLT instruction in your CPU.
+
+ * Passing for example the "endbase=0x9F000" option to the kernel,
+ you'll _force_ the kernel to not touch the memory between 0x9F000
+ and 1Mbyte. As default the kernel reads the endbase limit from
+ the BIOS. So you need to specify this option only if the BIOS
+ does not provide the right information to the kernel (or if you
+ don't have a BIOS at all :). You can discover the endbase value
+ of your running kernel with this command `dmesg | grep endbase`.
diff -urN 2.2.12-final3/arch/i386/kernel/setup.c 2.2.12-final3-endbase/arch/i386/kernel/setup.c
--- 2.2.12-final3/arch/i386/kernel/setup.c Sun Aug 22 15:51:43 1999
+++ 2.2.12-final3-endbase/arch/i386/kernel/setup.c Tue Aug 24 18:15:17 1999
@@ -122,6 +122,8 @@
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000

+#define BIOS_ENDBASE 0x9F000
+
#ifdef CONFIG_VISWS
char visws_board_type = -1;
char visws_board_rev = -1;
@@ -251,6 +253,7 @@

static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
+unsigned long i386_endbase __initdata = 0;

__initfunc(void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p))
@@ -258,6 +261,7 @@
unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
+ int read_endbase_from_BIOS = 1;

#ifdef CONFIG_VISWS
visws_get_board_type_and_rev();
@@ -326,6 +330,13 @@
}
}
}
+ else if (c == ' ' && !memcmp(from, "endbase=", 8))
+ {
+ if (to != command_line) to--;
+ i386_endbase = simple_strtoul(from+8, &from, 0);
+ i386_endbase += PAGE_OFFSET;
+ read_endbase_from_BIOS = 0;
+ }
c = *(from++);
if (!c)
break;
@@ -335,6 +346,29 @@
}
*to = '\0';
*cmdline_p = command_line;
+
+ if (read_endbase_from_BIOS)
+ {
+ /*
+ * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
+ * They seem to have done something stupid with the floppy
+ * controller as well..
+ * The amount of available base memory is now taken from
+ * WORD 40:13 in order to account for some recent systems,
+ * where its value is smaller than the standard BIOS_ENDBASE
+ * (this was pointed out by Josef Moellers from
+ * Siemens Paderborn (Germany) ).
+ */
+ i386_endbase = (*(unsigned short *)__va(0x413)*1024)&PAGE_MASK;
+ if (!i386_endbase || i386_endbase > 0xA0000)
+ {
+ printk(KERN_NOTICE
+ "endbase 0x%lx is weird so revert to %x\n",
+ i386_endbase, BIOS_ENDBASE);
+ i386_endbase = BIOS_ENDBASE;
+ }
+ i386_endbase += PAGE_OFFSET;
+ }

#define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */
#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
diff -urN 2.2.12-final3/arch/i386/kernel/smp.c 2.2.12-final3-endbase/arch/i386/kernel/smp.c
--- 2.2.12-final3/arch/i386/kernel/smp.c Tue Jul 13 00:33:20 1999
+++ 2.2.12-final3-endbase/arch/i386/kernel/smp.c Tue Aug 24 18:16:04 1999
@@ -657,13 +657,14 @@
return virt_to_phys(trampoline_base);
}

+extern unsigned long i386_endbase __initdata;
/*
* We are called very early to get the low memory for the
* SMP bootup trampoline page.
*/
unsigned long __init smp_alloc_memory(unsigned long mem_base)
{
- if (virt_to_phys((void *)mem_base) >= 0x9F000)
+ if (mem_base + PAGE_SIZE > i386_endbase)
panic("smp_alloc_memory: Insufficient low memory for kernel trampoline 0x%lx.", mem_base);
trampoline_base = (void *)mem_base;
return mem_base + PAGE_SIZE;
diff -urN 2.2.12-final3/arch/i386/mm/init.c 2.2.12-final3-endbase/arch/i386/mm/init.c
--- 2.2.12-final3/arch/i386/mm/init.c Sun Aug 22 15:51:43 1999
+++ 2.2.12-final3-endbase/arch/i386/mm/init.c Tue Aug 24 18:19:08 1999
@@ -384,6 +384,8 @@
printk(".\n");
}

+extern unsigned long i386_endbase __initdata;
+
__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
unsigned long start_low_mem = PAGE_SIZE;
@@ -392,7 +394,6 @@
int datapages = 0;
int initpages = 0;
unsigned long tmp;
- unsigned long endbase;

end_mem &= PAGE_MASK;
high_memory = (void *) end_mem;
@@ -416,14 +417,7 @@
#endif
start_mem = PAGE_ALIGN(start_mem);

- /*
- * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
- * They seem to have done something stupid with the floppy
- * controller as well..
- * The amount of available base memory is in WORD 40:13.
- */
- endbase = PAGE_OFFSET + ((*(unsigned short *)__va(0x413) * 1024) & PAGE_MASK);
- while (start_low_mem < endbase) {
+ while (start_low_mem < i386_endbase) {
clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
start_low_mem += PAGE_SIZE;
}
@@ -458,11 +452,12 @@
#endif
free_page(tmp);
}
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved (endbase 0x%lx), %dk data, %dk init)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10),
+ __pa(i386_endbase),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));

Andrea

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