diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-01-20 02:23:45 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-01-20 02:23:45 -0500 |
commit | 8f5d36ed5bb6e33024619eaee15b7ce2e3d115b3 (patch) | |
tree | 1a73934430a84fa926c7a12e1901d7e2639da4ff | |
parent | 5cdc5e9e69d4dc3a3630ae1fa666401b2a8dcde6 (diff) | |
parent | 6b7c38d55587f43bcd2cbce3a98b1c0826982090 (diff) |
Merge branch 'tj-percpu' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc into core/percpu
-rw-r--r-- | arch/x86/include/asm/pda.h | 45 | ||||
-rw-r--r-- | arch/x86/include/asm/percpu.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/pgtable_64.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 23 | ||||
-rw-r--r-- | arch/x86/include/asm/smp.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/stackprotector.h | 17 | ||||
-rw-r--r-- | arch/x86/include/asm/system.h | 22 | ||||
-rw-r--r-- | arch/x86/kernel/asm-offsets_64.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 21 | ||||
-rw-r--r-- | arch/x86/kernel/head64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/head_64.S | 37 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/setup_percpu.c | 34 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/vmlinux_64.lds.S | 8 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 1 | ||||
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 46 | ||||
-rw-r--r-- | include/linux/percpu.h | 41 |
18 files changed, 107 insertions, 212 deletions
diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h deleted file mode 100644 index 5976cd803e9a..000000000000 --- a/arch/x86/include/asm/pda.h +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | #ifndef _ASM_X86_PDA_H | ||
2 | #define _ASM_X86_PDA_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | #include <linux/stddef.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/cache.h> | ||
8 | #include <linux/threads.h> | ||
9 | #include <asm/page.h> | ||
10 | #include <asm/percpu.h> | ||
11 | |||
12 | /* Per processor datastructure. %gs points to it while the kernel runs */ | ||
13 | struct x8664_pda { | ||
14 | unsigned long unused1; | ||
15 | unsigned long unused2; | ||
16 | unsigned long unused3; | ||
17 | unsigned long unused4; | ||
18 | int unused5; | ||
19 | unsigned int unused6; /* 36 was cpunumber */ | ||
20 | unsigned long stack_canary; /* 40 stack canary value */ | ||
21 | /* gcc-ABI: this canary MUST be at | ||
22 | offset 40!!! */ | ||
23 | short in_bootmem; /* pda lives in bootmem */ | ||
24 | } ____cacheline_aligned_in_smp; | ||
25 | |||
26 | DECLARE_PER_CPU(struct x8664_pda, __pda); | ||
27 | extern void pda_init(int); | ||
28 | |||
29 | #define cpu_pda(cpu) (&per_cpu(__pda, cpu)) | ||
30 | |||
31 | #define read_pda(field) percpu_read(__pda.field) | ||
32 | #define write_pda(field, val) percpu_write(__pda.field, val) | ||
33 | #define add_pda(field, val) percpu_add(__pda.field, val) | ||
34 | #define sub_pda(field, val) percpu_sub(__pda.field, val) | ||
35 | #define or_pda(field, val) percpu_or(__pda.field, val) | ||
36 | |||
37 | /* This is not atomic against other CPUs -- CPU preemption needs to be off */ | ||
38 | #define test_and_clear_bit_pda(bit, field) \ | ||
39 | x86_test_and_clear_bit_percpu(bit, __pda.field) | ||
40 | |||
41 | #endif | ||
42 | |||
43 | #define refresh_stack_canary() write_pda(stack_canary, current->stack_canary) | ||
44 | |||
45 | #endif /* _ASM_X86_PDA_H */ | ||
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 165d5272ece1..ce980db5e59d 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -133,12 +133,6 @@ do { \ | |||
133 | /* We can use this directly for local CPU (faster). */ | 133 | /* We can use this directly for local CPU (faster). */ |
134 | DECLARE_PER_CPU(unsigned long, this_cpu_off); | 134 | DECLARE_PER_CPU(unsigned long, this_cpu_off); |
135 | 135 | ||
136 | #ifdef CONFIG_X86_64 | ||
137 | extern void load_pda_offset(int cpu); | ||
138 | #else | ||
139 | static inline void load_pda_offset(int cpu) { } | ||
140 | #endif | ||
141 | |||
142 | #endif /* !__ASSEMBLY__ */ | 136 | #endif /* !__ASSEMBLY__ */ |
143 | 137 | ||
144 | #ifdef CONFIG_SMP | 138 | #ifdef CONFIG_SMP |
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index ba09289accaa..1df9637dfda3 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
12 | #include <linux/bitops.h> | 12 | #include <linux/bitops.h> |
13 | #include <linux/threads.h> | 13 | #include <linux/threads.h> |
14 | #include <asm/pda.h> | ||
15 | 14 | ||
16 | extern pud_t level3_kernel_pgt[512]; | 15 | extern pud_t level3_kernel_pgt[512]; |
17 | extern pud_t level3_ident_pgt[512]; | 16 | extern pud_t level3_ident_pgt[512]; |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index f511246fa6cd..48676b943b92 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -379,8 +379,29 @@ union thread_xstate { | |||
379 | #ifdef CONFIG_X86_64 | 379 | #ifdef CONFIG_X86_64 |
380 | DECLARE_PER_CPU(struct orig_ist, orig_ist); | 380 | DECLARE_PER_CPU(struct orig_ist, orig_ist); |
381 | 381 | ||
382 | DECLARE_PER_CPU(char[IRQ_STACK_SIZE], irq_stack); | 382 | union irq_stack_union { |
383 | char irq_stack[IRQ_STACK_SIZE]; | ||
384 | /* | ||
385 | * GCC hardcodes the stack canary as %gs:40. Since the | ||
386 | * irq_stack is the object at %gs:0, we reserve the bottom | ||
387 | * 48 bytes of the irq stack for the canary. | ||
388 | */ | ||
389 | struct { | ||
390 | char gs_base[40]; | ||
391 | unsigned long stack_canary; | ||
392 | }; | ||
393 | }; | ||
394 | |||
395 | DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); | ||
383 | DECLARE_PER_CPU(char *, irq_stack_ptr); | 396 | DECLARE_PER_CPU(char *, irq_stack_ptr); |
397 | |||
398 | static inline void load_gs_base(int cpu) | ||
399 | { | ||
400 | /* Memory clobbers used to order pda/percpu accesses */ | ||
401 | mb(); | ||
402 | wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); | ||
403 | mb(); | ||
404 | } | ||
384 | #endif | 405 | #endif |
385 | 406 | ||
386 | extern void print_cpu_info(struct cpuinfo_x86 *); | 407 | extern void print_cpu_info(struct cpuinfo_x86 *); |
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 68636e767a91..45ef8a1b9d7c 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h | |||
@@ -15,7 +15,6 @@ | |||
15 | # include <asm/io_apic.h> | 15 | # include <asm/io_apic.h> |
16 | # endif | 16 | # endif |
17 | #endif | 17 | #endif |
18 | #include <asm/pda.h> | ||
19 | #include <asm/thread_info.h> | 18 | #include <asm/thread_info.h> |
20 | #include <asm/cpumask.h> | 19 | #include <asm/cpumask.h> |
21 | 20 | ||
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index c7f0d10bae7b..36a700acaf2b 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #define _ASM_STACKPROTECTOR_H 1 | 2 | #define _ASM_STACKPROTECTOR_H 1 |
3 | 3 | ||
4 | #include <asm/tsc.h> | 4 | #include <asm/tsc.h> |
5 | #include <asm/pda.h> | 5 | #include <asm/processor.h> |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Initialize the stackprotector canary value. | 8 | * Initialize the stackprotector canary value. |
@@ -16,13 +16,12 @@ static __always_inline void boot_init_stack_canary(void) | |||
16 | u64 tsc; | 16 | u64 tsc; |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * If we're the non-boot CPU, nothing set the PDA stack | 19 | * Build time only check to make sure the stack_canary is at |
20 | * canary up for us - and if we are the boot CPU we have | 20 | * offset 40 in the pda; this is a gcc ABI requirement |
21 | * a 0 stack canary. This is a good place for updating | 21 | */ |
22 | * it, as we wont ever return from this function (so the | 22 | BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40); |
23 | * invalid canaries already on the stack wont ever | 23 | |
24 | * trigger). | 24 | /* |
25 | * | ||
26 | * We both use the random pool and the current TSC as a source | 25 | * We both use the random pool and the current TSC as a source |
27 | * of randomness. The TSC only matters for very early init, | 26 | * of randomness. The TSC only matters for very early init, |
28 | * there it already has some randomness on most systems. Later | 27 | * there it already has some randomness on most systems. Later |
@@ -33,7 +32,7 @@ static __always_inline void boot_init_stack_canary(void) | |||
33 | canary += tsc + (tsc << 32UL); | 32 | canary += tsc + (tsc << 32UL); |
34 | 33 | ||
35 | current->stack_canary = canary; | 34 | current->stack_canary = canary; |
36 | write_pda(stack_canary, canary); | 35 | percpu_write(irq_stack_union.stack_canary, canary); |
37 | } | 36 | } |
38 | 37 | ||
39 | #endif | 38 | #endif |
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 8cadfe9b1194..52eb748a68af 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h | |||
@@ -86,17 +86,28 @@ do { \ | |||
86 | , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \ | 86 | , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \ |
87 | "r12", "r13", "r14", "r15" | 87 | "r12", "r13", "r14", "r15" |
88 | 88 | ||
89 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
90 | #define __switch_canary \ | ||
91 | "movq %P[task_canary](%%rsi),%%r8\n\t" \ | ||
92 | "movq %%r8,%%gs:%P[gs_canary]\n\t" | ||
93 | #define __switch_canary_param \ | ||
94 | , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) \ | ||
95 | , [gs_canary] "i" (offsetof(union irq_stack_union, stack_canary)) | ||
96 | #else /* CC_STACKPROTECTOR */ | ||
97 | #define __switch_canary | ||
98 | #define __switch_canary_param | ||
99 | #endif /* CC_STACKPROTECTOR */ | ||
100 | |||
89 | /* Save restore flags to clear handle leaking NT */ | 101 | /* Save restore flags to clear handle leaking NT */ |
90 | #define switch_to(prev, next, last) \ | 102 | #define switch_to(prev, next, last) \ |
91 | asm volatile(SAVE_CONTEXT \ | 103 | asm volatile(SAVE_CONTEXT \ |
92 | "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ | 104 | "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ |
93 | "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ | 105 | "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ |
94 | "call __switch_to\n\t" \ | 106 | "call __switch_to\n\t" \ |
95 | ".globl thread_return\n" \ | 107 | ".globl thread_return\n" \ |
96 | "thread_return:\n\t" \ | 108 | "thread_return:\n\t" \ |
97 | "movq "__percpu_arg([current_task])",%%rsi\n\t" \ | 109 | "movq "__percpu_arg([current_task])",%%rsi\n\t" \ |
98 | "movq %P[task_canary](%%rsi),%%r8\n\t" \ | 110 | __switch_canary \ |
99 | "movq %%r8,%%gs:%P[pda_canary]\n\t" \ | ||
100 | "movq %P[thread_info](%%rsi),%%r8\n\t" \ | 111 | "movq %P[thread_info](%%rsi),%%r8\n\t" \ |
101 | LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ | 112 | LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ |
102 | "movq %%rax,%%rdi\n\t" \ | 113 | "movq %%rax,%%rdi\n\t" \ |
@@ -108,9 +119,8 @@ do { \ | |||
108 | [ti_flags] "i" (offsetof(struct thread_info, flags)), \ | 119 | [ti_flags] "i" (offsetof(struct thread_info, flags)), \ |
109 | [tif_fork] "i" (TIF_FORK), \ | 120 | [tif_fork] "i" (TIF_FORK), \ |
110 | [thread_info] "i" (offsetof(struct task_struct, stack)), \ | 121 | [thread_info] "i" (offsetof(struct task_struct, stack)), \ |
111 | [task_canary] "i" (offsetof(struct task_struct, stack_canary)),\ | 122 | [current_task] "m" (per_cpu_var(current_task)) \ |
112 | [current_task] "m" (per_cpu_var(current_task)), \ | 123 | __switch_canary_param \ |
113 | [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary))\ | ||
114 | : "memory", "cc" __EXTRA_CLOBBER) | 124 | : "memory", "cc" __EXTRA_CLOBBER) |
115 | #endif | 125 | #endif |
116 | 126 | ||
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 64c834a39aa8..8793ab33e2c1 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
12 | #include <linux/suspend.h> | 12 | #include <linux/suspend.h> |
13 | #include <linux/kbuild.h> | 13 | #include <linux/kbuild.h> |
14 | #include <asm/pda.h> | ||
15 | #include <asm/processor.h> | 14 | #include <asm/processor.h> |
16 | #include <asm/segment.h> | 15 | #include <asm/segment.h> |
17 | #include <asm/thread_info.h> | 16 | #include <asm/thread_info.h> |
@@ -48,10 +47,6 @@ int main(void) | |||
48 | #endif | 47 | #endif |
49 | BLANK(); | 48 | BLANK(); |
50 | #undef ENTRY | 49 | #undef ENTRY |
51 | #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) | ||
52 | DEFINE(pda_size, sizeof(struct x8664_pda)); | ||
53 | BLANK(); | ||
54 | #undef ENTRY | ||
55 | #ifdef CONFIG_PARAVIRT | 50 | #ifdef CONFIG_PARAVIRT |
56 | BLANK(); | 51 | BLANK(); |
57 | OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled); | 52 | OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled); |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7976a6a0f65c..3887fcf6e519 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/genapic.h> | 30 | #include <asm/genapic.h> |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #include <asm/pda.h> | ||
34 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
35 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
36 | #include <asm/desc.h> | 35 | #include <asm/desc.h> |
@@ -881,12 +880,13 @@ __setup("clearcpuid=", setup_disablecpuid); | |||
881 | #ifdef CONFIG_X86_64 | 880 | #ifdef CONFIG_X86_64 |
882 | struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; | 881 | struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; |
883 | 882 | ||
884 | DEFINE_PER_CPU_PAGE_ALIGNED(char[IRQ_STACK_SIZE], irq_stack); | 883 | DEFINE_PER_CPU_FIRST(union irq_stack_union, |
884 | irq_stack_union) __aligned(PAGE_SIZE); | ||
885 | #ifdef CONFIG_SMP | 885 | #ifdef CONFIG_SMP |
886 | DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ | 886 | DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ |
887 | #else | 887 | #else |
888 | DEFINE_PER_CPU(char *, irq_stack_ptr) = | 888 | DEFINE_PER_CPU(char *, irq_stack_ptr) = |
889 | per_cpu_var(irq_stack) + IRQ_STACK_SIZE - 64; | 889 | per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64; |
890 | #endif | 890 | #endif |
891 | 891 | ||
892 | DEFINE_PER_CPU(unsigned long, kernel_stack) = | 892 | DEFINE_PER_CPU(unsigned long, kernel_stack) = |
@@ -895,15 +895,6 @@ EXPORT_PER_CPU_SYMBOL(kernel_stack); | |||
895 | 895 | ||
896 | DEFINE_PER_CPU(unsigned int, irq_count) = -1; | 896 | DEFINE_PER_CPU(unsigned int, irq_count) = -1; |
897 | 897 | ||
898 | void __cpuinit pda_init(int cpu) | ||
899 | { | ||
900 | /* Setup up data that may be needed in __get_free_pages early */ | ||
901 | loadsegment(fs, 0); | ||
902 | loadsegment(gs, 0); | ||
903 | |||
904 | load_pda_offset(cpu); | ||
905 | } | ||
906 | |||
907 | static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks | 898 | static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks |
908 | [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]) | 899 | [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]) |
909 | __aligned(PAGE_SIZE); | 900 | __aligned(PAGE_SIZE); |
@@ -967,9 +958,9 @@ void __cpuinit cpu_init(void) | |||
967 | struct task_struct *me; | 958 | struct task_struct *me; |
968 | int i; | 959 | int i; |
969 | 960 | ||
970 | /* CPU 0 is initialised in head64.c */ | 961 | loadsegment(fs, 0); |
971 | if (cpu != 0) | 962 | loadsegment(gs, 0); |
972 | pda_init(cpu); | 963 | load_gs_base(cpu); |
973 | 964 | ||
974 | #ifdef CONFIG_NUMA | 965 | #ifdef CONFIG_NUMA |
975 | if (cpu != 0 && percpu_read(node_number) == 0 && | 966 | if (cpu != 0 && percpu_read(node_number) == 0 && |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index af67d3227ea6..f5b272247690 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -91,8 +91,6 @@ void __init x86_64_start_kernel(char * real_mode_data) | |||
91 | if (console_loglevel == 10) | 91 | if (console_loglevel == 10) |
92 | early_printk("Kernel alive\n"); | 92 | early_printk("Kernel alive\n"); |
93 | 93 | ||
94 | pda_init(0); | ||
95 | |||
96 | x86_64_start_reservations(real_mode_data); | 94 | x86_64_start_reservations(real_mode_data); |
97 | } | 95 | } |
98 | 96 | ||
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index c8ace880661b..a0a2b5ca9b7d 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
@@ -207,19 +207,15 @@ ENTRY(secondary_startup_64) | |||
207 | 207 | ||
208 | #ifdef CONFIG_SMP | 208 | #ifdef CONFIG_SMP |
209 | /* | 209 | /* |
210 | * early_gdt_base should point to the gdt_page in static percpu init | 210 | * Fix up static pointers that need __per_cpu_load added. The assembler |
211 | * data area. Computing this requires two symbols - __per_cpu_load | 211 | * is unable to do this directly. This is only needed for the boot cpu. |
212 | * and per_cpu__gdt_page. As linker can't do no such relocation, do | 212 | * These values are set up with the correct base addresses by C code for |
213 | * it by hand. As early_gdt_descr is manipulated by C code for | 213 | * secondary cpus. |
214 | * secondary CPUs, this should be done only once for the boot CPU | ||
215 | * when early_gdt_descr_base contains zero. | ||
216 | */ | 214 | */ |
217 | movq early_gdt_descr_base(%rip), %rax | 215 | movq initial_gs(%rip), %rax |
218 | testq %rax, %rax | 216 | cmpl $0, per_cpu__cpu_number(%rax) |
219 | jnz 1f | 217 | jne 1f |
220 | movq $__per_cpu_load, %rax | 218 | addq %rax, early_gdt_descr_base(%rip) |
221 | addq $per_cpu__gdt_page, %rax | ||
222 | movq %rax, early_gdt_descr_base(%rip) | ||
223 | 1: | 219 | 1: |
224 | #endif | 220 | #endif |
225 | /* | 221 | /* |
@@ -246,13 +242,10 @@ ENTRY(secondary_startup_64) | |||
246 | 242 | ||
247 | /* Set up %gs. | 243 | /* Set up %gs. |
248 | * | 244 | * |
249 | * On SMP, %gs should point to the per-cpu area. For initial | 245 | * The base of %gs always points to the bottom of the irqstack |
250 | * boot, make %gs point to the init data section. For a | 246 | * union. If the stack protector canary is enabled, it is |
251 | * secondary CPU,initial_gs should be set to its pda address | 247 | * located at %gs:40. Note that, on SMP, the boot cpu uses |
252 | * before the CPU runs this code. | 248 | * init data section till per cpu areas are set up. |
253 | * | ||
254 | * On UP, initial_gs points to PER_CPU_VAR(__pda) and doesn't | ||
255 | * change. | ||
256 | */ | 249 | */ |
257 | movl $MSR_GS_BASE,%ecx | 250 | movl $MSR_GS_BASE,%ecx |
258 | movq initial_gs(%rip),%rax | 251 | movq initial_gs(%rip),%rax |
@@ -285,7 +278,7 @@ ENTRY(secondary_startup_64) | |||
285 | #ifdef CONFIG_SMP | 278 | #ifdef CONFIG_SMP |
286 | .quad __per_cpu_load | 279 | .quad __per_cpu_load |
287 | #else | 280 | #else |
288 | .quad PER_CPU_VAR(__pda) | 281 | .quad PER_CPU_VAR(irq_stack_union) |
289 | #endif | 282 | #endif |
290 | __FINITDATA | 283 | __FINITDATA |
291 | 284 | ||
@@ -431,12 +424,8 @@ NEXT_PAGE(level2_spare_pgt) | |||
431 | .globl early_gdt_descr | 424 | .globl early_gdt_descr |
432 | early_gdt_descr: | 425 | early_gdt_descr: |
433 | .word GDT_ENTRIES*8-1 | 426 | .word GDT_ENTRIES*8-1 |
434 | #ifdef CONFIG_SMP | ||
435 | early_gdt_descr_base: | 427 | early_gdt_descr_base: |
436 | .quad 0x0000000000000000 | ||
437 | #else | ||
438 | .quad per_cpu__gdt_page | 428 | .quad per_cpu__gdt_page |
439 | #endif | ||
440 | 429 | ||
441 | ENTRY(phys_base) | 430 | ENTRY(phys_base) |
442 | /* This must match the first entry in level2_kernel_pgt */ | 431 | /* This must match the first entry in level2_kernel_pgt */ |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index aa89eabf09e0..c422eebb0c58 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <asm/processor.h> | 47 | #include <asm/processor.h> |
48 | #include <asm/i387.h> | 48 | #include <asm/i387.h> |
49 | #include <asm/mmu_context.h> | 49 | #include <asm/mmu_context.h> |
50 | #include <asm/pda.h> | ||
51 | #include <asm/prctl.h> | 50 | #include <asm/prctl.h> |
52 | #include <asm/desc.h> | 51 | #include <asm/desc.h> |
53 | #include <asm/proto.h> | 52 | #include <asm/proto.h> |
@@ -638,13 +637,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
638 | percpu_write(kernel_stack, | 637 | percpu_write(kernel_stack, |
639 | (unsigned long)task_stack_page(next_p) + | 638 | (unsigned long)task_stack_page(next_p) + |
640 | THREAD_SIZE - KERNEL_STACK_OFFSET); | 639 | THREAD_SIZE - KERNEL_STACK_OFFSET); |
641 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
642 | /* | ||
643 | * Build time only check to make sure the stack_canary is at | ||
644 | * offset 40 in the pda; this is a gcc ABI requirement | ||
645 | */ | ||
646 | BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); | ||
647 | #endif | ||
648 | 640 | ||
649 | /* | 641 | /* |
650 | * Now maybe reload the debug registers and handle I/O bitmaps | 642 | * Now maybe reload the debug registers and handle I/O bitmaps |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index efbafbbff584..90b8e154bb53 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
@@ -77,30 +77,6 @@ static void __init setup_node_to_cpumask_map(void); | |||
77 | static inline void setup_node_to_cpumask_map(void) { } | 77 | static inline void setup_node_to_cpumask_map(void) { } |
78 | #endif | 78 | #endif |
79 | 79 | ||
80 | /* | ||
81 | * Define load_pda_offset() and per-cpu __pda for x86_64. | ||
82 | * load_pda_offset() is responsible for loading the offset of pda into | ||
83 | * %gs. | ||
84 | * | ||
85 | * On SMP, pda offset also duals as percpu base address and thus it | ||
86 | * should be at the start of per-cpu area. To achieve this, it's | ||
87 | * preallocated in vmlinux_64.lds.S directly instead of using | ||
88 | * DEFINE_PER_CPU(). | ||
89 | */ | ||
90 | #ifdef CONFIG_X86_64 | ||
91 | void __cpuinit load_pda_offset(int cpu) | ||
92 | { | ||
93 | /* Memory clobbers used to order pda/percpu accesses */ | ||
94 | mb(); | ||
95 | wrmsrl(MSR_GS_BASE, cpu_pda(cpu)); | ||
96 | mb(); | ||
97 | } | ||
98 | #ifndef CONFIG_SMP | ||
99 | DEFINE_PER_CPU(struct x8664_pda, __pda); | ||
100 | #endif | ||
101 | EXPORT_PER_CPU_SYMBOL(__pda); | ||
102 | #endif /* CONFIG_SMP && CONFIG_X86_64 */ | ||
103 | |||
104 | #ifdef CONFIG_X86_64 | 80 | #ifdef CONFIG_X86_64 |
105 | 81 | ||
106 | /* correctly size the local cpu masks */ | 82 | /* correctly size the local cpu masks */ |
@@ -207,15 +183,13 @@ void __init setup_per_cpu_areas(void) | |||
207 | per_cpu(cpu_number, cpu) = cpu; | 183 | per_cpu(cpu_number, cpu) = cpu; |
208 | #ifdef CONFIG_X86_64 | 184 | #ifdef CONFIG_X86_64 |
209 | per_cpu(irq_stack_ptr, cpu) = | 185 | per_cpu(irq_stack_ptr, cpu) = |
210 | (char *)per_cpu(irq_stack, cpu) + IRQ_STACK_SIZE - 64; | 186 | per_cpu(irq_stack_union.irq_stack, cpu) + IRQ_STACK_SIZE - 64; |
211 | /* | 187 | /* |
212 | * CPU0 modified pda in the init data area, reload pda | 188 | * Up to this point, CPU0 has been using .data.init |
213 | * offset for CPU0 and clear the area for others. | 189 | * area. Reload %gs offset for CPU0. |
214 | */ | 190 | */ |
215 | if (cpu == 0) | 191 | if (cpu == 0) |
216 | load_pda_offset(0); | 192 | load_gs_base(cpu); |
217 | else | ||
218 | memset(cpu_pda(cpu), 0, sizeof(*cpu_pda(cpu))); | ||
219 | #endif | 193 | #endif |
220 | 194 | ||
221 | DBG("PERCPU: cpu %4d %p\n", cpu, ptr); | 195 | DBG("PERCPU: cpu %4d %p\n", cpu, ptr); |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 98c2d055284b..ed5aee5f3fcc 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #ifdef CONFIG_X86_64 | 59 | #ifdef CONFIG_X86_64 |
60 | #include <asm/pgalloc.h> | 60 | #include <asm/pgalloc.h> |
61 | #include <asm/proto.h> | 61 | #include <asm/proto.h> |
62 | #include <asm/pda.h> | ||
63 | #else | 62 | #else |
64 | #include <asm/processor-flags.h> | 63 | #include <asm/processor-flags.h> |
65 | #include <asm/arch_hooks.h> | 64 | #include <asm/arch_hooks.h> |
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index a09abb8fb97f..c9740996430a 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S | |||
@@ -220,8 +220,7 @@ SECTIONS | |||
220 | * so that it can be accessed as a percpu variable. | 220 | * so that it can be accessed as a percpu variable. |
221 | */ | 221 | */ |
222 | . = ALIGN(PAGE_SIZE); | 222 | . = ALIGN(PAGE_SIZE); |
223 | PERCPU_VADDR_PREALLOC(0, :percpu, pda_size) | 223 | PERCPU_VADDR(0, :percpu) |
224 | per_cpu____pda = __per_cpu_start; | ||
225 | #else | 224 | #else |
226 | PERCPU(PAGE_SIZE) | 225 | PERCPU(PAGE_SIZE) |
227 | #endif | 226 | #endif |
@@ -262,3 +261,8 @@ SECTIONS | |||
262 | */ | 261 | */ |
263 | ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), | 262 | ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), |
264 | "kernel image bigger than KERNEL_IMAGE_SIZE") | 263 | "kernel image bigger than KERNEL_IMAGE_SIZE") |
264 | |||
265 | #ifdef CONFIG_SMP | ||
266 | ASSERT((per_cpu__irq_stack_union == 0), | ||
267 | "irq_stack_union is not at start of per-cpu area"); | ||
268 | #endif | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 75b94139e1f2..bef941f61451 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1645,7 +1645,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1645 | #ifdef CONFIG_X86_64 | 1645 | #ifdef CONFIG_X86_64 |
1646 | /* Disable until direct per-cpu data access. */ | 1646 | /* Disable until direct per-cpu data access. */ |
1647 | have_vcpu_info_placement = 0; | 1647 | have_vcpu_info_placement = 0; |
1648 | pda_init(0); | ||
1649 | #endif | 1648 | #endif |
1650 | 1649 | ||
1651 | xen_smp_init(); | 1650 | xen_smp_init(); |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index aa6b9b1b30b5..53e21f36a802 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -430,22 +430,10 @@ | |||
430 | *(.initcall7.init) \ | 430 | *(.initcall7.init) \ |
431 | *(.initcall7s.init) | 431 | *(.initcall7s.init) |
432 | 432 | ||
433 | #define PERCPU_PROLOG(vaddr) \ | ||
434 | VMLINUX_SYMBOL(__per_cpu_load) = .; \ | ||
435 | .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ | ||
436 | - LOAD_OFFSET) { \ | ||
437 | VMLINUX_SYMBOL(__per_cpu_start) = .; | ||
438 | |||
439 | #define PERCPU_EPILOG(phdr) \ | ||
440 | VMLINUX_SYMBOL(__per_cpu_end) = .; \ | ||
441 | } phdr \ | ||
442 | . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); | ||
443 | |||
444 | /** | 433 | /** |
445 | * PERCPU_VADDR_PREALLOC - define output section for percpu area with prealloc | 434 | * PERCPU_VADDR - define output section for percpu area |
446 | * @vaddr: explicit base address (optional) | 435 | * @vaddr: explicit base address (optional) |
447 | * @phdr: destination PHDR (optional) | 436 | * @phdr: destination PHDR (optional) |
448 | * @prealloc: the size of prealloc area | ||
449 | * | 437 | * |
450 | * Macro which expands to output section for percpu area. If @vaddr | 438 | * Macro which expands to output section for percpu area. If @vaddr |
451 | * is not blank, it specifies explicit base address and all percpu | 439 | * is not blank, it specifies explicit base address and all percpu |
@@ -457,39 +445,23 @@ | |||
457 | * section in the linker script will go there too. @phdr should have | 445 | * section in the linker script will go there too. @phdr should have |
458 | * a leading colon. | 446 | * a leading colon. |
459 | * | 447 | * |
460 | * If @prealloc is non-zero, the specified number of bytes will be | ||
461 | * reserved at the start of percpu area. As the prealloc area is | ||
462 | * likely to break alignment, this macro puts areas in increasing | ||
463 | * alignment order. | ||
464 | * | ||
465 | * This macro defines three symbols, __per_cpu_load, __per_cpu_start | 448 | * This macro defines three symbols, __per_cpu_load, __per_cpu_start |
466 | * and __per_cpu_end. The first one is the vaddr of loaded percpu | 449 | * and __per_cpu_end. The first one is the vaddr of loaded percpu |
467 | * init data. __per_cpu_start equals @vaddr and __per_cpu_end is the | 450 | * init data. __per_cpu_start equals @vaddr and __per_cpu_end is the |
468 | * end offset. | 451 | * end offset. |
469 | */ | 452 | */ |
470 | #define PERCPU_VADDR_PREALLOC(vaddr, segment, prealloc) \ | ||
471 | PERCPU_PROLOG(vaddr) \ | ||
472 | . += prealloc; \ | ||
473 | *(.data.percpu) \ | ||
474 | *(.data.percpu.shared_aligned) \ | ||
475 | *(.data.percpu.page_aligned) \ | ||
476 | PERCPU_EPILOG(segment) | ||
477 | |||
478 | /** | ||
479 | * PERCPU_VADDR - define output section for percpu area | ||
480 | * @vaddr: explicit base address (optional) | ||
481 | * @phdr: destination PHDR (optional) | ||
482 | * | ||
483 | * Macro which expands to output section for percpu area. Mostly | ||
484 | * identical to PERCPU_VADDR_PREALLOC(@vaddr, @phdr, 0) other than | ||
485 | * using slighly different layout. | ||
486 | */ | ||
487 | #define PERCPU_VADDR(vaddr, phdr) \ | 453 | #define PERCPU_VADDR(vaddr, phdr) \ |
488 | PERCPU_PROLOG(vaddr) \ | 454 | VMLINUX_SYMBOL(__per_cpu_load) = .; \ |
455 | .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ | ||
456 | - LOAD_OFFSET) { \ | ||
457 | VMLINUX_SYMBOL(__per_cpu_start) = .; \ | ||
458 | *(.data.percpu.first) \ | ||
489 | *(.data.percpu.page_aligned) \ | 459 | *(.data.percpu.page_aligned) \ |
490 | *(.data.percpu) \ | 460 | *(.data.percpu) \ |
491 | *(.data.percpu.shared_aligned) \ | 461 | *(.data.percpu.shared_aligned) \ |
492 | PERCPU_EPILOG(phdr) | 462 | VMLINUX_SYMBOL(__per_cpu_end) = .; \ |
463 | } phdr \ | ||
464 | . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); | ||
493 | 465 | ||
494 | /** | 466 | /** |
495 | * PERCPU - define output section for percpu area, simple version | 467 | * PERCPU - define output section for percpu area, simple version |
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 9f2a3751873a..0e24202b5a4e 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
@@ -9,34 +9,39 @@ | |||
9 | #include <asm/percpu.h> | 9 | #include <asm/percpu.h> |
10 | 10 | ||
11 | #ifdef CONFIG_SMP | 11 | #ifdef CONFIG_SMP |
12 | #define DEFINE_PER_CPU(type, name) \ | 12 | #define PER_CPU_BASE_SECTION ".data.percpu" |
13 | __attribute__((__section__(".data.percpu"))) \ | ||
14 | PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name | ||
15 | 13 | ||
16 | #ifdef MODULE | 14 | #ifdef MODULE |
17 | #define SHARED_ALIGNED_SECTION ".data.percpu" | 15 | #define PER_CPU_SHARED_ALIGNED_SECTION "" |
18 | #else | 16 | #else |
19 | #define SHARED_ALIGNED_SECTION ".data.percpu.shared_aligned" | 17 | #define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned" |
20 | #endif | 18 | #endif |
19 | #define PER_CPU_FIRST_SECTION ".first" | ||
21 | 20 | ||
22 | #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ | 21 | #else |
23 | __attribute__((__section__(SHARED_ALIGNED_SECTION))) \ | 22 | |
24 | PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name \ | 23 | #define PER_CPU_BASE_SECTION ".data" |
25 | ____cacheline_aligned_in_smp | 24 | #define PER_CPU_SHARED_ALIGNED_SECTION "" |
25 | #define PER_CPU_FIRST_SECTION "" | ||
26 | |||
27 | #endif | ||
26 | 28 | ||
27 | #define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ | 29 | #define DEFINE_PER_CPU_SECTION(type, name, section) \ |
28 | __attribute__((__section__(".data.percpu.page_aligned"))) \ | 30 | __attribute__((__section__(PER_CPU_BASE_SECTION section))) \ |
29 | PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name | 31 | PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name |
30 | #else | 32 | |
31 | #define DEFINE_PER_CPU(type, name) \ | 33 | #define DEFINE_PER_CPU(type, name) \ |
32 | PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name | 34 | DEFINE_PER_CPU_SECTION(type, name, "") |
33 | 35 | ||
34 | #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ | 36 | #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ |
35 | DEFINE_PER_CPU(type, name) | 37 | DEFINE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \ |
38 | ____cacheline_aligned_in_smp | ||
36 | 39 | ||
37 | #define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ | 40 | #define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ |
38 | DEFINE_PER_CPU(type, name) | 41 | DEFINE_PER_CPU_SECTION(type, name, ".page_aligned") |
39 | #endif | 42 | |
43 | #define DEFINE_PER_CPU_FIRST(type, name) \ | ||
44 | DEFINE_PER_CPU_SECTION(type, name, PER_CPU_FIRST_SECTION) | ||
40 | 45 | ||
41 | #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) | 46 | #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) |
42 | #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) | 47 | #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) |