patch-2.4.3 linux/arch/sparc/mm/init.c

Next file: linux/arch/sparc/mm/srmmu.c
Previous file: linux/arch/sparc/mm/fault.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.2/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
@@ -1,10 +1,10 @@
-/*  $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $
+/*  $Id: init.c,v 1.97 2001/02/26 02:57:34 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be)
  *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *  Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
+ *  Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
  */
 
 #include <linux/config.h>
@@ -53,7 +53,7 @@
 
 unsigned long highstart_pfn, highend_pfn;
 unsigned long totalram_pages;
-static unsigned long totalhigh_pages;
+unsigned long totalhigh_pages;
 
 /*
  * BAD_PAGE is the page that is used for page faults when linux
@@ -134,42 +134,79 @@
 #define DEBUG_BOOTMEM
 
 extern unsigned long cmdline_memory_size;
-extern unsigned long last_valid_pfn;
+unsigned long last_valid_pfn;
+
+unsigned long calc_highpages(void)
+{
+	int i;
+	int nr = 0;
+
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
+		unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
+
+		if (end_pfn <= max_low_pfn)
+			continue;
 
-void __init bootmem_init(void)
+		if (start_pfn < max_low_pfn)
+			start_pfn = max_low_pfn;
+
+		nr += end_pfn - start_pfn;
+	}
+
+	return nr;
+}
+
+unsigned long calc_max_low_pfn(void)
+{
+	int i;
+	unsigned long tmp = (SRMMU_MAXMEM >> PAGE_SHIFT);
+	unsigned long curr_pfn, last_pfn;
+
+	last_pfn = (sp_banks[0].base_addr + sp_banks[0].num_bytes) >> PAGE_SHIFT;
+	for (i = 1; sp_banks[i].num_bytes != 0; i++) {
+		curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
+
+		if (curr_pfn >= tmp) {
+			if (last_pfn < tmp)
+				tmp = last_pfn;
+			break;
+		}
+
+		last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
+	}
+
+	return tmp;
+}
+
+unsigned long __init bootmem_init(unsigned long *pages_avail)
 {
 	unsigned long bootmap_size, start_pfn, max_pfn;
 	unsigned long end_of_phys_memory = 0UL;
-	unsigned long bootmap_pfn;
+	unsigned long bootmap_pfn, bytes_avail, size;
 	int i;
 
-	/* XXX It is a bit ambiguous here, whether we should
-	 * XXX treat the user specified mem=xxx as total wanted
-	 * XXX physical memory, or as a limit to the upper
-	 * XXX physical address we allow.  For now it is the
-	 * XXX latter. -DaveM
-	 */
 #ifdef DEBUG_BOOTMEM
 	prom_printf("bootmem_init: Scan sp_banks,  ");
 #endif
+	bytes_avail = 0UL;
 	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
 		end_of_phys_memory = sp_banks[i].base_addr +
 			sp_banks[i].num_bytes;
+		bytes_avail += sp_banks[i].num_bytes;
 		if (cmdline_memory_size) {
-			if (end_of_phys_memory > cmdline_memory_size) {
-				if (cmdline_memory_size < sp_banks[i].base_addr) {
-					end_of_phys_memory =
-						sp_banks[i-1].base_addr +
-						sp_banks[i-1].num_bytes;
+			if (bytes_avail > cmdline_memory_size) {
+				unsigned long slack = bytes_avail - cmdline_memory_size;
+
+				bytes_avail -= slack;
+				end_of_phys_memory -= slack;
+
+				sp_banks[i].num_bytes -= slack;
+				if (sp_banks[i].num_bytes == 0) {
 					sp_banks[i].base_addr = 0xdeadbeef;
-					sp_banks[i].num_bytes = 0;
 				} else {
-					sp_banks[i].num_bytes -=
-						(end_of_phys_memory -
-						 cmdline_memory_size);
-					end_of_phys_memory = cmdline_memory_size;
-					sp_banks[++i].base_addr = 0xdeadbeef;
-					sp_banks[i].num_bytes = 0;
+					sp_banks[i+1].num_bytes = 0;
+					sp_banks[i+1].base_addr = 0xdeadbeef;
 				}
 				break;
 			}
@@ -195,9 +232,9 @@
 	highstart_pfn = highend_pfn = max_pfn;
 
 	if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) {
-		highstart_pfn = max_low_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT);
-		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
-		(highend_pfn - highstart_pfn) >> (20-PAGE_SHIFT));
+		highstart_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT);
+		max_low_pfn = calc_max_low_pfn();
+		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", calc_highpages());
 	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -225,13 +262,14 @@
 	prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],mlpfn[%lx])\n",
 		    start_pfn, bootmap_pfn, max_low_pfn);
 #endif
-	bootmap_size = init_bootmem(bootmap_pfn, max_low_pfn);
+	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, phys_base>>PAGE_SHIFT, max_low_pfn);
 
 	/* Now register the available physical memory with the
 	 * allocator.
 	 */
+	*pages_avail = 0;
 	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
-		unsigned long curr_pfn, last_pfn, size;
+		unsigned long curr_pfn, last_pfn;
 
 		curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
 		if (curr_pfn >= max_low_pfn)
@@ -249,7 +287,7 @@
 			continue;
 
 		size = (last_pfn - curr_pfn) << PAGE_SHIFT;
-
+		*pages_avail += last_pfn - curr_pfn;
 #ifdef DEBUG_BOOTMEM
 		prom_printf("free_bootmem: base[%lx] size[%lx]\n",
 			    sp_banks[i].base_addr,
@@ -259,29 +297,42 @@
 			     size);
 	}
 
-	/* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */
-#ifdef DEBUG_BOOTMEM
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
+	if (initrd_start) {
+		size = initrd_end - initrd_start;
+#ifdef DEBUG_BOOTMEM
 		prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
-			     initrd_start, initrd_end - initrd_start);
+			     initrd_start, size);
 #endif
-	prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
-		    phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
-	prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
-		    (bootmap_pfn << PAGE_SHIFT), bootmap_size);
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start) {
-		reserve_bootmem(initrd_start, initrd_end - initrd_start);
+		/* Reserve the initrd image area. */
+		reserve_bootmem(initrd_start, size);
+		*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+
 		initrd_start += PAGE_OFFSET;
 		initrd_end += PAGE_OFFSET;
 	}
 #endif
-	reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
-	reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size);
+	/* Reserve the kernel text/data/bss. */
+	size = (start_pfn << PAGE_SHIFT) - phys_base;
+#ifdef DEBUG_BOOTMEM
+	prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", phys_base, size);
+#endif
+	reserve_bootmem(phys_base, size);
+	*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/* Reserve the bootmem map.   We do not account for it
+	 * in pages_avail because we will release that memory
+	 * in free_all_bootmem.
+	 */
+	size = bootmap_size;
+#ifdef DEBUG_BOOTMEM
+	prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+		    (bootmap_pfn << PAGE_SHIFT), size);
+#endif
+	reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
+	*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
 
-	last_valid_pfn = max_pfn;
+	return max_pfn;
 }
 
 /*
@@ -293,8 +344,6 @@
 extern void srmmu_paging_init(void);
 extern void device_scan(void);
 
-unsigned long last_valid_pfn;
-
 void __init paging_init(void)
 {
 	switch(sparc_cpu_model) {
@@ -359,71 +408,6 @@
 	}
 }
 
-void __init free_mem_map_range(struct page *first, struct page *last)
-{
-	first = (struct page *) PAGE_ALIGN((unsigned long)first);
-	last  = (struct page *) ((unsigned long)last & PAGE_MASK);
-#ifdef DEBUG_BOOTMEM
-	prom_printf("[%p,%p] ", first, last);
-#endif
-	while (first < last) {
-		ClearPageReserved(virt_to_page(first));
-		set_page_count(virt_to_page(first), 1);
-		free_page((unsigned long)first);
-		totalram_pages++;
-		num_physpages++;
-
-		first = (struct page *)((unsigned long)first + PAGE_SIZE);
-	}
-}
-
-/* Walk through holes in sp_banks regions, if the mem_map array
- * areas representing those holes consume a page or more, free
- * up such pages.  This helps a lot on machines where physical
- * ram is configured such that it begins at some hugh value.
- *
- * The sp_banks array is sorted by base address.
- */
-void __init free_unused_mem_map(void)
-{
-	int i;
-
-#ifdef DEBUG_BOOTMEM
-	prom_printf("free_unused_mem_map: ");
-#endif
-	for (i = 0; sp_banks[i].num_bytes; i++) {
-		if (i == 0) {
-			struct page *first, *last;
-
-			first = mem_map;
-			last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
-			free_mem_map_range(first, last);
-		} else {
-			struct page *first, *last;
-			unsigned long prev_end;
-
-			prev_end = sp_banks[i-1].base_addr +
-				sp_banks[i-1].num_bytes;
-			prev_end = PAGE_ALIGN(prev_end);
-			first = &mem_map[prev_end >> PAGE_SHIFT];
-			last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
-
-			free_mem_map_range(first, last);
-
-			if (!sp_banks[i+1].num_bytes) {
-				prev_end = sp_banks[i].base_addr +
-					sp_banks[i].num_bytes;
-				first = &mem_map[prev_end >> PAGE_SHIFT];
-				last = &mem_map[last_valid_pfn];
-				free_mem_map_range(first, last);
-			}
-		}
-	}
-#ifdef DEBUG_BOOTMEM
-	prom_printf("\n");
-#endif
-}
-
 void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
 {
 	unsigned long tmp;
@@ -458,9 +442,8 @@
 	/* Saves us work later. */
 	memset((void *)&empty_zero_page, 0, PAGE_SIZE);
 
-	i = last_valid_pfn >> (8 + 5);
+	i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
 	i += 1;
-
 	sparc_valid_addr_bitmap = (unsigned long *)
 		__alloc_bootmem(i << 2, SMP_CACHE_BYTES, 0UL);
 
@@ -472,7 +455,7 @@
 
 	taint_real_pages();
 
-	max_mapnr = last_valid_pfn;
+	max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT);
 	high_memory = __va(max_low_pfn << PAGE_SHIFT);
 
 #ifdef DEBUG_BOOTMEM
@@ -480,10 +463,6 @@
 #endif
 	num_physpages = totalram_pages = free_all_bootmem();
 
-#if 0
-	free_unused_mem_map();
-#endif
-
 	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
 		unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
 		unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
@@ -513,19 +492,6 @@
 	       initpages << (PAGE_SHIFT-10),
 	       totalhigh_pages << (PAGE_SHIFT-10),
 	       (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
-
-	/* NOTE NOTE NOTE NOTE
-	 * Please keep track of things and make sure this
-	 * always matches the code in mm/page_alloc.c -DaveM
-	 */
-	i = nr_free_pages() >> 7;
-	if (i < 48)
-		i = 48;
-	if (i > 256)
-		i = 256;
-	freepages.min = i;
-	freepages.low = i << 1;
-	freepages.high = freepages.low + i;
 }
 
 void free_initmem (void)

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