x86: include mach_wakecpu.h in smpboot_64
[sfrench/cifs-2.6.git] / arch / x86 / kernel / smpboot_64.c
index 2cc1b8b0601cbe2fabc97b6bc743195e65a8095d..c6c993f4c4158a9b0bf397d7c80435e40af361d1 100644 (file)
@@ -60,6 +60,8 @@
 #include <asm/hw_irq.h>
 #include <asm/numa.h>
 
+#include <mach_wakecpu.h>
+
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
@@ -85,35 +87,6 @@ struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
 #define set_idle_for_cpu(x,p)   (idle_thread_array[(x)] = (p))
 #endif
 
-
-/*
- * Currently trivial. Write the real->protected mode
- * bootstrap into the page concerned. The caller
- * has made sure it's suitably aligned.
- */
-
-static unsigned long __cpuinit setup_trampoline(void)
-{
-       void *tramp = __va(SMP_TRAMPOLINE_BASE); 
-       memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
-       return virt_to_phys(tramp);
-}
-
-/*
- * The bootstrap kernel entry code has set these up. Save them for
- * a given CPU
- */
-
-static void __cpuinit smp_store_cpu_info(int id)
-{
-       struct cpuinfo_x86 *c = &cpu_data(id);
-
-       *c = boot_cpu_data;
-       c->cpu_index = id;
-       identify_cpu(c);
-       print_cpu_info(c);
-}
-
 static atomic_t init_deasserted __cpuinitdata;
 
 /*
@@ -131,8 +104,7 @@ void __cpuinit smp_callin(void)
         * our local APIC.  We have to wait for the IPI or we'll
         * lock up on an APIC access.
         */
-       while (!atomic_read(&init_deasserted))
-               cpu_relax();
+       wait_for_init_deassert(&init_deasserted);
 
        /*
         * (This works even if the APIC is not enabled.)
@@ -256,12 +228,13 @@ void __cpuinit start_secondary(void)
         */
        spin_unlock(&vector_lock);
        cpu_set(smp_processor_id(), cpu_online_map);
-       per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
-
        unlock_ipi_call_lock();
 
+       per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+
        setup_secondary_clock();
 
+       wmb();
        cpu_idle();
 }
 
@@ -269,7 +242,7 @@ extern volatile unsigned long init_rsp;
 extern void (*initial_code)(void);
 
 #ifdef APIC_DEBUG
-static void inquire_remote_apic(int apicid)
+static void __inquire_remote_apic(int apicid)
 {
        unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
        char *names[] = { "ID", "VERSION", "SPIV" };
@@ -289,8 +262,8 @@ static void inquire_remote_apic(int apicid)
                        printk(KERN_CONT
                               "a previous APIC delivery may have failed\n");
 
-               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
-               apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
+               apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+               apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
 
                timeout = 0;
                do {
@@ -318,17 +291,26 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        unsigned long send_status, accept_status = 0;
        int maxlvt, num_starts, j;
 
+       /*
+        * Be paranoid about clearing APIC errors.
+        */
+       if (APIC_INTEGRATED(apic_version[phys_apicid])) {
+               apic_read_around(APIC_SPIV);
+               apic_write(APIC_ESR, 0);
+               apic_read(APIC_ESR);
+       }
+
        Dprintk("Asserting INIT.\n");
 
        /*
         * Turn INIT on target chip
         */
-       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+       apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
        /*
         * Send IPI
         */
-       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+       apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
                                | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
@@ -339,10 +321,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        Dprintk("Deasserting INIT.\n");
 
        /* Target chip */
-       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+       apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
        /* Send IPI */
-       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+       apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
        send_status = safe_apic_wait_icr_idle();
@@ -350,7 +332,18 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        mb();
        atomic_set(&init_deasserted, 1);
 
-       num_starts = 2;
+       if (APIC_INTEGRATED(apic_version[phys_apicid]))
+               num_starts = 2;
+       else
+               num_starts = 0;
+
+       /*
+        * Paravirt / VMI wants a startup IPI hook here to set up the
+        * target processor state.
+        */
+       startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
+                       (unsigned long) init_rsp);
+
 
        /*
         * Run STARTUP IPI loop.
@@ -361,6 +354,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
 
        for (j = 1; j <= num_starts; j++) {
                Dprintk("Sending STARTUP #%d.\n",j);
+               apic_read_around(APIC_SPIV);
                apic_write(APIC_ESR, 0);
                apic_read(APIC_ESR);
                Dprintk("After apic_write.\n");
@@ -370,11 +364,11 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
                 */
 
                /* Target chip */
-               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+               apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
                /* Boot on the stack */
                /* Kick the second */
-               apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
+               apic_write_around(APIC_ICR, APIC_DM_STARTUP | (start_rip>>12));
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -394,6 +388,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
                 * Due to the Pentium erratum 3AP.
                 */
                if (maxlvt > 3) {
+                       apic_read_around(APIC_SPIV);
                        apic_write(APIC_ESR, 0);
                }
                accept_status = (apic_read(APIC_ESR) & 0xEF);
@@ -566,6 +561,8 @@ do_rest:
                if (cpu_isset(cpu, cpu_callin_map)) {
                        /* number CPUs logically, starting from 1 (BSP is 0) */
                        Dprintk("CPU has booted.\n");
+                       printk(KERN_INFO "CPU%d: ", cpu);
+                       print_cpu_info(&cpu_data(cpu));
                } else {
                        boot_error = 1;
                        if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
@@ -749,6 +746,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
         */
 
        setup_boot_clock();
+       printk(KERN_INFO "CPU%d: ", 0);
+       print_cpu_info(&cpu_data(0));
 }
 
 /*
@@ -820,12 +819,20 @@ int __cpuinit native_cpu_up(unsigned int cpu)
        return err;
 }
 
+extern void impress_friends(void);
+extern void smp_checks(void);
+
 /*
  * Finish the SMP boot.
  */
 void __init native_smp_cpus_done(unsigned int max_cpus)
 {
        smp_cleanup_boot();
+
+       Dprintk("Boot done.\n");
+
+       impress_friends();
+       smp_checks();
        setup_ioapic_dest();
        check_nmi_watchdog();
 }