aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/smpboot.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2007-05-02 13:27:16 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:16 -0400
commit7c3576d261ce046789a7db14f43303f8120910c7 (patch)
treead27a8459bbcdb183fe2411aec3b840942992ad5 /arch/i386/kernel/smpboot.c
parent7a61d35d4b4056e7711031202da7605e052f4137 (diff)
[PATCH] i386: Convert PDA into the percpu section
Currently x86 (similar to x84-64) has a special per-cpu structure called "i386_pda" which can be easily and efficiently referenced via the %fs register. An ELF section is more flexible than a structure, allowing any piece of code to use this area. Indeed, such a section already exists: the per-cpu area. So this patch: (1) Removes the PDA and uses per-cpu variables for each current member. (2) Replaces the __KERNEL_PDA segment with __KERNEL_PERCPU. (3) Creates a per-cpu mirror of __per_cpu_offset called this_cpu_off, which can be used to calculate addresses for this CPU's variables. (4) Simplifies startup, because %fs doesn't need to be loaded with a special segment at early boot; it can be deferred until the first percpu area is allocated (or never for UP). The result is less code and one less x86-specific concept. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r--arch/i386/kernel/smpboot.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 61e2842add36..f79b6233db78 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -53,7 +53,6 @@
53#include <asm/desc.h> 53#include <asm/desc.h>
54#include <asm/arch_hooks.h> 54#include <asm/arch_hooks.h>
55#include <asm/nmi.h> 55#include <asm/nmi.h>
56#include <asm/pda.h>
57 56
58#include <mach_apic.h> 57#include <mach_apic.h>
59#include <mach_wakecpu.h> 58#include <mach_wakecpu.h>
@@ -99,6 +98,9 @@ EXPORT_SYMBOL(x86_cpu_to_apicid);
99 98
100u8 apicid_2_node[MAX_APICID]; 99u8 apicid_2_node[MAX_APICID];
101 100
101DEFINE_PER_CPU(unsigned long, this_cpu_off);
102EXPORT_PER_CPU_SYMBOL(this_cpu_off);
103
102/* 104/*
103 * Trampoline 80x86 program as an array. 105 * Trampoline 80x86 program as an array.
104 */ 106 */
@@ -456,7 +458,6 @@ extern struct {
456 void * esp; 458 void * esp;
457 unsigned short ss; 459 unsigned short ss;
458} stack_start; 460} stack_start;
459extern struct i386_pda *start_pda;
460 461
461#ifdef CONFIG_NUMA 462#ifdef CONFIG_NUMA
462 463
@@ -784,20 +785,17 @@ static inline struct task_struct * alloc_idle_task(int cpu)
784/* Initialize the CPU's GDT. This is either the boot CPU doing itself 785/* Initialize the CPU's GDT. This is either the boot CPU doing itself
785 (still using the master per-cpu area), or a CPU doing it for a 786 (still using the master per-cpu area), or a CPU doing it for a
786 secondary which will soon come up. */ 787 secondary which will soon come up. */
787static __cpuinit void init_gdt(int cpu, struct task_struct *idle) 788static __cpuinit void init_gdt(int cpu)
788{ 789{
789 struct desc_struct *gdt = get_cpu_gdt_table(cpu); 790 struct desc_struct *gdt = get_cpu_gdt_table(cpu);
790 struct i386_pda *pda = &per_cpu(_cpu_pda, cpu);
791 791
792 pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a, 792 pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a,
793 (u32 *)&gdt[GDT_ENTRY_PDA].b, 793 (u32 *)&gdt[GDT_ENTRY_PERCPU].b,
794 (unsigned long)pda, sizeof(*pda) - 1, 794 __per_cpu_offset[cpu], 0xFFFFF,
795 0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */ 795 0x80 | DESCTYPE_S | 0x2, 0x8);
796 796
797 memset(pda, 0, sizeof(*pda)); 797 per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
798 pda->_pda = pda; 798 per_cpu(cpu_number, cpu) = cpu;
799 pda->cpu_number = cpu;
800 pda->pcurrent = idle;
801} 799}
802 800
803/* Defined in head.S */ 801/* Defined in head.S */
@@ -824,9 +822,9 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
824 if (IS_ERR(idle)) 822 if (IS_ERR(idle))
825 panic("failed fork for CPU %d", cpu); 823 panic("failed fork for CPU %d", cpu);
826 824
827 init_gdt(cpu, idle); 825 init_gdt(cpu);
826 per_cpu(current_task, cpu) = idle;
828 early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); 827 early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
829 start_pda = cpu_pda(cpu);
830 828
831 idle->thread.eip = (unsigned long) start_secondary; 829 idle->thread.eip = (unsigned long) start_secondary;
832 /* start_eip had better be page-aligned! */ 830 /* start_eip had better be page-aligned! */
@@ -1188,14 +1186,14 @@ static inline void switch_to_new_gdt(void)
1188 gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); 1186 gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
1189 gdt_descr.size = GDT_SIZE - 1; 1187 gdt_descr.size = GDT_SIZE - 1;
1190 load_gdt(&gdt_descr); 1188 load_gdt(&gdt_descr);
1191 asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory"); 1189 asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
1192} 1190}
1193 1191
1194void __init native_smp_prepare_boot_cpu(void) 1192void __init native_smp_prepare_boot_cpu(void)
1195{ 1193{
1196 unsigned int cpu = smp_processor_id(); 1194 unsigned int cpu = smp_processor_id();
1197 1195
1198 init_gdt(cpu, current); 1196 init_gdt(cpu);
1199 switch_to_new_gdt(); 1197 switch_to_new_gdt();
1200 1198
1201 cpu_set(cpu, cpu_online_map); 1199 cpu_set(cpu, cpu_online_map);