linux/arch/xtensa/mm/init.c
<<
>>
Prefs
   1/*
   2 * arch/xtensa/mm/init.c
   3 *
   4 * Derived from MIPS, PPC.
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file "COPYING" in the main directory of this archive
   8 * for more details.
   9 *
  10 * Copyright (C) 2001 - 2005 Tensilica Inc.
  11 *
  12 * Chris Zankel <chris@zankel.net>
  13 * Joe Taylor   <joe@tensilica.com, joetylr@yahoo.com>
  14 * Marc Gauthier
  15 * Kevin Chea
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/errno.h>
  20#include <linux/bootmem.h>
  21#include <linux/swap.h>
  22#include <linux/mman.h>
  23#include <linux/nodemask.h>
  24#include <linux/mm.h>
  25#include <linux/slab.h>
  26
  27#include <asm/bootparam.h>
  28#include <asm/page.h>
  29
  30/* References to section boundaries */
  31
  32extern char _ftext, _etext, _fdata, _edata, _rodata_end;
  33extern char __init_begin, __init_end;
  34
  35/*
  36 * mem_reserve(start, end, must_exist)
  37 *
  38 * Reserve some memory from the memory pool.
  39 *
  40 * Parameters:
  41 *  start       Start of region,
  42 *  end         End of region,
  43 *  must_exist  Must exist in memory pool.
  44 *
  45 * Returns:
  46 *  0 (memory area couldn't be mapped)
  47 * -1 (success)
  48 */
  49
  50int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
  51{
  52        int i;
  53
  54        if (start == end)
  55                return 0;
  56
  57        start = start & PAGE_MASK;
  58        end = PAGE_ALIGN(end);
  59
  60        for (i = 0; i < sysmem.nr_banks; i++)
  61                if (start < sysmem.bank[i].end
  62                    && end >= sysmem.bank[i].start)
  63                        break;
  64
  65        if (i == sysmem.nr_banks) {
  66                if (must_exist)
  67                        printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
  68                                "not in any region!\n", start, end);
  69                return 0;
  70        }
  71
  72        if (start > sysmem.bank[i].start) {
  73                if (end < sysmem.bank[i].end) {
  74                        /* split entry */
  75                        if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
  76                                panic("meminfo overflow\n");
  77                        sysmem.bank[sysmem.nr_banks].start = end;
  78                        sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
  79                        sysmem.nr_banks++;
  80                }
  81                sysmem.bank[i].end = start;
  82        } else {
  83                if (end < sysmem.bank[i].end)
  84                        sysmem.bank[i].start = end;
  85                else {
  86                        /* remove entry */
  87                        sysmem.nr_banks--;
  88                        sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
  89                        sysmem.bank[i].end   = sysmem.bank[sysmem.nr_banks].end;
  90                }
  91        }
  92        return -1;
  93}
  94
  95
  96/*
  97 * Initialize the bootmem system and give it all the memory we have available.
  98 */
  99
 100void __init bootmem_init(void)
 101{
 102        unsigned long pfn;
 103        unsigned long bootmap_start, bootmap_size;
 104        int i;
 105
 106        max_low_pfn = max_pfn = 0;
 107        min_low_pfn = ~0;
 108
 109        for (i=0; i < sysmem.nr_banks; i++) {
 110                pfn = PAGE_ALIGN(sysmem.bank[i].start) >> PAGE_SHIFT;
 111                if (pfn < min_low_pfn)
 112                        min_low_pfn = pfn;
 113                pfn = PAGE_ALIGN(sysmem.bank[i].end - 1) >> PAGE_SHIFT;
 114                if (pfn > max_pfn)
 115                        max_pfn = pfn;
 116        }
 117
 118        if (min_low_pfn > max_pfn)
 119                panic("No memory found!\n");
 120
 121        max_low_pfn = max_pfn < MAX_MEM_PFN >> PAGE_SHIFT ?
 122                max_pfn : MAX_MEM_PFN >> PAGE_SHIFT;
 123
 124        /* Find an area to use for the bootmem bitmap. */
 125
 126        bootmap_size = bootmem_bootmap_pages(max_low_pfn - min_low_pfn);
 127        bootmap_size <<= PAGE_SHIFT;
 128        bootmap_start = ~0;
 129
 130        for (i=0; i<sysmem.nr_banks; i++)
 131                if (sysmem.bank[i].end - sysmem.bank[i].start >= bootmap_size) {
 132                        bootmap_start = sysmem.bank[i].start;
 133                        break;
 134                }
 135
 136        if (bootmap_start == ~0UL)
 137                panic("Cannot find %ld bytes for bootmap\n", bootmap_size);
 138
 139        /* Reserve the bootmem bitmap area */
 140
 141        mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1);
 142        bootmap_size = init_bootmem_node(NODE_DATA(0),
 143                                         bootmap_start >> PAGE_SHIFT,
 144                                         min_low_pfn,
 145                                         max_low_pfn);
 146
 147        /* Add all remaining memory pieces into the bootmem map */
 148
 149        for (i=0; i<sysmem.nr_banks; i++)
 150                free_bootmem(sysmem.bank[i].start,
 151                             sysmem.bank[i].end - sysmem.bank[i].start);
 152
 153}
 154
 155
 156void __init zones_init(void)
 157{
 158        unsigned long zones_size[MAX_NR_ZONES];
 159        int i;
 160
 161        /* All pages are DMA-able, so we put them all in the DMA zone. */
 162
 163        zones_size[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET;
 164        for (i = 1; i < MAX_NR_ZONES; i++)
 165                zones_size[i] = 0;
 166
 167#ifdef CONFIG_HIGHMEM
 168        zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
 169#endif
 170
 171        free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL);
 172}
 173
 174/*
 175 * Initialize memory pages.
 176 */
 177
 178void __init mem_init(void)
 179{
 180        unsigned long codesize, reservedpages, datasize, initsize;
 181        unsigned long highmemsize, tmp, ram;
 182
 183        max_mapnr = num_physpages = max_low_pfn - ARCH_PFN_OFFSET;
 184        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 185        highmemsize = 0;
 186
 187#ifdef CONFIG_HIGHMEM
 188#error HIGHGMEM not implemented in init.c
 189#endif
 190
 191        totalram_pages += free_all_bootmem();
 192
 193        reservedpages = ram = 0;
 194        for (tmp = 0; tmp < max_mapnr; tmp++) {
 195                ram++;
 196                if (PageReserved(mem_map+tmp))
 197                        reservedpages++;
 198        }
 199
 200        codesize =  (unsigned long) &_etext - (unsigned long) &_ftext;
 201        datasize =  (unsigned long) &_edata - (unsigned long) &_fdata;
 202        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 203
 204        printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
 205               "%ldk data, %ldk init %ldk highmem)\n",
 206               nr_free_pages() << (PAGE_SHIFT-10),
 207               ram << (PAGE_SHIFT-10),
 208               codesize >> 10,
 209               reservedpages << (PAGE_SHIFT-10),
 210               datasize >> 10,
 211               initsize >> 10,
 212               highmemsize >> 10);
 213}
 214
 215void
 216free_reserved_mem(void *start, void *end)
 217{
 218        for (; start < end; start += PAGE_SIZE) {
 219                ClearPageReserved(virt_to_page(start));
 220                init_page_count(virt_to_page(start));
 221                free_page((unsigned long)start);
 222                totalram_pages++;
 223        }
 224}
 225
 226#ifdef CONFIG_BLK_DEV_INITRD
 227extern int initrd_is_mapped;
 228
 229void free_initrd_mem(unsigned long start, unsigned long end)
 230{
 231        if (initrd_is_mapped) {
 232                free_reserved_mem((void*)start, (void*)end);
 233                printk ("Freeing initrd memory: %ldk freed\n",(end-start)>>10);
 234        }
 235}
 236#endif
 237
 238void free_initmem(void)
 239{
 240        free_reserved_mem(&__init_begin, &__init_end);
 241        printk("Freeing unused kernel memory: %dk freed\n",
 242               (&__init_end - &__init_begin) >> 10);
 243}
 244