patch-2.3.23 linux/arch/i386/kernel/setup.c

Next file: linux/arch/i386/kernel/smpboot.c
Previous file: linux/arch/i386/kernel/pci-visws.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.22/linux/arch/i386/kernel/setup.c linux/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 @@
 } /* 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 @@
 		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 @@
 } /* 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 @@
 		 * "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 @@
 				}
 				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 @@
 	}
 	*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)
-
-	high_pfn = MAXMEM_PFN;
-	if (max_pfn < high_pfn)
-		high_pfn = max_pfn;
+#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;
+
+	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 @@
 #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);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)