1/* 2 * Copyright (C) 2004-2006 Atmel Corporation 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9#include <linux/kernel.h> 10#include <linux/gfp.h> 11#include <linux/mm.h> 12#include <linux/swap.h> 13#include <linux/init.h> 14#include <linux/mmzone.h> 15#include <linux/module.h> 16#include <linux/bootmem.h> 17#include <linux/pagemap.h> 18#include <linux/nodemask.h> 19 20#include <asm/page.h> 21#include <asm/mmu_context.h> 22#include <asm/tlb.h> 23#include <asm/io.h> 24#include <asm/dma.h> 25#include <asm/setup.h> 26#include <asm/sections.h> 27 28DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 29 30pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_data; 31 32struct page *empty_zero_page; 33EXPORT_SYMBOL(empty_zero_page); 34 35/* 36 * Cache of MMU context last used. 37 */ 38unsigned long mmu_context_cache = NO_CONTEXT; 39 40/* 41 * paging_init() sets up the page tables 42 * 43 * This routine also unmaps the page at virtual kernel address 0, so 44 * that we can trap those pesky NULL-reference errors in the kernel. 45 */ 46void __init paging_init(void) 47{ 48 extern unsigned long _evba; 49 void *zero_page; 50 int nid; 51 52 /* 53 * Make sure we can handle exceptions before enabling 54 * paging. Not that we should ever _get_ any exceptions this 55 * early, but you never know... 56 */ 57 printk("Exception vectors start at %p\n", &_evba); 58 sysreg_write(EVBA, (unsigned long)&_evba); 59 60 /* 61 * Since we are ready to handle exceptions now, we should let 62 * the CPU generate them... 63 */ 64 __asm__ __volatile__ ("csrf %0" : : "i"(SR_EM_BIT)); 65 66 /* 67 * Allocate the zero page. The allocator will panic if it 68 * can't satisfy the request, so no need to check. 69 */ 70 zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0), 71 PAGE_SIZE); 72 73 sysreg_write(PTBR, (unsigned long)swapper_pg_dir); 74 enable_mmu(); 75 printk ("CPU: Paging enabled\n"); 76 77 for_each_online_node(nid) { 78 pg_data_t *pgdat = NODE_DATA(nid); 79 unsigned long zones_size[MAX_NR_ZONES]; 80 unsigned long low, start_pfn; 81 82 start_pfn = pgdat->bdata->node_min_pfn; 83 low = pgdat->bdata->node_low_pfn; 84 85 memset(zones_size, 0, sizeof(zones_size)); 86 zones_size[ZONE_NORMAL] = low - start_pfn; 87 88 printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n", 89 nid, start_pfn, low); 90 91 free_area_init_node(nid, zones_size, start_pfn, NULL); 92 93 printk("Node %u: mem_map starts at %p\n", 94 pgdat->node_id, pgdat->node_mem_map); 95 } 96 97 mem_map = NODE_DATA(0)->node_mem_map; 98 99 empty_zero_page = virt_to_page(zero_page); 100 flush_dcache_page(empty_zero_page); 101} 102 103void __init mem_init(void) 104{ 105 int codesize, reservedpages, datasize, initsize; 106 int nid, i; 107 108 reservedpages = 0; 109 high_memory = NULL; 110 111 /* this will put all low memory onto the freelists */ 112 for_each_online_node(nid) { 113 pg_data_t *pgdat = NODE_DATA(nid); 114 unsigned long node_pages = 0; 115 void *node_high_memory; 116 117 num_physpages += pgdat->node_present_pages; 118 119 if (pgdat->node_spanned_pages != 0) 120 node_pages = free_all_bootmem_node(pgdat); 121 122 totalram_pages += node_pages; 123 124 for (i = 0; i < node_pages; i++) 125 if (PageReserved(pgdat->node_mem_map + i)) 126 reservedpages++; 127 128 node_high_memory = (void *)((pgdat->node_start_pfn 129 + pgdat->node_spanned_pages) 130 << PAGE_SHIFT); 131 if (node_high_memory > high_memory) 132 high_memory = node_high_memory; 133 } 134 135 max_mapnr = MAP_NR(high_memory); 136 137 codesize = (unsigned long)_etext - (unsigned long)_text; 138 datasize = (unsigned long)_edata - (unsigned long)_data; 139 initsize = (unsigned long)__init_end - (unsigned long)__init_begin; 140 141 printk ("Memory: %luk/%luk available (%dk kernel code, " 142 "%dk reserved, %dk data, %dk init)\n", 143 nr_free_pages() << (PAGE_SHIFT - 10), 144 totalram_pages << (PAGE_SHIFT - 10), 145 codesize >> 10, 146 reservedpages << (PAGE_SHIFT - 10), 147 datasize >> 10, 148 initsize >> 10); 149} 150 151static inline void free_area(unsigned long addr, unsigned long end, char *s) 152{ 153 unsigned int size = (end - addr) >> 10; 154 155 for (; addr < end; addr += PAGE_SIZE) { 156 struct page *page = virt_to_page(addr); 157 ClearPageReserved(page); 158 init_page_count(page); 159 free_page(addr); 160 totalram_pages++; 161 } 162 163 if (size && s) 164 printk(KERN_INFO "Freeing %s memory: %dK (%lx - %lx)\n", 165 s, size, end - (size << 10), end); 166} 167 168void free_initmem(void) 169{ 170 free_area((unsigned long)__init_begin, (unsigned long)__init_end, 171 "init"); 172} 173 174#ifdef CONFIG_BLK_DEV_INITRD 175 176void free_initrd_mem(unsigned long start, unsigned long end) 177{ 178 free_area(start, end, "initrd"); 179} 180 181#endif 182