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
- Lines: 273
- Date:
Wed Aug 9 13:49:55 2000
- Orig file:
v2.4.0-test5/linux/arch/sparc/mm/init.c
- Orig date:
Fri Jul 14 12:12:07 2000
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)