diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2007-05-02 13:27:16 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-05-02 13:27:16 -0400 |
commit | 7c3576d261ce046789a7db14f43303f8120910c7 (patch) | |
tree | ad27a8459bbcdb183fe2411aec3b840942992ad5 /arch/i386/kernel/smpboot.c | |
parent | 7a61d35d4b4056e7711031202da7605e052f4137 (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.c | 30 |
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 | ||
100 | u8 apicid_2_node[MAX_APICID]; | 99 | u8 apicid_2_node[MAX_APICID]; |
101 | 100 | ||
101 | DEFINE_PER_CPU(unsigned long, this_cpu_off); | ||
102 | EXPORT_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; |
459 | extern 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. */ |
787 | static __cpuinit void init_gdt(int cpu, struct task_struct *idle) | 788 | static __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 | ||
1194 | void __init native_smp_prepare_boot_cpu(void) | 1192 | void __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); |