diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/asm-offsets_64.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/head_64.S | 13 | ||||
-rw-r--r-- | arch/x86/kernel/setup_percpu.c | 34 | ||||
-rw-r--r-- | arch/x86/kernel/vmlinux_64.lds.S | 8 |
5 files changed, 19 insertions, 47 deletions
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 64c834a39aa8..94f9c8b39d20 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
@@ -48,10 +48,6 @@ int main(void) | |||
48 | #endif | 48 | #endif |
49 | BLANK(); | 49 | BLANK(); |
50 | #undef ENTRY | 50 | #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 | 51 | #ifdef CONFIG_PARAVIRT |
56 | BLANK(); | 52 | BLANK(); |
57 | OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled); | 53 | OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled); |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f83a4d6160f0..098934e72a16 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -881,12 +881,13 @@ __setup("clearcpuid=", setup_disablecpuid); | |||
881 | #ifdef CONFIG_X86_64 | 881 | #ifdef CONFIG_X86_64 |
882 | struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; | 882 | struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; |
883 | 883 | ||
884 | DEFINE_PER_CPU_PAGE_ALIGNED(char[IRQ_STACK_SIZE], irq_stack); | 884 | DEFINE_PER_CPU_FIRST(union irq_stack_union, |
885 | irq_stack_union) __aligned(PAGE_SIZE); | ||
885 | #ifdef CONFIG_SMP | 886 | #ifdef CONFIG_SMP |
886 | DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ | 887 | DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ |
887 | #else | 888 | #else |
888 | DEFINE_PER_CPU(char *, irq_stack_ptr) = | 889 | DEFINE_PER_CPU(char *, irq_stack_ptr) = |
889 | per_cpu_var(irq_stack) + IRQ_STACK_SIZE - 64; | 890 | per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64; |
890 | #endif | 891 | #endif |
891 | 892 | ||
892 | DEFINE_PER_CPU(unsigned long, kernel_stack) = | 893 | DEFINE_PER_CPU(unsigned long, kernel_stack) = |
@@ -960,7 +961,7 @@ void __cpuinit cpu_init(void) | |||
960 | 961 | ||
961 | loadsegment(fs, 0); | 962 | loadsegment(fs, 0); |
962 | loadsegment(gs, 0); | 963 | loadsegment(gs, 0); |
963 | load_pda_offset(cpu); | 964 | load_gs_base(cpu); |
964 | 965 | ||
965 | #ifdef CONFIG_NUMA | 966 | #ifdef CONFIG_NUMA |
966 | if (cpu != 0 && percpu_read(node_number) == 0 && | 967 | if (cpu != 0 && percpu_read(node_number) == 0 && |
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 98ea26a2fca1..a0a2b5ca9b7d 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
@@ -242,13 +242,10 @@ ENTRY(secondary_startup_64) | |||
242 | 242 | ||
243 | /* Set up %gs. | 243 | /* Set up %gs. |
244 | * | 244 | * |
245 | * 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 |
246 | * boot, make %gs point to the init data section. For a | 246 | * union. If the stack protector canary is enabled, it is |
247 | * secondary CPU,initial_gs should be set to its pda address | 247 | * located at %gs:40. Note that, on SMP, the boot cpu uses |
248 | * before the CPU runs this code. | 248 | * init data section till per cpu areas are set up. |
249 | * | ||
250 | * On UP, initial_gs points to PER_CPU_VAR(__pda) and doesn't | ||
251 | * change. | ||
252 | */ | 249 | */ |
253 | movl $MSR_GS_BASE,%ecx | 250 | movl $MSR_GS_BASE,%ecx |
254 | movq initial_gs(%rip),%rax | 251 | movq initial_gs(%rip),%rax |
@@ -281,7 +278,7 @@ ENTRY(secondary_startup_64) | |||
281 | #ifdef CONFIG_SMP | 278 | #ifdef CONFIG_SMP |
282 | .quad __per_cpu_load | 279 | .quad __per_cpu_load |
283 | #else | 280 | #else |
284 | .quad PER_CPU_VAR(__pda) | 281 | .quad PER_CPU_VAR(irq_stack_union) |
285 | #endif | 282 | #endif |
286 | __FINITDATA | 283 | __FINITDATA |
287 | 284 | ||
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/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 | ||