--- linux-2.2.14/lib/vsprintf.c.orig Fri Apr 7 01:35:42 2000 +++ linux-2.2.14/lib/vsprintf.c Fri Apr 7 01:37:15 2000 @@ -290,7 +290,9 @@ --fmt; continue; } - if (qualifier == 'l') + if (qualifier == 'L') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') num = va_arg(args, unsigned long); else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); --- linux-2.2.14/include/asm-i386/e820.h.orig Fri Apr 7 00:58:05 2000 +++ linux-2.2.14/include/asm-i386/e820.h Fri Apr 7 01:17:25 2000 @@ -0,0 +1,112 @@ +/* + * structures and definitions for the int 15, ax=e820 memory map + * scheme. + * + * In a nutshell, arch/i386/boot/setup.S populates a scratch table + * in the empty_zero_block that contains a list of usable address/size + * duples. In arch/i386/kernel/setup.c, this information is + * transferred into the bios[], then converted into a list of valid + * memory regions in region[], and that new information is used in + * arch/i386/mm/init.c to mark pages available or not. + * + */ +#ifndef __E820_HEADER +#define __E820_HEADER + +#define E820MAP 0x2d0 /* our map */ +#define E820MAX 32 /* number of entries in E820MAP */ +#define E820PHYSMAX 64 /* number of entries in physical_memory.region */ +#define E820NR 0x1e8 /* # entries in E820MAP */ +#define E820LEN 20 /* size of an e820 entry */ + +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 + +#define HIGH_MEMORY (1024*1024) + +/* HACK: These macros map between page numbers and physical addresses. + * They used to be in arch/i386/kernel/setup.c, but have been moved here + * so that they can also be used in arch/i386/mm/init.c. + */ +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) + +/* + * FLAG_E820_DEBUG enables bunches of debug messages. + */ +#define FLAG_E820_DEBUG 1 + +/* + * FLAG_E820_GULLIBLE tells check_memory_region() to believe the bios + * when it says that memory in the 0x9fc00-0x100000 region is okay. In + * most cases, this will NOT be the case and attempting to use this will + * result in your machine being converted to gravel as Linux scribbles + * in that memory region, but if you're trying to install Linux on an + * ultra-low memory machine and you can make this region usable, this + * might be useful. If you enable this flag, you also need to set the + * corresponding flag in physical_memory.pflag before the memory will + * actually be used. + */ +#define FLAG_E820_GULLIBLE 0 + + +/* FLAG_E820_RECLAIM tells add_memory_region/check_memory_region to + * attempt to use E820 reclaim memory sections. To have reclaim work, + * you need to configure it on, _plus_ CONFIG_ACPI needs to be turned off. + */ +#if defined(CONFIG_E820_RECLAIM) && !defined(CONFIG_ACPI) +# define FLAG_E820_RECLAIM 1 +#else +# define FLAG_E820_RECLAIM 0 +#endif + +/* FLAG_E820_4GB_ONLY tells the memory region adder to truncate memory + * segments to the first 4 gb of memory. + */ +#define FLAG_E820_4GB_ONLY 0 + + +#ifndef __ASSEMBLY__ + +struct e820 { + __u64 addr; /* addr,size,type are returned by e820 bios call */ + __u64 size; + __u32 type; + __u16 len; /* %ecx(out) from the e820 bios call */ +} __attribute__ ((__packed__)); + +struct physical_region { + __u64 start; + __u64 end; +} ; + +struct physical_memory { + int p_flags; /* assert sizeof(int) >= 3 bits */ + +#define CHK_PMEM_GULLIBLE 0x02 /* user-settable in smap= */ +#define CHK_PMEM_RECLAIM 0x04 /* command line */ + + int nr_bios; /* bios[] holds memory region */ + int nr_region; /* region[] holds valid mem */ + struct e820 bios[E820MAX]; /* returned by the bios */ + struct physical_region region[E820PHYSMAX]; /* that we want to allocate */ +} ; + +#define NR_HOLES 10 + +struct excluded_memory { + int nr_hole; + struct __hole { + __u64 start; + __u64 end; + __u32 mask; + } hole[NR_HOLES]; +} ; + +extern struct physical_memory physical_memory; +#endif/*!__ASSEMBLY__*/ + +#endif/*__E820_HEADER*/ --- linux-2.2.14/arch/i386/boot/setup.S.orig Fri Apr 7 00:20:11 2000 +++ linux-2.2.14/arch/i386/boot/setup.S Fri Apr 7 01:09:17 2000 @@ -37,6 +37,7 @@ #include #include #include +#include ! Signature words to ensure LILO loaded us right #define SIG1 0xAA55 @@ -59,7 +60,7 @@ entry start start: - jmp start_of_setup + jmp trampoline ! ------------------------ start of header -------------------------------- ! ! SETUP-header, must start at CS:2 (old 0x9020:2) @@ -119,6 +120,8 @@ heap_end_ptr: .word modelist+1024 ! space from here (exclusive) down to ! end of setup code can be used by setup ! for local heap purposes. +trampoline: call start_of_setup + .space 1024 ! ------------------------ end of header ---------------------------------- start_of_setup: @@ -243,43 +246,97 @@ db 0 loader_ok: -! Get memory size (extended mem, kB) +! MEMORY DETECTION CODE -#ifndef STANDARD_MEMORY_BIOS_CALL - push ebx + xor eax, eax + mov [0x1e0], eax ! zero e801_mem_low + mov [0x1e4], eax ! " e801_mem_high + mov [E820NR], al ! " e820_nr - xor ebx,ebx ! preload new memory slot with 0k - mov [0x1e0], ebx +! +! Try three different memory detection schemes. First, try +! e820h, which lets us assemble a memory map, then try e801h, +! which returns a 32-bit memory size, and finally 88h, which +! returns 0-64m +! - mov ax,#0xe801 - int 0x15 - jc oldstylemem - -! Memory size is in 1 k chunksizes, to avoid confusing loadlin. -! We store the 0xe801 memory size in a completely different place, -! because it will most likely be longer than 16 bits. -! (use 1e0 because that's what Larry Augustine uses in his -! alternative new memory detection scheme, and it's sensible -! to write everything into the same place.) - - and ebx, #0xffff ! clear sign extend - shl ebx, 6 ! and go from 64k to 1k chunks - mov [0x1e0],ebx ! store extended memory size - - and eax, #0xffff ! clear sign extend - add [0x1e0],eax ! and add lower memory into total size. - - ! and fall into the old memory detection code to populate the - ! compatibility slot. +#ifdef CONFIG_MEM_E820 -oldstylemem: - pop ebx -#else - mov dword ptr [0x1e0], #0 -#endif +! +! method E820H: +! the memory map from hell. e820h returns memory classified into +! a whole bunch of different types, and allows memory holes and +! everything. We scan through this memory map and build a list +! of the first E820MAX memory areas, which we return at [E820MAP]. +! +meme820: + xor ebx, ebx ! continuation counter + + push ds ! es:di points at the whitelist + pop es + mov di, #E820MAP +jmpe820: + mov edx, #0x534d4150 ! ascii `SMAP' + mov eax, #0x0000e820 ! e820, upper word zeroed + mov ecx, #E820LEN ! 20 bytes is what we want. + + int 0x15 ! make the call + jc fin820 ! fall out if it fails + + cmp eax, #0x534d4150 ! did the bios move for you? + je stash820 + + xor ah, ah ! no? chuck the whole thing. + mov [E820NR], ah + jmp fin820 + +stash820: + inc [E820NR] ! up the # of records + mov al, [E820NR] ! If the table fills up + cmp al, #E820MAX ! we must flee + jnl fin820 + + mov E820LEN(di),cx ! stash recsize + cmp ebx,#0 ! any more records in the pipe? + jz fin820 ! apparently not + + mov ax, di ! point %es:%di at the next + add ax, #E820LEN+2 ! record + mov di, ax + jmp jmpe820 +fin820: + +#endif/*CONFIG_MEM_E820*/ + +#ifdef CONFIG_MEM_E801 +! +! method E801H: +! e801 returns 2 memory chunks: 1 from 1mb to 16mb, and 1 from 16mb up. +! return the both of them, low in 1e0h, for compatability with older +! versions of memory detection code, and high in 1e4h. +! + +meme801: + mov ax, #0xE801 + int 0x15 + jc fine801 + + and ecx, #0xffff ! clear sign extend + mov [0x1e0], ecx ! store 1kb between 1-16mb + and edx, #0xffff ! clear sign extend + mov [0x1e4], edx ! store 64kb chunks above 16mb +fine801: + +#endif/*CONFIG_MEM_E801*/ + +! +! Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +! 64mb, depending on the bios) in ax. +! mov ah,#0x88 int 0x15 - mov [2],ax + mov [2], ax +/* END OF MEMORY DETECTION CODE */ ! Set the keyboard repeat rate to the max --- linux-2.2.14/arch/i386/mm/init.c.orig Fri Apr 7 00:53:36 2000 +++ linux-2.2.14/arch/i386/mm/init.c Fri Apr 7 02:56:03 2000 @@ -27,6 +27,7 @@ #include #include #include +#include extern void show_net_buffers(void); extern unsigned long init_smp_mappings(unsigned long); @@ -394,14 +395,14 @@ int datapages = 0; int initpages = 0; unsigned long tmp; + unsigned long start_low_page; + unsigned long start_mem_page; + int i; end_mem &= PAGE_MASK; high_memory = (void *) end_mem; max_mapnr = num_physpages = MAP_NR(end_mem); - /* clear the zero-page */ - memset(empty_zero_page, 0, PAGE_SIZE); - /* mark usable pages in the mem_map[] */ start_low_mem = PAGE_ALIGN(start_low_mem)+PAGE_OFFSET; @@ -417,15 +418,33 @@ #endif start_mem = PAGE_ALIGN(start_mem); + start_mem_page = PFN_UP(__pa(start_mem)); + start_low_page = PFN_UP(__pa(start_low_mem)); + while (start_low_mem < i386_endbase) { clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags); start_low_mem += PAGE_SIZE; } - while (start_mem < end_mem) { - clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); - start_mem += PAGE_SIZE; + for (i = 0; i < physical_memory.nr_region; i++) { + unsigned long start, end; + + start = PFN_UP(physical_memory.region[i].start); + end = PFN_DOWN(physical_memory.region[i].end); + + if (start < start_low_page) + start = start_low_page; + else if ( start >= PFN_UP(HIGH_MEMORY) && start < start_mem_page) + start = start_mem_page; + + for (; start < end; ++start) + clear_bit(PG_reserved, &mem_map[start].flags); } + + /* clear the zero-page */ + memset(empty_zero_page, 0, PAGE_SIZE); + + 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); --- linux-2.2.14/arch/i386/kernel/setup.c.orig Fri Apr 7 00:28:46 2000 +++ linux-2.2.14/arch/i386/kernel/setup.c Fri Apr 7 02:33:53 2000 @@ -59,6 +59,7 @@ #include #include #include +#include /* * Machine setup.. @@ -92,6 +93,9 @@ unsigned char table[0]; }; + +struct physical_memory physical_memory; + unsigned char aux_device_present; #ifdef CONFIG_BLK_DEV_RAM @@ -110,7 +114,15 @@ #define PARAM ((unsigned char *)empty_zero_page) #define SCREEN_INFO (*(struct screen_info *) (PARAM+0)) #define EXT_MEM_K (*(unsigned short *) (PARAM+2)) -#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0)) +#define E801_MEM_LOW (*(unsigned long *) (PARAM+0x1e0)) +#define E801_MEM_HIGH (*(unsigned long *) (PARAM+0x1e4)) +#define E820_MAP_NR (*(char*) (PARAM+E820NR)) +#define E820_MAP ((unsigned long *) (PARAM+E820MAP)) +#define E820_ERR (*(unsigned short *) (PARAM+E820MAP)) + +#define Region physical_memory.region +#define Bios physical_memory.bios + #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40)) #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80)) #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0)) @@ -257,6 +269,342 @@ } #endif +unsigned long __init memparse(char *ptr, char **retptr) +{ + unsigned long ret; + + ret = simple_strtoul(ptr, retptr, 0); + + if (**retptr == 'K' || **retptr == 'k') { + ret <<= 10; + (*retptr)++; + } + else if (**retptr == 'M' || **retptr == 'm') { + ret <<= 20; + (*retptr)++; + } + else if (**retptr == 'G' || **retptr == 'g') { + ret <<= 30; + (*retptr)++; + } + return ret; +} /* memparse */ + + +enum region_flags { RF_RECLAIM =0x01, + RF_NOT_RAM =0x02, + RF_OVERFLOW=0x04, + RF_ZERO =0x08, + RF_MERGED =0x10, + RF_ADDED =0x20, + RF_SHORT =0x40, + RF_TOOLONG =0x80 } ; + +enum region_flags __init add_memory_region(__u64 start, __u64 end, __u32 type) +{ + int i, x; + enum region_flags flag = 0; + +#if FLAG_E820_RECLAIM + if ( (physical_memory.p_flags & CHK_PMEM_RECLAIM) && (type == E820_ACPI) ) + flag |= RF_RECLAIM; + else if (type != E820_RAM) + return RF_NOT_RAM; +#else + if (type != E820_RAM) + return RF_NOT_RAM; +#endif + + if (start == end) + return flag|RF_ZERO; + + if (start > end) + return RF_TOOLONG; + +#ifdef CONFIG_E820_MERGE + /* see if we can merge this region with an existing one */ + + for (x=0; x < physical_memory.nr_region; x++) + if (end == Region[x].start) { + /* glue memory region onto the start of this one */ + Region[x].start = start; + break; + } + else if (Region[x].end == start) { + /* glue memory region onto the end of this one */ + Region[x].end = end; + break; + } + if (x < physical_memory.nr_region) { + /* If we've merged a region, check to see if the new region + * want to merge with anyone else. + */ + if (x > 0 && Region[x].start == Region[x-1].end) { + Region[x-1].end = Region[x].end; + for (i=x; i < physical_memory.nr_region; i++) + Region[x] = Region[x+1]; + physical_memory.nr_region--; + x--; + } + if (x < physical_memory.nr_region-1 && Region[x].end == Region[x+1].start) { + Region[x].end = Region[x+1].end; + for (i=x+1; i < physical_memory.nr_region-1; i++) + Region[x] = Region[x+1]; + physical_memory.nr_region--; + } + else + return flag|RF_MERGED; + } +#endif + + if (physical_memory.nr_region == E820MAX) + return flag|RF_OVERFLOW; + + /* insert the new region in order */ + for (x=0; x < physical_memory.nr_region; x++) + if (end < Region[x].start) { + /* add it in here */ + for (i=physical_memory.nr_region; i>x; --i) + Region[i] = Region[i-1]; + Region[x].start = start; + Region[x].end = end; + physical_memory.nr_region++; + return flag|RF_ADDED; + } + Region[physical_memory.nr_region].start = start; + Region[physical_memory.nr_region].end = end; + physical_memory.nr_region++; + return flag|RF_ADDED; +} /* add_memory_region */ + + +#define GIGABYTE(x) ((x) * 1024LL * 1024LL * 1024LL) +#define MEGABYTE(x) ((x) * 1024LL * 1024LL) +#if FLAG_E820_DEBUG +# define E820DBG(x) printk x +#else +# define E820DBG(x) +#endif + +/* + * Do NOT EVER look at the BIOS memory size location. + * It does not work on many machines. + */ +#define LOWMEMSIZE() (639 * 1024) + + +#if FLAG_E820_DEBUG +void +report(enum region_flags code) +{ + if (code & RF_RECLAIM) + printk(" reclaimed"); + if (code & RF_ADDED) + printk(" added"); + if (code & RF_MERGED) + printk(" merged"); + if (code & RF_NOT_RAM) + printk(" rom"); + if (code & RF_ZERO) + printk(" zero-length"); + + if (code & RF_SHORT) + printk(" ERROR: short record"); + else if (code & RF_OVERFLOW) + printk(" ERROR: table overflow"); + else if (code & RF_TOOLONG) + printk(" ERROR: start+size > 64 bits"); +} +#endif + + +static struct excluded_memory memory_hole; +#define Hole memory_hole.hole + +int __init +prune_region(int x) +{ + int i, ct; + + for (ct = 0; ct < memory_hole.nr_hole; ct++) { + + if (Region[x].start >= Hole[ct].start || Region[x].end <= Hole[ct].end || Hole[ct].mask != 0) + continue; + + if (Region[x].start >= Hole[ct].start) { + if (Region[x].end < Hole[ct].end) { + E820DBG(("SMAP: %010Lx - %010Lx dropped\n", + Region[x].start, Region[x].end)); + for (i=x; i < physical_memory.nr_region; i++) + Region[i] = Region[i+1]; + physical_memory.nr_region--; + return --x; + } + else { + E820DBG(("SMAP: %010Lx - %010Lx trimmed to %010Lx - %010Lx\n", + Region[x].start, Region[x].end, + Hole[ct].start, Region[x].end)); + Region[x].start = Hole[ct].start; + } + } + else if (Region[x].end < Hole[ct].end || physical_memory.nr_region >= E820PHYSMAX) { + if (physical_memory.nr_region >= E820PHYSMAX) + E820DBG(("SMAP: Memory region overflow\n")); + E820DBG(("SMAP: %010Lx - %010Lx trimmed to %010Lx - %010Lx\n", + Region[x].start, Region[x].end, + Region[x].start, Hole[ct].start)); + Region[x].end = Hole[ct].start; + } + else { + E820DBG(("SMAP: %010Lx - %010Lx split to %010Lx - %010Lx, %010Lx - %010Lx\n", + Region[x].start, Region[x].end, + Region[x].start, Hole[ct].start, + Hole[ct].end, Region[x].end)); + for (i=physical_memory.nr_region; i > x; --i) + Region[i+1] = Region[i]; + + Region[x+1].start = Hole[ct].end; + Region[x+1].end = Region[x].end; + Region[x].end = Hole[ct].start; + physical_memory.nr_region++; + } + } + return x; +} + + +/* + * region_check() validates the physical_memory map, plus lops out memory + * that lives in suspicious places. + */ +int __init +region_check(void) +{ + unsigned int x; + + for (x=0; x < physical_memory.nr_region; x++) { + if (x < physical_memory.nr_region-1 + && Region[x].end >= Region[x+1].start) { + printk("SMAP: region %d (%010Lx - %010Lx) overlaps region %d (%010Lx - %010Lx)\n", + x, Region[x].start, + Region[x].end, + x+1, Region[x+1].start, + Region[x+1].end); + return 1; + } + if ( (x = prune_region(x)) < 0) + return 1; + } + return 0; +} /* region_check */ + + +void __init +add_memory_hole(__u64 start, __u64 end, __u32 mask) +{ + int idx; + + if ( (idx=memory_hole.nr_hole) < NR_HOLES) { + Hole[idx].start = start; + Hole[idx].end = end; + Hole[idx].mask = mask; + memory_hole.nr_hole ++ ; + } +} + + +void __init +setup_memory_region(void) +{ + int i; + enum region_flags ret; + + add_memory_hole(LOWMEMSIZE(), HIGH_MEMORY, 0); +#define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */ +#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)) + add_memory_hole(MAXMEM, (__u64)-1, 0); + +#ifdef CONFIG_MEM_E820 + /* + * If we're lucky and live on a modern system, the setup code + * will have given us a memory map that we can use to properly + * set up memory. If we aren't, we'll fake a memory map. + * + * We check to see that the memory map contains at least 2 elements + * before we'll use it, because the detection code in setup.S may + * not be perfect and most every PC known to man has two memory + * regions: one from 0 to ~640k, and one from 1mb up. + */ + if ( (E820_MAP_NR > 1) && (E820_MAP_NR < E820MAX) ) { + /* got a memory map; copy it into a safe place. + */ + physical_memory.p_flags = (FLAG_E820_RECLAIM ? CHK_PMEM_RECLAIM : 0) ; + physical_memory.nr_bios = E820_MAP_NR; + memcpy(&(Bios), E820_MAP, E820_MAP_NR * sizeof Bios[0]); + for (i=0; i < E820_MAP_NR; i++) { + E820DBG(("SMAP: %010Lx - %010Lx ", + Bios[i].addr, + Bios[i].addr + Bios[i].size)); + if ( Bios[i].len < E820LEN) + ret = RF_SHORT; + else + ret = add_memory_region(Bios[i].addr, + Bios[i].addr + Bios[i].size, + Bios[i].type); +#if FLAG_E820_DEBUG + switch (Bios[i].type) { + case E820_RAM: printk("(usable)"); + break; + case E820_RESERVED: + printk("(reserved)"); + break; + case E820_ACPI: + printk("(ACPI data)"); + break; + case E820_NVS: + printk("(ACPI NVS)"); + break; + default: + printk("(type %lu)", + (unsigned long)Bios[i].type); + break; + } + if ( Bios[i].len != E820LEN ) + printk(" [record is %d bytes long]", Bios[i].len); + + report(ret); + printk("\n"); +#endif + if (ret & (RF_SHORT|RF_TOOLONG|RF_OVERFLOW)) + goto oldstyle; + } + /* after putting in the e820 map, massage it into shape + * for use by the kernel. If region_check returns anything + * except 0, something is very ill in the state of the + * bios map. + */ + if (region_check() == 0) + return /* the map is fine, so we'll use it */; + } +#endif + + oldstyle: + physical_memory.nr_region = 0; + physical_memory.p_flags = 0; + +#ifdef CONFIG_MEM_E801 + if (E801_MEM_LOW > 0) { + add_memory_region(0, (E801_MEM_LOW<<10)+HIGH_MEMORY, E820_RAM); + add_memory_region(MEGABYTE(16), MEGABYTE(16)+(E801_MEM_HIGH<<16), E820_RAM); + } + else +#endif + add_memory_region(0, HIGH_MEMORY+(EXT_MEM_K << 10), E820_RAM); + + region_check(); +} /* setup_memory_region */ + + static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; @@ -268,6 +616,7 @@ unsigned long memory_start, memory_end; char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; + int i; int read_endbase_from_BIOS = 1; #ifdef CONFIG_VISWS @@ -287,17 +636,9 @@ BIOS_revision = SYS_DESC_TABLE.table[2]; } aux_device_present = AUX_DEVICE_INFO; - memory_end = (1<<20) + (EXT_MEM_K<<10); -#ifndef STANDARD_MEMORY_BIOS_CALL - { - unsigned long memory_alt_end = (1<<20) + (ALT_MEM_K<<10); - /* printk(KERN_DEBUG "Memory sizing: %08x %08x\n", memory_end, memory_alt_end); */ - if (memory_alt_end > memory_end) - memory_end = memory_alt_end; - } -#endif - memory_end &= PAGE_MASK; + setup_memory_region(); + #ifdef CONFIG_BLK_DEV_RAM rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); @@ -327,14 +668,11 @@ from += 9+4; boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE; } else { - memory_end = simple_strtoul(from+4, &from, 0); - if ( *from == 'K' || *from == 'k' ) { - memory_end = memory_end << 10; - from++; - } else if ( *from == 'M' || *from == 'm' ) { - memory_end = memory_end << 20; - from++; - } + long size = memparse(from+4, &from); + + physical_memory.nr_region = 0; + add_memory_region(0, size, E820_RAM); + region_check(); } } else if (c == ' ' && !memcmp(from, "endbase=", 8)) @@ -351,6 +689,13 @@ break; *(to++) = c; } + + for (memory_end = i = 0; i < physical_memory.nr_region; i++) + if (memory_end < Region[i].end) + memory_end = Region[i].end; + + memory_end &= PAGE_MASK; + *to = '\0'; *cmdline_p = command_line; @@ -378,16 +723,6 @@ i386_endbase = BIOS_ENDBASE; } i386_endbase += PAGE_OFFSET; - } - -#define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */ -#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)) - - if (memory_end > MAXMEM) - { - memory_end = MAXMEM; - printk(KERN_WARNING "Warning only %ldMB will be used.\n", - MAXMEM>>20); } memory_end += PAGE_OFFSET; --- linux-2.2.14/arch/i386/defconfig.orig Fri Apr 7 00:21:49 2000 +++ linux-2.2.14/arch/i386/defconfig Fri Apr 7 01:16:57 2000 @@ -21,6 +21,10 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y +CONFIG_MEM_E820=y +# CONFIG_E820_RECLAIM is not set +# CONFIG_E820_MERGE is not set +CONFIG_MEM_E801=y CONFIG_1GB=y # CONFIG_2GB is not set # CONFIG_MATH_EMULATION is not set --- linux-2.2.14/arch/i386/config.in.orig Fri Apr 7 00:21:54 2000 +++ linux-2.2.14/arch/i386/config.in Fri Apr 7 01:16:34 2000 @@ -33,6 +33,20 @@ define_bool CONFIG_X86_GOOD_APIC y fi +mainmenu_option next_comment +comment "Memory detection" +bool 'Use bios call E820 to detect memory' CONFIG_MEM_E820 +if [ "$CONFIG_MEM_E820" = "y" ]; then + bool 'Reclaim ACPI tables' CONFIG_E820_RECLAIM + bool 'Merge adjacent memory regions' CONFIG_E820_MERGE + bool 'Also use bios call E801 to detect memory' CONFIG_MEM_E801 +else + define_bool CONFIG_MEM_E801 n + define_bool CONFIG_E820_RECLAIM n + define_bool CONFIG_E820_MERGE n +fi +endmenu + choice 'Maximum Physical Memory' \ "1GB CONFIG_1GB \ 2GB CONFIG_2GB" 1GB