Merge branch 'linus' into perfcounters/core
[cascardo/linux.git] / arch / x86 / kernel / head_64.S
index 26cfdc1..a0a2b5c 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/msr.h>
 #include <asm/cache.h>
 #include <asm/processor-flags.h>
+#include <asm/percpu.h>
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/asm-offsets.h>
@@ -204,6 +205,19 @@ ENTRY(secondary_startup_64)
        pushq $0
        popfq
 
+#ifdef CONFIG_SMP
+       /*
+        * Fix up static pointers that need __per_cpu_load added.  The assembler
+        * is unable to do this directly.  This is only needed for the boot cpu.
+        * These values are set up with the correct base addresses by C code for
+        * secondary cpus.
+        */
+       movq    initial_gs(%rip), %rax
+       cmpl    $0, per_cpu__cpu_number(%rax)
+       jne     1f
+       addq    %rax, early_gdt_descr_base(%rip)
+1:
+#endif
        /*
         * We must switch to a new descriptor in kernel space for the GDT
         * because soon the kernel won't have access anymore to the userspace
@@ -226,12 +240,15 @@ ENTRY(secondary_startup_64)
        movl %eax,%fs
        movl %eax,%gs
 
-       /* 
-        * Setup up a dummy PDA. this is just for some early bootup code
-        * that does in_interrupt() 
-        */ 
+       /* Set up %gs.
+        *
+        * The base of %gs always points to the bottom of the irqstack
+        * union.  If the stack protector canary is enabled, it is
+        * located at %gs:40.  Note that, on SMP, the boot cpu uses
+        * init data section till per cpu areas are set up.
+        */
        movl    $MSR_GS_BASE,%ecx
-       movq    $empty_zero_page,%rax
+       movq    initial_gs(%rip),%rax
        movq    %rax,%rdx
        shrq    $32,%rdx
        wrmsr   
@@ -257,6 +274,12 @@ ENTRY(secondary_startup_64)
        .align  8
        ENTRY(initial_code)
        .quad   x86_64_start_kernel
+       ENTRY(initial_gs)
+#ifdef CONFIG_SMP
+       .quad   __per_cpu_load
+#else
+       .quad   PER_CPU_VAR(irq_stack_union)
+#endif
        __FINITDATA
 
        ENTRY(stack_start)
@@ -305,7 +328,7 @@ ENTRY(early_idt_handler)
        call dump_stack
 #ifdef CONFIG_KALLSYMS 
        leaq early_idt_ripmsg(%rip),%rdi
-       movq 8(%rsp),%rsi       # get rip again
+       movq 0(%rsp),%rsi       # get rip again
        call __print_symbol
 #endif
 #endif /* EARLY_PRINTK */
@@ -401,7 +424,8 @@ NEXT_PAGE(level2_spare_pgt)
        .globl early_gdt_descr
 early_gdt_descr:
        .word   GDT_ENTRIES*8-1
-       .quad   per_cpu__gdt_page
+early_gdt_descr_base:
+       .quad   per_cpu__gdt_page
 
 ENTRY(phys_base)
        /* This must match the first entry in level2_kernel_pgt */