Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | /* * memory.c: PROM library functions for acquiring/using memory descriptors * given to us from the ARCS firmware. * * Copyright (C) 1996 by David S. Miller * Copyright (C) 1999, 2000, 2001 by Ralf Baechle * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. * * PROM library functions for acquiring/using memory descriptors given to us * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set * because on some machines like SGI IP27 the ARC memory configuration data * completly bogus and alternate easier to use mechanisms are available. */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/bootmem.h> #include <linux/swap.h> #include <asm/sgialib.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/bootinfo.h> #undef DEBUG struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) { return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current); } #ifdef DEBUG /* convenient for debugging */ static char *arcs_mtypes[8] = { "Exception Block", "ARCS Romvec Page", "Free/Contig RAM", "Generic Free RAM", "Bad Memory", "Standalone Program Pages", "ARCS Temp Storage Area", "ARCS Permanent Storage Area" }; static char *arc_mtypes[8] = { "Exception Block", "SystemParameterBlock", "FreeMemory", "Bad Memory", "LoadedProgram", "FirmwareTemporary", "FirmwarePermanent", "FreeContiguous" }; #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \ : arc_mtypes[a.arc] #endif static inline int memtype_classify_arcs (union linux_memtypes type) { switch (type.arcs) { case arcs_fcontig: case arcs_free: return BOOT_MEM_RAM; case arcs_atmp: return BOOT_MEM_ROM_DATA; case arcs_eblock: case arcs_rvpage: case arcs_bmem: case arcs_prog: case arcs_aperm: return BOOT_MEM_RESERVED; default: BUG(); } while(1); /* Nuke warning. */ } static inline int memtype_classify_arc (union linux_memtypes type) { switch (type.arc) { case arc_free: case arc_fcontig: return BOOT_MEM_RAM; case arc_atmp: return BOOT_MEM_ROM_DATA; case arc_eblock: case arc_rvpage: case arc_bmem: case arc_prog: case arc_aperm: return BOOT_MEM_RESERVED; 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); } void __init prom_meminit(void) { struct linux_mdesc *p; #ifdef DEBUG int i = 0; 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)); p = ArcGetMemoryDescriptor(p); i++; } #endif p = PROM_NULL_MDESC; while ((p = ArcGetMemoryDescriptor(p))) { unsigned long base, size; long type; base = p->base << PAGE_SHIFT; size = p->pages << PAGE_SHIFT; type = prom_memtype_classify(p->type); add_memory_region(base, size, type); } } void __init prom_free_prom_memory (void) { unsigned long freed = 0; unsigned long addr; int i; for (i = 0; i < boot_mem_map.nr_map; i++) { if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; addr = boot_mem_map.map[i].addr; while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); set_page_count(virt_to_page(__va(addr)), 1); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; } } printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10); } |