summaryrefslogtreecommitdiffstats
path: root/arch/mips64/arc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-27 23:21:57 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-27 23:21:57 +0000
commit511bcd7c5924ce9e98ad1cb851988f7448dfef0f (patch)
tree6194d472814ef315450ee5fe190c3cbbdc762c49 /arch/mips64/arc
parent0a20dc624ae03f1acb9e72b704907f3b5c79cff9 (diff)
Bootmem fixes for IP22.
Diffstat (limited to 'arch/mips64/arc')
-rw-r--r--arch/mips64/arc/memory.c248
1 files changed, 126 insertions, 122 deletions
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);
}