setup.c revision 8df32c636e785069ba7d223ceb9b72c182902295
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. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 2001, 2002 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> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/addrspace.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/bootinfo.h> 26ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechle#include <asm/cache.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sections.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechlestruct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cpu_data); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_VT 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct screen_info screen_info; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Despite it's name this variable is even if we don't have PCI 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int PCI_DMA_BUS_IS_PHYS; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup information 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These are initialized so they are in the .data section 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 52ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleunsigned long mips_machtype __read_mostly = MACH_UNKNOWN; 53ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleunsigned long mips_machgroup __read_mostly = MACH_GROUP_UNKNOWN; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_machtype); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_machgroup); 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 1388df32c636e785069ba7d223ceb9b72c182902295Franck Bui-Huustatic void __init parse_cmdline_early(void) 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c = ' ', *to = command_line, *from = saved_command_line; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start_at, mem_size; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len = 0; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int usermem = 0; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Determined physical RAM map:\n"); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds print_memory_map(); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "mem=XXX[kKmM]" defines a memory region from 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 to <XXX>, overriding the determined size. 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <YYY> to <YYY>+<XXX>, overriding the determined size. 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (c == ' ' && !memcmp(from, "mem=", 4)) { 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (to != command_line) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to--; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a user specifies memory size, we 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * blow away any automatically generated 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * size. 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (usermem == 0) { 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.nr_map = 0; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usermem = 1; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem_size = memparse(from + 4, &from); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*from == '@') 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start_at = memparse(from + 1, &from); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start_at = 0; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_memory_region(start_at, mem_size, BOOT_MEM_RAM); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c = *(from++); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!c) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (CL_SIZE <= ++len) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(to++) = c; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *to = '\0'; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (usermem) { 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("User-defined physical RAM map:\n"); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds print_memory_map(); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 189d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu/* 190d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Manage initrd 191d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 192d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_BLK_DEV_INITRD 193d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 194d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic int __init parse_rd_cmdline(unsigned long *rd_start, unsigned long *rd_end) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "rd_start=0xNNNNNNNN" defines the memory address of an initrd 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "rd_size=0xNN" it's size 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start = 0; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long size = 0; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long end; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char cmd_line[CL_SIZE]; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *start_str; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *size_str; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *tmp; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(cmd_line, command_line); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *command_line = 0; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = cmd_line; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ignore "rd_start=" strings in other parameters. */ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start_str = strstr(cmd_line, "rd_start="); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (start_str && start_str != cmd_line && *(start_str - 1) != ' ') 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start_str = strstr(start_str, " rd_start="); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (start_str) { 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (start_str != cmd_line) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strncat(command_line, tmp, start_str - tmp); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = memparse(start_str + 9, &start_str); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = start_str + 1; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start_str = strstr(start_str, " rd_start="); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*tmp) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(command_line, tmp); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(cmd_line, command_line); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *command_line = 0; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = cmd_line; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ignore "rd_size" strings in other parameters. */ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_str = strstr(cmd_line, "rd_size="); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size_str && size_str != cmd_line && *(size_str - 1) != ' ') 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_str = strstr(size_str, " rd_size="); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (size_str) { 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size_str != cmd_line) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strncat(command_line, tmp, size_str - tmp); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = memparse(size_str + 8, &size_str); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = size_str + 1; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_str = strstr(size_str, " rd_size="); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*tmp) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(command_line, tmp); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242875d43e72b5bf22161a81de7554f88eccf8a51aeRalf Baechle#ifdef CONFIG_64BIT 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* HACK: Guess if the sign extension was forgotten */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (start > 0x0000000080000000 && start < 0x00000000ffffffff) 245460c0422c3861ab63a14c2be600a96a9e68b89f2Atsushi Nemoto start |= 0xffffffff00000000UL; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = start + size; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (start && end) { 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rd_start = start; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rd_end = end; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 257d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic unsigned long __init init_initrd(void) 258d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 259d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu unsigned long tmp, end; 260d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu u32 *initrd_header; 261d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 262d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu ROOT_DEV = Root_RAM0; 263d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 264d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (parse_rd_cmdline(&initrd_start, &initrd_end)) 265d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu return initrd_end; 266d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu /* 267d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Board specific code should have set up initrd_start 268d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * and initrd_end... 269d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 270d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu end = (unsigned long)&_end; 271d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu tmp = PAGE_ALIGN(end) - sizeof(u32) * 2; 272d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (tmp < end) 273d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu tmp += PAGE_SIZE; 274d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 275d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_header = (u32 *)tmp; 276d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (initrd_header[0] == 0x494E5244) { 277d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_start = (unsigned long)&initrd_header[2]; 278d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_end = initrd_start + initrd_header[1]; 279d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 280d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu return initrd_end; 281d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 282d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 283d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init finalize_initrd(void) 284d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 285d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu unsigned long size = initrd_end - initrd_start; 286d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 287d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (size == 0) { 288d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(KERN_INFO "Initrd not found or empty"); 289d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu goto disable; 290d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 291d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { 292d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk("Initrd extends beyond end of memory"); 293d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu goto disable; 294d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 295d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 296d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu reserve_bootmem(CPHYSADDR(initrd_start), size); 297d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_below_start_ok = 1; 298d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 299d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n", 300d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_start, size); 301d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu return; 302d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huudisable: 303d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(" - disabling initrd\n"); 304d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_start = 0; 305d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_end = 0; 306d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 307d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 308d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else /* !CONFIG_BLK_DEV_INITRD */ 309d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 310d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#define init_initrd() 0 311d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#define finalize_initrd() do {} while (0) 312d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 313d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif 314d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 315b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu/* 316b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the bootmem allocator. It also setup initrd related data 317b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * if needed. 318b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 319d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_SGI_IP27 320d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 321b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huustatic void __init bootmem_init(void) 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 323d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu init_initrd(); 324d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu finalize_initrd(); 325d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 326d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 327d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else /* !CONFIG_SGI_IP27 */ 328d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 329d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init bootmem_init(void) 330d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 331d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu unsigned long reserved_end; 332b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu unsigned long highest = 0; 333b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu unsigned long mapstart = -1UL; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long bootmap_size; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 338d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Init any data related to initrd. It's a nop if INITRD is 339d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * not selected. Once that done we can determine the low bound 340d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * of usable memory. 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 342d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu reserved_end = init_initrd(); 343d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end))); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 345b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* 346b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Find the highest page frame number we have available. 347b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, end; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = PFN_UP(boot_mem_map.map[i].addr); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = PFN_DOWN(boot_mem_map.map[i].addr 356b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu + boot_mem_map.map[i].size); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 358b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end > highest) 359b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu highest = end; 360b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end <= reserved_end) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 362b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start >= mapstart) 363b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu continue; 364b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu mapstart = max(reserved_end, start); 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine low and high memory ranges 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 370b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (highest > PFN_DOWN(HIGHMEM_START)) { 371b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#ifdef CONFIG_HIGHMEM 372b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu highstart_pfn = PFN_DOWN(HIGHMEM_START); 373b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu highend_pfn = highest; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 375b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu highest = PFN_DOWN(HIGHMEM_START); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 379b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the boot-time allocator with low memory only. 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 381b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu bootmap_size = init_bootmem(mapstart, highest); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register fully available low RAM pages with the bootmem allocator. 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 387b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu unsigned long start, end, size; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reserve usable memory. 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 395b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu start = PFN_UP(boot_mem_map.map[i].addr); 396b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu end = PFN_DOWN(boot_mem_map.map[i].addr 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds + boot_mem_map.map[i].size); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 399b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * We are rounding up the start address of usable memory 400b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * and at the end of the usable range downwards. 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 402b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start >= max_low_pfn) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 404b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start < reserved_end) 405b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu start = reserved_end; 406b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end > max_low_pfn) 407b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu end = max_low_pfn; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 410b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * ... finally, is the area going away? 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 412b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end <= start) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 414b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu size = end - start; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register lowmem ranges */ 417b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT); 418b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu memory_present(0, start, end); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* 422b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Reserve the bootmap memory. 423b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 424b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu reserve_bootmem(PFN_PHYS(mapstart), bootmap_size); 425b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu 426d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu /* 427d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Reserve initrd memory if needed. 428d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 429d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu finalize_initrd(); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 432d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif /* CONFIG_SGI_IP27 */ 433d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 4342925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle/* 4352925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * arch_mem_init - initialize memory managment subsystem 4362925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4372925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o plat_mem_setup() detects the memory configuration and will record detected 4382925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * memory areas using add_memory_region. 4392925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o parse_cmdline_early() parses the command line for mem= options which, 4402925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * iff detected, will override the results of the automatic detection. 4412925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4422925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the memory configuration of the system is known to the 4432925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * kernel but generic memory managment system is still entirely uninitialized. 4442925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4452925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o bootmem_init() 4462925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o sparse_init() 4472925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o paging_init() 4482925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4492925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the bootmem allocator is ready to use. 4502925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4512925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * NOTE: historically plat_mem_setup did the entire platform initialization. 4522925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * This was rather impractical because it meant plat_mem_setup had to 4532925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * get away without any kind of memory allocator. To keep old code from 4542925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * breaking plat_setup was just renamed to plat_setup and a second platform 4552925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * initialization hook for anything else was introduced. 4562925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle */ 4572925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4582925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechleextern void plat_mem_setup(void); 4592925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4602925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechlestatic void __init arch_mem_init(char **cmdline_p) 4612925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle{ 4622925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle /* call board setup routine */ 4632925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle plat_mem_setup(); 4642925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4652925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle strlcpy(command_line, arcs_cmdline, sizeof(command_line)); 4662925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); 4672925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4682925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *cmdline_p = command_line; 4692925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4702925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle parse_cmdline_early(); 4712925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle bootmem_init(); 4722925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle sparse_init(); 4732925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle paging_init(); 4742925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle} 4752925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 476b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#define MAXMEM HIGHMEM_START 477b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#define MAXMEM_PFN PFN_DOWN(MAXMEM) 478b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu 4798df32c636e785069ba7d223ceb9b72c182902295Franck Bui-Huustatic void __init resource_init(void) 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4836adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle if (UNCAC_BASE != IO_BASE) 4846adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle return; 4856adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds code_resource.start = virt_to_phys(&_text); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds code_resource.end = virt_to_phys(&_etext) - 1; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_resource.start = virt_to_phys(&_etext); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_resource.end = virt_to_phys(&_edata) - 1; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Request address space for all standard RAM. 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *res; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, end; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = boot_mem_map.map[i].addr; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (start >= MAXMEM) 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (end >= MAXMEM) 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = MAXMEM - 1; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = alloc_bootmem(sizeof(struct resource)); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (boot_mem_map.map[i].type) { 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RAM: 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_ROM_DATA: 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->name = "System RAM"; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RESERVED: 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->name = "reserved"; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->start = start; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->end = end; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(&iomem_resource, res); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't know which RAM region contains kernel data, 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so we try it repeatedly and let the resource manager 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * test it. 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(res, &code_resource); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(res, &data_resource); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef MAXMEM 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef MAXMEM_PFN 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init setup_arch(char **cmdline_p) 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_probe(); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prom_init(); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_report(); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VT) 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VGA_CONSOLE) 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds conswitchp = &vga_con; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#elif defined(CONFIG_DUMMY_CONSOLE) 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds conswitchp = &dummy_con; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5492925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle arch_mem_init(cmdline_p); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource_init(); 5529b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle#ifdef CONFIG_SMP 5539b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle plat_smp_setup(); 5549b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle#endif 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init fpu_disable(char *s) 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 559f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle int i; 560f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle 561f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle for (i = 0; i < NR_CPUS; i++) 562f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle cpu_data[i].options &= ~MIPS_CPU_FPU; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("nofpu", fpu_disable); 568e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle 569e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechleint __init dsp_disable(char *s) 570e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle{ 571e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle cpu_data[0].ases &= ~MIPS_ASE_DSP; 572e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle 573e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle return 1; 574e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle} 575e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle 576e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle__setup("nodsp", dsp_disable); 577