diff options
Diffstat (limited to 'arch/x86/kernel/head_64.S')
-rw-r--r-- | arch/x86/kernel/head_64.S | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 0e275d495563..7ee0363871e8 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
@@ -204,6 +204,23 @@ ENTRY(secondary_startup_64) | |||
204 | pushq $0 | 204 | pushq $0 |
205 | popfq | 205 | popfq |
206 | 206 | ||
207 | #ifdef CONFIG_SMP | ||
208 | /* | ||
209 | * early_gdt_base should point to the gdt_page in static percpu init | ||
210 | * data area. Computing this requires two symbols - __per_cpu_load | ||
211 | * and per_cpu__gdt_page. As linker can't do no such relocation, do | ||
212 | * it by hand. As early_gdt_descr is manipulated by C code for | ||
213 | * secondary CPUs, this should be done only once for the boot CPU | ||
214 | * when early_gdt_descr_base contains zero. | ||
215 | */ | ||
216 | movq early_gdt_descr_base(%rip), %rax | ||
217 | testq %rax, %rax | ||
218 | jnz 1f | ||
219 | movq $__per_cpu_load, %rax | ||
220 | addq $per_cpu__gdt_page, %rax | ||
221 | movq %rax, early_gdt_descr_base(%rip) | ||
222 | 1: | ||
223 | #endif | ||
207 | /* | 224 | /* |
208 | * We must switch to a new descriptor in kernel space for the GDT | 225 | * We must switch to a new descriptor in kernel space for the GDT |
209 | * because soon the kernel won't have access anymore to the userspace | 226 | * because soon the kernel won't have access anymore to the userspace |
@@ -401,7 +418,12 @@ NEXT_PAGE(level2_spare_pgt) | |||
401 | .globl early_gdt_descr | 418 | .globl early_gdt_descr |
402 | early_gdt_descr: | 419 | early_gdt_descr: |
403 | .word GDT_ENTRIES*8-1 | 420 | .word GDT_ENTRIES*8-1 |
404 | .quad per_cpu__gdt_page | 421 | #ifdef CONFIG_SMP |
422 | early_gdt_descr_base: | ||
423 | .quad 0x0000000000000000 | ||
424 | #else | ||
425 | .quad per_cpu__gdt_page | ||
426 | #endif | ||
405 | 427 | ||
406 | ENTRY(phys_base) | 428 | ENTRY(phys_base) |
407 | /* This must match the first entry in level2_kernel_pgt */ | 429 | /* This must match the first entry in level2_kernel_pgt */ |