diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 23:21:57 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 23:21:57 +0000 |
commit | 511bcd7c5924ce9e98ad1cb851988f7448dfef0f (patch) | |
tree | 6194d472814ef315450ee5fe190c3cbbdc762c49 /arch | |
parent | 0a20dc624ae03f1acb9e72b704907f3b5c79cff9 (diff) |
Bootmem fixes for IP22.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/arc/memory.c | 108 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 19 | ||||
-rw-r--r-- | arch/mips64/arc/memory.c | 248 | ||||
-rw-r--r-- | arch/mips64/mm/init.c | 18 | ||||
-rw-r--r-- | arch/mips64/sgi-ip27/ip27-memory.c | 4 |
5 files changed, 212 insertions, 185 deletions
diff --git a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c index a3b02dc67..4582297c2 100644 --- a/arch/mips/arc/memory.c +++ b/arch/mips/arc/memory.c @@ -4,7 +4,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: memory.c,v 1.8 2000/01/17 23:32:46 ralf Exp $ + * $Id: memory.c,v 1.9 2000/01/27 01:05:23 ralf Exp $ */ #include <linux/init.h> #include <linux/kernel.h> @@ -24,9 +24,10 @@ extern char _end; -struct linux_mdesc * __init prom_getmdesc(struct linux_mdesc *curr) +struct linux_mdesc * __init +ArcGetMemoryDescriptor(struct linux_mdesc *Current) { - return romvec->get_mdesc(curr); + return romvec->get_mdesc(Current); } #ifdef DEBUG /* convenient for debugging */ @@ -54,7 +55,7 @@ static char *arc_mtypes[8] = { #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc] #endif -static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; +static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS]; #define MEMTYPE_DONTUSE 0 #define MEMTYPE_PROM 1 @@ -103,102 +104,125 @@ static inline int memtype_classify_arc (union linux_memtypes type) static int __init prom_memtype_classify (union linux_memtypes type) { if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */ - return memtype_classify_arc(type); + return memtype_classify_arcs(type); return memtype_classify_arc(type); } -static unsigned long __init find_max_low_pfn(void) +static inline unsigned long find_max_low_pfn(void) { struct prom_pmemblock *p, *highest; + unsigned long pfn; - for (p = prom_pblocks, highest = 0; p->size != 0; p++) { + p = pblocks; + highest = 0; + while (p->size != 0) { if (!highest || p->base > highest->base) highest = p; + p++; } + + pfn = (highest->base + highest->size) >> PAGE_SHIFT; #ifdef DEBUG - prom_printf("find_max_low_pfn: mips_memory_upper = %08lx\n", highest); + prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn); #endif - return (highest->base + highest->size) >> PAGE_SHIFT; + return pfn; } -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((x) << PAGE_SHIFT) -#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) +static inline struct prom_pmemblock *find_largest_memblock(void) +{ + struct prom_pmemblock *p, *largest; + + p = pblocks; + largest = 0; + while (p->size != 0) { + if (!largest || p->size > largest->size) + largest = p; + p++; + } + + return largest; +} void __init prom_meminit(void) { - unsigned long start_pfn; + struct prom_pmemblock *largest; + unsigned long bootmap_size; struct linux_mdesc *p; int totram; int i = 0; #ifdef DEBUG prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); - p = prom_getmdesc(PROM_NULL_MDESC); + p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); while(p) { prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", i, p, p->base, p->pages, mtypes(p->type)); - p = prom_getmdesc(p); + p = ArcGetMemoryDescriptor(p); i++; } #endif totram = 0; - p = prom_getmdesc(PROM_NULL_MDESC); i = 0; - while (p) { - prom_pblocks[i].type = prom_memtype_classify(p->type); - prom_pblocks[i].base = p->base << PAGE_SHIFT; - prom_pblocks[i].size = p->pages << PAGE_SHIFT; + p = PROM_NULL_MDESC; + while ((p = ArcGetMemoryDescriptor(p))) { + pblocks[i].type = prom_memtype_classify(p->type); + pblocks[i].base = p->base << PAGE_SHIFT; + pblocks[i].size = p->pages << PAGE_SHIFT; - switch (prom_pblocks[i].type) { + switch (pblocks[i].type) { case MEMTYPE_FREE: - totram += prom_pblocks[i].size; + totram += pblocks[i].size; #ifdef DEBUG - prom_printf("free_chunk[%d]: base=%08lx size=%d\n", - i, prom_pblocks[i].base, - prom_pblocks[i].size); + prom_printf("free_chunk[%d]: base=%08lx size=%x\n", + i, pblocks[i].base, + pblocks[i].size); #endif i++; break; case MEMTYPE_PROM: #ifdef DEBUG - prom_printf("prom_chunk[%d]: base=%08lx size=%d\n", - i, prom_pblocks[i].base, - prom_pblocks[i].size); + prom_printf("prom_chunk[%d]: base=%08lx size=%x\n", + i, pblocks[i].base, + pblocks[i].size); #endif i++; break; default: break; } - p = prom_getmdesc(p); } - prom_pblocks[i].size = 0; + pblocks[i].size = 0; - /* Setup upper physical memory bound. */ max_low_pfn = find_max_low_pfn(); + largest = find_largest_memblock(); + bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn); - start_pfn = PFN_UP((unsigned long)&_end - PAGE_OFFSET); - init_bootmem(start_pfn, max_low_pfn); + for (i = 0; pblocks[i].size; i++) + if (pblocks[i].type == MEMTYPE_FREE) + free_bootmem(pblocks[i].base, pblocks[i].size); - for (i = 0; prom_pblocks[i].size; i++) - if (prom_pblocks[i].type == MEMTYPE_FREE) - free_bootmem(prom_pblocks[i].base, prom_pblocks[i].size); + /* This test is simpleminded. It will fail if the bootmem bitmap + falls into multiple adjacent ARC memory areas. */ + if (bootmap_size > largest->size) { + prom_printf("CRITIAL: overwriting PROM data.\n"); + BUG(); + } + reserve_bootmem(largest->base, bootmap_size); - printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", - totram, (totram/1024), (totram/1024/1024)); + printk("PROMLIB: Total free ram %dK / %dMB.\n", + totram >> 10, totram >> 20); } -void __init prom_free_prom_memory (void) +void __init +prom_free_prom_memory (void) { struct prom_pmemblock *p; unsigned long freed = 0; unsigned long addr; - for (p = prom_pblocks; p->size != 0; p++) { + for (p = pblocks; p->size != 0; p++) { if (p->type != MEMTYPE_PROM) continue; @@ -211,5 +235,5 @@ void __init prom_free_prom_memory (void) freed += PAGE_SIZE; } } - printk("Freeing prom memory: %ldk freed\n", freed >> 10); + printk("Freeing prom memory: %ldkb freed\n", freed >> 10); } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index cf74a6dd5..20ff288ce 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.20 2000/01/26 00:07:44 ralf Exp $ +/* $Id: init.c,v 1.21 2000/01/27 01:05:23 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -259,7 +259,7 @@ extern int page_is_ram(unsigned long pagenr); void __init mem_init(void) { unsigned long codesize, reservedpages, datasize, initsize; - unsigned long tmp; + unsigned long tmp, nonram; max_mapnr = num_physpages = max_low_pfn; high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); @@ -267,21 +267,22 @@ void __init mem_init(void) totalram_pages += free_all_bootmem(); totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ - reservedpages = 0; + reservedpages = nonram = 0; for (tmp = 0; tmp < max_low_pfn; tmp++) - /* - * Only count resrved RAM pages - */ - if (page_is_ram(tmp) && PageReserved(mem_map+tmp)) - reservedpages++; + if (page_is_ram(tmp)) { + nonram++; + if (PageReserved(mem_map+tmp)) + reservedpages++; + } codesize = (unsigned long) &_etext - (unsigned long) &_ftext; datasize = (unsigned long) &_edata - (unsigned long) &_fdata; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " "%ldk data, %ldk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), - max_mapnr << (PAGE_SHIFT-10), + (max_mapnr - nonram) << (PAGE_SHIFT-10), codesize >> 10, reservedpages << (PAGE_SHIFT-10), datasize >> 10, diff --git a/arch/mips64/arc/memory.c b/arch/mips64/arc/memory.c index a63d8d631..78a37a841 100644 --- a/arch/mips64/arc/memory.c +++ b/arch/mips64/arc/memory.c @@ -1,4 +1,4 @@ -/* $Id: memory.c,v 1.4 1999/11/19 20:35:22 ralf Exp $ +/* $Id: memory.c,v 1.4 2000/01/17 23:32:46 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -19,6 +19,7 @@ #include <linux/types.h> #include <linux/sched.h> #include <linux/mm.h> +#include <linux/bootmem.h> #include <linux/swap.h> #include <linux/config.h> @@ -29,14 +30,16 @@ #undef DEBUG +extern char _end; + struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) { return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current); } -#ifdef DEBUG -static char *arcs_mtypes[8] = { /* convenient for debugging */ +#ifdef DEBUG /* convenient for debugging */ +static char *arcs_mtypes[8] = { "Exception Block", "ARCS Romvec Page", "Free/Contig RAM", @@ -57,188 +60,189 @@ static char *arc_mtypes[8] = { "FirmwarePermanent", "FreeContigiuous" }; - #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc] +#endif -#endif /* DEBUG */ - -static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; - -struct prom_pmemblock * __init prom_getpblock_array(void) -{ - return &prom_pblocks[0]; -} +static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS]; #define MEMTYPE_DONTUSE 0 #define MEMTYPE_PROM 1 #define MEMTYPE_FREE 2 -static int __init -prom_memtype_classify (union linux_memtypes type) +static inline int memtype_classify_arcs (union linux_memtypes type) { - if (prom_flags & PROM_FLAG_ARCS) { - switch (type.arcs) { - case arcs_free: - case arcs_fcontig: - return MEMTYPE_FREE; - case arcs_atmp: - case arcs_aperm: - return MEMTYPE_PROM; - default: - return MEMTYPE_DONTUSE; - } - } else { - switch (type.arc) { - case arc_free: - case arc_fcontig: - return MEMTYPE_FREE; - case arc_rvpage: - case arc_atmp: - case arc_aperm: - return MEMTYPE_PROM; - default: - return MEMTYPE_DONTUSE; - } + switch (type.arcs) { + case arcs_fcontig: + case arcs_free: + return MEMTYPE_FREE; + case arcs_atmp: + return MEMTYPE_PROM; + case arcs_eblock: + case arcs_rvpage: + case arcs_bmem: + case arcs_prog: + case arcs_aperm: + return MEMTYPE_DONTUSE; + default: + BUG(); } + while(1); /* Nuke warning. */ } -static void __init -prom_setup_memupper(void) +static inline int memtype_classify_arc (union linux_memtypes type) +{ + switch (type.arc) { + case arc_free: + case arc_fcontig: + return MEMTYPE_FREE; + case arc_atmp: + return MEMTYPE_PROM; + case arc_eblock: + case arc_rvpage: + case arc_bmem: + case arc_prog: + case arc_aperm: + return MEMTYPE_DONTUSE; + default: + BUG(); + } + while(1); /* Nuke warning. */ +} + +static int __init prom_memtype_classify (union linux_memtypes type) +{ + if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */ + return memtype_classify_arcs(type); + + return memtype_classify_arc(type); +} + +static inline unsigned long find_max_low_pfn(void) { struct prom_pmemblock *p, *highest; + unsigned long pfn; - for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) { - if(p->base == 0xdeadbeef) - prom_printf("WHEEE, bogus pmemblock\n"); - if(!highest || p->base > highest->base) + p = pblocks; + highest = 0; + while (p->size != 0) { + if (!highest || p->base > highest->base) highest = p; + p++; } - mips_memory_upper = (long) highest->base + highest->size; - -#ifdef CONFIG_SGI_IP22 - /* Evil temporary hack - free_area_init may overwrite firmware reserved - memory during the initialization on an Indy if we have more than - a certain amount of memory. For now on Indys we limit memory to - 64mb max. */ - if (mips_memory_upper > PAGE_OFFSET + 0x08000000 + 64 * 1024 * 1024) { - prom_printf("WARNING: Limiting memory to 64mb.\n"); - mips_memory_upper = PAGE_OFFSET + 0x08000000 + 64 * 1024 * 1024; - } -#endif + + pfn = (highest->base + highest->size) >> PAGE_SHIFT; #ifdef DEBUG - prom_printf("prom_setup_memupper: mips_memory_upper = %016lx\n", - mips_memory_upper); + prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn); #endif + return pfn; } -void __init -prom_meminit(void) +static inline struct prom_pmemblock *find_largest_memblock(void) { + struct prom_pmemblock *p, *largest; + + p = pblocks; + largest = 0; + while (p->size != 0) { + if (!largest || p->size > largest->size) + largest = p; + p++; + } + + return largest; +} + +void __init prom_meminit(void) +{ + struct prom_pmemblock *largest; + unsigned long bootmap_size; struct linux_mdesc *p; - unsigned long totram; - int i; + int totram; + int i = 0; #ifdef DEBUG - i = 0; - p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); + p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); while(p) { prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", - i, p, p->base, p->pages, mtypes(p->type)); + i, p, p->base, p->pages, mtypes(p->type)); p = ArcGetMemoryDescriptor(p); i++; } #endif - p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); + totram = 0; i = 0; - while(p) { - prom_pblocks[i].type = prom_memtype_classify (p->type); - prom_pblocks[i].base = PAGE_OFFSET + (p->base << PAGE_SHIFT); - prom_pblocks[i].size = p->pages << PAGE_SHIFT; - switch (prom_pblocks[i].type) { + p = PROM_NULL_MDESC; + while ((p = ArcGetMemoryDescriptor(p))) { + pblocks[i].type = prom_memtype_classify(p->type); + pblocks[i].base = p->base << PAGE_SHIFT; + pblocks[i].size = p->pages << PAGE_SHIFT; + + switch (pblocks[i].type) { case MEMTYPE_FREE: - totram += prom_pblocks[i].size; + totram += pblocks[i].size; #ifdef DEBUG - prom_printf("free_chunk[%d]: base=%08lx size=%x" - " total=%x\n", - i, prom_pblocks[i].base, - prom_pblocks[i].size, totram); + prom_printf("free_chunk[%d]: base=%08lx size=%x\n", + i, pblocks[i].base, + pblocks[i].size); #endif i++; break; case MEMTYPE_PROM: #ifdef DEBUG prom_printf("prom_chunk[%d]: base=%08lx size=%x\n", - i, prom_pblocks[i].base, - prom_pblocks[i].size); + i, pblocks[i].base, + pblocks[i].size); #endif i++; break; default: break; } - p = ArcGetMemoryDescriptor(p); } - prom_pblocks[i].base = 0xdeadbeef; - prom_pblocks[i].size = 0; /* indicates last elem. of array */ - printk("PROMLIB: Total free ram %ld bytes (%ldK,%ldMB)\n", - totram, (totram/1024), (totram/1024/1024)); + pblocks[i].size = 0; - /* Setup upper physical memory bound. */ - prom_setup_memupper(); -} + max_low_pfn = find_max_low_pfn(); + largest = find_largest_memblock(); + bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn); -/* Called from mem_init() to fixup the mem_map page settings. */ -void __init -prom_fixup_mem_map(unsigned long start, unsigned long end) -{ - struct prom_pmemblock *p; - int i, nents; - - /* Determine number of pblockarray entries. */ - p = prom_getpblock_array(); - for(i = 0; p[i].size; i++) - ; - nents = i; -restart: - while(start < end) { - for(i = 0; i < nents; i++) { - unsigned long base, size; - - base = (unsigned long) (long) p[i].base; - size = p[i].size; - if ((p[i].type == MEMTYPE_FREE) - && (start >= base) - && (start < base + size)) { - start = base + size; - start &= PAGE_MASK; - goto restart; - } - } - set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); - start += PAGE_SIZE; + for (i = 0; pblocks[i].size; i++) + if (pblocks[i].type == MEMTYPE_FREE) + free_bootmem(pblocks[i].base, pblocks[i].size); + + /* This test is simpleminded. It will fail if the bootmem bitmap + falls into multiple adjacent ARC memory areas. */ + if (bootmap_size > largest->size) { + prom_printf("CRITIAL: overwriting PROM data.\n"); + BUG(); } + reserve_bootmem(largest->base, bootmap_size); + + printk("PROMLIB: Total free ram %dK / %dMB.\n", + totram >> 10, totram >> 20); } void __init prom_free_prom_memory (void) { struct prom_pmemblock *p; - unsigned long addr, base; unsigned long freed = 0; + unsigned long addr, end; - for (p = prom_getpblock_array(); p->size != 0; p++) { + for (p = pblocks; p->size != 0; p++) { if (p->type != MEMTYPE_PROM) continue; - addr = base = (unsigned long) (long) p->base; - while (addr < base + p->size) { - mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - atomic_set(&mem_map[MAP_NR(addr)].count, 1); + + addr = PAGE_OFFSET + (unsigned long) (long) p->base; + end = addr + (unsigned long) (long) p->size; + while (addr < end) { + ClearPageReserved(mem_map + MAP_NR(addr)); + set_page_count(mem_map + MAP_NR(addr), 1); free_page(addr); - freed += PAGE_SIZE; addr += PAGE_SIZE; + freed += PAGE_SIZE; } } - printk("Freeing prom memory: %ldkb freed\n", freed / 1024); + printk("Freeing prom memory: %ldkb freed\n", freed >> 10); } diff --git a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c index 682db726c..473e798e8 100644 --- a/arch/mips64/mm/init.c +++ b/arch/mips64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.6 2000/01/17 03:46:25 ralf Exp $ +/* $Id: init.c,v 1.7 2000/01/27 01:05:24 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -354,7 +354,7 @@ extern int page_is_ram(unsigned long pagenr); void __init mem_init(void) { unsigned long codesize, reservedpages, datasize, initsize; - unsigned long tmp; + unsigned long tmp, nonram; max_mapnr = num_physpages = max_low_pfn; high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); @@ -362,13 +362,13 @@ void __init mem_init(void) totalram_pages += free_all_bootmem(); totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ - reservedpages = 0; + reservedpages = nonram = 0; for (tmp = 0; tmp < max_low_pfn; tmp++) - /* - * Only count reserved RAM pages - */ - if (page_is_ram(tmp) && PageReserved(mem_map+tmp)) - reservedpages++; + if (page_is_ram(tmp)) { + nonram++; + if (PageReserved(mem_map+tmp)) + reservedpages++; + } codesize = (unsigned long) &_etext - (unsigned long) &_ftext; datasize = (unsigned long) &_edata - (unsigned long) &_fdata; @@ -377,7 +377,7 @@ void __init mem_init(void) printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " "%ldk data, %ldk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), - max_mapnr << (PAGE_SHIFT-10), + (max_mapnr - nonram) << (PAGE_SHIFT-10), codesize >> 10, reservedpages << (PAGE_SHIFT-10), datasize >> 10, diff --git a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c index ca1b1e6cc..286c510b7 100644 --- a/arch/mips64/sgi-ip27/ip27-memory.c +++ b/arch/mips64/sgi-ip27/ip27-memory.c @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: ip27-memory.c,v 1.2 2000/01/27 01:05:24 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -23,8 +23,6 @@ extern char _end; #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((x) << PAGE_SHIFT) #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) void __init |