setup.c revision 20d60d9973c3b441902b0a3f4f6f7e7ade08f77d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Linus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Waldorf Electronics 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996 Stoned Elipot 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Silicon Graphics, Inc. 1120d60d9973c3b441902b0a3f4f6f7e7ade08f77dMaciej W. Rozycki * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 16894673ee6122a3ce1958e1fe096901ba5356a96bJon Smirl#include <linux/screen_info.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/initrd.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/root_dev.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 2222a9835c350782a5c3257343713932af3ac92ee0Dave Hansen#include <linux/pfn.h> 236312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto#include <linux/debugfs.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/addrspace.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/bootinfo.h> 2720d60d9973c3b441902b0a3f4f6f7e7ade08f77dMaciej W. Rozycki#include <asm/bugs.h> 28ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechle#include <asm/cache.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sections.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechlestruct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cpu_data); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_VT 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct screen_info screen_info; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Despite it's name this variable is even if we don't have PCI 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int PCI_DMA_BUS_IS_PHYS; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup information 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These are initialized so they are in the .data section 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 54ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleunsigned long mips_machtype __read_mostly = MACH_UNKNOWN; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_machtype); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct boot_mem_map boot_mem_map; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char command_line[CL_SIZE]; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mips_io_port_base is the begin of the address space to which x86 style 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I/O ports are mapped. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 67ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleconst unsigned long mips_io_port_base __read_mostly = -1; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_io_port_base); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the processor. 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long isa_slot_offset; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(isa_slot_offset); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct resource code_resource = { .name = "Kernel code", }; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct resource data_resource = { .name = "Kernel data", }; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init add_memory_region(phys_t start, phys_t size, long type) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x = boot_mem_map.nr_map; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 85b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* Sanity check */ 86b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start + size < start) { 87b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu printk("Trying to add an invalid memory region, skipped\n"); 88b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu return; 89b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu } 90b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to merge with previous entry if any. This is far less than 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perfect but is sufficient for most real world cases. 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (x && prev->addr + prev->size == start && prev->type == type) { 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->size += size; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (x == BOOT_MEM_MAP_MAX) { 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Ooops! Too many entries in the memory map!\n"); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.map[x].addr = start; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.map[x].size = size; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.map[x].type = type; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.nr_map++; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init print_memory_map(void) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const int field = 2 * sizeof(unsigned long); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" memory: %0*Lx @ %0*Lx ", 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds field, (unsigned long long) boot_mem_map.map[i].size, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds field, (unsigned long long) boot_mem_map.map[i].addr); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (boot_mem_map.map[i].type) { 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RAM: 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("(usable)\n"); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_ROM_DATA: 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("(ROM data)\n"); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RESERVED: 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("(reserved)\n"); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("type %lu\n", boot_mem_map.map[i].type); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 138d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu/* 139d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Manage initrd 140d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 141d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_BLK_DEV_INITRD 142d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 143a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int __init rd_start_early(char *p) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 145a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu unsigned long start = memparse(p, &p); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 147875d43e72b5bf22161a81de7554f88eccf8a51aeRalf Baechle#ifdef CONFIG_64BIT 148a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu /* Guess if the sign extension was forgotten by bootloader */ 149a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (start < XKPHYS) 150a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu start = (int)start; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 152a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu initrd_start = start; 153a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu initrd_end += start; 154a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu return 0; 155a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu} 156a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huuearly_param("rd_start", rd_start_early); 157a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 158a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int __init rd_size_early(char *p) 159a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu{ 160a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu initrd_end += memparse(p, &p); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 163a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huuearly_param("rd_size", rd_size_early); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 165a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu/* it returns the next free pfn after initrd */ 166d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic unsigned long __init init_initrd(void) 167d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 168a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu unsigned long end; 169d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu u32 *initrd_header; 170d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 171d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu /* 172a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * Board specific code or command line parser should have 173a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * already set up initrd_start and initrd_end. In these cases 174a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * perfom sanity checks and use them if all looks good. 175d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 176a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (initrd_start && initrd_end > initrd_start) 177a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto sanitize; 178a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 179a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu /* 180a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * See if initrd has been added to the kernel image by 181a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * arch/mips/boot/addinitrd.c. In that case a header is 182a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * prepended to initrd and is made up by 8 bytes. The fisrt 183a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * word is a magic number and the second one is the size of 184a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * initrd. Initrd start must be page aligned in any cases. 185a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu */ 186a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8; 187a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (initrd_header[0] != 0x494E5244) 188a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto disable; 189a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_start = (unsigned long)(initrd_header + 2); 190a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_end = initrd_start + initrd_header[1]; 191a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 192a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huusanitize: 193a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (initrd_start & ~PAGE_MASK) { 194a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu printk(KERN_ERR "initrd start must be page aligned\n"); 195a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto disable; 196d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 197a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (initrd_start < PAGE_OFFSET) { 198a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu printk(KERN_ERR "initrd start < PAGE_OFFSET\n"); 199a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto disable; 200a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu } 201a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 202a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu /* 203a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * Sanitize initrd addresses. For example firmware 204a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * can't guess if they need to pass them through 205a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * 64-bits values if the kernel has been built in pure 206a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * 32-bit. We need also to switch from KSEG0 to XKPHYS 207a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * addresses now, so the code can now safely use __pa(). 208a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu */ 209a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu end = __pa(initrd_end); 210a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_end = (unsigned long)__va(end); 211a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_start = (unsigned long)__va(__pa(initrd_start)); 212a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 213a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu ROOT_DEV = Root_RAM0; 214a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu return PFN_UP(end); 215a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huudisable: 216a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_start = 0; 217a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_end = 0; 218a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu return 0; 219d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 220d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 221d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init finalize_initrd(void) 222d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 223d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu unsigned long size = initrd_end - initrd_start; 224d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 225d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (size == 0) { 226d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(KERN_INFO "Initrd not found or empty"); 227d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu goto disable; 228d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 229d4df6d4e7a66b7a9bd57f5dc7d80d6b55dc12dbbFranck Bui-Huu if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { 230d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk("Initrd extends beyond end of memory"); 231d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu goto disable; 232d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 233d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 234d4df6d4e7a66b7a9bd57f5dc7d80d6b55dc12dbbFranck Bui-Huu reserve_bootmem(__pa(initrd_start), size); 235d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_below_start_ok = 1; 236d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 237d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", 238d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_start, size); 239d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu return; 240d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huudisable: 241d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(" - disabling initrd\n"); 242d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_start = 0; 243d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_end = 0; 244d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 245d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 246d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else /* !CONFIG_BLK_DEV_INITRD */ 247d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 2489ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechlestatic unsigned long __init init_initrd(void) 2499ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle{ 2509ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle return 0; 2519ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle} 2529ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle 253d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#define finalize_initrd() do {} while (0) 254d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 255d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif 256d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 257b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu/* 258b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the bootmem allocator. It also setup initrd related data 259b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * if needed. 260b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 261d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_SGI_IP27 262d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 263b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huustatic void __init bootmem_init(void) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 265d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu init_initrd(); 266d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu finalize_initrd(); 267d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 268d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 269d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else /* !CONFIG_SGI_IP27 */ 270d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 271d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init bootmem_init(void) 272d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 273e452e94e21e8f4a3c2ff045b301ca21c1f6d03bfAtsushi Nemoto unsigned long reserved_end; 274db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu unsigned long mapstart = ~0UL; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long bootmap_size; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 279d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Init any data related to initrd. It's a nop if INITRD is 280d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * not selected. Once that done we can determine the low bound 281d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * of usable memory. 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 283a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end))); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* 286db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu * max_low_pfn is not a number of pages. The number of pages 287db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu * of the system is given by 'max_low_pfn - min_low_pfn'. 288db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu */ 289db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu min_low_pfn = ~0UL; 290db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu max_low_pfn = 0; 291db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu 292db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu /* 293b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Find the highest page frame number we have available. 294b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, end; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = PFN_UP(boot_mem_map.map[i].addr); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = PFN_DOWN(boot_mem_map.map[i].addr 303b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu + boot_mem_map.map[i].size); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 305db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (end > max_low_pfn) 306db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu max_low_pfn = end; 307db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (start < min_low_pfn) 308db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu min_low_pfn = start; 309b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end <= reserved_end) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 311b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start >= mapstart) 312b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu continue; 313b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu mapstart = max(reserved_end, start); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 316db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (min_low_pfn >= max_low_pfn) 317db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu panic("Incorrect memory mapping !!!"); 3186f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu if (min_low_pfn > ARCH_PFN_OFFSET) { 319db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu printk(KERN_INFO 320db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu "Wasting %lu bytes for tracking %lu unused pages\n", 3216f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), 3226f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu min_low_pfn - ARCH_PFN_OFFSET); 3236f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu } else if (min_low_pfn < ARCH_PFN_OFFSET) { 3246f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu printk(KERN_INFO 3256f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu "%lu free pages won't be used\n", 3266f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu ARCH_PFN_OFFSET - min_low_pfn); 327db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu } 3286f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu min_low_pfn = ARCH_PFN_OFFSET; 329db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine low and high memory ranges 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 333db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) { 334b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#ifdef CONFIG_HIGHMEM 335b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu highstart_pfn = PFN_DOWN(HIGHMEM_START); 336db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu highend_pfn = max_low_pfn; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 338db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu max_low_pfn = PFN_DOWN(HIGHMEM_START); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 342b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the boot-time allocator with low memory only. 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 344db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, 345db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu min_low_pfn, max_low_pfn); 346cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 347cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 348cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle for (i = 0; i < boot_mem_map.nr_map; i++) { 349cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle unsigned long start, end; 350cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 351cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle start = PFN_UP(boot_mem_map.map[i].addr); 352cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle end = PFN_DOWN(boot_mem_map.map[i].addr 353cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle + boot_mem_map.map[i].size); 354cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 355e452e94e21e8f4a3c2ff045b301ca21c1f6d03bfAtsushi Nemoto if (start <= min_low_pfn) 356e452e94e21e8f4a3c2ff045b301ca21c1f6d03bfAtsushi Nemoto start = min_low_pfn; 357cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle if (start >= end) 358cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle continue; 359cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 360cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle#ifndef CONFIG_HIGHMEM 361cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle if (end > max_low_pfn) 362cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle end = max_low_pfn; 363cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 364cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle /* 365cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle * ... finally, is the area going away? 366cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle */ 367cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle if (end <= start) 368cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle continue; 369cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle#endif 370cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 371cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle add_active_range(0, start, end); 372cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle } 373cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register fully available low RAM pages with the bootmem allocator. 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 378b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu unsigned long start, end, size; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reserve usable memory. 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 386b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu start = PFN_UP(boot_mem_map.map[i].addr); 387b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu end = PFN_DOWN(boot_mem_map.map[i].addr 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds + boot_mem_map.map[i].size); 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 390b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * We are rounding up the start address of usable memory 391b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * and at the end of the usable range downwards. 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 393b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start >= max_low_pfn) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 395b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start < reserved_end) 396b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu start = reserved_end; 397b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end > max_low_pfn) 398b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu end = max_low_pfn; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 401b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * ... finally, is the area going away? 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 403b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end <= start) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 405b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu size = end - start; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register lowmem ranges */ 408b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT); 409b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu memory_present(0, start, end); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 412b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* 413b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Reserve the bootmap memory. 414b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 415b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu reserve_bootmem(PFN_PHYS(mapstart), bootmap_size); 416b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu 417d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu /* 418d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Reserve initrd memory if needed. 419d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 420d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu finalize_initrd(); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 423d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif /* CONFIG_SGI_IP27 */ 424d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 4252925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle/* 4262925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * arch_mem_init - initialize memory managment subsystem 4272925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4282925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o plat_mem_setup() detects the memory configuration and will record detected 4292925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * memory areas using add_memory_region. 4302925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4312925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the memory configuration of the system is known to the 4322925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * kernel but generic memory managment system is still entirely uninitialized. 4332925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4342925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o bootmem_init() 4352925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o sparse_init() 4362925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o paging_init() 4372925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4382925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the bootmem allocator is ready to use. 4392925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4402925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * NOTE: historically plat_mem_setup did the entire platform initialization. 4412925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * This was rather impractical because it meant plat_mem_setup had to 4422925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * get away without any kind of memory allocator. To keep old code from 4432925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * breaking plat_setup was just renamed to plat_setup and a second platform 4442925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * initialization hook for anything else was introduced. 4452925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle */ 4462925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 447a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int usermem __initdata = 0; 448a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 449a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int __init early_parse_mem(char *p) 450a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu{ 451a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu unsigned long start, size; 452a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 453a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu /* 454a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * If a user specifies memory size, we 455a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * blow away any automatically generated 456a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * size. 457a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu */ 458a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu if (usermem == 0) { 459a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu boot_mem_map.nr_map = 0; 460a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu usermem = 1; 461a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu } 462a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu start = 0; 463a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu size = memparse(p, &p); 464a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu if (*p == '@') 465a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu start = memparse(p + 1, &p); 466a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 467a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu add_memory_region(start, size, BOOT_MEM_RAM); 468a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu return 0; 469a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu} 470a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huuearly_param("mem", early_parse_mem); 4712925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4722925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechlestatic void __init arch_mem_init(char **cmdline_p) 4732925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle{ 474a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu extern void plat_mem_setup(void); 475a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 4762925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle /* call board setup routine */ 4772925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle plat_mem_setup(); 4782925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 479a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu printk("Determined physical RAM map:\n"); 480a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu print_memory_map(); 481a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 4822925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle strlcpy(command_line, arcs_cmdline, sizeof(command_line)); 48343cd34645d3bf35cbaa68f28b85d12d0b9e08ab9Alon Bar-Lev strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 4842925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4852925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *cmdline_p = command_line; 4862925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 487a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu parse_early_param(); 488a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 489a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu if (usermem) { 490a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu printk("User-defined physical RAM map:\n"); 491a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu print_memory_map(); 492a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu } 493a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 4942925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle bootmem_init(); 4952925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle sparse_init(); 4962925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle paging_init(); 4972925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle} 4982925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4998df32c636e785069ba7d223ceb9b72c182902295Franck Bui-Huustatic void __init resource_init(void) 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5036adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle if (UNCAC_BASE != IO_BASE) 5046adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle return; 5056adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle 506f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu code_resource.start = __pa_symbol(&_text); 507f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu code_resource.end = __pa_symbol(&_etext) - 1; 508f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu data_resource.start = __pa_symbol(&_etext); 509f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu data_resource.end = __pa_symbol(&_edata) - 1; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Request address space for all standard RAM. 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *res; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, end; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = boot_mem_map.map[i].addr; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; 5201c6fd44d7ed3d105b2eaa29d72b415ca51e40d32Franck Bui-Huu if (start >= HIGHMEM_START) 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 5221c6fd44d7ed3d105b2eaa29d72b415ca51e40d32Franck Bui-Huu if (end >= HIGHMEM_START) 5231c6fd44d7ed3d105b2eaa29d72b415ca51e40d32Franck Bui-Huu end = HIGHMEM_START - 1; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = alloc_bootmem(sizeof(struct resource)); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (boot_mem_map.map[i].type) { 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RAM: 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_ROM_DATA: 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->name = "System RAM"; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RESERVED: 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->name = "reserved"; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->start = start; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->end = end; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(&iomem_resource, res); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't know which RAM region contains kernel data, 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so we try it repeatedly and let the resource manager 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * test it. 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(res, &code_resource); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(res, &data_resource); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init setup_arch(char **cmdline_p) 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_probe(); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prom_init(); 55636a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle 55736a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle#ifdef CONFIG_EARLY_PRINTK 55836a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle { 55936a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle extern void setup_early_printk(void); 56036a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle 56136a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle setup_early_printk(); 56236a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle } 56336a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle#endif 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_report(); 56520d60d9973c3b441902b0a3f4f6f7e7ade08f77dMaciej W. Rozycki check_bugs_early(); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VT) 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VGA_CONSOLE) 569e0daad449c5195fa4552c60392eeee4e5c58d31cRalf Baechle conswitchp = &vga_con; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#elif defined(CONFIG_DUMMY_CONSOLE) 571e0daad449c5195fa4552c60392eeee4e5c58d31cRalf Baechle conswitchp = &dummy_con; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5752925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle arch_mem_init(cmdline_p); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource_init(); 5789b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle#ifdef CONFIG_SMP 5799b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle plat_smp_setup(); 5809b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle#endif 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 583f49a747c4adadd96addf4dbf4a44f439513fb29bAtsushi Nemotostatic int __init fpu_disable(char *s) 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 585f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle int i; 586f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle 587f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle for (i = 0; i < NR_CPUS; i++) 588f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle cpu_data[i].options &= ~MIPS_CPU_FPU; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("nofpu", fpu_disable); 594e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle 595f49a747c4adadd96addf4dbf4a44f439513fb29bAtsushi Nemotostatic int __init dsp_disable(char *s) 596e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle{ 597e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle cpu_data[0].ases &= ~MIPS_ASE_DSP; 598e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle 599e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle return 1; 600e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle} 601e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle 602e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle__setup("nodsp", dsp_disable); 60369a6c312e5ebb2e929ceb67e6246e2d9314f1d29Atsushi Nemoto 60469a6c312e5ebb2e929ceb67e6246e2d9314f1d29Atsushi Nemotounsigned long kernelsp[NR_CPUS]; 60569a6c312e5ebb2e929ceb67e6246e2d9314f1d29Atsushi Nemotounsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; 6066312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto 6076312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto#ifdef CONFIG_DEBUG_FS 6086312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemotostruct dentry *mips_debugfs_dir; 6096312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemotostatic int __init debugfs_mips(void) 6106312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto{ 6116312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto struct dentry *d; 6126312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto 6136312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto d = debugfs_create_dir("mips", NULL); 6146312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto if (IS_ERR(d)) 6156312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto return PTR_ERR(d); 6166312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto mips_debugfs_dir = d; 6176312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto return 0; 6186312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto} 6196312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemotoarch_initcall(debugfs_mips); 6206312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto#endif 621