| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 1 | /* | 
 | 2 |  *  PowerPC version | 
 | 3 |  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 
 | 4 |  * | 
 | 5 |  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 
 | 6 |  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | 
 | 7 |  *    Copyright (C) 1996 Paul Mackerras | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 8 |  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | 
 | 9 |  * | 
 | 10 |  *  Derived from "arch/i386/mm/init.c" | 
 | 11 |  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | 
 | 12 |  * | 
 | 13 |  *  This program is free software; you can redistribute it and/or | 
 | 14 |  *  modify it under the terms of the GNU General Public License | 
 | 15 |  *  as published by the Free Software Foundation; either version | 
 | 16 |  *  2 of the License, or (at your option) any later version. | 
 | 17 |  * | 
 | 18 |  */ | 
 | 19 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 20 | #include <linux/module.h> | 
 | 21 | #include <linux/sched.h> | 
 | 22 | #include <linux/kernel.h> | 
 | 23 | #include <linux/errno.h> | 
 | 24 | #include <linux/string.h> | 
 | 25 | #include <linux/types.h> | 
 | 26 | #include <linux/mm.h> | 
 | 27 | #include <linux/stddef.h> | 
 | 28 | #include <linux/init.h> | 
 | 29 | #include <linux/bootmem.h> | 
 | 30 | #include <linux/highmem.h> | 
 | 31 | #include <linux/initrd.h> | 
 | 32 | #include <linux/pagemap.h> | 
| Yinghai Lu | 95f72d1 | 2010-07-12 14:36:09 +1000 | [diff] [blame] | 33 | #include <linux/memblock.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 34 | #include <linux/gfp.h> | 
| Becky Bruce | 41151e7 | 2011-06-28 09:54:48 +0000 | [diff] [blame] | 35 | #include <linux/slab.h> | 
 | 36 | #include <linux/hugetlb.h> | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 37 |  | 
 | 38 | #include <asm/pgalloc.h> | 
 | 39 | #include <asm/prom.h> | 
 | 40 | #include <asm/io.h> | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 41 | #include <asm/pgtable.h> | 
 | 42 | #include <asm/mmu.h> | 
 | 43 | #include <asm/smp.h> | 
 | 44 | #include <asm/machdep.h> | 
 | 45 | #include <asm/btext.h> | 
 | 46 | #include <asm/tlb.h> | 
| Paul Mackerras | 7c8c6b9 | 2005-10-06 12:23:33 +1000 | [diff] [blame] | 47 | #include <asm/sections.h> | 
| Becky Bruce | 41151e7 | 2011-06-28 09:54:48 +0000 | [diff] [blame] | 48 | #include <asm/hugetlb.h> | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 49 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 50 | #include "mmu_decl.h" | 
 | 51 |  | 
 | 52 | #if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL) | 
| Uwe Kleine-König | 9ddc5b6 | 2010-01-20 17:02:24 +0100 | [diff] [blame] | 53 | /* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */ | 
| Dale Farnsworth | ccdcef7 | 2008-12-17 10:09:13 +0000 | [diff] [blame] | 54 | #if (CONFIG_LOWMEM_SIZE > (0xF0000000 - PAGE_OFFSET)) | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 55 | #error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL" | 
 | 56 | #endif | 
 | 57 | #endif | 
 | 58 | #define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE | 
 | 59 |  | 
| Stefan Roese | 2bf3016 | 2008-07-10 01:09:23 +1000 | [diff] [blame] | 60 | phys_addr_t total_memory; | 
 | 61 | phys_addr_t total_lowmem; | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 62 |  | 
| Kumar Gala | 37dd2ba | 2008-04-22 04:22:34 +1000 | [diff] [blame] | 63 | phys_addr_t memstart_addr = (phys_addr_t)~0ull; | 
 | 64 | EXPORT_SYMBOL(memstart_addr); | 
 | 65 | phys_addr_t kernstart_addr; | 
 | 66 | EXPORT_SYMBOL(kernstart_addr); | 
| Suzuki Poulose | 368ff8f | 2011-12-14 22:58:37 +0000 | [diff] [blame] | 67 |  | 
 | 68 | #ifdef CONFIG_RELOCATABLE_PPC32 | 
 | 69 | /* Used in __va()/__pa() */ | 
 | 70 | long long virt_phys_offset; | 
 | 71 | EXPORT_SYMBOL(virt_phys_offset); | 
 | 72 | #endif | 
 | 73 |  | 
| Kumar Gala | 99c62dd | 2008-04-16 05:52:21 +1000 | [diff] [blame] | 74 | phys_addr_t lowmem_end_addr; | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 75 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 76 | int boot_mapsize; | 
 | 77 | #ifdef CONFIG_PPC_PMAC | 
 | 78 | unsigned long agp_special_page; | 
| Paul Mackerras | 5c8c56e | 2005-10-22 14:42:51 +1000 | [diff] [blame] | 79 | EXPORT_SYMBOL(agp_special_page); | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 80 | #endif | 
 | 81 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 82 | void MMU_init(void); | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 83 |  | 
 | 84 | /* XXX should be in current.h  -- paulus */ | 
 | 85 | extern struct task_struct *current_set[NR_CPUS]; | 
 | 86 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 87 | /* | 
 | 88 |  * this tells the system to map all of ram with the segregs | 
 | 89 |  * (i.e. page tables) instead of the bats. | 
 | 90 |  * -- Cort | 
 | 91 |  */ | 
 | 92 | int __map_without_bats; | 
 | 93 | int __map_without_ltlbs; | 
 | 94 |  | 
| Albert Herranz | c5df7f7 | 2009-12-12 06:31:54 +0000 | [diff] [blame] | 95 | /* | 
 | 96 |  * This tells the system to allow ioremapping memory marked as reserved. | 
 | 97 |  */ | 
 | 98 | int __allow_ioremap_reserved; | 
 | 99 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 100 | /* max amount of low RAM to map in */ | 
 | 101 | unsigned long __max_low_memory = MAX_LOW_MEM; | 
 | 102 |  | 
 | 103 | /* | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 104 |  * Check for command-line options that affect what MMU_init will do. | 
 | 105 |  */ | 
 | 106 | void MMU_setup(void) | 
 | 107 | { | 
 | 108 | 	/* Check for nobats option (used in mapin_ram). */ | 
 | 109 | 	if (strstr(cmd_line, "nobats")) { | 
 | 110 | 		__map_without_bats = 1; | 
 | 111 | 	} | 
 | 112 |  | 
 | 113 | 	if (strstr(cmd_line, "noltlbs")) { | 
 | 114 | 		__map_without_ltlbs = 1; | 
 | 115 | 	} | 
| Benjamin Herrenschmidt | 88df6e9 | 2007-04-12 15:30:22 +1000 | [diff] [blame] | 116 | #ifdef CONFIG_DEBUG_PAGEALLOC | 
 | 117 | 	__map_without_bats = 1; | 
 | 118 | 	__map_without_ltlbs = 1; | 
 | 119 | #endif | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 120 | } | 
 | 121 |  | 
 | 122 | /* | 
 | 123 |  * MMU_init sets up the basic memory mappings for the kernel, | 
 | 124 |  * including both RAM and possibly some I/O regions, | 
 | 125 |  * and sets up the page tables and the MMU hardware ready to go. | 
 | 126 |  */ | 
 | 127 | void __init MMU_init(void) | 
 | 128 | { | 
 | 129 | 	if (ppc_md.progress) | 
 | 130 | 		ppc_md.progress("MMU:enter", 0x111); | 
 | 131 |  | 
 | 132 | 	/* parse args from command line */ | 
 | 133 | 	MMU_setup(); | 
 | 134 |  | 
| Becky Bruce | 41151e7 | 2011-06-28 09:54:48 +0000 | [diff] [blame] | 135 | 	/* | 
 | 136 | 	 * Reserve gigantic pages for hugetlb.  This MUST occur before | 
 | 137 | 	 * lowmem_end_addr is initialized below. | 
 | 138 | 	 */ | 
 | 139 | 	reserve_hugetlb_gpages(); | 
 | 140 |  | 
| Yinghai Lu | 95f72d1 | 2010-07-12 14:36:09 +1000 | [diff] [blame] | 141 | 	if (memblock.memory.cnt > 1) { | 
| Albert Herranz | de32400 | 2009-12-12 06:31:53 +0000 | [diff] [blame] | 142 | #ifndef CONFIG_WII | 
| Tejun Heo | 6fbef13 | 2011-12-08 10:22:07 -0800 | [diff] [blame] | 143 | 		memblock_enforce_memory_limit(memblock.memory.regions[0].size); | 
| Paul Mackerras | 7c8c6b9 | 2005-10-06 12:23:33 +1000 | [diff] [blame] | 144 | 		printk(KERN_WARNING "Only using first contiguous memory region"); | 
| Albert Herranz | de32400 | 2009-12-12 06:31:53 +0000 | [diff] [blame] | 145 | #else | 
 | 146 | 		wii_memory_fixups(); | 
 | 147 | #endif | 
| Paul Mackerras | 7c8c6b9 | 2005-10-06 12:23:33 +1000 | [diff] [blame] | 148 | 	} | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 149 |  | 
| Yinghai Lu | 95f72d1 | 2010-07-12 14:36:09 +1000 | [diff] [blame] | 150 | 	total_lowmem = total_memory = memblock_end_of_DRAM() - memstart_addr; | 
| Kumar Gala | d7917ba | 2008-04-16 05:52:22 +1000 | [diff] [blame] | 151 | 	lowmem_end_addr = memstart_addr + total_lowmem; | 
| Paul Mackerras | 7c8c6b9 | 2005-10-06 12:23:33 +1000 | [diff] [blame] | 152 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 153 | #ifdef CONFIG_FSL_BOOKE | 
 | 154 | 	/* Freescale Book-E parts expect lowmem to be mapped by fixed TLB | 
 | 155 | 	 * entries, so we need to adjust lowmem to match the amount we can map | 
 | 156 | 	 * in the fixed entries */ | 
 | 157 | 	adjust_total_lowmem(); | 
 | 158 | #endif /* CONFIG_FSL_BOOKE */ | 
| Paul Mackerras | fa39dc4 | 2005-10-26 21:54:21 +1000 | [diff] [blame] | 159 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 160 | 	if (total_lowmem > __max_low_memory) { | 
 | 161 | 		total_lowmem = __max_low_memory; | 
| Kumar Gala | d7917ba | 2008-04-16 05:52:22 +1000 | [diff] [blame] | 162 | 		lowmem_end_addr = memstart_addr + total_lowmem; | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 163 | #ifndef CONFIG_HIGHMEM | 
 | 164 | 		total_memory = total_lowmem; | 
| Scott Wood | 6dd2270 | 2011-01-27 10:30:44 +0000 | [diff] [blame] | 165 | 		memblock_enforce_memory_limit(total_lowmem); | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 166 | #endif /* CONFIG_HIGHMEM */ | 
 | 167 | 	} | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 168 |  | 
 | 169 | 	/* Initialize the MMU hardware */ | 
 | 170 | 	if (ppc_md.progress) | 
 | 171 | 		ppc_md.progress("MMU:hw init", 0x300); | 
 | 172 | 	MMU_init_hw(); | 
 | 173 |  | 
 | 174 | 	/* Map in all of RAM starting at KERNELBASE */ | 
 | 175 | 	if (ppc_md.progress) | 
 | 176 | 		ppc_md.progress("MMU:mapin", 0x301); | 
 | 177 | 	mapin_ram(); | 
 | 178 |  | 
| Benjamin Herrenschmidt | f637a49 | 2009-05-27 13:44:50 +1000 | [diff] [blame] | 179 | 	/* Initialize early top-down ioremap allocator */ | 
 | 180 | 	ioremap_bot = IOREMAP_TOP; | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 181 |  | 
 | 182 | 	/* Map in I/O resources */ | 
 | 183 | 	if (ppc_md.progress) | 
 | 184 | 		ppc_md.progress("MMU:setio", 0x302); | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 185 |  | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 186 | 	if (ppc_md.progress) | 
 | 187 | 		ppc_md.progress("MMU:exit", 0x211); | 
| Benjamin Herrenschmidt | 51d3082 | 2005-11-23 17:57:25 +1100 | [diff] [blame] | 188 |  | 
 | 189 | 	/* From now on, btext is no longer BAT mapped if it was at all */ | 
 | 190 | #ifdef CONFIG_BOOTX_TEXT | 
 | 191 | 	btext_unmap(); | 
 | 192 | #endif | 
| Benjamin Herrenschmidt | e63075a | 2010-07-06 15:39:01 -0700 | [diff] [blame] | 193 |  | 
 | 194 | 	/* Shortly after that, the entire linear mapping will be available */ | 
 | 195 | 	memblock_set_current_limit(lowmem_end_addr); | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 196 | } | 
 | 197 |  | 
 | 198 | /* This is only called until mem_init is done. */ | 
 | 199 | void __init *early_get_page(void) | 
 | 200 | { | 
| Benjamin Herrenschmidt | e63075a | 2010-07-06 15:39:01 -0700 | [diff] [blame] | 201 | 	if (init_bootmem_done) | 
 | 202 | 		return alloc_bootmem_pages(PAGE_SIZE); | 
 | 203 | 	else | 
 | 204 | 		return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); | 
| Paul Mackerras | 14cf11a | 2005-09-26 16:04:21 +1000 | [diff] [blame] | 205 | } | 
 | 206 |  | 
| Benjamin Herrenschmidt | cd3db0c | 2010-07-06 15:39:02 -0700 | [diff] [blame] | 207 | #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */ | 
 | 208 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | 
 | 209 | 				phys_addr_t first_memblock_size) | 
 | 210 | { | 
 | 211 | 	/* We don't currently support the first MEMBLOCK not mapping 0 | 
 | 212 | 	 * physical on those processors | 
 | 213 | 	 */ | 
 | 214 | 	BUG_ON(first_memblock_base != 0); | 
 | 215 |  | 
 | 216 | 	/* 8xx can only access 8MB at the moment */ | 
 | 217 | 	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); | 
 | 218 | } | 
 | 219 | #endif /* CONFIG_8xx */ |