diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
commit | 546db14ee74118296f425f3b91634fb767d67290 (patch) | |
tree | 22b613a3da8d4bf663eec5e155af01b87fdf9094 /arch/i386/kernel/setup.c | |
parent | 1e25e41c4f5474e14452094492dbc169b800e4c8 (diff) |
Merge with Linux 2.3.23. The new bootmem stuff has broken various
platforms. At this time I've only verified that IP22 support compiles
and IP27 actually works.
Diffstat (limited to 'arch/i386/kernel/setup.c')
-rw-r--r-- | arch/i386/kernel/setup.c | 252 |
1 files changed, 166 insertions, 86 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 734cfca65..31c77bb1d 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -54,7 +54,8 @@ #ifdef CONFIG_BLK_DEV_RAM #include <linux/blk.h> #endif -#include <linux/bigmem.h> +#include <linux/highmem.h> +#include <linux/bootmem.h> #include <asm/processor.h> #include <linux/console.h> #include <asm/uaccess.h> @@ -401,12 +402,15 @@ void __init add_memory_region(unsigned long start, } /* add_memory_region */ -#define LOWMEMSIZE() ((*(unsigned short *)__va(0x413)) * 1024) - +/* + * Do NOT EVER look at the BIOS memory size location. + * It does not work on many machines. + */ +#define LOWMEMSIZE() (0x9f000) void __init setup_memory_region(void) { -#define E820_DEBUG 0 +#define E820_DEBUG 1 #ifdef E820_DEBUG int i; #endif @@ -432,9 +436,8 @@ void __init setup_memory_region(void) memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]); #ifdef E820_DEBUG for (i=0; i < e820.nr_map; i++) { - printk("e820: %ld @ %08lx ", - (unsigned long)(e820.map[i].size), - (unsigned long)(e820.map[i].addr)); + printk("e820: %08x @ %08x ", (int)e820.map[i].size, + (int)e820.map[i].addr); switch (e820.map[i].type) { case E820_RAM: printk("(usable)\n"); break; @@ -464,48 +467,11 @@ void __init setup_memory_region(void) } /* setup_memory_region */ -void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) +static inline void parse_mem_cmdline (char ** cmdline_p) { - unsigned long high_pfn, max_pfn; char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; - int i; - int usermem=0; - -#ifdef CONFIG_VISWS - visws_get_board_type_and_rev(); -#endif - - ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); - drive_info = DRIVE_INFO; - screen_info = SCREEN_INFO; - apm_bios_info = APM_BIOS_INFO; - if( SYS_DESC_TABLE.length != 0 ) { - MCA_bus = SYS_DESC_TABLE.table[3] &0x2; - machine_id = SYS_DESC_TABLE.table[0]; - machine_submodel_id = SYS_DESC_TABLE.table[1]; - BIOS_revision = SYS_DESC_TABLE.table[2]; - } - aux_device_present = AUX_DEVICE_INFO; - -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - setup_memory_region(); - - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long) &_text; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) &_end; - - code_resource.start = virt_to_bus(&_text); - code_resource.end = virt_to_bus(&_etext)-1; - data_resource.start = virt_to_bus(&_etext); - data_resource.end = virt_to_bus(&_edata)-1; + int usermem = 0; /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); @@ -519,8 +485,9 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from * <start> to <start>+<mem>, overriding the bios size. */ - if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") { - if (to != command_line) to--; + if (c == ' ' && !memcmp(from, "mem=", 4)) { + if (to != command_line) + to--; if (!memcmp(from+4, "nopentium", 9)) { from += 9+4; boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE; @@ -542,7 +509,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne } mem_size = memparse(from+4, &from); if (*from == '@') - start_at = memparse(from+1,&from); + start_at = memparse(from+1, &from); else { start_at = HIGH_MEMORY; mem_size -= HIGH_MEMORY; @@ -559,54 +526,166 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne } *to = '\0'; *cmdline_p = command_line; +} - /* Find the highest page frame number we have available */ - max_pfn = 0; - for (i=0; i < e820.nr_map; i++) { - /* RAM? */ - if (e820.map[i].type == E820_RAM) { - unsigned long end_pfn = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT; +void __init setup_arch(char **cmdline_p) +{ + unsigned long bootmap_size; + unsigned long start_pfn, max_pfn, max_low_pfn; + int i; - if (end_pfn > max_pfn) - max_pfn = end_pfn; - } +#ifdef CONFIG_VISWS + visws_get_board_type_and_rev(); +#endif + + ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); + drive_info = DRIVE_INFO; + screen_info = SCREEN_INFO; + apm_bios_info = APM_BIOS_INFO; + if( SYS_DESC_TABLE.length != 0 ) { + MCA_bus = SYS_DESC_TABLE.table[3] &0x2; + machine_id = SYS_DESC_TABLE.table[0]; + machine_submodel_id = SYS_DESC_TABLE.table[1]; + BIOS_revision = SYS_DESC_TABLE.table[2]; } + aux_device_present = AUX_DEVICE_INFO; -/* - * We can only allocate a limited amount of direct-mapped memory - */ -#define VMALLOC_RESERVE (128 << 20) /* 128MB for vmalloc and initrd */ -#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)) -#define MAXMEM_PFN (MAXMEM >> PAGE_SHIFT) +#ifdef CONFIG_BLK_DEV_RAM + rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; + rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); + rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); +#endif + setup_memory_region(); + + if (!MOUNT_ROOT_RDONLY) + root_mountflags &= ~MS_RDONLY; + init_mm.start_code = (unsigned long) &_text; + init_mm.end_code = (unsigned long) &_etext; + init_mm.end_data = (unsigned long) &_edata; + init_mm.brk = (unsigned long) &_end; - high_pfn = MAXMEM_PFN; - if (max_pfn < high_pfn) - high_pfn = max_pfn; + code_resource.start = virt_to_bus(&_text); + code_resource.end = virt_to_bus(&_etext)-1; + data_resource.start = virt_to_bus(&_etext); + data_resource.end = virt_to_bus(&_edata)-1; + + parse_mem_cmdline(cmdline_p); + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) /* - * But the bigmem stuff may be able to use more of it - * (but currently only up to about 4GB) + * 128MB for vmalloc and initrd */ -#ifdef CONFIG_BIGMEM - #define MAXBIGMEM ((unsigned long)(~(VMALLOC_RESERVE-1))) - #define MAXBIGMEM_PFN (MAXBIGMEM >> PAGE_SHIFT) - if (max_pfn > MAX_PFN) - max_pfn = MAX_PFN; - -/* When debugging, make half of "normal" memory be BIGMEM memory instead */ -#ifdef BIGMEM_DEBUG - high_pfn >>= 1; -#endif +#define VMALLOC_RESERVE (unsigned long)(128 << 20) +#define MAXMEM (unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE) +#define MAXMEM_PFN PFN_DOWN(MAXMEM) + + /* + * partially used pages are not usable - thus + * we are rounding upwards: + */ + start_pfn = PFN_UP(__pa(&_end)); - bigmem_start = high_pfn << PAGE_SHIFT; - bigmem_end = max_pfn << PAGE_SHIFT; - printk(KERN_NOTICE "%ldMB BIGMEM available.\n", (bigmem_end-bigmem_start) >> 20); + /* + * Find the highest page frame number we have available + */ + max_pfn = 0; + for (i = 0; i < e820.nr_map; i++) { + unsigned long curr_pfn; + /* RAM? */ + if (e820.map[i].type != E820_RAM) + continue; + curr_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size); + if (curr_pfn > max_pfn) + max_pfn = curr_pfn; + } + + /* + * Determine low and high memory ranges: + */ + max_low_pfn = max_pfn; + if (max_low_pfn > MAXMEM_PFN) + max_low_pfn = MAXMEM_PFN; + +#ifdef CONFIG_HIGHMEM + highstart_pfn = highend_pfn = max_pfn; + if (max_pfn > MAXMEM_PFN) { + highstart_pfn = MAXMEM_PFN; + highend_pfn = max_pfn; + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", + pages_to_mb(highend_pfn - highstart_pfn)); + } #endif + /* + * Initialize the boot-time allocator (with low memory only): + */ + bootmap_size = init_bootmem(start_pfn, max_low_pfn); + + /* + * FIXME: what about high memory? + */ + ram_resources[1].end = PFN_PHYS(max_low_pfn); + + /* + * Register fully available low RAM pages with the bootmem allocator. + */ + for (i = 0; i < e820.nr_map; i++) { + unsigned long curr_pfn, last_pfn, size; + /* + * Reserve usable low memory + */ + if (e820.map[i].type != E820_RAM) + continue; + /* + * We are rounding up the start address of usable memory: + */ + curr_pfn = PFN_UP(e820.map[i].addr); + if (curr_pfn >= max_low_pfn) + continue; + /* + * ... and at the end of the usable range downwards: + */ + last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size); - ram_resources[1].end = (high_pfn << PAGE_SHIFT)-1; + if (last_pfn > max_low_pfn) + last_pfn = max_low_pfn; - *memory_start_p = (unsigned long) &_end; - *memory_end_p = PAGE_OFFSET + (high_pfn << PAGE_SHIFT); + /* + * .. finally, did all the rounding and playing + * around just make the area go away? + */ + if (last_pfn <= curr_pfn) + continue; + + size = last_pfn - curr_pfn; + free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); + } + /* + * Reserve the bootmem bitmap itself as well. We do this in two + * steps (first step was init_bootmem()) because this catches + * the (very unlikely) case of us accidentally initializing the + * bootmem allocator with an invalid RAM area. + */ + reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) + + bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY)); + + /* + * reserve physical page 0 - it's a special BIOS page on many boxes, + * enabling clean reboots, SMP operation, laptop functions. + */ + reserve_bootmem(0, PAGE_SIZE); + +#ifdef __SMP__ + /* + * But first pinch a few for the stack/trampoline stuff + * FIXME: Don't need the extra page at 4K, but need to fix + * trampoline before removing it. (see the GDT stuff) + */ + reserve_bootmem(PAGE_SIZE, PAGE_SIZE); + smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ +#endif #ifdef __SMP__ /* @@ -616,10 +695,11 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne #endif #ifdef CONFIG_BLK_DEV_INITRD +// FIXME needs to do the new bootmem alloc stuff if (LOADER_TYPE) { initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; initrd_end = initrd_start+INITRD_SIZE; - if (initrd_end > memory_end) { + if (initrd_end > (max_low_pfn << PAGE_SHIFT)) { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", initrd_end,memory_end); |