Index: oldkernel/linux/Documentation/i386/zero-page.txt diff -u linux/Documentation/i386/zero-page.txt:1.1.1.1 linux/Documentation/i386/zero-page.txt:1.2 --- linux/Documentation/i386/zero-page.txt:1.1.1.1 Wed May 31 12:33:54 2000 +++ linux/Documentation/i386/zero-page.txt Thu Jun 1 17:04:05 2000 @@ -30,6 +30,7 @@ 0xb0 - 0x1df Free. Add more parameters here if you really need them. 0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb +0x1e8 char number of entries in E820MAP (below) 0x1f1 char size of setup.S, number of sectors 0x1f2 unsigned short MOUNT_ROOT_RDONLY (if !=0) 0x1f4 unsigned short size of compressed kernel-part in the @@ -64,7 +65,7 @@ 0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image 0x220 4 bytes (setup.S) 0x224 unsigned short setup.S heap end pointer -0x226 - 0x7ff setup.S code. +0x2d0 - 0x550 E820MAP 0x800 string, 2K max COMMAND_LINE, the kernel commandline as copied using CL_OFFSET. Index: oldkernel/linux/arch/i386/boot/setup.S diff -u linux/arch/i386/boot/setup.S:1.2 linux/arch/i386/boot/setup.S:1.3 --- linux/arch/i386/boot/setup.S:1.2 Thu Jun 1 15:34:08 2000 +++ linux/arch/i386/boot/setup.S Thu Jun 1 17:04:05 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: @@ -245,37 +248,87 @@ loader_ok: ! Get memory size (extended mem, kB) + xor eax, eax ! preload new memory slots with 0k + mov dword ptr [0x1e0], eax #ifndef STANDARD_MEMORY_BIOS_CALL - push ebx + mov byte ptr [E820NR], al +! 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 + +! 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 32 memory areas, which we return at [E820MAP]. +! +meme820: + mov edx, #0x534d4150 ! ascii `SMAP' + xor ebx, ebx ! continuation counter + + mov di, #E820MAP ! point into the whitelist + ! so we can have the bios + ! directly write into it. + +jmpe820: + mov eax, #0x0000e820 ! e820, upper word zeroed + mov ecx, #20 ! size of the e820rec + + push ds ! data record. + pop es + int 0x15 ! make the call + jc bail820 ! fall to e801 if it fails - xor ebx,ebx ! preload new memory slot with 0k - mov [0x1e0], ebx + cmp eax, #0x534d4150 ! check the return is `SMAP' + jne bail820 ! fall to e801 if it fails - 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, +! cmp dword ptr [16+di], #1 ! is this usable memory? +! jne again820 + + ! If this is usable memory, we save it by simply advancing di by + ! sizeof(e820rec). + ! +good820: + mov al, byte ptr [E820NR] ! up to 32 good entries, that is + cmp al, #E820MAX + jnl bail820 + inc byte ptr [E820NR] + mov ax, di + add ax, #20 + mov di, ax + +again820: + cmp ebx, #0 ! check to see if ebx is + jne jmpe820 ! set to EOF + +bail820: + + +! method E801H: +! memory size is in 1k 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.) +meme801: - 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. + mov ax,#0xe801 + int 0x15 + jc mem88 -oldstylemem: - pop ebx -#else - mov dword ptr [0x1e0], #0 + and edx, #0xffff ! clear sign extend + shl edx, 6 ! and go from 64k to 1k chunks + mov [0x1e0],edx ! store extended memory size + + and ecx, #0xffff ! clear sign extend + add [0x1e0],ecx ! and add lower memory into total size. + +! Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +! 64mb, depending on the bios) in ax. +mem88: + #endif mov ah,#0x88 int 0x15 Index: oldkernel/linux/arch/i386/kernel/setup.c diff -u linux/arch/i386/kernel/setup.c:1.4 linux/arch/i386/kernel/setup.c:1.5 --- linux/arch/i386/kernel/setup.c:1.4 Thu Jun 1 16:47:27 2000 +++ linux/arch/i386/kernel/setup.c Thu Jun 1 17:04:06 2000 @@ -62,6 +62,7 @@ #include #include #include +#include /* * Machine setup.. @@ -95,6 +96,8 @@ unsigned char table[0]; }; +struct e820map e820 = { 0 }; + unsigned char aux_device_present; #ifdef CONFIG_BLK_DEV_RAM @@ -125,6 +128,8 @@ #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 E820_MAP_NR (*(char*) (PARAM+E820NR)) +#define E820_MAP ((unsigned long *) (PARAM+E820MAP)) #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)) @@ -305,9 +310,37 @@ #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); */ + unsigned long mem_high; + int i; + if (memory_alt_end > memory_end) memory_end = memory_alt_end; + else + memory_alt_end = memory_end; + + e820.nr_map = E820_MAP_NR; + if (e820.nr_map > E820MAX) + e820.nr_map = E820MAX; + memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]); + + /* If a memory region is below "memory_alt_end", it + will be marked as available. Above "memory_alt_end", + we have to use E820_TYPE_OK. */ + mem_high = 0; + for (i=0; i < e820.nr_map; i++) { + if (E820_REG_OK(e820.map[i]) + && (e820.map[i].addrlow < memory_alt_end + || (E820_TYPE_OK(e820.map[i]) + && mem_high == e820.map[i].addrlow))) { + mem_high = e820.map[i].addrlow + + e820.map[i].sizelow; + e820.map[i].type |= E820_AVAILABLE; + if (mem_high > memory_end) + memory_end = mem_high; + } + else + break; + } } #endif Index: oldkernel/linux/arch/i386/mm/init.c diff -u linux/arch/i386/mm/init.c:1.3 linux/arch/i386/mm/init.c:1.4 --- linux/arch/i386/mm/init.c:1.3 Thu Jun 1 16:47:27 2000 +++ linux/arch/i386/mm/init.c Thu Jun 1 17:04:06 2000 @@ -30,6 +30,7 @@ #include #include #include +#include extern void show_net_buffers(void); extern unsigned long init_smp_mappings(unsigned long); @@ -379,6 +380,50 @@ int initpages = 0; int bigpages = 0; unsigned long tmp; + unsigned long start_seg = 0; + unsigned long size_seg = ~0; + int nr_map = 0; + int i, type; + const char *available; + const char *mem_type [] = { + "usable", + "reserved", + "ACPI data", + "NVS data" + + }; + + for (i=0; i < e820.nr_map; i++) { + available = (e820.map[i].type & E820_AVAILABLE) + ? "available" : "unavailable"; + type = e820.map[i].type & ~E820_AVAILABLE; + switch (type) { + case E820_RAM: + case E820_RESERVED: + case E820_ACPI: + case E820_NVS: + type--; + printk("e820 region %d: (%lu, %lu) @ 0x%08lx%08lx (%s) [%s]\n", + i, e820.map[i].sizehigh, e820.map[i].sizelow, + e820.map[i].addrhigh, e820.map[i].addrlow, + mem_type [type], available); + break; + default: + printk("e820 region %d: (%lu, %lu) @ 0x%08lx%08lx (type %d) [%s]\n", + i, e820.map[i].sizehigh, e820.map[i].sizelow, + e820.map[i].addrhigh, e820.map[i].addrlow, + type, available); + break; + } + } + + if (nr_map < e820.nr_map + && (e820.map[i].type & E820_AVAILABLE)) { + start_seg = e820.map[nr_map].addrlow + PAGE_OFFSET; + size_seg = e820.map[nr_map].sizelow; + nr_map++; + } + end_mem &= PAGE_MASK; #ifdef CONFIG_BIGMEM @@ -418,7 +463,22 @@ } while (start_mem < end_mem) { - clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); + if (start_mem > start_seg) { + if (start_mem < start_seg + size_seg) + clear_bit(PG_reserved, + &mem_map[MAP_NR(start_mem)].flags); + else if (nr_map < e820.nr_map + && (e820.map[i].type & E820_AVAILABLE)) { + start_seg = e820.map[nr_map].addrlow + PAGE_OFFSET; + size_seg = e820.map[nr_map].sizelow; + nr_map++; + continue; /* be paranoid in case the */ + /* e820 code hasn't collapsed */ + /* adjacent usable memory */ + } + else + break; /* no more valid memory */ + } start_mem += PAGE_SIZE; } for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) { Index: oldkernel/linux/include/asm-i386/e820.h diff -u /dev/null linux/include/asm-i386/e820.h:1.1 --- /dev/null Mon Jul 31 21:14:46 2000 +++ linux/include/asm-i386/e820.h Thu Jun 1 17:04:06 2000 @@ -0,0 +1,54 @@ +/* + * 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 e820map, and in arch/i386/mm/init.c, that + * new information is used to mark pages reserved or not. + * + */ +#ifndef __E820_HEADER +#define __E820_HEADER + +#define E820MAP 0x2d0 /* our map */ +#define E820MAX 32 /* number of entries in E820MAP */ +#define E820NR 0x1e8 /* # entries in E820MAP */ + +#define E820_RAM 1 /* Memory available to OS. */ +#define E820_RESERVED 2 /* Memory reserved for BIOS. */ +#define E820_ACPI 3 /* Memory for ACPI. */ +#define E820_NVS 4 /* Memory for NVS. */ + +/* Memory available to OS. */ +#define E820_AVAILABLE 0x80000000 + +/* Memory region is ok. */ +#define E820_REG_OK(m) ((m).addrhigh == 0x0 && (m).sizehigh == 0x0) + +/* Memory region type is ok. */ +#define E820_TYPE_OK(m) ((m).type == E820_RAM) + +#ifndef __ASSEMBLY__ + +struct e820map { + int nr_map; + struct { + /* low 4 bytes of start of memory segment */ + unsigned long addrlow; + /* high 4 bytes of start of memory segment */ + unsigned long addrhigh; + /* low 4 bytes of size of memory segment */ + unsigned long sizelow; + /* high 4 bytes of size of memory segment */ + unsigned long sizehigh; + /* type of memory segment */ + unsigned long type; + } map[E820MAX]; +}; + +extern struct e820map e820; +#endif/*!__ASSEMBLY__*/ + +#endif/*__E820_HEADER*/