diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2006-12-06 20:14:02 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:02 -0500 |
commit | 62111195800d80c66cdc69063ea3145878c99fbf (patch) | |
tree | 35bc9792b3ac232e70e106ff2f4c0193c3bb72ff /arch/i386/kernel/smpboot.c | |
parent | 9ca36101a8d74704d78f10910f89d62de96f9dc8 (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.c | 28 |
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) | |||
536 | static void __devinit start_secondary(void *unused) | 537 | static 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 */ | ||
605 | extern struct { | 607 | extern struct { |
606 | void * esp; | 608 | void * esp; |
607 | unsigned short ss; | 609 | unsigned short ss; |
608 | } stack_start; | 610 | } stack_start; |
611 | extern struct i386_pda *start_pda; | ||
612 | extern 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; |