diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2009-02-04 19:58:26 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-02-04 19:58:26 -0500 |
commit | 327641da8e3e227f42690479182b896fd19486be (patch) | |
tree | 05fa7f317e854f2da5d46d4c8977486d71bb2b21 /arch/x86 | |
parent | 1f4f931501e9270c156d05ee76b7b872de486304 (diff) | |
parent | ef3892bd63420380d115f755d351d2071f1f805f (diff) |
Merge branch 'core/percpu' into x86/paravirt
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 25 | ||||
-rw-r--r-- | arch/x86/kernel/setup_percpu.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/vmlinux_64.lds.S | 5 | ||||
-rw-r--r-- | arch/x86/mach-voyager/voyager_smp.c | 11 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 3 | ||||
-rw-r--r-- | arch/x86/xen/smp.c | 5 |
9 files changed, 36 insertions, 22 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index befa20b4a68c..656d02ea509b 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -768,7 +768,8 @@ extern int sysenter_setup(void); | |||
768 | extern struct desc_ptr early_gdt_descr; | 768 | extern struct desc_ptr early_gdt_descr; |
769 | 769 | ||
770 | extern void cpu_set_gdt(int); | 770 | extern void cpu_set_gdt(int); |
771 | extern void switch_to_new_gdt(void); | 771 | extern void switch_to_new_gdt(int); |
772 | extern void load_percpu_segment(int); | ||
772 | extern void cpu_init(void); | 773 | extern void cpu_init(void); |
773 | 774 | ||
774 | static inline unsigned long get_debugctlmsr(void) | 775 | static inline unsigned long get_debugctlmsr(void) |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 652fdc9a757a..0f73ea423089 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -253,23 +253,28 @@ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) | |||
253 | 253 | ||
254 | __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; | 254 | __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; |
255 | 255 | ||
256 | void load_percpu_segment(int cpu) | ||
257 | { | ||
258 | #ifdef CONFIG_X86_32 | ||
259 | loadsegment(fs, __KERNEL_PERCPU); | ||
260 | #else | ||
261 | loadsegment(gs, 0); | ||
262 | wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); | ||
263 | #endif | ||
264 | } | ||
265 | |||
256 | /* Current gdt points %fs at the "master" per-cpu area: after this, | 266 | /* Current gdt points %fs at the "master" per-cpu area: after this, |
257 | * it's on the real one. */ | 267 | * it's on the real one. */ |
258 | void switch_to_new_gdt(void) | 268 | void switch_to_new_gdt(int cpu) |
259 | { | 269 | { |
260 | struct desc_ptr gdt_descr; | 270 | struct desc_ptr gdt_descr; |
261 | int cpu = smp_processor_id(); | ||
262 | 271 | ||
263 | gdt_descr.address = (long)get_cpu_gdt_table(cpu); | 272 | gdt_descr.address = (long)get_cpu_gdt_table(cpu); |
264 | gdt_descr.size = GDT_SIZE - 1; | 273 | gdt_descr.size = GDT_SIZE - 1; |
265 | load_gdt(&gdt_descr); | 274 | load_gdt(&gdt_descr); |
266 | /* Reload the per-cpu base */ | 275 | /* Reload the per-cpu base */ |
267 | #ifdef CONFIG_X86_32 | 276 | |
268 | loadsegment(fs, __KERNEL_PERCPU); | 277 | load_percpu_segment(cpu); |
269 | #else | ||
270 | loadsegment(gs, 0); | ||
271 | wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); | ||
272 | #endif | ||
273 | } | 278 | } |
274 | 279 | ||
275 | static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; | 280 | static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; |
@@ -993,7 +998,7 @@ void __cpuinit cpu_init(void) | |||
993 | * and set up the GDT descriptor: | 998 | * and set up the GDT descriptor: |
994 | */ | 999 | */ |
995 | 1000 | ||
996 | switch_to_new_gdt(); | 1001 | switch_to_new_gdt(cpu); |
997 | loadsegment(fs, 0); | 1002 | loadsegment(fs, 0); |
998 | 1003 | ||
999 | load_idt((const struct desc_ptr *)&idt_descr); | 1004 | load_idt((const struct desc_ptr *)&idt_descr); |
@@ -1098,7 +1103,7 @@ void __cpuinit cpu_init(void) | |||
1098 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | 1103 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); |
1099 | 1104 | ||
1100 | load_idt(&idt_descr); | 1105 | load_idt(&idt_descr); |
1101 | switch_to_new_gdt(); | 1106 | switch_to_new_gdt(cpu); |
1102 | 1107 | ||
1103 | /* | 1108 | /* |
1104 | * Set up and load the per-CPU TSS and LDT | 1109 | * Set up and load the per-CPU TSS and LDT |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 0d1e7ac439f4..ef91747bbed5 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
@@ -122,7 +122,7 @@ void __init setup_per_cpu_areas(void) | |||
122 | * area. Reload any changed state for the boot CPU. | 122 | * area. Reload any changed state for the boot CPU. |
123 | */ | 123 | */ |
124 | if (cpu == boot_cpu_id) | 124 | if (cpu == boot_cpu_id) |
125 | switch_to_new_gdt(); | 125 | switch_to_new_gdt(cpu); |
126 | 126 | ||
127 | DBG("PERCPU: cpu %4d %p\n", cpu, ptr); | 127 | DBG("PERCPU: cpu %4d %p\n", cpu, ptr); |
128 | } | 128 | } |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f9dbcff43546..612d3c74f6a3 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -1185,7 +1185,7 @@ out: | |||
1185 | void __init native_smp_prepare_boot_cpu(void) | 1185 | void __init native_smp_prepare_boot_cpu(void) |
1186 | { | 1186 | { |
1187 | int me = smp_processor_id(); | 1187 | int me = smp_processor_id(); |
1188 | switch_to_new_gdt(); | 1188 | switch_to_new_gdt(me); |
1189 | /* already set me in cpu_online_mask in boot_cpu_init() */ | 1189 | /* already set me in cpu_online_mask in boot_cpu_init() */ |
1190 | cpumask_set_cpu(me, cpu_callout_mask); | 1190 | cpumask_set_cpu(me, cpu_callout_mask); |
1191 | per_cpu(cpu_state, me) = CPU_ONLINE; | 1191 | per_cpu(cpu_state, me) = CPU_ONLINE; |
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 89fce1b6d01f..f4b2f27d19b9 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
@@ -259,7 +259,7 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, | |||
259 | * the cpu's, all of which are still in the mask. | 259 | * the cpu's, all of which are still in the mask. |
260 | */ | 260 | */ |
261 | __get_cpu_var(ptcstats).ptc_i++; | 261 | __get_cpu_var(ptcstats).ptc_i++; |
262 | return 0; | 262 | return flush_mask; |
263 | } | 263 | } |
264 | 264 | ||
265 | /* | 265 | /* |
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index c9740996430a..07f62d287ff0 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S | |||
@@ -22,6 +22,7 @@ PHDRS { | |||
22 | #ifdef CONFIG_SMP | 22 | #ifdef CONFIG_SMP |
23 | percpu PT_LOAD FLAGS(7); /* RWE */ | 23 | percpu PT_LOAD FLAGS(7); /* RWE */ |
24 | #endif | 24 | #endif |
25 | data.init2 PT_LOAD FLAGS(7); /* RWE */ | ||
25 | note PT_NOTE FLAGS(0); /* ___ */ | 26 | note PT_NOTE FLAGS(0); /* ___ */ |
26 | } | 27 | } |
27 | SECTIONS | 28 | SECTIONS |
@@ -215,7 +216,7 @@ SECTIONS | |||
215 | /* | 216 | /* |
216 | * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the | 217 | * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the |
217 | * output PHDR, so the next output section - __data_nosave - should | 218 | * output PHDR, so the next output section - __data_nosave - should |
218 | * switch it back to data.init. Also, pda should be at the head of | 219 | * start another section data.init2. Also, pda should be at the head of |
219 | * percpu area. Preallocate it and define the percpu offset symbol | 220 | * percpu area. Preallocate it and define the percpu offset symbol |
220 | * so that it can be accessed as a percpu variable. | 221 | * so that it can be accessed as a percpu variable. |
221 | */ | 222 | */ |
@@ -232,7 +233,7 @@ SECTIONS | |||
232 | __nosave_begin = .; | 233 | __nosave_begin = .; |
233 | .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { | 234 | .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { |
234 | *(.data.nosave) | 235 | *(.data.nosave) |
235 | } :data.init /* switch back to data.init, see PERCPU_VADDR() above */ | 236 | } :data.init2 /* use another section data.init2, see PERCPU_VADDR() above */ |
236 | . = ALIGN(PAGE_SIZE); | 237 | . = ALIGN(PAGE_SIZE); |
237 | __nosave_end = .; | 238 | __nosave_end = .; |
238 | 239 | ||
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 331cd6d56483..58c7cac3440d 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c | |||
@@ -1746,12 +1746,13 @@ static void __init voyager_smp_prepare_cpus(unsigned int max_cpus) | |||
1746 | 1746 | ||
1747 | static void __cpuinit voyager_smp_prepare_boot_cpu(void) | 1747 | static void __cpuinit voyager_smp_prepare_boot_cpu(void) |
1748 | { | 1748 | { |
1749 | switch_to_new_gdt(); | 1749 | int cpu = smp_processor_id(); |
1750 | switch_to_new_gdt(cpu); | ||
1750 | 1751 | ||
1751 | cpu_set(smp_processor_id(), cpu_online_map); | 1752 | cpu_set(cpu, cpu_online_map); |
1752 | cpu_set(smp_processor_id(), cpu_callout_map); | 1753 | cpu_set(cpu, cpu_callout_map); |
1753 | cpu_set(smp_processor_id(), cpu_possible_map); | 1754 | cpu_set(cpu, cpu_possible_map); |
1754 | cpu_set(smp_processor_id(), cpu_present_map); | 1755 | cpu_set(cpu, cpu_present_map); |
1755 | } | 1756 | } |
1756 | 1757 | ||
1757 | static int __cpuinit voyager_cpu_up(unsigned int cpu) | 1758 | static int __cpuinit voyager_cpu_up(unsigned int cpu) |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index ff6d530ccc77..cd022c43dfbc 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -917,6 +917,9 @@ asmlinkage void __init xen_start_kernel(void) | |||
917 | have_vcpu_info_placement = 0; | 917 | have_vcpu_info_placement = 0; |
918 | #endif | 918 | #endif |
919 | 919 | ||
920 | /* setup percpu state */ | ||
921 | load_percpu_segment(0); | ||
922 | |||
920 | xen_smp_init(); | 923 | xen_smp_init(); |
921 | 924 | ||
922 | /* Get mfn list */ | 925 | /* Get mfn list */ |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 7735e3dd359c..88d5d5ec6beb 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -170,7 +170,8 @@ static void __init xen_smp_prepare_boot_cpu(void) | |||
170 | 170 | ||
171 | /* We've switched to the "real" per-cpu gdt, so make sure the | 171 | /* We've switched to the "real" per-cpu gdt, so make sure the |
172 | old memory can be recycled */ | 172 | old memory can be recycled */ |
173 | make_lowmem_page_readwrite(&per_cpu_var(gdt_page)); | 173 | make_lowmem_page_readwrite(__per_cpu_load + |
174 | (unsigned long)&per_cpu_var(gdt_page)); | ||
174 | 175 | ||
175 | xen_setup_vcpu_info_placement(); | 176 | xen_setup_vcpu_info_placement(); |
176 | } | 177 | } |
@@ -235,6 +236,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) | |||
235 | ctxt->user_regs.ss = __KERNEL_DS; | 236 | ctxt->user_regs.ss = __KERNEL_DS; |
236 | #ifdef CONFIG_X86_32 | 237 | #ifdef CONFIG_X86_32 |
237 | ctxt->user_regs.fs = __KERNEL_PERCPU; | 238 | ctxt->user_regs.fs = __KERNEL_PERCPU; |
239 | #else | ||
240 | ctxt->gs_base_kernel = per_cpu_offset(cpu); | ||
238 | #endif | 241 | #endif |
239 | ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle; | 242 | ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle; |
240 | ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ | 243 | ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ |