15f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen/* 25f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * Copyright (C) 2004-2006 Atmel Corporation 35f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * 45f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * This program is free software; you can redistribute it and/or modify 55f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * it under the terms of the GNU General Public License version 2 as 65f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * published by the Free Software Foundation. 75f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */ 85f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 95f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/kernel.h> 105a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 115f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/mm.h> 125f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/swap.h> 135f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/init.h> 145f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/mmzone.h> 158bd8974fcddc468d66bd67f33c578f37987b302eHaavard Skinnemoen#include <linux/module.h> 165f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/bootmem.h> 175f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/pagemap.h> 185f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/nodemask.h> 195f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 205f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/page.h> 215f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/mmu_context.h> 225f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/tlb.h> 235f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/io.h> 245f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/dma.h> 255f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/setup.h> 265f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/sections.h> 275f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 28abe1ee3a221d53778c3e58747bbec6e518e5471bTim Abbottpgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_data; 295f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 305f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstruct page *empty_zero_page; 318bd8974fcddc468d66bd67f33c578f37987b302eHaavard SkinnemoenEXPORT_SYMBOL(empty_zero_page); 325f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 335f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen/* 345f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * Cache of MMU context last used. 355f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */ 365f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenunsigned long mmu_context_cache = NO_CONTEXT; 375f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 385f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen/* 395f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * paging_init() sets up the page tables 405f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * 415f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * This routine also unmaps the page at virtual kernel address 0, so 425f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * that we can trap those pesky NULL-reference errors in the kernel. 435f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */ 445f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid __init paging_init(void) 455f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{ 465f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen extern unsigned long _evba; 475f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen void *zero_page; 485f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen int nid; 495f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 505f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen /* 515f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * Make sure we can handle exceptions before enabling 525f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * paging. Not that we should ever _get_ any exceptions this 535f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * early, but you never know... 545f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */ 555f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen printk("Exception vectors start at %p\n", &_evba); 565f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen sysreg_write(EVBA, (unsigned long)&_evba); 575f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 585f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen /* 595f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * Since we are ready to handle exceptions now, we should let 605f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * the CPU generate them... 615f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */ 625f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen __asm__ __volatile__ ("csrf %0" : : "i"(SR_EM_BIT)); 635f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 645f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen /* 655f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * Allocate the zero page. The allocator will panic if it 665f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * can't satisfy the request, so no need to check. 675f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */ 685f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0), 695f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen PAGE_SIZE); 705f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 71ebe74597a55fef00edc80a414ef5c6477d035e0aHaavard Skinnemoen sysreg_write(PTBR, (unsigned long)swapper_pg_dir); 72ebe74597a55fef00edc80a414ef5c6477d035e0aHaavard Skinnemoen enable_mmu(); 73ebe74597a55fef00edc80a414ef5c6477d035e0aHaavard Skinnemoen printk ("CPU: Paging enabled\n"); 745f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 755f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen for_each_online_node(nid) { 765f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen pg_data_t *pgdat = NODE_DATA(nid); 775f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen unsigned long zones_size[MAX_NR_ZONES]; 785f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen unsigned long low, start_pfn; 795f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 803560e249abda6bee41a07a7bf0383a6e193e2839Johannes Weiner start_pfn = pgdat->bdata->node_min_pfn; 815f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen low = pgdat->bdata->node_low_pfn; 825f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 835f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen memset(zones_size, 0, sizeof(zones_size)); 845f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen zones_size[ZONE_NORMAL] = low - start_pfn; 855f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 865f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n", 875f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen nid, start_pfn, low); 885f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 899109fb7b3520de187ebc3646c209d66a233f7169Johannes Weiner free_area_init_node(nid, zones_size, start_pfn, NULL); 905f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 915f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen printk("Node %u: mem_map starts at %p\n", 925f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen pgdat->node_id, pgdat->node_mem_map); 935f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen } 945f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 955f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen mem_map = NODE_DATA(0)->node_mem_map; 965f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 975f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen empty_zero_page = virt_to_page(zero_page); 985f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen flush_dcache_page(empty_zero_page); 995f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen} 1005f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 1015f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid __init mem_init(void) 1025f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{ 1036703bdf669f0e4bbeb8f9c1afb87c54bdd60e852Jiang Liu pg_data_t *pgdat; 1045f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 1055f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen high_memory = NULL; 106ce7549e1d824e08871beddb6c7945635dfc4341dJiang Liu for_each_online_pgdat(pgdat) 107ce7549e1d824e08871beddb6c7945635dfc4341dJiang Liu high_memory = max_t(void *, high_memory, 108ce7549e1d824e08871beddb6c7945635dfc4341dJiang Liu __va(pgdat_end_pfn(pgdat) << PAGE_SHIFT)); 1095f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 110ce7549e1d824e08871beddb6c7945635dfc4341dJiang Liu set_max_mapnr(MAP_NR(high_memory)); 111ce7549e1d824e08871beddb6c7945635dfc4341dJiang Liu free_all_bootmem(); 1126703bdf669f0e4bbeb8f9c1afb87c54bdd60e852Jiang Liu mem_init_print_info(NULL); 1135f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen} 1145f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 1155f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid free_initmem(void) 1165f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{ 117dbe67df4ba78c79db547c7864e1120981c144c97Jiang Liu free_initmem_default(-1); 1185f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen} 1195f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen 1205f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#ifdef CONFIG_BLK_DEV_INITRD 1215f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid free_initrd_mem(unsigned long start, unsigned long end) 1225f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{ 123dbe67df4ba78c79db547c7864e1120981c144c97Jiang Liu free_reserved_area((void *)start, (void *)end, -1, "initrd"); 1245f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen} 1255f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#endif 126