11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/init/main.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * GK 2/5/95 - Changed to support mounting root fs via NFS 71da177e4SLinus Torvalds * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 81da177e4SLinus Torvalds * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 91da177e4SLinus Torvalds * Simplified starting of init: Michael A. Griffith <[email protected]> 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/types.h> 131da177e4SLinus Torvalds #include <linux/module.h> 141da177e4SLinus Torvalds #include <linux/proc_fs.h> 151da177e4SLinus Torvalds #include <linux/kernel.h> 161da177e4SLinus Torvalds #include <linux/syscalls.h> 179b5609fdSIngo Molnar #include <linux/stackprotector.h> 181da177e4SLinus Torvalds #include <linux/string.h> 191da177e4SLinus Torvalds #include <linux/ctype.h> 201da177e4SLinus Torvalds #include <linux/delay.h> 211da177e4SLinus Torvalds #include <linux/ioport.h> 221da177e4SLinus Torvalds #include <linux/init.h> 231da177e4SLinus Torvalds #include <linux/initrd.h> 241da177e4SLinus Torvalds #include <linux/bootmem.h> 254a7a16dcSLen Brown #include <linux/acpi.h> 261da177e4SLinus Torvalds #include <linux/tty.h> 271da177e4SLinus Torvalds #include <linux/percpu.h> 281da177e4SLinus Torvalds #include <linux/kmod.h> 29db64fe02SNick Piggin #include <linux/vmalloc.h> 301da177e4SLinus Torvalds #include <linux/kernel_stat.h> 31d7cd5611SRusty Russell #include <linux/start_kernel.h> 321da177e4SLinus Torvalds #include <linux/security.h> 333d442233SJens Axboe #include <linux/smp.h> 341da177e4SLinus Torvalds #include <linux/profile.h> 351da177e4SLinus Torvalds #include <linux/rcupdate.h> 361da177e4SLinus Torvalds #include <linux/moduleparam.h> 371da177e4SLinus Torvalds #include <linux/kallsyms.h> 381da177e4SLinus Torvalds #include <linux/writeback.h> 391da177e4SLinus Torvalds #include <linux/cpu.h> 401da177e4SLinus Torvalds #include <linux/cpuset.h> 41ddbcc7e8SPaul Menage #include <linux/cgroup.h> 421da177e4SLinus Torvalds #include <linux/efi.h> 43906568c9SThomas Gleixner #include <linux/tick.h> 446168a702SAndrew Morton #include <linux/interrupt.h> 45c757249aSShailabh Nagar #include <linux/taskstats_kern.h> 46ca74e92bSShailabh Nagar #include <linux/delayacct.h> 471da177e4SLinus Torvalds #include <linux/unistd.h> 481da177e4SLinus Torvalds #include <linux/rmap.h> 491da177e4SLinus Torvalds #include <linux/mempolicy.h> 501da177e4SLinus Torvalds #include <linux/key.h> 51b6cd0b77SAdrian Bunk #include <linux/buffer_head.h> 5294b6da5aSKAMEZAWA Hiroyuki #include <linux/page_cgroup.h> 539a11b49aSIngo Molnar #include <linux/debug_locks.h> 543ac7fe5aSThomas Gleixner #include <linux/debugobjects.h> 55fbb9ce95SIngo Molnar #include <linux/lockdep.h> 563c7b4e6bSCatalin Marinas #include <linux/kmemleak.h> 5784d73786SSukadev Bhattiprolu #include <linux/pid_namespace.h> 581f21782eSAdrian Bunk #include <linux/device.h> 5973c27992SEric W. Biederman #include <linux/kthread.h> 60e6fe6649SAdrian Bunk #include <linux/sched.h> 61a1c9eea9SAdrian Bunk #include <linux/signal.h> 62199f0ca5SAkinobu Mita #include <linux/idr.h> 630b4b3827SJason Wessel #include <linux/kgdb.h> 6468bf21aaSSteven Rostedt #include <linux/ftrace.h> 6522a9d645SArjan van de Ven #include <linux/async.h> 66dfec072eSVegard Nossum #include <linux/kmemcheck.h> 676ae6996aSFeng Tang #include <linux/sfi.h> 682b2af54aSKay Sievers #include <linux/shmem_fs.h> 695a0e3ad6STejun Heo #include <linux/slab.h> 7024a24bb6SPeter Zijlstra #include <linux/perf_event.h> 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #include <asm/io.h> 731da177e4SLinus Torvalds #include <asm/bugs.h> 741da177e4SLinus Torvalds #include <asm/setup.h> 75a940199fSAndi Kleen #include <asm/sections.h> 7637b73c82SArjan van de Ven #include <asm/cacheflush.h> 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds #ifdef CONFIG_X86_LOCAL_APIC 791da177e4SLinus Torvalds #include <asm/smp.h> 801da177e4SLinus Torvalds #endif 811da177e4SLinus Torvalds 82aae5f662SSam Ravnborg static int kernel_init(void *); 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds extern void init_IRQ(void); 851da177e4SLinus Torvalds extern void fork_init(unsigned long); 861da177e4SLinus Torvalds extern void mca_init(void); 871da177e4SLinus Torvalds extern void sbus_init(void); 881da177e4SLinus Torvalds extern void prio_tree_init(void); 891da177e4SLinus Torvalds extern void radix_tree_init(void); 9037b73c82SArjan van de Ven #ifndef CONFIG_DEBUG_RODATA 9137b73c82SArjan van de Ven static inline void mark_rodata_ro(void) { } 9237b73c82SArjan van de Ven #endif 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds #ifdef CONFIG_TC 951da177e4SLinus Torvalds extern void tc_init(void); 961da177e4SLinus Torvalds #endif 971da177e4SLinus Torvalds 982ce802f6STejun Heo /* 992ce802f6STejun Heo * Debug helper: via this flag we know that we are in 'early bootup code' 1002ce802f6STejun Heo * where only the boot processor is running with IRQ disabled. This means 1012ce802f6STejun Heo * two things - IRQ must not be enabled before the flag is cleared and some 1022ce802f6STejun Heo * operations which are not allowed with IRQ disabled are allowed while the 1032ce802f6STejun Heo * flag is set. 1042ce802f6STejun Heo */ 1052ce802f6STejun Heo bool early_boot_irqs_disabled __read_mostly; 1062ce802f6STejun Heo 107a6826048SPaul E. McKenney enum system_states system_state __read_mostly; 1081da177e4SLinus Torvalds EXPORT_SYMBOL(system_state); 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds /* 1111da177e4SLinus Torvalds * Boot command-line arguments 1121da177e4SLinus Torvalds */ 1131da177e4SLinus Torvalds #define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT 1141da177e4SLinus Torvalds #define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds extern void time_init(void); 1171da177e4SLinus Torvalds /* Default late time init is NULL. archs can override this later. */ 118d2e3192bSJan Beulich void (*__initdata late_time_init)(void); 1191da177e4SLinus Torvalds extern void softirq_init(void); 1201da177e4SLinus Torvalds 12130d7e0d4SAlon Bar-Lev /* Untouched command line saved by arch-specific code. */ 12230d7e0d4SAlon Bar-Lev char __initdata boot_command_line[COMMAND_LINE_SIZE]; 12330d7e0d4SAlon Bar-Lev /* Untouched saved command line (eg. for /proc) */ 12430d7e0d4SAlon Bar-Lev char *saved_command_line; 12530d7e0d4SAlon Bar-Lev /* Command line for parameter parsing */ 12630d7e0d4SAlon Bar-Lev static char *static_command_line; 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds static char *execute_command; 129ffdfc409SOlof Johansson static char *ramdisk_execute_command; 1301da177e4SLinus Torvalds 1318b3b2955SJan Beulich /* 1328b3b2955SJan Beulich * If set, this is an indication to the drivers that reset the underlying 1338b3b2955SJan Beulich * device before going ahead with the initialization otherwise driver might 1348b3b2955SJan Beulich * rely on the BIOS and skip the reset operation. 1358b3b2955SJan Beulich * 1368b3b2955SJan Beulich * This is useful if kernel is booting in an unreliable environment. 1378b3b2955SJan Beulich * For ex. kdump situaiton where previous kernel has crashed, BIOS has been 1388b3b2955SJan Beulich * skipped and devices will be in unknown state. 1398b3b2955SJan Beulich */ 1408b3b2955SJan Beulich unsigned int reset_devices; 1418b3b2955SJan Beulich EXPORT_SYMBOL(reset_devices); 1421da177e4SLinus Torvalds 1437e96287dSVivek Goyal static int __init set_reset_devices(char *str) 1447e96287dSVivek Goyal { 1457e96287dSVivek Goyal reset_devices = 1; 1467e96287dSVivek Goyal return 1; 1477e96287dSVivek Goyal } 1487e96287dSVivek Goyal 1497e96287dSVivek Goyal __setup("reset_devices", set_reset_devices); 1507e96287dSVivek Goyal 151d7627467SDavid Howells static const char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; 152d7627467SDavid Howells const char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; 1531da177e4SLinus Torvalds static const char *panic_later, *panic_param; 1541da177e4SLinus Torvalds 155914dcaa8SRusty Russell extern const struct obs_kernel_param __setup_start[], __setup_end[]; 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds static int __init obsolete_checksetup(char *line) 1581da177e4SLinus Torvalds { 159914dcaa8SRusty Russell const struct obs_kernel_param *p; 16033df0d19SRusty Russell int had_early_param = 0; 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds p = __setup_start; 1631da177e4SLinus Torvalds do { 1641da177e4SLinus Torvalds int n = strlen(p->str); 165b1e4d20cSMichal Schmidt if (parameqn(line, p->str, n)) { 1661da177e4SLinus Torvalds if (p->early) { 16733df0d19SRusty Russell /* Already done in parse_early_param? 16833df0d19SRusty Russell * (Needs exact match on param part). 16933df0d19SRusty Russell * Keep iterating, as we can have early 17033df0d19SRusty Russell * params and __setups of same names 8( */ 1711da177e4SLinus Torvalds if (line[n] == '\0' || line[n] == '=') 17233df0d19SRusty Russell had_early_param = 1; 1731da177e4SLinus Torvalds } else if (!p->setup_func) { 1741da177e4SLinus Torvalds printk(KERN_WARNING "Parameter %s is obsolete," 1751da177e4SLinus Torvalds " ignored\n", p->str); 1761da177e4SLinus Torvalds return 1; 1771da177e4SLinus Torvalds } else if (p->setup_func(line + n)) 1781da177e4SLinus Torvalds return 1; 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds p++; 1811da177e4SLinus Torvalds } while (p < __setup_end); 18233df0d19SRusty Russell 18333df0d19SRusty Russell return had_early_param; 1841da177e4SLinus Torvalds } 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds /* 1871da177e4SLinus Torvalds * This should be approx 2 Bo*oMips to start (note initial shift), and will 1881da177e4SLinus Torvalds * still work even if initially too large, it will just take slightly longer 1891da177e4SLinus Torvalds */ 1901da177e4SLinus Torvalds unsigned long loops_per_jiffy = (1<<12); 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds EXPORT_SYMBOL(loops_per_jiffy); 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds static int __init debug_kernel(char *str) 1951da177e4SLinus Torvalds { 1961da177e4SLinus Torvalds console_loglevel = 10; 197f6f21c81SYinghai Lu return 0; 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds static int __init quiet_kernel(char *str) 2011da177e4SLinus Torvalds { 2021da177e4SLinus Torvalds console_loglevel = 4; 203f6f21c81SYinghai Lu return 0; 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds 206f6f21c81SYinghai Lu early_param("debug", debug_kernel); 207f6f21c81SYinghai Lu early_param("quiet", quiet_kernel); 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds static int __init loglevel(char *str) 2101da177e4SLinus Torvalds { 211808bf29bSAlexander Sverdlin int newlevel; 212808bf29bSAlexander Sverdlin 213808bf29bSAlexander Sverdlin /* 214808bf29bSAlexander Sverdlin * Only update loglevel value when a correct setting was passed, 215808bf29bSAlexander Sverdlin * to prevent blind crashes (when loglevel being set to 0) that 216808bf29bSAlexander Sverdlin * are quite hard to debug 217808bf29bSAlexander Sverdlin */ 218808bf29bSAlexander Sverdlin if (get_option(&str, &newlevel)) { 219808bf29bSAlexander Sverdlin console_loglevel = newlevel; 220d9d4fcfeSAlex Riesen return 0; 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 223808bf29bSAlexander Sverdlin return -EINVAL; 224808bf29bSAlexander Sverdlin } 225808bf29bSAlexander Sverdlin 226f6f21c81SYinghai Lu early_param("loglevel", loglevel); 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds /* Change NUL term back to "=", to make "param" the whole string. */ 229a99cd112SChris Metcalf static int __init repair_env_string(char *param, char *val) 230a99cd112SChris Metcalf { 2311da177e4SLinus Torvalds if (val) { 2321da177e4SLinus Torvalds /* param=val or param="val"? */ 2331da177e4SLinus Torvalds if (val == param+strlen(param)+1) 2341da177e4SLinus Torvalds val[-1] = '='; 2351da177e4SLinus Torvalds else if (val == param+strlen(param)+2) { 2361da177e4SLinus Torvalds val[-2] = '='; 2371da177e4SLinus Torvalds memmove(val-1, val, strlen(val)+1); 2381da177e4SLinus Torvalds val--; 2391da177e4SLinus Torvalds } else 2401da177e4SLinus Torvalds BUG(); 2411da177e4SLinus Torvalds } 242a99cd112SChris Metcalf return 0; 243a99cd112SChris Metcalf } 244a99cd112SChris Metcalf 245a99cd112SChris Metcalf /* 246a99cd112SChris Metcalf * Unknown boot options get handed to init, unless they look like 247a99cd112SChris Metcalf * unused parameters (modprobe will find them in /proc/cmdline). 248a99cd112SChris Metcalf */ 249a99cd112SChris Metcalf static int __init unknown_bootoption(char *param, char *val) 250a99cd112SChris Metcalf { 251a99cd112SChris Metcalf repair_env_string(param, val); 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds /* Handle obsolete-style parameters */ 2541da177e4SLinus Torvalds if (obsolete_checksetup(param)) 2551da177e4SLinus Torvalds return 0; 2561da177e4SLinus Torvalds 257f066a4f6SRusty Russell /* Unused module parameter. */ 258f066a4f6SRusty Russell if (strchr(param, '.') && (!val || strchr(param, '.') < val)) 2591da177e4SLinus Torvalds return 0; 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds if (panic_later) 2621da177e4SLinus Torvalds return 0; 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds if (val) { 2651da177e4SLinus Torvalds /* Environment option */ 2661da177e4SLinus Torvalds unsigned int i; 2671da177e4SLinus Torvalds for (i = 0; envp_init[i]; i++) { 2681da177e4SLinus Torvalds if (i == MAX_INIT_ENVS) { 2691da177e4SLinus Torvalds panic_later = "Too many boot env vars at `%s'"; 2701da177e4SLinus Torvalds panic_param = param; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds if (!strncmp(param, envp_init[i], val - param)) 2731da177e4SLinus Torvalds break; 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds envp_init[i] = param; 2761da177e4SLinus Torvalds } else { 2771da177e4SLinus Torvalds /* Command line option */ 2781da177e4SLinus Torvalds unsigned int i; 2791da177e4SLinus Torvalds for (i = 0; argv_init[i]; i++) { 2801da177e4SLinus Torvalds if (i == MAX_INIT_ARGS) { 2811da177e4SLinus Torvalds panic_later = "Too many boot init vars at `%s'"; 2821da177e4SLinus Torvalds panic_param = param; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds } 2851da177e4SLinus Torvalds argv_init[i] = param; 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds return 0; 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds static int __init init_setup(char *str) 2911da177e4SLinus Torvalds { 2921da177e4SLinus Torvalds unsigned int i; 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds execute_command = str; 2951da177e4SLinus Torvalds /* 2961da177e4SLinus Torvalds * In case LILO is going to boot us with default command line, 2971da177e4SLinus Torvalds * it prepends "auto" before the whole cmdline which makes 2981da177e4SLinus Torvalds * the shell think it should execute a script with such name. 2991da177e4SLinus Torvalds * So we ignore all arguments entered _before_ init=... [MJ] 3001da177e4SLinus Torvalds */ 3011da177e4SLinus Torvalds for (i = 1; i < MAX_INIT_ARGS; i++) 3021da177e4SLinus Torvalds argv_init[i] = NULL; 3031da177e4SLinus Torvalds return 1; 3041da177e4SLinus Torvalds } 3051da177e4SLinus Torvalds __setup("init=", init_setup); 3061da177e4SLinus Torvalds 307ffdfc409SOlof Johansson static int __init rdinit_setup(char *str) 308ffdfc409SOlof Johansson { 309ffdfc409SOlof Johansson unsigned int i; 310ffdfc409SOlof Johansson 311ffdfc409SOlof Johansson ramdisk_execute_command = str; 312ffdfc409SOlof Johansson /* See "auto" comment in init_setup */ 313ffdfc409SOlof Johansson for (i = 1; i < MAX_INIT_ARGS; i++) 314ffdfc409SOlof Johansson argv_init[i] = NULL; 315ffdfc409SOlof Johansson return 1; 316ffdfc409SOlof Johansson } 317ffdfc409SOlof Johansson __setup("rdinit=", rdinit_setup); 318ffdfc409SOlof Johansson 3191da177e4SLinus Torvalds #ifndef CONFIG_SMP 32034db18a0SAmerigo Wang static const unsigned int setup_max_cpus = NR_CPUS; 3211da177e4SLinus Torvalds #ifdef CONFIG_X86_LOCAL_APIC 3221da177e4SLinus Torvalds static void __init smp_init(void) 3231da177e4SLinus Torvalds { 3241da177e4SLinus Torvalds APIC_init_uniprocessor(); 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds #else 3271da177e4SLinus Torvalds #define smp_init() do { } while (0) 3281da177e4SLinus Torvalds #endif 3291da177e4SLinus Torvalds 330e0982e90SMike Travis static inline void setup_nr_cpu_ids(void) { } 3311da177e4SLinus Torvalds static inline void smp_prepare_cpus(unsigned int maxcpus) { } 3321da177e4SLinus Torvalds #endif 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds /* 33530d7e0d4SAlon Bar-Lev * We need to store the untouched command line for future reference. 33630d7e0d4SAlon Bar-Lev * We also need to store the touched command line since the parameter 33730d7e0d4SAlon Bar-Lev * parsing is performed in place, and we should allow a component to 33830d7e0d4SAlon Bar-Lev * store reference of name/value for future reference. 33930d7e0d4SAlon Bar-Lev */ 34030d7e0d4SAlon Bar-Lev static void __init setup_command_line(char *command_line) 34130d7e0d4SAlon Bar-Lev { 34230d7e0d4SAlon Bar-Lev saved_command_line = alloc_bootmem(strlen (boot_command_line)+1); 34330d7e0d4SAlon Bar-Lev static_command_line = alloc_bootmem(strlen (command_line)+1); 34430d7e0d4SAlon Bar-Lev strcpy (saved_command_line, boot_command_line); 34530d7e0d4SAlon Bar-Lev strcpy (static_command_line, command_line); 34630d7e0d4SAlon Bar-Lev } 34730d7e0d4SAlon Bar-Lev 34830d7e0d4SAlon Bar-Lev /* 3491da177e4SLinus Torvalds * We need to finalize in a non-__init function or else race conditions 3501da177e4SLinus Torvalds * between the root thread and the init thread may cause start_kernel to 3511da177e4SLinus Torvalds * be reaped by free_initmem before the root thread has proceeded to 3521da177e4SLinus Torvalds * cpu_idle. 3531da177e4SLinus Torvalds * 3541da177e4SLinus Torvalds * gcc-3.4 accidentally inlines this function, so use noinline. 3551da177e4SLinus Torvalds */ 3561da177e4SLinus Torvalds 357b433c3d4SPeter Zijlstra static __initdata DECLARE_COMPLETION(kthreadd_done); 358b433c3d4SPeter Zijlstra 359f99ebf0aSRakib Mullick static noinline void __init_refok rest_init(void) 3601da177e4SLinus Torvalds { 36173c27992SEric W. Biederman int pid; 36273c27992SEric W. Biederman 3637db905e6SPaul E. McKenney rcu_scheduler_starting(); 364b433c3d4SPeter Zijlstra /* 36597158569SPeter Zijlstra * We need to spawn init first so that it obtains pid 1, however 366b433c3d4SPeter Zijlstra * the init task will end up wanting to create kthreads, which, if 367b433c3d4SPeter Zijlstra * we schedule it before we create kthreadd, will OOPS. 368b433c3d4SPeter Zijlstra */ 369aae5f662SSam Ravnborg kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); 3701da177e4SLinus Torvalds numa_default_policy(); 37173c27992SEric W. Biederman pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); 372d11c563dSPaul E. McKenney rcu_read_lock(); 3735cd20455SPavel Emelyanov kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); 374d11c563dSPaul E. McKenney rcu_read_unlock(); 375b433c3d4SPeter Zijlstra complete(&kthreadd_done); 376f340c0d1SIngo Molnar 377f340c0d1SIngo Molnar /* 378f340c0d1SIngo Molnar * The boot idle thread must execute schedule() 3791df21055SIngo Molnar * at least once to get things moving: 380f340c0d1SIngo Molnar */ 3811df21055SIngo Molnar init_idle_bootup_task(current); 382bd2f5536SThomas Gleixner schedule_preempt_disabled(); 3835bfb5d69SNick Piggin /* Call into cpu_idle with preempt disabled */ 3841da177e4SLinus Torvalds cpu_idle(); 3851da177e4SLinus Torvalds } 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds /* Check for early params. */ 3881da177e4SLinus Torvalds static int __init do_early_param(char *param, char *val) 3891da177e4SLinus Torvalds { 390914dcaa8SRusty Russell const struct obs_kernel_param *p; 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds for (p = __setup_start; p < __setup_end; p++) { 393b1e4d20cSMichal Schmidt if ((p->early && parameq(param, p->str)) || 39418a8bd94SYinghai Lu (strcmp(param, "console") == 0 && 39518a8bd94SYinghai Lu strcmp(p->str, "earlycon") == 0) 39618a8bd94SYinghai Lu ) { 3971da177e4SLinus Torvalds if (p->setup_func(val) != 0) 3981da177e4SLinus Torvalds printk(KERN_WARNING 3991da177e4SLinus Torvalds "Malformed early option '%s'\n", param); 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds } 4021da177e4SLinus Torvalds /* We accept everything at this stage. */ 4031da177e4SLinus Torvalds return 0; 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds 40613977091SMagnus Damm void __init parse_early_options(char *cmdline) 40713977091SMagnus Damm { 408026cee00SPawel Moll parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param); 40913977091SMagnus Damm } 41013977091SMagnus Damm 4111da177e4SLinus Torvalds /* Arch code calls this early on, or if not, just before other parsing. */ 4121da177e4SLinus Torvalds void __init parse_early_param(void) 4131da177e4SLinus Torvalds { 4141da177e4SLinus Torvalds static __initdata int done = 0; 4151da177e4SLinus Torvalds static __initdata char tmp_cmdline[COMMAND_LINE_SIZE]; 4161da177e4SLinus Torvalds 4171da177e4SLinus Torvalds if (done) 4181da177e4SLinus Torvalds return; 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds /* All fall through to do_early_param. */ 42130d7e0d4SAlon Bar-Lev strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); 42213977091SMagnus Damm parse_early_options(tmp_cmdline); 4231da177e4SLinus Torvalds done = 1; 4241da177e4SLinus Torvalds } 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds /* 4271da177e4SLinus Torvalds * Activate the first processor. 4281da177e4SLinus Torvalds */ 4291da177e4SLinus Torvalds 43044fd2299SStas Sergeev static void __init boot_cpu_init(void) 43144fd2299SStas Sergeev { 43244fd2299SStas Sergeev int cpu = smp_processor_id(); 43344fd2299SStas Sergeev /* Mark the boot cpu "present", "online" etc for SMP and UP case */ 434915441b6SRusty Russell set_cpu_online(cpu, true); 435933b0618SPeter Zijlstra set_cpu_active(cpu, true); 436915441b6SRusty Russell set_cpu_present(cpu, true); 437915441b6SRusty Russell set_cpu_possible(cpu, true); 43844fd2299SStas Sergeev } 43944fd2299SStas Sergeev 440839ad62eSBenjamin Herrenschmidt void __init __weak smp_setup_processor_id(void) 441033ab7f8SAndrew Morton { 442033ab7f8SAndrew Morton } 443033ab7f8SAndrew Morton 4448c9843e5SBenjamin Herrenschmidt void __init __weak thread_info_cache_init(void) 4458c9843e5SBenjamin Herrenschmidt { 4468c9843e5SBenjamin Herrenschmidt } 4478c9843e5SBenjamin Herrenschmidt 448444f478fSPekka Enberg /* 449444f478fSPekka Enberg * Set up kernel memory allocators 450444f478fSPekka Enberg */ 451444f478fSPekka Enberg static void __init mm_init(void) 452444f478fSPekka Enberg { 453ca371c0dSKAMEZAWA Hiroyuki /* 4547fa87ce7SJim Cromie * page_cgroup requires contiguous pages, 4557fa87ce7SJim Cromie * bigger than MAX_ORDER unless SPARSEMEM. 456ca371c0dSKAMEZAWA Hiroyuki */ 457ca371c0dSKAMEZAWA Hiroyuki page_cgroup_init_flatmem(); 458444f478fSPekka Enberg mem_init(); 459444f478fSPekka Enberg kmem_cache_init(); 460099a19d9STejun Heo percpu_init_late(); 461c868d550SBenjamin Herrenschmidt pgtable_cache_init(); 462444f478fSPekka Enberg vmalloc_init(); 463444f478fSPekka Enberg } 464444f478fSPekka Enberg 4651da177e4SLinus Torvalds asmlinkage void __init start_kernel(void) 4661da177e4SLinus Torvalds { 4671da177e4SLinus Torvalds char * command_line; 468914dcaa8SRusty Russell extern const struct kernel_param __start___param[], __stop___param[]; 469033ab7f8SAndrew Morton 4701da177e4SLinus Torvalds /* 471fbb9ce95SIngo Molnar * Need to run as early as possible, to initialize the 472fbb9ce95SIngo Molnar * lockdep hash: 473fbb9ce95SIngo Molnar */ 474fbb9ce95SIngo Molnar lockdep_init(); 47573839c5bSMing Lei smp_setup_processor_id(); 4763ac7fe5aSThomas Gleixner debug_objects_early_init(); 47742059429SIngo Molnar 47842059429SIngo Molnar /* 47942059429SIngo Molnar * Set up the the initial canary ASAP: 48042059429SIngo Molnar */ 48142059429SIngo Molnar boot_init_stack_canary(); 48242059429SIngo Molnar 483ddbcc7e8SPaul Menage cgroup_init_early(); 484fbb9ce95SIngo Molnar 485fbb9ce95SIngo Molnar local_irq_disable(); 4862ce802f6STejun Heo early_boot_irqs_disabled = true; 487fbb9ce95SIngo Molnar 488fbb9ce95SIngo Molnar /* 4891da177e4SLinus Torvalds * Interrupts are still disabled. Do necessary setups, then 4901da177e4SLinus Torvalds * enable them 4911da177e4SLinus Torvalds */ 492906568c9SThomas Gleixner tick_init(); 49344fd2299SStas Sergeev boot_cpu_init(); 4941da177e4SLinus Torvalds page_address_init(); 495657cafa6SAlex Riesen printk(KERN_NOTICE "%s", linux_banner); 4961da177e4SLinus Torvalds setup_arch(&command_line); 497cf475ad2SBalbir Singh mm_init_owner(&init_mm, &init_task); 4986345d24dSLinus Torvalds mm_init_cpumask(&init_mm); 49930d7e0d4SAlon Bar-Lev setup_command_line(command_line); 500e0982e90SMike Travis setup_nr_cpu_ids(); 501d6647bdfSTejun Heo setup_per_cpu_areas(); 50244fd2299SStas Sergeev smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ 5031da177e4SLinus Torvalds 5041f522509SHaicheng Li build_all_zonelists(NULL); 50583b519e8SPekka Enberg page_alloc_init(); 50683b519e8SPekka Enberg 50783b519e8SPekka Enberg printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line); 50883b519e8SPekka Enberg parse_early_param(); 50983b519e8SPekka Enberg parse_args("Booting kernel", static_command_line, __start___param, 51083b519e8SPekka Enberg __stop___param - __start___param, 511026cee00SPawel Moll 0, 0, &unknown_bootoption); 51297ce2c88SJeremy Fitzhardinge 51397ce2c88SJeremy Fitzhardinge jump_label_init(); 51497ce2c88SJeremy Fitzhardinge 51583b519e8SPekka Enberg /* 51683b519e8SPekka Enberg * These use large bootmem allocations and must precede 51783b519e8SPekka Enberg * kmem_cache_init() 51883b519e8SPekka Enberg */ 519162a7e75SMike Travis setup_log_buf(0); 52083b519e8SPekka Enberg pidhash_init(); 52183b519e8SPekka Enberg vfs_caches_init_early(); 52283b519e8SPekka Enberg sort_main_extable(); 52383b519e8SPekka Enberg trap_init(); 524444f478fSPekka Enberg mm_init(); 525de03c72cSKOSAKI Motohiro 5261da177e4SLinus Torvalds /* 5271da177e4SLinus Torvalds * Set up the scheduler prior starting any interrupts (such as the 5281da177e4SLinus Torvalds * timer interrupt). Full topology setup happens at smp_init() 5291da177e4SLinus Torvalds * time - but meanwhile we still have a functioning scheduler. 5301da177e4SLinus Torvalds */ 5311da177e4SLinus Torvalds sched_init(); 5321da177e4SLinus Torvalds /* 5331da177e4SLinus Torvalds * Disable preemption - early bootup scheduling is extremely 5341da177e4SLinus Torvalds * fragile until we cpu_idle() for the first time. 5351da177e4SLinus Torvalds */ 5361da177e4SLinus Torvalds preempt_disable(); 537c4a68306SArd van Breemen if (!irqs_disabled()) { 538c4a68306SArd van Breemen printk(KERN_WARNING "start_kernel(): bug: interrupts were " 539c4a68306SArd van Breemen "enabled *very* early, fixing it\n"); 540c4a68306SArd van Breemen local_irq_disable(); 541c4a68306SArd van Breemen } 5429f58a205SPeter Zijlstra idr_init_cache(); 54324a24bb6SPeter Zijlstra perf_event_init(); 5441da177e4SLinus Torvalds rcu_init(); 545773e3eb7SYinghai Lu radix_tree_init(); 5460b8f1efaSYinghai Lu /* init some links before init_ISA_irqs() */ 5470b8f1efaSYinghai Lu early_irq_init(); 5481da177e4SLinus Torvalds init_IRQ(); 5493c7b4e6bSCatalin Marinas prio_tree_init(); 5501da177e4SLinus Torvalds init_timers(); 551c0a31329SThomas Gleixner hrtimers_init(); 5521da177e4SLinus Torvalds softirq_init(); 553ad596171Sjohn stultz timekeeping_init(); 55488fecaa2Sjohn stultz time_init(); 55593e02814SHeiko Carstens profile_init(); 556d8ad7d11STakao Indoh call_function_init(); 55793e02814SHeiko Carstens if (!irqs_disabled()) 55824d431d0SRon Lee printk(KERN_CRIT "start_kernel(): bug: interrupts were " 55924d431d0SRon Lee "enabled early\n"); 5602ce802f6STejun Heo early_boot_irqs_disabled = false; 56193e02814SHeiko Carstens local_irq_enable(); 562dcce284aSBenjamin Herrenschmidt 5637e85ee0cSPekka Enberg kmem_cache_init_late(); 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds /* 5661da177e4SLinus Torvalds * HACK ALERT! This is early. We're enabling the console before 5671da177e4SLinus Torvalds * we've done PCI setups etc, and console_init() must be aware of 5681da177e4SLinus Torvalds * this. But we do want output early, in case something goes wrong. 5691da177e4SLinus Torvalds */ 5701da177e4SLinus Torvalds console_init(); 5711da177e4SLinus Torvalds if (panic_later) 5721da177e4SLinus Torvalds panic(panic_later, panic_param); 573fbb9ce95SIngo Molnar 574fbb9ce95SIngo Molnar lockdep_info(); 575fbb9ce95SIngo Molnar 5769a11b49aSIngo Molnar /* 5779a11b49aSIngo Molnar * Need to run this when irqs are enabled, because it wants 5789a11b49aSIngo Molnar * to self-test [hard/soft]-irqs on/off lock inversion bugs 5799a11b49aSIngo Molnar * too: 5809a11b49aSIngo Molnar */ 5819a11b49aSIngo Molnar locking_selftest(); 5829a11b49aSIngo Molnar 5831da177e4SLinus Torvalds #ifdef CONFIG_BLK_DEV_INITRD 5841da177e4SLinus Torvalds if (initrd_start && !initrd_below_start_ok && 585bd673c7cSGeert Uytterhoeven page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { 5861da177e4SLinus Torvalds printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - " 587fb6624ebSGeert Uytterhoeven "disabling it.\n", 588bd673c7cSGeert Uytterhoeven page_to_pfn(virt_to_page((void *)initrd_start)), 589bd673c7cSGeert Uytterhoeven min_low_pfn); 5901da177e4SLinus Torvalds initrd_start = 0; 5911da177e4SLinus Torvalds } 5921da177e4SLinus Torvalds #endif 59394b6da5aSKAMEZAWA Hiroyuki page_cgroup_init(); 5943ac7fe5aSThomas Gleixner debug_objects_mem_init(); 5959b090f2dSCatalin Marinas kmemleak_init(); 596e7c8d5c9SChristoph Lameter setup_per_cpu_pageset(); 5971da177e4SLinus Torvalds numa_policy_init(); 5981da177e4SLinus Torvalds if (late_time_init) 5991da177e4SLinus Torvalds late_time_init(); 600fa84e9eeSThomas Gleixner sched_clock_init(); 6011da177e4SLinus Torvalds calibrate_delay(); 6021da177e4SLinus Torvalds pidmap_init(); 6031da177e4SLinus Torvalds anon_vma_init(); 6041da177e4SLinus Torvalds #ifdef CONFIG_X86 6051da177e4SLinus Torvalds if (efi_enabled) 6061da177e4SLinus Torvalds efi_enter_virtual_mode(); 6071da177e4SLinus Torvalds #endif 6088c9843e5SBenjamin Herrenschmidt thread_info_cache_init(); 609d84f4f99SDavid Howells cred_init(); 6104481374cSJan Beulich fork_init(totalram_pages); 6111da177e4SLinus Torvalds proc_caches_init(); 6121da177e4SLinus Torvalds buffer_init(); 6131da177e4SLinus Torvalds key_init(); 6141da177e4SLinus Torvalds security_init(); 6150b4b3827SJason Wessel dbg_late_init(); 6164481374cSJan Beulich vfs_caches_init(totalram_pages); 6171da177e4SLinus Torvalds signals_init(); 6181da177e4SLinus Torvalds /* rootfs populating might need page-writeback */ 6191da177e4SLinus Torvalds page_writeback_init(); 6201da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS 6211da177e4SLinus Torvalds proc_root_init(); 6221da177e4SLinus Torvalds #endif 623ddbcc7e8SPaul Menage cgroup_init(); 6241da177e4SLinus Torvalds cpuset_init(); 625c757249aSShailabh Nagar taskstats_init_early(); 626ca74e92bSShailabh Nagar delayacct_init(); 6271da177e4SLinus Torvalds 6281da177e4SLinus Torvalds check_bugs(); 6291da177e4SLinus Torvalds 6301da177e4SLinus Torvalds acpi_early_init(); /* before LAPIC and SMP init */ 6316ae6996aSFeng Tang sfi_init_late(); 6321da177e4SLinus Torvalds 63368bf21aaSSteven Rostedt ftrace_init(); 63468bf21aaSSteven Rostedt 6351da177e4SLinus Torvalds /* Do the rest non-__init'ed, we're now alive */ 6361da177e4SLinus Torvalds rest_init(); 6371da177e4SLinus Torvalds } 6381da177e4SLinus Torvalds 639b99b87f7SPeter Oberparleiter /* Call all constructor functions linked into the kernel. */ 640b99b87f7SPeter Oberparleiter static void __init do_ctors(void) 641b99b87f7SPeter Oberparleiter { 642b99b87f7SPeter Oberparleiter #ifdef CONFIG_CONSTRUCTORS 643196a15b4SH Hartley Sweeten ctor_fn_t *fn = (ctor_fn_t *) __ctors_start; 644b99b87f7SPeter Oberparleiter 645196a15b4SH Hartley Sweeten for (; fn < (ctor_fn_t *) __ctors_end; fn++) 646196a15b4SH Hartley Sweeten (*fn)(); 647b99b87f7SPeter Oberparleiter #endif 648b99b87f7SPeter Oberparleiter } 649b99b87f7SPeter Oberparleiter 6502329abfaSRusty Russell bool initcall_debug; 651d0ea3d7dSRusty Russell core_param(initcall_debug, initcall_debug, bool, 0644); 6521da177e4SLinus Torvalds 6534a683bf9SIngo Molnar static char msgbuf[64]; 6544a683bf9SIngo Molnar 655e4461271SKevin Winchester static int __init_or_module do_one_initcall_debug(initcall_t fn) 6561da177e4SLinus Torvalds { 65774239072SFrederic Weisbecker ktime_t calltime, delta, rettime; 65830dbb20eSAmérico Wang unsigned long long duration; 65930dbb20eSAmérico Wang int ret; 6601da177e4SLinus Torvalds 66122c5c03bSKevin Winchester printk(KERN_DEBUG "calling %pF @ %i\n", fn, task_pid_nr(current)); 66274239072SFrederic Weisbecker calltime = ktime_get(); 66330dbb20eSAmérico Wang ret = fn(); 66474239072SFrederic Weisbecker rettime = ktime_get(); 66574239072SFrederic Weisbecker delta = ktime_sub(rettime, calltime); 66630dbb20eSAmérico Wang duration = (unsigned long long) ktime_to_ns(delta) >> 10; 66722c5c03bSKevin Winchester printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n", fn, 66830dbb20eSAmérico Wang ret, duration); 66922c5c03bSKevin Winchester 67022c5c03bSKevin Winchester return ret; 6718f0c45cdSIngo Molnar } 6728f0c45cdSIngo Molnar 673e4461271SKevin Winchester int __init_or_module do_one_initcall(initcall_t fn) 67422c5c03bSKevin Winchester { 67522c5c03bSKevin Winchester int count = preempt_count(); 67622c5c03bSKevin Winchester int ret; 67722c5c03bSKevin Winchester 67822c5c03bSKevin Winchester if (initcall_debug) 67922c5c03bSKevin Winchester ret = do_one_initcall_debug(fn); 68022c5c03bSKevin Winchester else 68122c5c03bSKevin Winchester ret = fn(); 68222c5c03bSKevin Winchester 683e662e1cfSCyrill Gorcunov msgbuf[0] = 0; 684e662e1cfSCyrill Gorcunov 68530dbb20eSAmérico Wang if (ret && ret != -ENODEV && initcall_debug) 68630dbb20eSAmérico Wang sprintf(msgbuf, "error code %d ", ret); 687e662e1cfSCyrill Gorcunov 6881da177e4SLinus Torvalds if (preempt_count() != count) { 689a76bfd0dSCyrill Gorcunov strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); 6901da177e4SLinus Torvalds preempt_count() = count; 6911da177e4SLinus Torvalds } 6921da177e4SLinus Torvalds if (irqs_disabled()) { 693a76bfd0dSCyrill Gorcunov strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); 6941da177e4SLinus Torvalds local_irq_enable(); 6951da177e4SLinus Torvalds } 696e662e1cfSCyrill Gorcunov if (msgbuf[0]) { 69796d746c6SLinus Torvalds printk("initcall %pF returned with %s\n", fn, msgbuf); 6981da177e4SLinus Torvalds } 69959f9415fSArjan van de Ven 70030dbb20eSAmérico Wang return ret; 7011da177e4SLinus Torvalds } 7021da177e4SLinus Torvalds 703e0df154fSLinus Torvalds 704026cee00SPawel Moll extern initcall_t __initcall_start[]; 705026cee00SPawel Moll extern initcall_t __initcall0_start[]; 706026cee00SPawel Moll extern initcall_t __initcall1_start[]; 707026cee00SPawel Moll extern initcall_t __initcall2_start[]; 708026cee00SPawel Moll extern initcall_t __initcall3_start[]; 709026cee00SPawel Moll extern initcall_t __initcall4_start[]; 710026cee00SPawel Moll extern initcall_t __initcall5_start[]; 711026cee00SPawel Moll extern initcall_t __initcall6_start[]; 712026cee00SPawel Moll extern initcall_t __initcall7_start[]; 713026cee00SPawel Moll extern initcall_t __initcall_end[]; 714026cee00SPawel Moll 715026cee00SPawel Moll static initcall_t *initcall_levels[] __initdata = { 716026cee00SPawel Moll __initcall0_start, 717026cee00SPawel Moll __initcall1_start, 718026cee00SPawel Moll __initcall2_start, 719026cee00SPawel Moll __initcall3_start, 720026cee00SPawel Moll __initcall4_start, 721026cee00SPawel Moll __initcall5_start, 722026cee00SPawel Moll __initcall6_start, 723026cee00SPawel Moll __initcall7_start, 724026cee00SPawel Moll __initcall_end, 725026cee00SPawel Moll }; 726026cee00SPawel Moll 727026cee00SPawel Moll static char *initcall_level_names[] __initdata = { 728026cee00SPawel Moll "early parameters", 729026cee00SPawel Moll "core parameters", 730026cee00SPawel Moll "postcore parameters", 731026cee00SPawel Moll "arch parameters", 732026cee00SPawel Moll "subsys parameters", 733026cee00SPawel Moll "fs parameters", 734026cee00SPawel Moll "device parameters", 735026cee00SPawel Moll "late parameters", 736026cee00SPawel Moll }; 737026cee00SPawel Moll 738026cee00SPawel Moll static void __init do_initcall_level(int level) 739026cee00SPawel Moll { 740026cee00SPawel Moll extern const struct kernel_param __start___param[], __stop___param[]; 741026cee00SPawel Moll initcall_t *fn; 742026cee00SPawel Moll 743026cee00SPawel Moll strcpy(static_command_line, saved_command_line); 744026cee00SPawel Moll parse_args(initcall_level_names[level], 745026cee00SPawel Moll static_command_line, __start___param, 746026cee00SPawel Moll __stop___param - __start___param, 747026cee00SPawel Moll level, level, 748a99cd112SChris Metcalf repair_env_string); 749026cee00SPawel Moll 750026cee00SPawel Moll for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) 751026cee00SPawel Moll do_one_initcall(*fn); 752026cee00SPawel Moll } 753e0df154fSLinus Torvalds 754e0df154fSLinus Torvalds static void __init do_initcalls(void) 755e0df154fSLinus Torvalds { 756026cee00SPawel Moll int level; 757e0df154fSLinus Torvalds 758026cee00SPawel Moll for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) 759026cee00SPawel Moll do_initcall_level(level); 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds /* 7631da177e4SLinus Torvalds * Ok, the machine is now initialized. None of the devices 7641da177e4SLinus Torvalds * have been touched yet, but the CPU subsystem is up and 7651da177e4SLinus Torvalds * running, and memory and process management works. 7661da177e4SLinus Torvalds * 7671da177e4SLinus Torvalds * Now we can finally start doing some real work.. 7681da177e4SLinus Torvalds */ 7691da177e4SLinus Torvalds static void __init do_basic_setup(void) 7701da177e4SLinus Torvalds { 771759ee091SLai Jiangshan cpuset_init_smp(); 7721da177e4SLinus Torvalds usermodehelper_init(); 77341ffe5d5SHugh Dickins shmem_init(); 7741da177e4SLinus Torvalds driver_init(); 775b04c3afbSEric W. Biederman init_irq_proc(); 776b99b87f7SPeter Oberparleiter do_ctors(); 777d5767c53SLinus Torvalds usermodehelper_enable(); 778b0f84374Swangyanqing do_initcalls(); 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds 7817babe8dbSEduard - Gabriel Munteanu static void __init do_pre_smp_initcalls(void) 782c2147a50SEduard - Gabriel Munteanu { 783196a15b4SH Hartley Sweeten initcall_t *fn; 784c2147a50SEduard - Gabriel Munteanu 785026cee00SPawel Moll for (fn = __initcall_start; fn < __initcall0_start; fn++) 786196a15b4SH Hartley Sweeten do_one_initcall(*fn); 787c2147a50SEduard - Gabriel Munteanu } 788c2147a50SEduard - Gabriel Munteanu 789d7627467SDavid Howells static void run_init_process(const char *init_filename) 7901da177e4SLinus Torvalds { 7911da177e4SLinus Torvalds argv_init[0] = init_filename; 79267608567SArnd Bergmann kernel_execve(init_filename, argv_init, envp_init); 7931da177e4SLinus Torvalds } 7941da177e4SLinus Torvalds 795ee5bfa64SVivek Goyal /* This is a non __init function. Force it to be noinline otherwise gcc 796ee5bfa64SVivek Goyal * makes it inline to init() and it becomes part of init.text section 797ee5bfa64SVivek Goyal */ 798f99ebf0aSRakib Mullick static noinline int init_post(void) 799ee5bfa64SVivek Goyal { 80022a9d645SArjan van de Ven /* need to finish all async __init code before freeing the memory */ 80122a9d645SArjan van de Ven async_synchronize_full(); 802ee5bfa64SVivek Goyal free_initmem(); 803ee5bfa64SVivek Goyal mark_rodata_ro(); 804ee5bfa64SVivek Goyal system_state = SYSTEM_RUNNING; 805ee5bfa64SVivek Goyal numa_default_policy(); 806ee5bfa64SVivek Goyal 807ee5bfa64SVivek Goyal 808fae5fa44SOleg Nesterov current->signal->flags |= SIGNAL_UNKILLABLE; 809fae5fa44SOleg Nesterov 810ee5bfa64SVivek Goyal if (ramdisk_execute_command) { 811ee5bfa64SVivek Goyal run_init_process(ramdisk_execute_command); 812ee5bfa64SVivek Goyal printk(KERN_WARNING "Failed to execute %s\n", 813ee5bfa64SVivek Goyal ramdisk_execute_command); 814ee5bfa64SVivek Goyal } 815ee5bfa64SVivek Goyal 816ee5bfa64SVivek Goyal /* 817ee5bfa64SVivek Goyal * We try each of these until one succeeds. 818ee5bfa64SVivek Goyal * 819ee5bfa64SVivek Goyal * The Bourne shell can be used instead of init if we are 820ee5bfa64SVivek Goyal * trying to recover a really broken machine. 821ee5bfa64SVivek Goyal */ 822ee5bfa64SVivek Goyal if (execute_command) { 823ee5bfa64SVivek Goyal run_init_process(execute_command); 824ee5bfa64SVivek Goyal printk(KERN_WARNING "Failed to execute %s. Attempting " 825ee5bfa64SVivek Goyal "defaults...\n", execute_command); 826ee5bfa64SVivek Goyal } 827ee5bfa64SVivek Goyal run_init_process("/sbin/init"); 828ee5bfa64SVivek Goyal run_init_process("/etc/init"); 829ee5bfa64SVivek Goyal run_init_process("/bin/init"); 830ee5bfa64SVivek Goyal run_init_process("/bin/sh"); 831ee5bfa64SVivek Goyal 8329a85b8d6SAndreas Mohr panic("No init found. Try passing init= option to kernel. " 8339a85b8d6SAndreas Mohr "See Linux Documentation/init.txt for guidance."); 834ee5bfa64SVivek Goyal } 835ee5bfa64SVivek Goyal 836aae5f662SSam Ravnborg static int __init kernel_init(void * unused) 8371da177e4SLinus Torvalds { 838b433c3d4SPeter Zijlstra /* 839b433c3d4SPeter Zijlstra * Wait until kthreadd is all set-up. 840b433c3d4SPeter Zijlstra */ 841b433c3d4SPeter Zijlstra wait_for_completion(&kthreadd_done); 842*31a67102SLinus Torvalds 843*31a67102SLinus Torvalds /* Now the scheduler is fully set up and can do blocking allocations */ 844*31a67102SLinus Torvalds gfp_allowed_mask = __GFP_BITS_MASK; 845*31a67102SLinus Torvalds 84658568d2aSMiao Xie /* 84758568d2aSMiao Xie * init can allocate pages on any node 84858568d2aSMiao Xie */ 8495ab116c9SMiao Xie set_mems_allowed(node_states[N_HIGH_MEMORY]); 8501da177e4SLinus Torvalds /* 8511da177e4SLinus Torvalds * init can run on any cpu. 8521da177e4SLinus Torvalds */ 8531a2142afSRusty Russell set_cpus_allowed_ptr(current, cpu_all_mask); 8541da177e4SLinus Torvalds 8559ec52099SCedric Le Goater cad_pid = task_pid(current); 8569ec52099SCedric Le Goater 857ca74a6f8SAndi Kleen smp_prepare_cpus(setup_max_cpus); 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds do_pre_smp_initcalls(); 860004417a6SPeter Zijlstra lockup_detector_init(); 8611da177e4SLinus Torvalds 8621da177e4SLinus Torvalds smp_init(); 8631da177e4SLinus Torvalds sched_init_smp(); 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvalds do_basic_setup(); 8661da177e4SLinus Torvalds 8672bd3a997SEric W. Biederman /* Open the /dev/console on the rootfs, this should never fail */ 8682bd3a997SEric W. Biederman if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) 8692bd3a997SEric W. Biederman printk(KERN_WARNING "Warning: unable to open an initial console.\n"); 8702bd3a997SEric W. Biederman 8712bd3a997SEric W. Biederman (void) sys_dup(0); 8722bd3a997SEric W. Biederman (void) sys_dup(0); 8731da177e4SLinus Torvalds /* 8741da177e4SLinus Torvalds * check if there is an early userspace init. If yes, let it do all 8751da177e4SLinus Torvalds * the work 8761da177e4SLinus Torvalds */ 877ffdfc409SOlof Johansson 878ffdfc409SOlof Johansson if (!ramdisk_execute_command) 879ffdfc409SOlof Johansson ramdisk_execute_command = "/init"; 880ffdfc409SOlof Johansson 881ffdfc409SOlof Johansson if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { 882ffdfc409SOlof Johansson ramdisk_execute_command = NULL; 8831da177e4SLinus Torvalds prepare_namespace(); 884ffdfc409SOlof Johansson } 8851da177e4SLinus Torvalds 8861da177e4SLinus Torvalds /* 8871da177e4SLinus Torvalds * Ok, we have completed the initial bootup, and 8881da177e4SLinus Torvalds * we're essentially up and running. Get rid of the 8891da177e4SLinus Torvalds * initmem segments and start the user-mode stuff.. 8901da177e4SLinus Torvalds */ 89171566a0dSFrederic Weisbecker 892ee5bfa64SVivek Goyal init_post(); 893ee5bfa64SVivek Goyal return 0; 8941da177e4SLinus Torvalds } 895