patch-2.4.0-test6 linux/arch/sparc/mm/init.c

Next file: linux/arch/sparc/mm/io-unit.c
Previous file: linux/arch/sparc/mm/generic.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.88 2000/07/10 20:56:53 anton Exp $
+/*  $Id: init.c,v 1.90 2000/08/09 00:00:15 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -51,7 +51,9 @@
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
 
-unsigned long totalram_pages = 0;
+unsigned long highstart_pfn, highend_pfn;
+unsigned long totalram_pages;
+static unsigned long totalhigh_pages;
 
 /*
  * BAD_PAGE is the page that is used for page faults when linux
@@ -79,6 +81,21 @@
 				       PAGE_SHARED));
 }
 
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+#define kmap_get_fixed_pte(vaddr) \
+	pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+void __init kmap_init(void)
+{
+	unsigned long pteval;
+
+	/* cache the first kmap pte */
+	kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN);
+	kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);
+}
+
 void show_mem(void)
 {
 	printk("Mem-info:\n");
@@ -119,22 +136,15 @@
 #define DEBUG_BOOTMEM
 
 extern unsigned long cmdline_memory_size;
+extern unsigned long last_valid_pfn;
 
-unsigned long __init bootmem_init(void)
+void __init bootmem_init(void)
 {
-	unsigned long bootmap_size, start_pfn, end_pfn;
+	unsigned long bootmap_size, start_pfn, max_pfn;
 	unsigned long end_of_phys_memory = 0UL;
 	unsigned long bootmap_pfn;
 	int i;
 
-	/* 
-	 * XXX Limit maximum memory until we implement highmem for sparc.
-	 * The nocache region has taken up some room but I'll rearrange
-	 * the virtual address regions soon - Anton
-	 */
-	if (!cmdline_memory_size || cmdline_memory_size > 0x0c000000)
-		cmdline_memory_size = 0x0c000000;
-
 	/* 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
@@ -181,7 +191,16 @@
 
 	bootmap_pfn = start_pfn;
 
-	end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+	max_pfn = end_of_phys_memory >> PAGE_SHIFT;
+
+	max_low_pfn = max_pfn;
+	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));
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
@@ -205,22 +224,41 @@
 #endif	
 	/* Initialize the boot-time allocator. */
 #ifdef DEBUG_BOOTMEM
-	prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n",
-		    start_pfn, bootmap_pfn, end_pfn);
+	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, end_pfn);
+	bootmap_size = init_bootmem(bootmap_pfn, max_low_pfn);
 
 	/* Now register the available physical memory with the
 	 * allocator.
 	 */
 	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		unsigned long curr_pfn, last_pfn, size;
+
+		curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
+		if (curr_pfn >= max_low_pfn)
+			break;
+
+		last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
+		if (last_pfn > max_low_pfn)
+			last_pfn = max_low_pfn;
+
+		/*
+		 * .. 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) << PAGE_SHIFT;
+
 #ifdef DEBUG_BOOTMEM
 		prom_printf("free_bootmem: base[%lx] size[%lx]\n",
 			    sp_banks[i].base_addr,
-			    sp_banks[i].num_bytes);
+			    size);
 #endif
 		free_bootmem(sp_banks[i].base_addr,
-			     sp_banks[i].num_bytes);
+			     size);
 	}
 
 	/* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */
@@ -245,10 +283,7 @@
 	reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
 	reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size);
 
-#ifdef DEBUG_BOOTMEM
-	prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
-#endif
-	return end_pfn;
+	last_valid_pfn = max_pfn;
 }
 
 /*
@@ -334,8 +369,8 @@
 	prom_printf("[%p,%p] ", first, last);
 #endif
 	while (first < last) {
-		ClearPageReserved(mem_map + MAP_NR(first));
-		set_page_count(mem_map + MAP_NR(first), 1);
+		ClearPageReserved(virt_to_page(first));
+		set_page_count(virt_to_page(first), 1);
 		free_page((unsigned long)first);
 		totalram_pages++;
 		num_physpages++;
@@ -391,6 +426,25 @@
 #endif
 }
 
+void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
+{
+	unsigned long tmp;
+
+#ifdef DEBUG_HIGHMEM
+	printk("mapping high region %08lx - %08lx\n", start_pfn, end_pfn);
+#endif
+
+	for (tmp = start_pfn; tmp < end_pfn; tmp++) {
+		struct page *page = mem_map + tmp;
+
+		ClearPageReserved(page);
+		set_bit(PG_highmem, &page->flags);
+		atomic_set(&page->count, 1);
+		__free_page(page);
+		totalhigh_pages++;
+	}
+}
+
 void __init mem_init(void)
 {
 	int codepages = 0;
@@ -401,6 +455,10 @@
 	unsigned long addr, last;
 #endif
 
+	highmem_start_page = mem_map + highstart_pfn;
+	/* cache the highmem_mapnr */
+	highmem_mapnr = highstart_pfn;
+
 	/* Saves us work later. */
 	memset((void *)&empty_zero_page, 0, PAGE_SIZE);
 
@@ -419,7 +477,7 @@
 	taint_real_pages();
 
 	max_mapnr = last_valid_pfn;
-	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
+	high_memory = __va(max_low_pfn << PAGE_SHIFT);
 
 #ifdef DEBUG_BOOTMEM
 	prom_printf("mem_init: Calling free_all_bootmem().\n");
@@ -430,6 +488,21 @@
 	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;
+
+		if (end_pfn <= highstart_pfn)
+			continue;
+
+		if (start_pfn < highstart_pfn)
+			start_pfn = highstart_pfn;
+
+		map_high_region(start_pfn, end_pfn);
+	}
+	
+	totalram_pages += totalhigh_pages;
+
 	codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
 	codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
 	datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
@@ -437,11 +510,12 @@
 	initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin));
 	initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
 
-	printk("Memory: %dk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
+	printk("Memory: %dk available (%dk kernel code, %dk data, %dk init, %ldk highmem) [%08lx,%08lx]\n",
 	       nr_free_pages() << (PAGE_SHIFT-10),
 	       codepages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10), 
 	       initpages << (PAGE_SHIFT-10),
+	       totalhigh_pages << (PAGE_SHIFT-10),
 	       (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
 
 	/* NOTE NOTE NOTE NOTE
@@ -468,7 +542,7 @@
 		struct page *p;
 
 		page = addr + phys_base;
-		p = mem_map + MAP_NR(page);
+		p = virt_to_page(page);
 
 		ClearPageReserved(p);
 		set_page_count(p, 1);
@@ -485,7 +559,7 @@
 	if (start < end)
 		printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 	for (; start < end; start += PAGE_SIZE) {
-		struct page *p = mem_map + MAP_NR(start);
+		struct page *p = virt_to_page(start);
 
 		ClearPageReserved(p);
 		set_page_count(p, 1);
@@ -501,9 +575,16 @@
 	val->sharedram = 0;
 	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
-
-	val->totalhigh = 0;
-	val->freehigh = 0;
+	val->totalhigh = totalhigh_pages;
+	val->freehigh = nr_free_highpages();
 
 	val->mem_unit = PAGE_SIZE;
+}
+
+void flush_page_to_ram(struct page *page)
+{
+	unsigned long vaddr;
+	vaddr = kmap(page);
+	__flush_page_to_ram(page_address(page));
+	kunmap(page);
 }

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