]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/i386/kernel/smpboot.c
Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
[linux-2.6-omap-h63xx.git] / arch / i386 / kernel / smpboot.c
index 02a9b66b6ac38ae95aa199e8d91e7576d10daeba..4bf0e3c83b8b3244536eb54a02d4d087c0b15cab 100644 (file)
  *             Dave Jones      :       Report invalid combinations of Athlon CPUs.
 *              Rusty Russell   :       Hacked into shape for new "hotplug" boot process. */
 
+
+/* SMP boot always wants to use real time delay to allow sufficient time for
+ * the APs to come online */
+#define USE_REAL_TIME_DELAY
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -52,6 +57,8 @@
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 #include <asm/nmi.h>
+#include <asm/pda.h>
+#include <asm/genapic.h>
 
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
@@ -536,11 +543,11 @@ set_cpu_sibling_map(int cpu)
 static void __devinit start_secondary(void *unused)
 {
        /*
-        * Dont put anything before smp_callin(), SMP
+        * Don't put *anything* before secondary_cpu_init(), SMP
         * booting is too fragile that we want to limit the
         * things done here to the most necessary things.
         */
-       cpu_init();
+       secondary_cpu_init();
        preempt_disable();
        smp_callin();
        while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
@@ -599,13 +606,16 @@ void __devinit initialize_secondary(void)
                "movl %0,%%esp\n\t"
                "jmp *%1"
                :
-               :"r" (current->thread.esp),"r" (current->thread.eip));
+               :"m" (current->thread.esp),"m" (current->thread.eip));
 }
 
+/* Static state in head.S used to set up a CPU */
 extern struct {
        void * esp;
        unsigned short ss;
 } stack_start;
+extern struct i386_pda *start_pda;
+extern struct Xgt_desc_struct cpu_gdt_descr;
 
 #ifdef CONFIG_NUMA
 
@@ -936,9 +946,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
        unsigned long start_eip;
        unsigned short nmi_high = 0, nmi_low = 0;
 
-       ++cpucount;
-       alternatives_smp_switch(1);
-
        /*
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
@@ -946,15 +953,30 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
        idle = alloc_idle_task(cpu);
        if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
+
+       /* Pre-allocate and initialize the CPU's GDT and PDA so it
+          doesn't have to do any memory allocation during the
+          delicate CPU-bringup phase. */
+       if (!init_gdt(cpu, idle)) {
+               printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu);
+               return -1;      /* ? */
+       }
+
        idle->thread.eip = (unsigned long) start_secondary;
        /* start_eip had better be page-aligned! */
        start_eip = setup_trampoline();
 
+       ++cpucount;
+       alternatives_smp_switch(1);
+
        /* So we see what's up   */
        printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
        /* Stack for startup_32 can be just as for start_secondary onwards */
        stack_start.esp = (void *) idle->thread.esp;
 
+       start_pda = cpu_pda(cpu);
+       cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu);
+
        irq_ctx_init(cpu);
 
        x86_cpu_to_apicid[cpu] = apicid;
@@ -1109,34 +1131,15 @@ exit:
 }
 #endif
 
-static void smp_tune_scheduling (void)
+static void smp_tune_scheduling(void)
 {
        unsigned long cachesize;       /* kB   */
-       unsigned long bandwidth = 350; /* MB/s */
-       /*
-        * Rough estimation for SMP scheduling, this is the number of
-        * cycles it takes for a fully memory-limited process to flush
-        * the SMP-local cache.
-        *
-        * (For a P5 this pretty much means we will choose another idle
-        *  CPU almost always at wakeup time (this is due to the small
-        *  L1 cache), on PIIs it's around 50-100 usecs, depending on
-        *  the cache size)
-        */
 
-       if (!cpu_khz) {
-               /*
-                * this basically disables processor-affinity
-                * scheduling on SMP without a TSC.
-                */
-               return;
-       } else {
+       if (cpu_khz) {
                cachesize = boot_cpu_data.x86_cache_size;
-               if (cachesize == -1) {
-                       cachesize = 16; /* Pentiums, 2x8kB cache */
-                       bandwidth = 100;
-               }
-               max_cache_size = cachesize * 1024;
+
+               if (cachesize > 0)
+                       max_cache_size = cachesize * 1024;
        }
 }
 
@@ -1462,6 +1465,12 @@ int __devinit __cpu_up(unsigned int cpu)
        cpu_set(cpu, smp_commenced_mask);
        while (!cpu_isset(cpu, cpu_online_map))
                cpu_relax();
+
+#ifdef CONFIG_X86_GENERICARCH
+       if (num_online_cpus() > 8 && genapic == &apic_default)
+               panic("Default flat APIC routing can't be used with > 8 cpus\n");
+#endif
+
        return 0;
 }