aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-01-13 06:41:35 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-16 08:20:03 -0500
commitb12d8db8fbfaed1e8222a15333a3645599636854 (patch)
tree4ae6ce55232885d0707eb464c5b43a54bdfe3ce4
parent9939ddaff52787b2a7c1adf1b2afc95421aa0884 (diff)
x86: make pda a percpu variable
[ Based on original patch from Christoph Lameter and Mike Travis. ] As pda is now allocated in percpu area, it can easily be made a proper percpu variable. Make it so by defining per cpu symbol from linker script and declaring it in C code for SMP and simply defining it for UP. This change cleans up code and brings SMP and UP closer a bit. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/include/asm/pda.h5
-rw-r--r--arch/x86/kernel/cpu/common.c3
-rw-r--r--arch/x86/kernel/head64.c10
-rw-r--r--arch/x86/kernel/head_64.S5
-rw-r--r--arch/x86/kernel/setup_percpu.c16
-rw-r--r--arch/x86/kernel/vmlinux_64.lds.S4
6 files changed, 23 insertions, 20 deletions
diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h
index e91558e37850..66ae1043393d 100644
--- a/arch/x86/include/asm/pda.h
+++ b/arch/x86/include/asm/pda.h
@@ -7,6 +7,7 @@
7#include <linux/cache.h> 7#include <linux/cache.h>
8#include <linux/threads.h> 8#include <linux/threads.h>
9#include <asm/page.h> 9#include <asm/page.h>
10#include <asm/percpu.h>
10 11
11/* Per processor datastructure. %gs points to it while the kernel runs */ 12/* Per processor datastructure. %gs points to it while the kernel runs */
12struct x8664_pda { 13struct x8664_pda {
@@ -39,10 +40,10 @@ struct x8664_pda {
39 unsigned irq_spurious_count; 40 unsigned irq_spurious_count;
40} ____cacheline_aligned_in_smp; 41} ____cacheline_aligned_in_smp;
41 42
42extern struct x8664_pda *_cpu_pda[NR_CPUS]; 43DECLARE_PER_CPU(struct x8664_pda, __pda);
43extern void pda_init(int); 44extern void pda_init(int);
44 45
45#define cpu_pda(i) (_cpu_pda[i]) 46#define cpu_pda(cpu) (&per_cpu(__pda, cpu))
46 47
47/* 48/*
48 * There is no fast way to get the base address of the PDA, all the accesses 49 * There is no fast way to get the base address of the PDA, all the accesses
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 7041acdf5579..c49498d40830 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -879,9 +879,6 @@ static __init int setup_disablecpuid(char *arg)
879__setup("clearcpuid=", setup_disablecpuid); 879__setup("clearcpuid=", setup_disablecpuid);
880 880
881#ifdef CONFIG_X86_64 881#ifdef CONFIG_X86_64
882struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
883EXPORT_SYMBOL(_cpu_pda);
884
885struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; 882struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
886 883
887static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; 884static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index e99b661a97f4..71b6f6ec96a2 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -26,18 +26,8 @@
26#include <asm/bios_ebda.h> 26#include <asm/bios_ebda.h>
27#include <asm/trampoline.h> 27#include <asm/trampoline.h>
28 28
29#ifndef CONFIG_SMP
30/* boot cpu pda, referenced by head_64.S to initialize %gs on UP */
31struct x8664_pda _boot_cpu_pda;
32#endif
33
34void __init x86_64_init_pda(void) 29void __init x86_64_init_pda(void)
35{ 30{
36#ifdef CONFIG_SMP
37 cpu_pda(0) = (void *)__per_cpu_load;
38#else
39 cpu_pda(0) = &_boot_cpu_pda;
40#endif
41 pda_init(0); 31 pda_init(0);
42} 32}
43 33
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 7a995d0e9f78..c8ace880661b 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -19,6 +19,7 @@
19#include <asm/msr.h> 19#include <asm/msr.h>
20#include <asm/cache.h> 20#include <asm/cache.h>
21#include <asm/processor-flags.h> 21#include <asm/processor-flags.h>
22#include <asm/percpu.h>
22 23
23#ifdef CONFIG_PARAVIRT 24#ifdef CONFIG_PARAVIRT
24#include <asm/asm-offsets.h> 25#include <asm/asm-offsets.h>
@@ -250,7 +251,7 @@ ENTRY(secondary_startup_64)
250 * secondary CPU,initial_gs should be set to its pda address 251 * secondary CPU,initial_gs should be set to its pda address
251 * before the CPU runs this code. 252 * before the CPU runs this code.
252 * 253 *
253 * On UP, initial_gs points to _boot_cpu_pda and doesn't 254 * On UP, initial_gs points to PER_CPU_VAR(__pda) and doesn't
254 * change. 255 * change.
255 */ 256 */
256 movl $MSR_GS_BASE,%ecx 257 movl $MSR_GS_BASE,%ecx
@@ -284,7 +285,7 @@ ENTRY(secondary_startup_64)
284#ifdef CONFIG_SMP 285#ifdef CONFIG_SMP
285 .quad __per_cpu_load 286 .quad __per_cpu_load
286#else 287#else
287 .quad _boot_cpu_pda 288 .quad PER_CPU_VAR(__pda)
288#endif 289#endif
289 __FINITDATA 290 __FINITDATA
290 291
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index be1ff34db112..daeedf82c15f 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -66,6 +66,16 @@ static void __init setup_node_to_cpumask_map(void);
66static inline void setup_node_to_cpumask_map(void) { } 66static inline void setup_node_to_cpumask_map(void) { }
67#endif 67#endif
68 68
69/*
70 * Define load_pda_offset() and per-cpu __pda for x86_64.
71 * load_pda_offset() is responsible for loading the offset of pda into
72 * %gs.
73 *
74 * On SMP, pda offset also duals as percpu base address and thus it
75 * should be at the start of per-cpu area. To achieve this, it's
76 * preallocated in vmlinux_64.lds.S directly instead of using
77 * DEFINE_PER_CPU().
78 */
69#ifdef CONFIG_X86_64 79#ifdef CONFIG_X86_64
70void __cpuinit load_pda_offset(int cpu) 80void __cpuinit load_pda_offset(int cpu)
71{ 81{
@@ -74,6 +84,10 @@ void __cpuinit load_pda_offset(int cpu)
74 wrmsrl(MSR_GS_BASE, cpu_pda(cpu)); 84 wrmsrl(MSR_GS_BASE, cpu_pda(cpu));
75 mb(); 85 mb();
76} 86}
87#ifndef CONFIG_SMP
88DEFINE_PER_CPU(struct x8664_pda, __pda);
89EXPORT_PER_CPU_SYMBOL(__pda);
90#endif
77 91
78#endif /* CONFIG_SMP && CONFIG_X86_64 */ 92#endif /* CONFIG_SMP && CONFIG_X86_64 */
79 93
@@ -180,8 +194,6 @@ void __init setup_per_cpu_areas(void)
180 memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); 194 memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start);
181 per_cpu_offset(cpu) = ptr - __per_cpu_start; 195 per_cpu_offset(cpu) = ptr - __per_cpu_start;
182#ifdef CONFIG_X86_64 196#ifdef CONFIG_X86_64
183 cpu_pda(cpu) = (void *)ptr;
184
185 /* 197 /*
186 * CPU0 modified pda in the init data area, reload pda 198 * CPU0 modified pda in the init data area, reload pda
187 * offset for CPU0 and clear the area for others. 199 * offset for CPU0 and clear the area for others.
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index 962f21f1d4d7..d2a0baa87d1b 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -217,10 +217,12 @@ SECTIONS
217 * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the 217 * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the
218 * output PHDR, so the next output section - __data_nosave - should 218 * output PHDR, so the next output section - __data_nosave - should
219 * switch it back to data.init. Also, pda should be at the head of 219 * switch it back to data.init. Also, pda should be at the head of
220 * percpu area. Preallocate it. 220 * percpu area. Preallocate it and define the percpu offset symbol
221 * so that it can be accessed as a percpu variable.
221 */ 222 */
222 . = ALIGN(PAGE_SIZE); 223 . = ALIGN(PAGE_SIZE);
223 PERCPU_VADDR_PREALLOC(0, :percpu, pda_size) 224 PERCPU_VADDR_PREALLOC(0, :percpu, pda_size)
225 per_cpu____pda = __per_cpu_start;
224#else 226#else
225 PERCPU(PAGE_SIZE) 227 PERCPU(PAGE_SIZE)
226#endif 228#endif