11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4SLinus Torvalds * for more details. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 1995 Linus Torvalds 71da177e4SLinus Torvalds * Copyright (C) 1995 Waldorf Electronics 81da177e4SLinus Torvalds * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle 91da177e4SLinus Torvalds * Copyright (C) 1996 Stoned Elipot 101da177e4SLinus Torvalds * Copyright (C) 1999 Silicon Graphics, Inc. 1120d60d99SMaciej W. Rozycki * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds #include <linux/init.h> 141da177e4SLinus Torvalds #include <linux/ioport.h> 1573bc256dSPaul Gortmaker #include <linux/export.h> 16894673eeSJon Smirl #include <linux/screen_info.h> 179d15ffc8STejun Heo #include <linux/memblock.h> 181da177e4SLinus Torvalds #include <linux/bootmem.h> 191da177e4SLinus Torvalds #include <linux/initrd.h> 201da177e4SLinus Torvalds #include <linux/root_dev.h> 211da177e4SLinus Torvalds #include <linux/highmem.h> 221da177e4SLinus Torvalds #include <linux/console.h> 2322a9835cSDave Hansen #include <linux/pfn.h> 246312e0eeSAtsushi Nemoto #include <linux/debugfs.h> 257aa1c8f4SRalf Baechle #include <linux/kexec.h> 264d9f77d2SJohn Crispin #include <linux/sizes.h> 27f4649382SZubair Lutfullah Kakakhel #include <linux/device.h> 28f4649382SZubair Lutfullah Kakakhel #include <linux/dma-contiguous.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <asm/addrspace.h> 311da177e4SLinus Torvalds #include <asm/bootinfo.h> 3220d60d99SMaciej W. Rozycki #include <asm/bugs.h> 33ec74e361SRalf Baechle #include <asm/cache.h> 34e934945dSJames Hogan #include <asm/cdmm.h> 351da177e4SLinus Torvalds #include <asm/cpu.h> 3675dcfc1dSPaul Burton #include <asm/debug.h> 371da177e4SLinus Torvalds #include <asm/sections.h> 381da177e4SLinus Torvalds #include <asm/setup.h> 3987353d8aSRalf Baechle #include <asm/smp-ops.h> 40f2ffa5abSDezhong Diao #include <asm/prom.h> 411da177e4SLinus Torvalds 42ec74e361SRalf Baechle struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds EXPORT_SYMBOL(cpu_data); 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds #ifdef CONFIG_VT 471da177e4SLinus Torvalds struct screen_info screen_info; 481da177e4SLinus Torvalds #endif 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* 511da177e4SLinus Torvalds * Despite it's name this variable is even if we don't have PCI 521da177e4SLinus Torvalds */ 531da177e4SLinus Torvalds unsigned int PCI_DMA_BUS_IS_PHYS; 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds /* 581da177e4SLinus Torvalds * Setup information 591da177e4SLinus Torvalds * 601da177e4SLinus Torvalds * These are initialized so they are in the .data section 611da177e4SLinus Torvalds */ 62ec74e361SRalf Baechle unsigned long mips_machtype __read_mostly = MACH_UNKNOWN; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds EXPORT_SYMBOL(mips_machtype); 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds struct boot_mem_map boot_mem_map; 671da177e4SLinus Torvalds 686acc7d48SDmitri Vorobiev static char __initdata command_line[COMMAND_LINE_SIZE]; 696acc7d48SDmitri Vorobiev char __initdata arcs_cmdline[COMMAND_LINE_SIZE]; 706acc7d48SDmitri Vorobiev 716acc7d48SDmitri Vorobiev #ifdef CONFIG_CMDLINE_BOOL 726acc7d48SDmitri Vorobiev static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; 736acc7d48SDmitri Vorobiev #endif 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds /* 761da177e4SLinus Torvalds * mips_io_port_base is the begin of the address space to which x86 style 771da177e4SLinus Torvalds * I/O ports are mapped. 781da177e4SLinus Torvalds */ 791befdd55SDavid Daney const unsigned long mips_io_port_base = -1; 801da177e4SLinus Torvalds EXPORT_SYMBOL(mips_io_port_base); 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds static struct resource code_resource = { .name = "Kernel code", }; 831da177e4SLinus Torvalds static struct resource data_resource = { .name = "Kernel data", }; 841da177e4SLinus Torvalds 854d9f77d2SJohn Crispin static void *detect_magic __initdata = detect_memory_region; 864d9f77d2SJohn Crispin 8715d45cceSRalf Baechle void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type) 881da177e4SLinus Torvalds { 891da177e4SLinus Torvalds int x = boot_mem_map.nr_map; 900ec7ec75SRalf Baechle int i; 911da177e4SLinus Torvalds 92b6f1f0deSFranck Bui-Huu /* Sanity check */ 93b6f1f0deSFranck Bui-Huu if (start + size < start) { 947178d2cdSJoe Perches pr_warn("Trying to add an invalid memory region, skipped\n"); 95b6f1f0deSFranck Bui-Huu return; 96b6f1f0deSFranck Bui-Huu } 97b6f1f0deSFranck Bui-Huu 981da177e4SLinus Torvalds /* 990ec7ec75SRalf Baechle * Try to merge with existing entry, if any. 1001da177e4SLinus Torvalds */ 1010ec7ec75SRalf Baechle for (i = 0; i < boot_mem_map.nr_map; i++) { 1020ec7ec75SRalf Baechle struct boot_mem_map_entry *entry = boot_mem_map.map + i; 1030ec7ec75SRalf Baechle unsigned long top; 1040ec7ec75SRalf Baechle 1050ec7ec75SRalf Baechle if (entry->type != type) 1060ec7ec75SRalf Baechle continue; 1070ec7ec75SRalf Baechle 1080ec7ec75SRalf Baechle if (start + size < entry->addr) 1090ec7ec75SRalf Baechle continue; /* no overlap */ 1100ec7ec75SRalf Baechle 1110ec7ec75SRalf Baechle if (entry->addr + entry->size < start) 1120ec7ec75SRalf Baechle continue; /* no overlap */ 1130ec7ec75SRalf Baechle 1140ec7ec75SRalf Baechle top = max(entry->addr + entry->size, start + size); 1150ec7ec75SRalf Baechle entry->addr = min(entry->addr, start); 1160ec7ec75SRalf Baechle entry->size = top - entry->addr; 1170ec7ec75SRalf Baechle 1181da177e4SLinus Torvalds return; 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 1210ec7ec75SRalf Baechle if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) { 122a64ae7a2SMike Crowe pr_err("Ooops! Too many entries in the memory map!\n"); 1231da177e4SLinus Torvalds return; 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds boot_mem_map.map[x].addr = start; 1271da177e4SLinus Torvalds boot_mem_map.map[x].size = size; 1281da177e4SLinus Torvalds boot_mem_map.map[x].type = type; 1291da177e4SLinus Torvalds boot_mem_map.nr_map++; 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds 13215d45cceSRalf Baechle void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max) 1334d9f77d2SJohn Crispin { 1344d9f77d2SJohn Crispin void *dm = &detect_magic; 13515d45cceSRalf Baechle phys_addr_t size; 1364d9f77d2SJohn Crispin 1374d9f77d2SJohn Crispin for (size = sz_min; size < sz_max; size <<= 1) { 1384d9f77d2SJohn Crispin if (!memcmp(dm, dm + size, sizeof(detect_magic))) 1394d9f77d2SJohn Crispin break; 1404d9f77d2SJohn Crispin } 1414d9f77d2SJohn Crispin 1424d9f77d2SJohn Crispin pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n", 1434d9f77d2SJohn Crispin ((unsigned long long) size) / SZ_1M, 1444d9f77d2SJohn Crispin (unsigned long long) start, 1454d9f77d2SJohn Crispin ((unsigned long long) sz_min) / SZ_1M, 1464d9f77d2SJohn Crispin ((unsigned long long) sz_max) / SZ_1M); 1474d9f77d2SJohn Crispin 1484d9f77d2SJohn Crispin add_memory_region(start, size, BOOT_MEM_RAM); 1494d9f77d2SJohn Crispin } 1504d9f77d2SJohn Crispin 1511da177e4SLinus Torvalds static void __init print_memory_map(void) 1521da177e4SLinus Torvalds { 1531da177e4SLinus Torvalds int i; 1541da177e4SLinus Torvalds const int field = 2 * sizeof(unsigned long); 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 157a64ae7a2SMike Crowe printk(KERN_INFO " memory: %0*Lx @ %0*Lx ", 1581da177e4SLinus Torvalds field, (unsigned long long) boot_mem_map.map[i].size, 1591da177e4SLinus Torvalds field, (unsigned long long) boot_mem_map.map[i].addr); 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds switch (boot_mem_map.map[i].type) { 1621da177e4SLinus Torvalds case BOOT_MEM_RAM: 163a64ae7a2SMike Crowe printk(KERN_CONT "(usable)\n"); 1641da177e4SLinus Torvalds break; 16543064c0cSDavid Daney case BOOT_MEM_INIT_RAM: 16643064c0cSDavid Daney printk(KERN_CONT "(usable after init)\n"); 16743064c0cSDavid Daney break; 1681da177e4SLinus Torvalds case BOOT_MEM_ROM_DATA: 169a64ae7a2SMike Crowe printk(KERN_CONT "(ROM data)\n"); 1701da177e4SLinus Torvalds break; 1711da177e4SLinus Torvalds case BOOT_MEM_RESERVED: 172a64ae7a2SMike Crowe printk(KERN_CONT "(reserved)\n"); 1731da177e4SLinus Torvalds break; 1741da177e4SLinus Torvalds default: 175a64ae7a2SMike Crowe printk(KERN_CONT "type %lu\n", boot_mem_map.map[i].type); 1761da177e4SLinus Torvalds break; 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds 181d2043ca8SFranck Bui-Huu /* 182d2043ca8SFranck Bui-Huu * Manage initrd 183d2043ca8SFranck Bui-Huu */ 184d2043ca8SFranck Bui-Huu #ifdef CONFIG_BLK_DEV_INITRD 185d2043ca8SFranck Bui-Huu 186a09fc446SFranck Bui-Huu static int __init rd_start_early(char *p) 1871da177e4SLinus Torvalds { 188a09fc446SFranck Bui-Huu unsigned long start = memparse(p, &p); 1891da177e4SLinus Torvalds 190875d43e7SRalf Baechle #ifdef CONFIG_64BIT 191a7837b76SFranck Bui-Huu /* Guess if the sign extension was forgotten by bootloader */ 192a7837b76SFranck Bui-Huu if (start < XKPHYS) 193a7837b76SFranck Bui-Huu start = (int)start; 1941da177e4SLinus Torvalds #endif 195a09fc446SFranck Bui-Huu initrd_start = start; 196a09fc446SFranck Bui-Huu initrd_end += start; 1971da177e4SLinus Torvalds return 0; 1981da177e4SLinus Torvalds } 199a09fc446SFranck Bui-Huu early_param("rd_start", rd_start_early); 200a09fc446SFranck Bui-Huu 201a09fc446SFranck Bui-Huu static int __init rd_size_early(char *p) 202a09fc446SFranck Bui-Huu { 203a09fc446SFranck Bui-Huu initrd_end += memparse(p, &p); 204a09fc446SFranck Bui-Huu return 0; 205a09fc446SFranck Bui-Huu } 206a09fc446SFranck Bui-Huu early_param("rd_size", rd_size_early); 2071da177e4SLinus Torvalds 208a7837b76SFranck Bui-Huu /* it returns the next free pfn after initrd */ 209d2043ca8SFranck Bui-Huu static unsigned long __init init_initrd(void) 2101da177e4SLinus Torvalds { 211a7837b76SFranck Bui-Huu unsigned long end; 2121da177e4SLinus Torvalds 213d2043ca8SFranck Bui-Huu /* 214a09fc446SFranck Bui-Huu * Board specific code or command line parser should have 215a09fc446SFranck Bui-Huu * already set up initrd_start and initrd_end. In these cases 216a09fc446SFranck Bui-Huu * perfom sanity checks and use them if all looks good. 217d2043ca8SFranck Bui-Huu */ 21832028f1fSRalf Baechle if (!initrd_start || initrd_end <= initrd_start) 219a7837b76SFranck Bui-Huu goto disable; 220a7837b76SFranck Bui-Huu 221a7837b76SFranck Bui-Huu if (initrd_start & ~PAGE_MASK) { 222a64ae7a2SMike Crowe pr_err("initrd start must be page aligned\n"); 223a7837b76SFranck Bui-Huu goto disable; 224a7837b76SFranck Bui-Huu } 225a7837b76SFranck Bui-Huu if (initrd_start < PAGE_OFFSET) { 226a64ae7a2SMike Crowe pr_err("initrd start < PAGE_OFFSET\n"); 227a7837b76SFranck Bui-Huu goto disable; 228a7837b76SFranck Bui-Huu } 229a7837b76SFranck Bui-Huu 230a7837b76SFranck Bui-Huu /* 231a7837b76SFranck Bui-Huu * Sanitize initrd addresses. For example firmware 232a7837b76SFranck Bui-Huu * can't guess if they need to pass them through 233a7837b76SFranck Bui-Huu * 64-bits values if the kernel has been built in pure 234a7837b76SFranck Bui-Huu * 32-bit. We need also to switch from KSEG0 to XKPHYS 235a7837b76SFranck Bui-Huu * addresses now, so the code can now safely use __pa(). 236a7837b76SFranck Bui-Huu */ 237a7837b76SFranck Bui-Huu end = __pa(initrd_end); 238a7837b76SFranck Bui-Huu initrd_end = (unsigned long)__va(end); 239a7837b76SFranck Bui-Huu initrd_start = (unsigned long)__va(__pa(initrd_start)); 240a7837b76SFranck Bui-Huu 241a7837b76SFranck Bui-Huu ROOT_DEV = Root_RAM0; 242a7837b76SFranck Bui-Huu return PFN_UP(end); 243a7837b76SFranck Bui-Huu disable: 244a09fc446SFranck Bui-Huu initrd_start = 0; 245a09fc446SFranck Bui-Huu initrd_end = 0; 246a7837b76SFranck Bui-Huu return 0; 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds 249d2043ca8SFranck Bui-Huu static void __init finalize_initrd(void) 250d2043ca8SFranck Bui-Huu { 251d2043ca8SFranck Bui-Huu unsigned long size = initrd_end - initrd_start; 252d2043ca8SFranck Bui-Huu 253d2043ca8SFranck Bui-Huu if (size == 0) { 254d2043ca8SFranck Bui-Huu printk(KERN_INFO "Initrd not found or empty"); 255d2043ca8SFranck Bui-Huu goto disable; 256d2043ca8SFranck Bui-Huu } 257d4df6d4eSFranck Bui-Huu if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { 258a64ae7a2SMike Crowe printk(KERN_ERR "Initrd extends beyond end of memory"); 259d2043ca8SFranck Bui-Huu goto disable; 260d2043ca8SFranck Bui-Huu } 261d2043ca8SFranck Bui-Huu 26272a7fe39SBernhard Walle reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); 263d2043ca8SFranck Bui-Huu initrd_below_start_ok = 1; 264d2043ca8SFranck Bui-Huu 265a64ae7a2SMike Crowe pr_info("Initial ramdisk at: 0x%lx (%lu bytes)\n", 266d2043ca8SFranck Bui-Huu initrd_start, size); 267d2043ca8SFranck Bui-Huu return; 268d2043ca8SFranck Bui-Huu disable: 269a64ae7a2SMike Crowe printk(KERN_CONT " - disabling initrd\n"); 270d2043ca8SFranck Bui-Huu initrd_start = 0; 271d2043ca8SFranck Bui-Huu initrd_end = 0; 272d2043ca8SFranck Bui-Huu } 273d2043ca8SFranck Bui-Huu 274d2043ca8SFranck Bui-Huu #else /* !CONFIG_BLK_DEV_INITRD */ 275d2043ca8SFranck Bui-Huu 2769ba126cfSRalf Baechle static unsigned long __init init_initrd(void) 2779ba126cfSRalf Baechle { 2789ba126cfSRalf Baechle return 0; 2799ba126cfSRalf Baechle } 2809ba126cfSRalf Baechle 281d2043ca8SFranck Bui-Huu #define finalize_initrd() do {} while (0) 282d2043ca8SFranck Bui-Huu 283d2043ca8SFranck Bui-Huu #endif 284d2043ca8SFranck Bui-Huu 285b6f1f0deSFranck Bui-Huu /* 286d2043ca8SFranck Bui-Huu * Initialize the bootmem allocator. It also setup initrd related data 287d2043ca8SFranck Bui-Huu * if needed. 288b6f1f0deSFranck Bui-Huu */ 289c4617318SHuacai Chen #if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA)) 290d2043ca8SFranck Bui-Huu 291d2043ca8SFranck Bui-Huu static void __init bootmem_init(void) 292d2043ca8SFranck Bui-Huu { 293d2043ca8SFranck Bui-Huu init_initrd(); 294d2043ca8SFranck Bui-Huu finalize_initrd(); 295d2043ca8SFranck Bui-Huu } 296d2043ca8SFranck Bui-Huu 297d2043ca8SFranck Bui-Huu #else /* !CONFIG_SGI_IP27 */ 298d2043ca8SFranck Bui-Huu 299d2043ca8SFranck Bui-Huu static void __init bootmem_init(void) 300d2043ca8SFranck Bui-Huu { 301e452e94eSAtsushi Nemoto unsigned long reserved_end; 302db84dc61SFranck Bui-Huu unsigned long mapstart = ~0UL; 303d2043ca8SFranck Bui-Huu unsigned long bootmap_size; 304d2043ca8SFranck Bui-Huu int i; 305d2043ca8SFranck Bui-Huu 306d2043ca8SFranck Bui-Huu /* 307f9a7febdSGreg Ungerer * Sanity check any INITRD first. We don't take it into account 308f9a7febdSGreg Ungerer * for bootmem setup initially, rely on the end-of-kernel-code 309f9a7febdSGreg Ungerer * as our memory range starting point. Once bootmem is inited we 310f9a7febdSGreg Ungerer * will reserve the area used for the initrd. 311d2043ca8SFranck Bui-Huu */ 312f9a7febdSGreg Ungerer init_initrd(); 313f9a7febdSGreg Ungerer reserved_end = (unsigned long) PFN_UP(__pa_symbol(&_end)); 314b6f1f0deSFranck Bui-Huu 315b6f1f0deSFranck Bui-Huu /* 316db84dc61SFranck Bui-Huu * max_low_pfn is not a number of pages. The number of pages 317db84dc61SFranck Bui-Huu * of the system is given by 'max_low_pfn - min_low_pfn'. 318db84dc61SFranck Bui-Huu */ 319db84dc61SFranck Bui-Huu min_low_pfn = ~0UL; 320db84dc61SFranck Bui-Huu max_low_pfn = 0; 321db84dc61SFranck Bui-Huu 322db84dc61SFranck Bui-Huu /* 323b6f1f0deSFranck Bui-Huu * Find the highest page frame number we have available. 324b6f1f0deSFranck Bui-Huu */ 3251da177e4SLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 3261da177e4SLinus Torvalds unsigned long start, end; 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 3291da177e4SLinus Torvalds continue; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds start = PFN_UP(boot_mem_map.map[i].addr); 3321da177e4SLinus Torvalds end = PFN_DOWN(boot_mem_map.map[i].addr 3331da177e4SLinus Torvalds + boot_mem_map.map[i].size); 3341da177e4SLinus Torvalds 335db84dc61SFranck Bui-Huu if (end > max_low_pfn) 336db84dc61SFranck Bui-Huu max_low_pfn = end; 337db84dc61SFranck Bui-Huu if (start < min_low_pfn) 338db84dc61SFranck Bui-Huu min_low_pfn = start; 339b6f1f0deSFranck Bui-Huu if (end <= reserved_end) 3401da177e4SLinus Torvalds continue; 341a6335fa1SAlexander Sverdlin #ifdef CONFIG_BLK_DEV_INITRD 34288d34269SAlexander Sverdlin /* Skip zones before initrd and initrd itself */ 343a6335fa1SAlexander Sverdlin if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end))) 344a6335fa1SAlexander Sverdlin continue; 345a6335fa1SAlexander Sverdlin #endif 346b6f1f0deSFranck Bui-Huu if (start >= mapstart) 347b6f1f0deSFranck Bui-Huu continue; 348b6f1f0deSFranck Bui-Huu mapstart = max(reserved_end, start); 3491da177e4SLinus Torvalds } 3501da177e4SLinus Torvalds 351db84dc61SFranck Bui-Huu if (min_low_pfn >= max_low_pfn) 352db84dc61SFranck Bui-Huu panic("Incorrect memory mapping !!!"); 3536f284a2cSFranck Bui-Huu if (min_low_pfn > ARCH_PFN_OFFSET) { 354a64ae7a2SMike Crowe pr_info("Wasting %lu bytes for tracking %lu unused pages\n", 3556f284a2cSFranck Bui-Huu (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), 3566f284a2cSFranck Bui-Huu min_low_pfn - ARCH_PFN_OFFSET); 3576f284a2cSFranck Bui-Huu } else if (min_low_pfn < ARCH_PFN_OFFSET) { 358a64ae7a2SMike Crowe pr_info("%lu free pages won't be used\n", 3596f284a2cSFranck Bui-Huu ARCH_PFN_OFFSET - min_low_pfn); 360db84dc61SFranck Bui-Huu } 3616f284a2cSFranck Bui-Huu min_low_pfn = ARCH_PFN_OFFSET; 362db84dc61SFranck Bui-Huu 3631da177e4SLinus Torvalds /* 3641da177e4SLinus Torvalds * Determine low and high memory ranges 3651da177e4SLinus Torvalds */ 366dc3bf353SRalf Baechle max_pfn = max_low_pfn; 367db84dc61SFranck Bui-Huu if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) { 3681da177e4SLinus Torvalds #ifdef CONFIG_HIGHMEM 369b6f1f0deSFranck Bui-Huu highstart_pfn = PFN_DOWN(HIGHMEM_START); 370db84dc61SFranck Bui-Huu highend_pfn = max_low_pfn; 3711da177e4SLinus Torvalds #endif 372db84dc61SFranck Bui-Huu max_low_pfn = PFN_DOWN(HIGHMEM_START); 373b6f1f0deSFranck Bui-Huu } 3741da177e4SLinus Torvalds 37588d34269SAlexander Sverdlin #ifdef CONFIG_BLK_DEV_INITRD 37688d34269SAlexander Sverdlin /* 37788d34269SAlexander Sverdlin * mapstart should be after initrd_end 37888d34269SAlexander Sverdlin */ 37988d34269SAlexander Sverdlin if (initrd_end) 38088d34269SAlexander Sverdlin mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end))); 38188d34269SAlexander Sverdlin #endif 38288d34269SAlexander Sverdlin 383b6f1f0deSFranck Bui-Huu /* 384b6f1f0deSFranck Bui-Huu * Initialize the boot-time allocator with low memory only. 385b6f1f0deSFranck Bui-Huu */ 386db84dc61SFranck Bui-Huu bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, 387db84dc61SFranck Bui-Huu min_low_pfn, max_low_pfn); 388cce335aeSRalf Baechle 389cce335aeSRalf Baechle 390cce335aeSRalf Baechle for (i = 0; i < boot_mem_map.nr_map; i++) { 391cce335aeSRalf Baechle unsigned long start, end; 392cce335aeSRalf Baechle 393cce335aeSRalf Baechle start = PFN_UP(boot_mem_map.map[i].addr); 394cce335aeSRalf Baechle end = PFN_DOWN(boot_mem_map.map[i].addr 395cce335aeSRalf Baechle + boot_mem_map.map[i].size); 396cce335aeSRalf Baechle 397e452e94eSAtsushi Nemoto if (start <= min_low_pfn) 398e452e94eSAtsushi Nemoto start = min_low_pfn; 399cce335aeSRalf Baechle if (start >= end) 400cce335aeSRalf Baechle continue; 401cce335aeSRalf Baechle 402cce335aeSRalf Baechle #ifndef CONFIG_HIGHMEM 403cce335aeSRalf Baechle if (end > max_low_pfn) 404cce335aeSRalf Baechle end = max_low_pfn; 405cce335aeSRalf Baechle 406cce335aeSRalf Baechle /* 407cce335aeSRalf Baechle * ... finally, is the area going away? 408cce335aeSRalf Baechle */ 409cce335aeSRalf Baechle if (end <= start) 410cce335aeSRalf Baechle continue; 411cce335aeSRalf Baechle #endif 412cce335aeSRalf Baechle 4139d15ffc8STejun Heo memblock_add_node(PFN_PHYS(start), PFN_PHYS(end - start), 0); 414cce335aeSRalf Baechle } 415cce335aeSRalf Baechle 4161da177e4SLinus Torvalds /* 4171da177e4SLinus Torvalds * Register fully available low RAM pages with the bootmem allocator. 4181da177e4SLinus Torvalds */ 4191da177e4SLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 420b6f1f0deSFranck Bui-Huu unsigned long start, end, size; 4211da177e4SLinus Torvalds 422b6f1f0deSFranck Bui-Huu start = PFN_UP(boot_mem_map.map[i].addr); 423b6f1f0deSFranck Bui-Huu end = PFN_DOWN(boot_mem_map.map[i].addr 4241da177e4SLinus Torvalds + boot_mem_map.map[i].size); 42543064c0cSDavid Daney 42643064c0cSDavid Daney /* 42743064c0cSDavid Daney * Reserve usable memory. 42843064c0cSDavid Daney */ 42943064c0cSDavid Daney switch (boot_mem_map.map[i].type) { 43043064c0cSDavid Daney case BOOT_MEM_RAM: 43143064c0cSDavid Daney break; 43243064c0cSDavid Daney case BOOT_MEM_INIT_RAM: 43343064c0cSDavid Daney memory_present(0, start, end); 43443064c0cSDavid Daney continue; 43543064c0cSDavid Daney default: 43643064c0cSDavid Daney /* Not usable memory */ 43743064c0cSDavid Daney continue; 43843064c0cSDavid Daney } 43943064c0cSDavid Daney 440b6f1f0deSFranck Bui-Huu /* 441b6f1f0deSFranck Bui-Huu * We are rounding up the start address of usable memory 442b6f1f0deSFranck Bui-Huu * and at the end of the usable range downwards. 443b6f1f0deSFranck Bui-Huu */ 444b6f1f0deSFranck Bui-Huu if (start >= max_low_pfn) 445b6f1f0deSFranck Bui-Huu continue; 446b6f1f0deSFranck Bui-Huu if (start < reserved_end) 447b6f1f0deSFranck Bui-Huu start = reserved_end; 448b6f1f0deSFranck Bui-Huu if (end > max_low_pfn) 449b6f1f0deSFranck Bui-Huu end = max_low_pfn; 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds /* 452b6f1f0deSFranck Bui-Huu * ... finally, is the area going away? 4531da177e4SLinus Torvalds */ 454b6f1f0deSFranck Bui-Huu if (end <= start) 4551da177e4SLinus Torvalds continue; 456b6f1f0deSFranck Bui-Huu size = end - start; 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds /* Register lowmem ranges */ 459b6f1f0deSFranck Bui-Huu free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT); 460b6f1f0deSFranck Bui-Huu memory_present(0, start, end); 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds 463b6f1f0deSFranck Bui-Huu /* 464b6f1f0deSFranck Bui-Huu * Reserve the bootmap memory. 465b6f1f0deSFranck Bui-Huu */ 46672a7fe39SBernhard Walle reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT); 467b6f1f0deSFranck Bui-Huu 468d2043ca8SFranck Bui-Huu /* 469d2043ca8SFranck Bui-Huu * Reserve initrd memory if needed. 470d2043ca8SFranck Bui-Huu */ 471d2043ca8SFranck Bui-Huu finalize_initrd(); 472d2043ca8SFranck Bui-Huu } 473d2043ca8SFranck Bui-Huu 4741da177e4SLinus Torvalds #endif /* CONFIG_SGI_IP27 */ 4751da177e4SLinus Torvalds 4762925aba4SRalf Baechle /* 477603e82edSJoe Perches * arch_mem_init - initialize memory management subsystem 4782925aba4SRalf Baechle * 4792925aba4SRalf Baechle * o plat_mem_setup() detects the memory configuration and will record detected 4802925aba4SRalf Baechle * memory areas using add_memory_region. 4812925aba4SRalf Baechle * 4822925aba4SRalf Baechle * At this stage the memory configuration of the system is known to the 483603e82edSJoe Perches * kernel but generic memory management system is still entirely uninitialized. 4842925aba4SRalf Baechle * 4852925aba4SRalf Baechle * o bootmem_init() 4862925aba4SRalf Baechle * o sparse_init() 4872925aba4SRalf Baechle * o paging_init() 488e1c05067SMasahiro Yamada * o dma_contiguous_reserve() 4892925aba4SRalf Baechle * 4902925aba4SRalf Baechle * At this stage the bootmem allocator is ready to use. 4912925aba4SRalf Baechle * 4922925aba4SRalf Baechle * NOTE: historically plat_mem_setup did the entire platform initialization. 4932925aba4SRalf Baechle * This was rather impractical because it meant plat_mem_setup had to 4942925aba4SRalf Baechle * get away without any kind of memory allocator. To keep old code from 4957f0dd768SRafał Miłecki * breaking plat_setup was just renamed to plat_mem_setup and a second platform 4962925aba4SRalf Baechle * initialization hook for anything else was introduced. 4972925aba4SRalf Baechle */ 4982925aba4SRalf Baechle 499982f6ffeSRalf Baechle static int usermem __initdata; 500a09fc446SFranck Bui-Huu 501a09fc446SFranck Bui-Huu static int __init early_parse_mem(char *p) 502a09fc446SFranck Bui-Huu { 503ad8f723aSJaedon Shin phys_addr_t start, size; 504a09fc446SFranck Bui-Huu 505a09fc446SFranck Bui-Huu /* 506a09fc446SFranck Bui-Huu * If a user specifies memory size, we 507a09fc446SFranck Bui-Huu * blow away any automatically generated 508a09fc446SFranck Bui-Huu * size. 509a09fc446SFranck Bui-Huu */ 510a09fc446SFranck Bui-Huu if (usermem == 0) { 511a09fc446SFranck Bui-Huu boot_mem_map.nr_map = 0; 512a09fc446SFranck Bui-Huu usermem = 1; 513a09fc446SFranck Bui-Huu } 514a09fc446SFranck Bui-Huu start = 0; 515a09fc446SFranck Bui-Huu size = memparse(p, &p); 516a09fc446SFranck Bui-Huu if (*p == '@') 517a09fc446SFranck Bui-Huu start = memparse(p + 1, &p); 518a09fc446SFranck Bui-Huu 519a09fc446SFranck Bui-Huu add_memory_region(start, size, BOOT_MEM_RAM); 520a09fc446SFranck Bui-Huu return 0; 521a09fc446SFranck Bui-Huu } 522a09fc446SFranck Bui-Huu early_param("mem", early_parse_mem); 5232925aba4SRalf Baechle 5244893fc88SCorey Minyard #ifdef CONFIG_PROC_VMCORE 5254893fc88SCorey Minyard unsigned long setup_elfcorehdr, setup_elfcorehdr_size; 5264893fc88SCorey Minyard static int __init early_parse_elfcorehdr(char *p) 5274893fc88SCorey Minyard { 5284893fc88SCorey Minyard int i; 5294893fc88SCorey Minyard 5304893fc88SCorey Minyard setup_elfcorehdr = memparse(p, &p); 5314893fc88SCorey Minyard 5324893fc88SCorey Minyard for (i = 0; i < boot_mem_map.nr_map; i++) { 5334893fc88SCorey Minyard unsigned long start = boot_mem_map.map[i].addr; 5344893fc88SCorey Minyard unsigned long end = (boot_mem_map.map[i].addr + 5354893fc88SCorey Minyard boot_mem_map.map[i].size); 5364893fc88SCorey Minyard if (setup_elfcorehdr >= start && setup_elfcorehdr < end) { 5374893fc88SCorey Minyard /* 5384893fc88SCorey Minyard * Reserve from the elf core header to the end of 5394893fc88SCorey Minyard * the memory segment, that should all be kdump 5404893fc88SCorey Minyard * reserved memory. 5414893fc88SCorey Minyard */ 5424893fc88SCorey Minyard setup_elfcorehdr_size = end - setup_elfcorehdr; 5434893fc88SCorey Minyard break; 5444893fc88SCorey Minyard } 5454893fc88SCorey Minyard } 5464893fc88SCorey Minyard /* 5474893fc88SCorey Minyard * If we don't find it in the memory map, then we shouldn't 5484893fc88SCorey Minyard * have to worry about it, as the new kernel won't use it. 5494893fc88SCorey Minyard */ 5504893fc88SCorey Minyard return 0; 5514893fc88SCorey Minyard } 5524893fc88SCorey Minyard early_param("elfcorehdr", early_parse_elfcorehdr); 5534893fc88SCorey Minyard #endif 5544893fc88SCorey Minyard 55515d45cceSRalf Baechle static void __init arch_mem_addpart(phys_addr_t mem, phys_addr_t end, int type) 556d3ff9338SCorey Minyard { 55715d45cceSRalf Baechle phys_addr_t size; 558d3ff9338SCorey Minyard int i; 559d3ff9338SCorey Minyard 560d3ff9338SCorey Minyard size = end - mem; 561d3ff9338SCorey Minyard if (!size) 562d3ff9338SCorey Minyard return; 563d3ff9338SCorey Minyard 564d3ff9338SCorey Minyard /* Make sure it is in the boot_mem_map */ 565d3ff9338SCorey Minyard for (i = 0; i < boot_mem_map.nr_map; i++) { 566d3ff9338SCorey Minyard if (mem >= boot_mem_map.map[i].addr && 567d3ff9338SCorey Minyard mem < (boot_mem_map.map[i].addr + 568d3ff9338SCorey Minyard boot_mem_map.map[i].size)) 569d3ff9338SCorey Minyard return; 570d3ff9338SCorey Minyard } 571d3ff9338SCorey Minyard add_memory_region(mem, size, type); 572d3ff9338SCorey Minyard } 573d3ff9338SCorey Minyard 574c2882b7fSPrem Mallappa #ifdef CONFIG_KEXEC 575c2882b7fSPrem Mallappa static inline unsigned long long get_total_mem(void) 576c2882b7fSPrem Mallappa { 577c2882b7fSPrem Mallappa unsigned long long total; 578c2882b7fSPrem Mallappa 579c2882b7fSPrem Mallappa total = max_pfn - min_low_pfn; 580c2882b7fSPrem Mallappa return total << PAGE_SHIFT; 581c2882b7fSPrem Mallappa } 582c2882b7fSPrem Mallappa 583c2882b7fSPrem Mallappa static void __init mips_parse_crashkernel(void) 584c2882b7fSPrem Mallappa { 585c2882b7fSPrem Mallappa unsigned long long total_mem; 586c2882b7fSPrem Mallappa unsigned long long crash_size, crash_base; 587c2882b7fSPrem Mallappa int ret; 588c2882b7fSPrem Mallappa 589c2882b7fSPrem Mallappa total_mem = get_total_mem(); 590c2882b7fSPrem Mallappa ret = parse_crashkernel(boot_command_line, total_mem, 591c2882b7fSPrem Mallappa &crash_size, &crash_base); 592c2882b7fSPrem Mallappa if (ret != 0 || crash_size <= 0) 593c2882b7fSPrem Mallappa return; 594c2882b7fSPrem Mallappa 595c2882b7fSPrem Mallappa crashk_res.start = crash_base; 596c2882b7fSPrem Mallappa crashk_res.end = crash_base + crash_size - 1; 597c2882b7fSPrem Mallappa } 598c2882b7fSPrem Mallappa 599c2882b7fSPrem Mallappa static void __init request_crashkernel(struct resource *res) 600c2882b7fSPrem Mallappa { 601c2882b7fSPrem Mallappa int ret; 602c2882b7fSPrem Mallappa 603c2882b7fSPrem Mallappa ret = request_resource(res, &crashk_res); 604c2882b7fSPrem Mallappa if (!ret) 605c2882b7fSPrem Mallappa pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", 606c2882b7fSPrem Mallappa (unsigned long)((crashk_res.end - 607c2882b7fSPrem Mallappa crashk_res.start + 1) >> 20), 608c2882b7fSPrem Mallappa (unsigned long)(crashk_res.start >> 20)); 609c2882b7fSPrem Mallappa } 610c2882b7fSPrem Mallappa #else /* !defined(CONFIG_KEXEC) */ 611c2882b7fSPrem Mallappa static void __init mips_parse_crashkernel(void) 612c2882b7fSPrem Mallappa { 613c2882b7fSPrem Mallappa } 614c2882b7fSPrem Mallappa 615c2882b7fSPrem Mallappa static void __init request_crashkernel(struct resource *res) 616c2882b7fSPrem Mallappa { 617c2882b7fSPrem Mallappa } 618c2882b7fSPrem Mallappa #endif /* !defined(CONFIG_KEXEC) */ 619c2882b7fSPrem Mallappa 620*2024972eSJonas Gorski #define USE_PROM_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER) 621*2024972eSJonas Gorski #define USE_DTB_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB) 622*2024972eSJonas Gorski #define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_EXTEND) 623*2024972eSJonas Gorski 6242925aba4SRalf Baechle static void __init arch_mem_init(char **cmdline_p) 6252925aba4SRalf Baechle { 626f4649382SZubair Lutfullah Kakakhel struct memblock_region *reg; 627a09fc446SFranck Bui-Huu extern void plat_mem_setup(void); 628a09fc446SFranck Bui-Huu 6292925aba4SRalf Baechle /* call board setup routine */ 6302925aba4SRalf Baechle plat_mem_setup(); 6312925aba4SRalf Baechle 632d3ff9338SCorey Minyard /* 633d3ff9338SCorey Minyard * Make sure all kernel memory is in the maps. The "UP" and 634d3ff9338SCorey Minyard * "DOWN" are opposite for initdata since if it crosses over 635d3ff9338SCorey Minyard * into another memory section you don't want that to be 636d3ff9338SCorey Minyard * freed when the initdata is freed. 637d3ff9338SCorey Minyard */ 638d3ff9338SCorey Minyard arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT, 639d3ff9338SCorey Minyard PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT, 640d3ff9338SCorey Minyard BOOT_MEM_RAM); 641d3ff9338SCorey Minyard arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT, 642d3ff9338SCorey Minyard PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT, 64343064c0cSDavid Daney BOOT_MEM_INIT_RAM); 64443064c0cSDavid Daney 645a64ae7a2SMike Crowe pr_info("Determined physical RAM map:\n"); 646a09fc446SFranck Bui-Huu print_memory_map(); 647a09fc446SFranck Bui-Huu 648*2024972eSJonas Gorski #if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE) 6496acc7d48SDmitri Vorobiev strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); 6506acc7d48SDmitri Vorobiev #else 651*2024972eSJonas Gorski if ((USE_PROM_CMDLINE && arcs_cmdline[0]) || 652*2024972eSJonas Gorski (USE_DTB_CMDLINE && !boot_command_line[0])) 653*2024972eSJonas Gorski strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); 654*2024972eSJonas Gorski 655*2024972eSJonas Gorski if (EXTEND_WITH_PROM && arcs_cmdline[0]) { 656*2024972eSJonas Gorski strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); 657*2024972eSJonas Gorski strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); 6586acc7d48SDmitri Vorobiev } 659*2024972eSJonas Gorski 660*2024972eSJonas Gorski #if defined(CONFIG_CMDLINE_BOOL) 661*2024972eSJonas Gorski if (builtin_cmdline[0]) { 662*2024972eSJonas Gorski strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); 663*2024972eSJonas Gorski strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); 664*2024972eSJonas Gorski } 6656acc7d48SDmitri Vorobiev #endif 6666acc7d48SDmitri Vorobiev #endif 6676acc7d48SDmitri Vorobiev strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); 6682925aba4SRalf Baechle 6692925aba4SRalf Baechle *cmdline_p = command_line; 6702925aba4SRalf Baechle 671a09fc446SFranck Bui-Huu parse_early_param(); 672a09fc446SFranck Bui-Huu 673a09fc446SFranck Bui-Huu if (usermem) { 674a64ae7a2SMike Crowe pr_info("User-defined physical RAM map:\n"); 675a09fc446SFranck Bui-Huu print_memory_map(); 676a09fc446SFranck Bui-Huu } 677a09fc446SFranck Bui-Huu 6782925aba4SRalf Baechle bootmem_init(); 6794893fc88SCorey Minyard #ifdef CONFIG_PROC_VMCORE 6804893fc88SCorey Minyard if (setup_elfcorehdr && setup_elfcorehdr_size) { 6814893fc88SCorey Minyard printk(KERN_INFO "kdump reserved memory at %lx-%lx\n", 6824893fc88SCorey Minyard setup_elfcorehdr, setup_elfcorehdr_size); 6834893fc88SCorey Minyard reserve_bootmem(setup_elfcorehdr, setup_elfcorehdr_size, 6844893fc88SCorey Minyard BOOTMEM_DEFAULT); 6854893fc88SCorey Minyard } 6864893fc88SCorey Minyard #endif 687c2882b7fSPrem Mallappa 688c2882b7fSPrem Mallappa mips_parse_crashkernel(); 6897aa1c8f4SRalf Baechle #ifdef CONFIG_KEXEC 6907aa1c8f4SRalf Baechle if (crashk_res.start != crashk_res.end) 6917aa1c8f4SRalf Baechle reserve_bootmem(crashk_res.start, 6927aa1c8f4SRalf Baechle crashk_res.end - crashk_res.start + 1, 6937aa1c8f4SRalf Baechle BOOTMEM_DEFAULT); 6947aa1c8f4SRalf Baechle #endif 695f2ffa5abSDezhong Diao device_tree_init(); 6962925aba4SRalf Baechle sparse_init(); 697ee71b7d2SDavid Daney plat_swiotlb_setup(); 6982925aba4SRalf Baechle paging_init(); 699f4649382SZubair Lutfullah Kakakhel 700f4649382SZubair Lutfullah Kakakhel dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); 701f4649382SZubair Lutfullah Kakakhel /* Tell bootmem about cma reserved memblock section */ 702f4649382SZubair Lutfullah Kakakhel for_each_memblock(reserved, reg) 70330fa0530SZubair Lutfullah Kakakhel if (reg->size != 0) 704f4649382SZubair Lutfullah Kakakhel reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); 7052925aba4SRalf Baechle } 7062925aba4SRalf Baechle 7078df32c63SFranck Bui-Huu static void __init resource_init(void) 7081da177e4SLinus Torvalds { 7091da177e4SLinus Torvalds int i; 7101da177e4SLinus Torvalds 7116adb5fe7SRalf Baechle if (UNCAC_BASE != IO_BASE) 7126adb5fe7SRalf Baechle return; 7136adb5fe7SRalf Baechle 714f5bffe3aSFranck Bui-Huu code_resource.start = __pa_symbol(&_text); 715f5bffe3aSFranck Bui-Huu code_resource.end = __pa_symbol(&_etext) - 1; 716f5bffe3aSFranck Bui-Huu data_resource.start = __pa_symbol(&_etext); 717f5bffe3aSFranck Bui-Huu data_resource.end = __pa_symbol(&_edata) - 1; 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 7201da177e4SLinus Torvalds struct resource *res; 7211da177e4SLinus Torvalds unsigned long start, end; 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds start = boot_mem_map.map[i].addr; 7241da177e4SLinus Torvalds end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; 7251c6fd44dSFranck Bui-Huu if (start >= HIGHMEM_START) 7261da177e4SLinus Torvalds continue; 7271c6fd44dSFranck Bui-Huu if (end >= HIGHMEM_START) 7281c6fd44dSFranck Bui-Huu end = HIGHMEM_START - 1; 7291da177e4SLinus Torvalds 7301da177e4SLinus Torvalds res = alloc_bootmem(sizeof(struct resource)); 7311da177e4SLinus Torvalds switch (boot_mem_map.map[i].type) { 7321da177e4SLinus Torvalds case BOOT_MEM_RAM: 73343064c0cSDavid Daney case BOOT_MEM_INIT_RAM: 7341da177e4SLinus Torvalds case BOOT_MEM_ROM_DATA: 7351da177e4SLinus Torvalds res->name = "System RAM"; 7361da177e4SLinus Torvalds break; 7371da177e4SLinus Torvalds case BOOT_MEM_RESERVED: 7381da177e4SLinus Torvalds default: 7391da177e4SLinus Torvalds res->name = "reserved"; 7401da177e4SLinus Torvalds } 7411da177e4SLinus Torvalds 7421da177e4SLinus Torvalds res->start = start; 7431da177e4SLinus Torvalds res->end = end; 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 7461da177e4SLinus Torvalds request_resource(&iomem_resource, res); 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds /* 7491da177e4SLinus Torvalds * We don't know which RAM region contains kernel data, 7501da177e4SLinus Torvalds * so we try it repeatedly and let the resource manager 7511da177e4SLinus Torvalds * test it. 7521da177e4SLinus Torvalds */ 7531da177e4SLinus Torvalds request_resource(res, &code_resource); 7541da177e4SLinus Torvalds request_resource(res, &data_resource); 7557aa1c8f4SRalf Baechle request_crashkernel(res); 7561da177e4SLinus Torvalds } 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds 7590f3f506bSHuacai Chen #ifdef CONFIG_SMP 7600f3f506bSHuacai Chen static void __init prefill_possible_map(void) 7610f3f506bSHuacai Chen { 7620f3f506bSHuacai Chen int i, possible = num_possible_cpus(); 7630f3f506bSHuacai Chen 7640f3f506bSHuacai Chen if (possible > nr_cpu_ids) 7650f3f506bSHuacai Chen possible = nr_cpu_ids; 7660f3f506bSHuacai Chen 7670f3f506bSHuacai Chen for (i = 0; i < possible; i++) 7680f3f506bSHuacai Chen set_cpu_possible(i, true); 7690f3f506bSHuacai Chen for (; i < NR_CPUS; i++) 7700f3f506bSHuacai Chen set_cpu_possible(i, false); 7710f3f506bSHuacai Chen 7720f3f506bSHuacai Chen nr_cpu_ids = possible; 7730f3f506bSHuacai Chen } 7740f3f506bSHuacai Chen #else 7750f3f506bSHuacai Chen static inline void prefill_possible_map(void) {} 7760f3f506bSHuacai Chen #endif 7770f3f506bSHuacai Chen 7781da177e4SLinus Torvalds void __init setup_arch(char **cmdline_p) 7791da177e4SLinus Torvalds { 7801da177e4SLinus Torvalds cpu_probe(); 7811da177e4SLinus Torvalds prom_init(); 78236a88530SRalf Baechle 783e934945dSJames Hogan setup_early_fdc_console(); 78436a88530SRalf Baechle #ifdef CONFIG_EARLY_PRINTK 78536a88530SRalf Baechle setup_early_printk(); 78636a88530SRalf Baechle #endif 7871da177e4SLinus Torvalds cpu_report(); 78820d60d99SMaciej W. Rozycki check_bugs_early(); 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds #if defined(CONFIG_VT) 7911da177e4SLinus Torvalds #if defined(CONFIG_VGA_CONSOLE) 7921da177e4SLinus Torvalds conswitchp = &vga_con; 7931da177e4SLinus Torvalds #elif defined(CONFIG_DUMMY_CONSOLE) 7941da177e4SLinus Torvalds conswitchp = &dummy_con; 7951da177e4SLinus Torvalds #endif 7961da177e4SLinus Torvalds #endif 7971da177e4SLinus Torvalds 7982925aba4SRalf Baechle arch_mem_init(cmdline_p); 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds resource_init(); 8019b6695a8SRalf Baechle plat_smp_setup(); 8020f3f506bSHuacai Chen prefill_possible_map(); 8036650df3cSDavid Daney 8046650df3cSDavid Daney cpu_cache_init(); 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds 80769a6c312SAtsushi Nemoto unsigned long kernelsp[NR_CPUS]; 80869a6c312SAtsushi Nemoto unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; 8096312e0eeSAtsushi Nemoto 8106312e0eeSAtsushi Nemoto #ifdef CONFIG_DEBUG_FS 8116312e0eeSAtsushi Nemoto struct dentry *mips_debugfs_dir; 8126312e0eeSAtsushi Nemoto static int __init debugfs_mips(void) 8136312e0eeSAtsushi Nemoto { 8146312e0eeSAtsushi Nemoto struct dentry *d; 8156312e0eeSAtsushi Nemoto 8166312e0eeSAtsushi Nemoto d = debugfs_create_dir("mips", NULL); 817b517531cSZhaolei if (!d) 818b517531cSZhaolei return -ENOMEM; 8196312e0eeSAtsushi Nemoto mips_debugfs_dir = d; 8206312e0eeSAtsushi Nemoto return 0; 8216312e0eeSAtsushi Nemoto } 8226312e0eeSAtsushi Nemoto arch_initcall(debugfs_mips); 8236312e0eeSAtsushi Nemoto #endif 824