Binary files 2.2.19pre2/ID and e820/ID differ
diff -urN 2.2.19pre2/arch/i386/kernel/setup.c e820/arch/i386/kernel/setup.c
--- 2.2.19pre2/arch/i386/kernel/setup.c	Wed Dec 20 03:31:39 2000
+++ e820/arch/i386/kernel/setup.c	Thu Dec 21 21:08:28 2000
@@ -104,7 +104,7 @@
 	unsigned short length;
 	unsigned char table[0];
 };
-struct e820map e820;
+struct e820map e820 __initdata = { 0, };
 
 unsigned char aux_device_present;
 
@@ -272,8 +272,9 @@
 					visws_board_rev);
 	}
 #endif
-void __init add_memory_region(unsigned long long start,
-                                  unsigned long long size, int type)
+
+static void __init add_memory_region(unsigned long long start,
+				     unsigned long long size, int type)
 {
        int x = e820.nr_map;
 
@@ -288,6 +289,8 @@
        e820.nr_map++;
 } /* add_memory_region */
 
+unsigned long i386_endbase __initdata =  0;
+
 static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 {
        /* Only one memory region (or negative)? Ignore it */
@@ -309,10 +312,10 @@
                 * Not right. Fix it up.
                 */
                if (type == E820_RAM) {
-                       if (start < 0x100000ULL && end > 0xA0000ULL) {
-                               if (start < 0xA0000ULL)
-                                       add_memory_region(start, 0xA0000ULL-start, type);
-                               if (end < 0x100000ULL)
+                       if (start < 0x100000ULL && end > i386_endbase) {
+                               if (start < i386_endbase)
+                                       add_memory_region(start, i386_endbase-start, type);
+                               if (end <= 0x100000ULL)
                                        continue;
                                start = 0x100000ULL;
                                size = end - start;
@@ -323,9 +326,33 @@
        return 0;
 }
 
-#define LOWMEMSIZE() (0x9f000)
+static void __init print_memory_map(char *who)
+{
+	int i;
 
-void __init setup_memory_region(void)
+	for (i = 0; i < e820.nr_map; i++) {
+		printk(" %s: %08lx @ %08lx ", who,
+		       (unsigned long) e820.map[i].size,
+		       (unsigned long) e820.map[i].addr);
+		switch (e820.map[i].type) {
+		case E820_RAM:	printk("(usable)\n");
+				break;
+		case E820_RESERVED:
+				printk("(reserved)\n");
+				break;
+		case E820_ACPI:
+				printk("(ACPI data)\n");
+				break;
+		case E820_NVS:
+				printk("(ACPI NVS)\n");
+				break;
+		default:	printk("type %lu\n", e820.map[i].type);
+				break;
+		}
+	}
+}
+
+static void __init setup_memory_region(void)
 {
        char *who = "BIOS-e820";
 
@@ -348,26 +375,27 @@
                }
 
                e820.nr_map = 0;
-               add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-               add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+               add_memory_region(0, i386_endbase, E820_RAM);
+               add_memory_region(HIGH_MEMORY, (mem_size << 10)-HIGH_MEMORY,
+				 E820_RAM);
        }
        printk("BIOS-provided physical RAM map:\n");
+       print_memory_map(who);
 } /* setup_memory_region */
 
 
 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))
 {
-	unsigned long memory_start, memory_end;
-	unsigned long max_pfn;
+	unsigned long memory_start, memory_end = 0;
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
 	int len = 0;
 	int read_endbase_from_BIOS = 1;
 	int i;
+	unsigned long user_mem = 0;
 
 #ifdef CONFIG_VISWS
 	visws_get_board_type_and_rev();
@@ -402,26 +430,6 @@
 	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
-       setup_memory_region();
-
-#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
-       max_pfn = 0;
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long start, end;
-               /* RAM? */
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-               start = PFN_UP(e820.map[i].addr);
-               end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-               if (start >= end)
-                       continue;
-               if (end > max_pfn)
-                       max_pfn = end;
-       }
-       memory_end = (max_pfn << PAGE_SHIFT);
-
-
 	for (;;) {
 		/*
 		 * "mem=nopentium" disables the 4MB page tables.
@@ -434,12 +442,12 @@
 				from += 9+4;
 				boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
 			} else {
-				memory_end = simple_strtoul(from+4, &from, 0);
+				user_mem = simple_strtoul(from+4, &from, 0);
 				if ( *from == 'K' || *from == 'k' ) {
-					memory_end = memory_end << 10;
+					user_mem = user_mem << 10;
 					from++;
 				} else if ( *from == 'M' || *from == 'm' ) {
-					memory_end = memory_end << 20;
+					user_mem = user_mem << 20;
 					from++;
 				}
 			}
@@ -448,7 +456,6 @@
 		{
 			if (to != command_line) to--;
 			i386_endbase = simple_strtoul(from+8, &from, 0);
-			i386_endbase += PAGE_OFFSET;
 			read_endbase_from_BIOS = 0;
 		}
 		c = *(from++);
@@ -484,7 +491,35 @@
 			}
 			i386_endbase = BIOS_ENDBASE;
 		}
-		i386_endbase += PAGE_OFFSET;
+	}
+
+	if (!user_mem)
+		setup_memory_region();
+	else {
+		e820.nr_map = 0;
+		add_memory_region(0, i386_endbase, E820_RAM);
+		add_memory_region(HIGH_MEMORY, user_mem-HIGH_MEMORY, E820_RAM);
+		printk("USER-provided physical RAM map:\n");
+		print_memory_map("USER");
+	}
+
+#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
+	for (i = 0; i < e820.nr_map; i++) {
+		unsigned long long start, end;
+		/* RAM? */
+		if (e820.map[i].type != E820_RAM)
+			continue;
+		start = e820.map[i].addr;
+		if (start >= 0xffffffff)
+			continue;
+		end = e820.map[i].addr + e820.map[i].size;
+		if (start >= end)
+			continue;
+		if (end > 0xffffffff)
+			end = 0xffffffff;
+		if (end > memory_end)
+			memory_end = end;
 	}
 
 #define VMALLOC_RESERVE	(64 << 20)	/* 64MB for vmalloc */
diff -urN 2.2.19pre2/arch/i386/kernel/smp.c e820/arch/i386/kernel/smp.c
--- 2.2.19pre2/arch/i386/kernel/smp.c	Mon Dec 11 16:57:44 2000
+++ e820/arch/i386/kernel/smp.c	Thu Dec 21 19:51:57 2000
@@ -680,7 +680,7 @@
  */
 unsigned long __init smp_alloc_memory(unsigned long mem_base)
 {
-	if (mem_base + PAGE_SIZE > i386_endbase)
+	if (mem_base + PAGE_SIZE > i386_endbase + PAGE_OFFSET)
 		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.19pre2/arch/i386/mm/init.c e820/arch/i386/mm/init.c
--- 2.2.19pre2/arch/i386/mm/init.c	Mon Dec 11 16:57:44 2000
+++ e820/arch/i386/mm/init.c	Thu Dec 21 20:23:06 2000
@@ -27,6 +27,7 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/fixmap.h>
+#include <asm/e820.h>
 
 extern void show_net_buffers(void);
 extern unsigned long init_smp_mappings(unsigned long);
@@ -384,8 +385,6 @@
 		printk(".\n");
 }
 
-extern unsigned long i386_endbase;
-
 __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 {
 	unsigned long start_low_mem = PAGE_SIZE;
@@ -417,15 +416,36 @@
 #endif
 	start_mem = PAGE_ALIGN(start_mem);
 
-	while (start_low_mem < i386_endbase) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
-		start_low_mem += PAGE_SIZE;
-	}
+	for (tmp = __pa(start_low_mem); tmp < __pa(end_mem);
+	     tmp += PAGE_SIZE) {
+		struct page * page = mem_map + (tmp >> PAGE_SHIFT);
+		int i;
+		extern struct e820map e820;
 
-	while (start_mem < end_mem) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-		start_mem += PAGE_SIZE;
+		/* don't include kernel memory and bootmem allocations */
+		if (tmp >= 0x100000 && tmp < __pa(start_mem))
+			continue;
+
+		for (i = 0; i < e820.nr_map; i++) {
+			unsigned long long start, end;
+			/* RAM? */
+			if (e820.map[i].type != E820_RAM)
+				continue;
+			start = e820.map[i].addr;
+			if (start >= 0xffffffff)
+				continue;
+			end = e820.map[i].addr + e820.map[i].size;
+			if (start >= end)
+				continue;
+			if (end > 0xffffffff)
+				end = 0xffffffff;
+
+			/* start and end are valid here */
+			if (start <= tmp && tmp+PAGE_SIZE <= end)
+				clear_bit(PG_reserved, &page->flags);
+		}
 	}
+
 	for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
 		if (tmp >= MAX_DMA_ADDRESS)
 			clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);