patch-2.4.25 linux-2.4.25/arch/sparc64/mm/init.c

Next file: linux-2.4.25/arch/x86_64/config.in
Previous file: linux-2.4.25/arch/sparc64/lib/VIScopy.S
Back to the patch index
Back to the overall index

diff -urN linux-2.4.24/arch/sparc64/mm/init.c linux-2.4.25/arch/sparc64/mm/init.c
@@ -34,6 +34,7 @@
 #include <asm/starfire.h>
 #include <asm/tlb.h>
 #include <asm/spitfire.h>
+#include <asm/sections.h>
 
 mmu_gather_t mmu_gathers[NR_CPUS];
 
@@ -44,7 +45,16 @@
 unsigned long *sparc64_valid_addr_bitmap;
 
 /* Ugly, but necessary... -DaveM */
-unsigned long phys_base;
+unsigned long phys_base, kern_base, kern_size;
+
+/* This is even uglier. We have a problem where the kernel may not be
+ * located at phys_base. However, initial __alloc_bootmem() calls need to
+ * be adjusted to be within the 4-8Megs that the kernel is mapped to, else
+ * those page mappings wont work. Things are ok after inherit_prom_mappings
+ * is called though. Dave says he'll clean this up some other time.
+ * -- BenC
+ */
+static unsigned long bootmap_base;
 
 /* get_new_mmu_context() uses "cache + 1".  */
 spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
@@ -52,9 +62,6 @@
 #define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
 unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
 
-/* References to section boundaries */
-extern char __init_begin, __init_end, _start, _end, etext, edata;
-
 /* Initial ramdisk setup */
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
@@ -344,7 +351,7 @@
 	n += 5 * sizeof(struct linux_prom_translation);
 	for (tsz = 1; tsz < n; tsz <<= 1)
 		/* empty */;
-	trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, 0UL);
+	trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base);
 	if (trans == NULL) {
 		prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
 		prom_halt();
@@ -364,7 +371,7 @@
 	 * in inherit_locked_prom_mappings()).
 	 */
 #define OBP_PMD_SIZE 2048
-	prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, 0UL);
+	prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base);
 	if (prompmd == NULL)
 		early_pgtable_allocfail("pmd");
 	memset(prompmd, 0, OBP_PMD_SIZE);
@@ -382,7 +389,7 @@
 				if (pmd_none(*pmdp)) {
 					ptep = __alloc_bootmem(BASE_PAGE_SIZE,
 							       BASE_PAGE_SIZE,
-							       0UL);
+							       bootmap_base);
 					if (ptep == NULL)
 						early_pgtable_allocfail("pte");
 					memset(ptep, 0, BASE_PAGE_SIZE);
@@ -1202,6 +1209,10 @@
 	unsigned long bootmap_pfn, bytes_avail, size;
 	int i;
 
+#ifdef CONFIG_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 +
@@ -1232,15 +1243,8 @@
 	 * image.  The kernel is hard mapped below PAGE_OFFSET in a
 	 * 4MB locked TLB translation.
 	 */
-	start_pfn  = PAGE_ALIGN((unsigned long) &_end) -
-		((unsigned long) KERNBASE);
+	start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT;
 
-	/* Adjust up to the physical address where the kernel begins. */
-	start_pfn += phys_base;
-
-	/* Now shift down to get the real physical page frame number. */
-	start_pfn >>= PAGE_SHIFT;
-	
 	bootmap_pfn = start_pfn;
 
 	end_pfn = end_of_phys_memory >> PAGE_SHIFT;
@@ -1268,19 +1272,33 @@
 	/* Initialize the boot-time allocator. */
 	max_pfn = max_low_pfn = end_pfn;
 	min_low_pfn = phys_base >> PAGE_SHIFT;
-	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, phys_base>>PAGE_SHIFT, end_pfn);
+
+#ifdef CONFIG_DEBUG_BOOTMEM
+	prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n",
+		    min_low_pfn, bootmap_pfn, max_low_pfn);
+#endif
+	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, min_low_pfn, end_pfn);
+
+	bootmap_base = bootmap_pfn << PAGE_SHIFT;
 
 	/* Now register the available physical memory with the
 	 * allocator.
 	 */
-	for (i = 0; sp_banks[i].num_bytes != 0; i++)
-		free_bootmem(sp_banks[i].base_addr,
-			     sp_banks[i].num_bytes);
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+#ifdef CONFIG_DEBUG_BOOTMEM
+		prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n",
+			    i, sp_banks[i].base_addr, sp_banks[i].num_bytes);
+#endif
+		free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes);
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start) {
 		size = initrd_end - initrd_start;
-
+#ifdef CONFIG_DEBUG_BOOTMEM
+		prom_printf("reserve_bootmem(initrd): base[%lx] size[%lx]\n",
+			    initrd_start, size);
+#endif
 		/* Resert the initrd image area. */
 		reserve_bootmem(initrd_start, size);
 		*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
@@ -1290,15 +1308,21 @@
 	}
 #endif
 	/* Reserve the kernel text/data/bss. */
-	size = (start_pfn << PAGE_SHIFT) - phys_base;
-	reserve_bootmem(phys_base, size);
-	*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+#ifdef CONFIG_DEBUG_BOOTMEM
+	prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size);
+#endif
+	reserve_bootmem(kern_base, kern_size);
+	*pages_avail -= PAGE_ALIGN(kern_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 CONFIG_DEBUG_BOOTMEM
+	prom_printf("reserve_bootmem(bootmap): 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;
 
@@ -1317,7 +1341,7 @@
 	extern pmd_t swapper_pmd_dir[1024];
 	extern unsigned int sparc64_vpte_patchme1[1];
 	extern unsigned int sparc64_vpte_patchme2[1];
-	unsigned long alias_base = phys_base + PAGE_OFFSET;
+	unsigned long alias_base = kern_base + PAGE_OFFSET;
 	unsigned long second_alias_page = 0;
 	unsigned long pt, flags, end_pfn, pages_avail;
 	unsigned long shift = alias_base - ((unsigned long)KERNBASE);
@@ -1337,7 +1361,7 @@
 	 * if this were not true we wouldn't boot up to this point
 	 * anyways.
 	 */
-	pt  = phys_base | _PAGE_VALID | _PAGE_SZ4MB;
+	pt  = kern_base | _PAGE_VALID | _PAGE_SZ4MB;
 	pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
 	__save_and_cli(flags);
 	if (tlb_type == spitfire) {
@@ -1417,14 +1441,6 @@
 	pages_avail = 0;
 	last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
 
-#ifdef CONFIG_SUN_SERIAL
-	/* This does not logically belong here, but we need to
-	 * call it at the moment we are able to use the bootmem
-	 * allocator.
-	 */
-	sun_serial_setup();
-#endif
-
 	/* Inherit non-locked OBP mappings. */
 	inherit_prom_mappings();
 	
@@ -1439,7 +1455,16 @@
 	}
 
 	inherit_locked_prom_mappings(1);
-	
+
+#ifdef CONFIG_SUN_SERIAL
+	/* This does not logically belong here, but we need to call it at
+	 * the moment we are able to use the bootmem allocator. This _has_
+	 * to be done after the prom_mappings above so since
+	 * __alloc_bootmem() doesn't work correctly until then.
+	 */
+	sun_serial_setup();
+#endif
+
 	/* We only created DTLB mapping of this stuff. */
 	spitfire_flush_dtlb_nucleus_page(alias_base);
 	if (second_alias_page)
@@ -1609,17 +1634,15 @@
 	i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
 	i += 1;
 	sparc64_valid_addr_bitmap = (unsigned long *)
-		__alloc_bootmem(i << 3, SMP_CACHE_BYTES, 0UL);
+		__alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base);
 	if (sparc64_valid_addr_bitmap == NULL) {
 		prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
 		prom_halt();
 	}
 	memset(sparc64_valid_addr_bitmap, 0, i << 3);
 
-	addr = PAGE_OFFSET + phys_base;
-	last = PAGE_ALIGN((unsigned long)&_end) -
-		((unsigned long) KERNBASE);
-	last += PAGE_OFFSET + phys_base;
+	addr = PAGE_OFFSET + kern_base;
+	last = PAGE_ALIGN(kern_size) + addr;
 	while (addr < last) {
 		set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
 		addr += PAGE_SIZE;
@@ -1630,6 +1653,9 @@
 	max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT);
 	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
+#ifdef CONFIG_DEBUG_BOOTMEM
+	prom_printf("mem_init: Calling free_all_bootmem().\n");
+#endif
 	num_physpages = free_all_bootmem() - 1;
 
 	/*
@@ -1656,7 +1682,7 @@
 		/* Put empty_pg_dir on pgd_quicklist */
 		extern pgd_t empty_pg_dir[1024];
 		unsigned long addr = (unsigned long)empty_pg_dir;
-		unsigned long alias_base = phys_base + PAGE_OFFSET -
+		unsigned long alias_base = kern_base + PAGE_OFFSET -
 			(long)(KERNBASE);
 		
 		memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
@@ -1691,7 +1717,7 @@
 		struct page *p;
 
 		page = (addr +
-			((unsigned long) __va(phys_base)) -
+			((unsigned long) __va(kern_base)) -
 			((unsigned long) KERNBASE));
 		p = virt_to_page(page);
 

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