aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/smpboot.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2006-12-06 20:14:02 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:02 -0500
commit62111195800d80c66cdc69063ea3145878c99fbf (patch)
tree35bc9792b3ac232e70e106ff2f4c0193c3bb72ff /arch/i386/kernel/smpboot.c
parent9ca36101a8d74704d78f10910f89d62de96f9dc8 (diff)
[PATCH] i386: Initialize the per-CPU data area
When a CPU is brought up, a PDA and GDT are allocated for it. The GDT's __KERNEL_PDA entry is pointed to the allocated PDA memory, so that all references using this segment descriptor will refer to the PDA. This patch rearranges CPU initialization a bit, so that the GDT/PDA are set up as early as possible in cpu_init(). Also for secondary CPUs, GDT+PDA are preallocated and initialized so all the secondary CPU needs to do is set up the ldt and load %gs. This will be important once smp_processor_id() and current use the PDA. In all cases, the PDA is set up in head.S, before a CPU starts running C code, so the PDA is always available. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Chuck Ebbert <76306.1226@compuserve.com> Cc: Zachary Amsden <zach@vmware.com> Cc: Jan Beulich <jbeulich@novell.com> Cc: Andi Kleen <ak@suse.de> Cc: James Bottomley <James.Bottomley@SteelEye.com> Cc: Matt Tolentino <matthew.e.tolentino@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r--arch/i386/kernel/smpboot.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 4bb8b77cd65b..095636620fa2 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -52,6 +52,7 @@
52#include <asm/desc.h> 52#include <asm/desc.h>
53#include <asm/arch_hooks.h> 53#include <asm/arch_hooks.h>
54#include <asm/nmi.h> 54#include <asm/nmi.h>
55#include <asm/pda.h>
55 56
56#include <mach_apic.h> 57#include <mach_apic.h>
57#include <mach_wakecpu.h> 58#include <mach_wakecpu.h>
@@ -536,11 +537,11 @@ set_cpu_sibling_map(int cpu)
536static void __devinit start_secondary(void *unused) 537static void __devinit start_secondary(void *unused)
537{ 538{
538 /* 539 /*
539 * Dont put anything before smp_callin(), SMP 540 * Don't put *anything* before secondary_cpu_init(), SMP
540 * booting is too fragile that we want to limit the 541 * booting is too fragile that we want to limit the
541 * things done here to the most necessary things. 542 * things done here to the most necessary things.
542 */ 543 */
543 cpu_init(); 544 secondary_cpu_init();
544 preempt_disable(); 545 preempt_disable();
545 smp_callin(); 546 smp_callin();
546 while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) 547 while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
@@ -599,13 +600,16 @@ void __devinit initialize_secondary(void)
599 "movl %0,%%esp\n\t" 600 "movl %0,%%esp\n\t"
600 "jmp *%1" 601 "jmp *%1"
601 : 602 :
602 :"r" (current->thread.esp),"r" (current->thread.eip)); 603 :"m" (current->thread.esp),"m" (current->thread.eip));
603} 604}
604 605
606/* Static state in head.S used to set up a CPU */
605extern struct { 607extern struct {
606 void * esp; 608 void * esp;
607 unsigned short ss; 609 unsigned short ss;
608} stack_start; 610} stack_start;
611extern struct i386_pda *start_pda;
612extern struct Xgt_desc_struct cpu_gdt_descr;
609 613
610#ifdef CONFIG_NUMA 614#ifdef CONFIG_NUMA
611 615
@@ -936,9 +940,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
936 unsigned long start_eip; 940 unsigned long start_eip;
937 unsigned short nmi_high = 0, nmi_low = 0; 941 unsigned short nmi_high = 0, nmi_low = 0;
938 942
939 ++cpucount;
940 alternatives_smp_switch(1);
941
942 /* 943 /*
943 * We can't use kernel_thread since we must avoid to 944 * We can't use kernel_thread since we must avoid to
944 * reschedule the child. 945 * reschedule the child.
@@ -946,15 +947,30 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
946 idle = alloc_idle_task(cpu); 947 idle = alloc_idle_task(cpu);
947 if (IS_ERR(idle)) 948 if (IS_ERR(idle))
948 panic("failed fork for CPU %d", cpu); 949 panic("failed fork for CPU %d", cpu);
950
951 /* Pre-allocate and initialize the CPU's GDT and PDA so it
952 doesn't have to do any memory allocation during the
953 delicate CPU-bringup phase. */
954 if (!init_gdt(cpu, idle)) {
955 printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu);
956 return -1; /* ? */
957 }
958
949 idle->thread.eip = (unsigned long) start_secondary; 959 idle->thread.eip = (unsigned long) start_secondary;
950 /* start_eip had better be page-aligned! */ 960 /* start_eip had better be page-aligned! */
951 start_eip = setup_trampoline(); 961 start_eip = setup_trampoline();
952 962
963 ++cpucount;
964 alternatives_smp_switch(1);
965
953 /* So we see what's up */ 966 /* So we see what's up */
954 printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); 967 printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
955 /* Stack for startup_32 can be just as for start_secondary onwards */ 968 /* Stack for startup_32 can be just as for start_secondary onwards */
956 stack_start.esp = (void *) idle->thread.esp; 969 stack_start.esp = (void *) idle->thread.esp;
957 970
971 start_pda = cpu_pda(cpu);
972 cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu);
973
958 irq_ctx_init(cpu); 974 irq_ctx_init(cpu);
959 975
960 x86_cpu_to_apicid[cpu] = apicid; 976 x86_cpu_to_apicid[cpu] = apicid;