[ROSE]: Socket locking is a great invention.
[powerpc.git] / init / main.c
index bc27d72..a92989e 100644 (file)
@@ -40,6 +40,8 @@
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
 #include <linux/efi.h>
+#include <linux/tick.h>
+#include <linux/interrupt.h>
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
 #include <linux/unistd.h>
@@ -50,9 +52,7 @@
 #include <linux/buffer_head.h>
 #include <linux/debug_locks.h>
 #include <linux/lockdep.h>
-#include <linux/utsrelease.h>
 #include <linux/pid_namespace.h>
-#include <linux/compile.h>
 #include <linux/device.h>
 
 #include <asm/io.h>
@@ -88,7 +88,6 @@ extern void init_IRQ(void);
 extern void fork_init(unsigned long);
 extern void mca_init(void);
 extern void sbus_init(void);
-extern void sysctl_init(void);
 extern void signals_init(void);
 extern void pidhash_init(void);
 extern void pidmap_init(void);
@@ -123,8 +122,12 @@ extern void time_init(void);
 void (*late_time_init)(void);
 extern void softirq_init(void);
 
-/* Untouched command line (eg. for /proc) saved by arch-specific code. */
-char saved_command_line[COMMAND_LINE_SIZE];
+/* Untouched command line saved by arch-specific code. */
+char __initdata boot_command_line[COMMAND_LINE_SIZE];
+/* Untouched saved command line (eg. for /proc) */
+char *saved_command_line;
+/* Command line for parameter parsing */
+static char *static_command_line;
 
 static char *execute_command;
 static char *ramdisk_execute_command;
@@ -384,28 +387,42 @@ static void __init setup_per_cpu_areas(void)
 /* Called by boot processor to activate the rest. */
 static void __init smp_init(void)
 {
-       unsigned int i;
+       unsigned int cpu;
+       unsigned highest = 0;
+
+       for_each_cpu_mask(cpu, cpu_possible_map)
+               highest = cpu;
+       nr_cpu_ids = highest + 1;
 
        /* FIXME: This should be done in userspace --RR */
-       for_each_present_cpu(i) {
+       for_each_present_cpu(cpu) {
                if (num_online_cpus() >= max_cpus)
                        break;
-               if (!cpu_online(i))
-                       cpu_up(i);
+               if (!cpu_online(cpu))
+                       cpu_up(cpu);
        }
 
        /* Any cleanup work */
        printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
        smp_cpus_done(max_cpus);
-#if 0
-       /* Get other processors into their bootup holding patterns. */
-
-       smp_commence();
-#endif
 }
 
 #endif
 
+/*
+ * We need to store the untouched command line for future reference.
+ * We also need to store the touched command line since the parameter
+ * parsing is performed in place, and we should allow a component to
+ * store reference of name/value for future reference.
+ */
+static void __init setup_command_line(char *command_line)
+{
+       saved_command_line = alloc_bootmem(strlen (boot_command_line)+1);
+       static_command_line = alloc_bootmem(strlen (command_line)+1);
+       strcpy (saved_command_line, boot_command_line);
+       strcpy (static_command_line, command_line);
+}
+
 /*
  * We need to finalize in a non-__init function or else race conditions
  * between the root thread and the init thread may cause start_kernel to
@@ -460,7 +477,7 @@ void __init parse_early_param(void)
                return;
 
        /* All fall through to do_early_param. */
-       strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE);
+       strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
        parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
        done = 1;
 }
@@ -482,12 +499,6 @@ void __init __attribute__((weak)) smp_setup_processor_id(void)
 {
 }
 
-static const char linux_banner[] =
-       "Linux version " UTS_RELEASE
-       " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
-       " (" LINUX_COMPILER ")"
-       " " UTS_VERSION "\n";
-
 asmlinkage void __init start_kernel(void)
 {
        char * command_line;
@@ -511,11 +522,13 @@ asmlinkage void __init start_kernel(void)
  * enable them
  */
        lock_kernel();
+       tick_init();
        boot_cpu_init();
        page_address_init();
        printk(KERN_NOTICE);
        printk(linux_banner);
        setup_arch(&command_line);
+       setup_command_line(command_line);
        unwind_setup();
        setup_per_cpu_areas();
        smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
@@ -533,9 +546,9 @@ asmlinkage void __init start_kernel(void)
        preempt_disable();
        build_all_zonelists();
        page_alloc_init();
-       printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);
+       printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
        parse_early_param();
-       parse_args("Booting kernel", command_line, __start___param,
+       parse_args("Booting kernel", static_command_line, __start___param,
                   __stop___param - __start___param,
                   &unknown_bootoption);
        if (!irqs_disabled()) {
@@ -695,15 +708,11 @@ static void __init do_basic_setup(void)
        init_workqueues();
        usermodehelper_init();
        driver_init();
-
-#ifdef CONFIG_SYSCTL
-       sysctl_init();
-#endif
-
+       init_irq_proc();
        do_initcalls();
 }
 
-static void do_pre_smp_initcalls(void)
+static void __init do_pre_smp_initcalls(void)
 {
        extern int spawn_ksoftirqd(void);
 #ifdef CONFIG_SMP
@@ -721,7 +730,49 @@ static void run_init_process(char *init_filename)
        kernel_execve(init_filename, argv_init, envp_init);
 }
 
-static int init(void * unused)
+/* This is a non __init function. Force it to be noinline otherwise gcc
+ * makes it inline to init() and it becomes part of init.text section
+ */
+static int noinline init_post(void)
+{
+       free_initmem();
+       unlock_kernel();
+       mark_rodata_ro();
+       system_state = SYSTEM_RUNNING;
+       numa_default_policy();
+
+       if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
+               printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+
+       (void) sys_dup(0);
+       (void) sys_dup(0);
+
+       if (ramdisk_execute_command) {
+               run_init_process(ramdisk_execute_command);
+               printk(KERN_WARNING "Failed to execute %s\n",
+                               ramdisk_execute_command);
+       }
+
+       /*
+        * We try each of these until one succeeds.
+        *
+        * The Bourne shell can be used instead of init if we are
+        * trying to recover a really broken machine.
+        */
+       if (execute_command) {
+               run_init_process(execute_command);
+               printk(KERN_WARNING "Failed to execute %s.  Attempting "
+                                       "defaults...\n", execute_command);
+       }
+       run_init_process("/sbin/init");
+       run_init_process("/etc/init");
+       run_init_process("/bin/init");
+       run_init_process("/bin/sh");
+
+       panic("No init found.  Try passing init= option to kernel.");
+}
+
+static int __init init(void * unused)
 {
        lock_kernel();
        /*
@@ -769,39 +820,6 @@ static int init(void * unused)
         * we're essentially up and running. Get rid of the
         * initmem segments and start the user-mode stuff..
         */
-       free_initmem();
-       unlock_kernel();
-       mark_rodata_ro();
-       system_state = SYSTEM_RUNNING;
-       numa_default_policy();
-
-       if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-               printk(KERN_WARNING "Warning: unable to open an initial console.\n");
-
-       (void) sys_dup(0);
-       (void) sys_dup(0);
-
-       if (ramdisk_execute_command) {
-               run_init_process(ramdisk_execute_command);
-               printk(KERN_WARNING "Failed to execute %s\n",
-                               ramdisk_execute_command);
-       }
-
-       /*
-        * We try each of these until one succeeds.
-        *
-        * The Bourne shell can be used instead of init if we are 
-        * trying to recover a really broken machine.
-        */
-       if (execute_command) {
-               run_init_process(execute_command);
-               printk(KERN_WARNING "Failed to execute %s.  Attempting "
-                                       "defaults...\n", execute_command);
-       }
-       run_init_process("/sbin/init");
-       run_init_process("/etc/init");
-       run_init_process("/bin/init");
-       run_init_process("/bin/sh");
-
-       panic("No init found.  Try passing init= option to kernel.");
+       init_post();
+       return 0;
 }