x86: load pointer to pda into %gs while brining up a CPU
authorTejun Heo <tj@kernel.org>
Tue, 13 Jan 2009 11:41:35 +0000 (20:41 +0900)
committerIngo Molnar <mingo@elte.hu>
Fri, 16 Jan 2009 13:19:26 +0000 (14:19 +0100)
[ Based on original patch from Christoph Lameter and Mike Travis. ]

CPU startup code in head_64.S loaded address of a zero page into %gs
for temporary use till pda is loaded but address to the actual pda is
available at the point.  Load the real address directly instead.

This will help unifying percpu and pda handling later on.

This patch is mostly taken from Mike Travis' "x86_64: Fold pda into
per cpu area" patch.

Signed-off-by: Tejun Heo <tj@kernel.org>
arch/x86/include/asm/trampoline.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/head64.c
arch/x86/kernel/head_64.S
arch/x86/kernel/smpboot.c

index 780ba0ab94f908da84b44d71f1740d47ac2677de..90f06c25221d792dab33f662c25012b7d0c39f59 100644 (file)
@@ -13,6 +13,7 @@ extern unsigned char *trampoline_base;
 
 extern unsigned long init_rsp;
 extern unsigned long initial_code;
+extern unsigned long initial_gs;
 
 #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
 #define TRAMPOLINE_BASE 0x6000
index 707c1f6f95faedfb7db7aed696c45c79461b0ea2..9ff67f8dc2c016e8016bd90c8c35d9f0c0359388 100644 (file)
@@ -101,6 +101,7 @@ int acpi_save_state_mem(void)
        stack_start.sp = temp_stack + sizeof(temp_stack);
        early_gdt_descr.address =
                        (unsigned long)get_cpu_gdt_table(smp_processor_id());
+       initial_gs = (unsigned long)cpu_pda(smp_processor_id());
 #endif
        initial_code = (unsigned long)wakeup_long64;
        saved_magic = 0x123456789abcdef0;
index bc2900ca82c7d54b2b25718afaf78289dd8eff94..76ffba2aa66d590c8480f8f46c6e45db9f373b59 100644 (file)
@@ -26,8 +26,8 @@
 #include <asm/bios_ebda.h>
 #include <asm/trampoline.h>
 
-/* boot cpu pda */
-static struct x8664_pda _boot_cpu_pda;
+/* boot cpu pda, referenced by head_64.S to initialize %gs for boot CPU */
+struct x8664_pda _boot_cpu_pda;
 
 #ifdef CONFIG_SMP
 /*
index 7ee0363871e8c60f61ae14601f00b0126cd1706f..2f0ab00898836860c1cc9dd7ba448b8f552e988e 100644 (file)
@@ -243,12 +243,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.
+        *
+        * %gs should point to the pda.  For initial boot, make %gs point
+        * to the _boot_cpu_pda in data section.  For a secondary CPU,
+        * initial_gs should be set to its pda address before the CPU runs
+        * this code.
+        */
        movl    $MSR_GS_BASE,%ecx
-       movq    $empty_zero_page,%rax
+       movq    initial_gs(%rip),%rax
        movq    %rax,%rdx
        shrq    $32,%rdx
        wrmsr   
@@ -274,6 +277,8 @@ ENTRY(secondary_startup_64)
        .align  8
        ENTRY(initial_code)
        .quad   x86_64_start_kernel
+       ENTRY(initial_gs)
+       .quad   _boot_cpu_pda
        __FINITDATA
 
        ENTRY(stack_start)
index 1a712da1dfa0ce99ac01299f766ad986548d05ef..70d846628bbfb9755a92232fffad3ea64668f133 100644 (file)
@@ -854,6 +854,7 @@ do_rest:
 #else
        cpu_pda(cpu)->pcurrent = c_idle.idle;
        clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
+       initial_gs = (unsigned long)cpu_pda(cpu);
 #endif
        early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
        initial_code = (unsigned long)start_secondary;