diff options
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 02a9b66b6ac3..4bf0e3c83b8b 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -33,6 +33,11 @@ | |||
33 | * Dave Jones : Report invalid combinations of Athlon CPUs. | 33 | * Dave Jones : Report invalid combinations of Athlon CPUs. |
34 | * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ | 34 | * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ |
35 | 35 | ||
36 | |||
37 | /* SMP boot always wants to use real time delay to allow sufficient time for | ||
38 | * the APs to come online */ | ||
39 | #define USE_REAL_TIME_DELAY | ||
40 | |||
36 | #include <linux/module.h> | 41 | #include <linux/module.h> |
37 | #include <linux/init.h> | 42 | #include <linux/init.h> |
38 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
@@ -52,6 +57,8 @@ | |||
52 | #include <asm/desc.h> | 57 | #include <asm/desc.h> |
53 | #include <asm/arch_hooks.h> | 58 | #include <asm/arch_hooks.h> |
54 | #include <asm/nmi.h> | 59 | #include <asm/nmi.h> |
60 | #include <asm/pda.h> | ||
61 | #include <asm/genapic.h> | ||
55 | 62 | ||
56 | #include <mach_apic.h> | 63 | #include <mach_apic.h> |
57 | #include <mach_wakecpu.h> | 64 | #include <mach_wakecpu.h> |
@@ -536,11 +543,11 @@ set_cpu_sibling_map(int cpu) | |||
536 | static void __devinit start_secondary(void *unused) | 543 | static void __devinit start_secondary(void *unused) |
537 | { | 544 | { |
538 | /* | 545 | /* |
539 | * Dont put anything before smp_callin(), SMP | 546 | * Don't put *anything* before secondary_cpu_init(), SMP |
540 | * booting is too fragile that we want to limit the | 547 | * booting is too fragile that we want to limit the |
541 | * things done here to the most necessary things. | 548 | * things done here to the most necessary things. |
542 | */ | 549 | */ |
543 | cpu_init(); | 550 | secondary_cpu_init(); |
544 | preempt_disable(); | 551 | preempt_disable(); |
545 | smp_callin(); | 552 | smp_callin(); |
546 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) | 553 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) |
@@ -599,13 +606,16 @@ void __devinit initialize_secondary(void) | |||
599 | "movl %0,%%esp\n\t" | 606 | "movl %0,%%esp\n\t" |
600 | "jmp *%1" | 607 | "jmp *%1" |
601 | : | 608 | : |
602 | :"r" (current->thread.esp),"r" (current->thread.eip)); | 609 | :"m" (current->thread.esp),"m" (current->thread.eip)); |
603 | } | 610 | } |
604 | 611 | ||
612 | /* Static state in head.S used to set up a CPU */ | ||
605 | extern struct { | 613 | extern struct { |
606 | void * esp; | 614 | void * esp; |
607 | unsigned short ss; | 615 | unsigned short ss; |
608 | } stack_start; | 616 | } stack_start; |
617 | extern struct i386_pda *start_pda; | ||
618 | extern struct Xgt_desc_struct cpu_gdt_descr; | ||
609 | 619 | ||
610 | #ifdef CONFIG_NUMA | 620 | #ifdef CONFIG_NUMA |
611 | 621 | ||
@@ -936,9 +946,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu) | |||
936 | unsigned long start_eip; | 946 | unsigned long start_eip; |
937 | unsigned short nmi_high = 0, nmi_low = 0; | 947 | unsigned short nmi_high = 0, nmi_low = 0; |
938 | 948 | ||
939 | ++cpucount; | ||
940 | alternatives_smp_switch(1); | ||
941 | |||
942 | /* | 949 | /* |
943 | * We can't use kernel_thread since we must avoid to | 950 | * We can't use kernel_thread since we must avoid to |
944 | * reschedule the child. | 951 | * reschedule the child. |
@@ -946,15 +953,30 @@ static int __devinit do_boot_cpu(int apicid, int cpu) | |||
946 | idle = alloc_idle_task(cpu); | 953 | idle = alloc_idle_task(cpu); |
947 | if (IS_ERR(idle)) | 954 | if (IS_ERR(idle)) |
948 | panic("failed fork for CPU %d", cpu); | 955 | panic("failed fork for CPU %d", cpu); |
956 | |||
957 | /* Pre-allocate and initialize the CPU's GDT and PDA so it | ||
958 | doesn't have to do any memory allocation during the | ||
959 | delicate CPU-bringup phase. */ | ||
960 | if (!init_gdt(cpu, idle)) { | ||
961 | printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu); | ||
962 | return -1; /* ? */ | ||
963 | } | ||
964 | |||
949 | idle->thread.eip = (unsigned long) start_secondary; | 965 | idle->thread.eip = (unsigned long) start_secondary; |
950 | /* start_eip had better be page-aligned! */ | 966 | /* start_eip had better be page-aligned! */ |
951 | start_eip = setup_trampoline(); | 967 | start_eip = setup_trampoline(); |
952 | 968 | ||
969 | ++cpucount; | ||
970 | alternatives_smp_switch(1); | ||
971 | |||
953 | /* So we see what's up */ | 972 | /* So we see what's up */ |
954 | printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); | 973 | 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 */ | 974 | /* Stack for startup_32 can be just as for start_secondary onwards */ |
956 | stack_start.esp = (void *) idle->thread.esp; | 975 | stack_start.esp = (void *) idle->thread.esp; |
957 | 976 | ||
977 | start_pda = cpu_pda(cpu); | ||
978 | cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu); | ||
979 | |||
958 | irq_ctx_init(cpu); | 980 | irq_ctx_init(cpu); |
959 | 981 | ||
960 | x86_cpu_to_apicid[cpu] = apicid; | 982 | x86_cpu_to_apicid[cpu] = apicid; |
@@ -1109,34 +1131,15 @@ exit: | |||
1109 | } | 1131 | } |
1110 | #endif | 1132 | #endif |
1111 | 1133 | ||
1112 | static void smp_tune_scheduling (void) | 1134 | static void smp_tune_scheduling(void) |
1113 | { | 1135 | { |
1114 | unsigned long cachesize; /* kB */ | 1136 | unsigned long cachesize; /* kB */ |
1115 | unsigned long bandwidth = 350; /* MB/s */ | ||
1116 | /* | ||
1117 | * Rough estimation for SMP scheduling, this is the number of | ||
1118 | * cycles it takes for a fully memory-limited process to flush | ||
1119 | * the SMP-local cache. | ||
1120 | * | ||
1121 | * (For a P5 this pretty much means we will choose another idle | ||
1122 | * CPU almost always at wakeup time (this is due to the small | ||
1123 | * L1 cache), on PIIs it's around 50-100 usecs, depending on | ||
1124 | * the cache size) | ||
1125 | */ | ||
1126 | 1137 | ||
1127 | if (!cpu_khz) { | 1138 | if (cpu_khz) { |
1128 | /* | ||
1129 | * this basically disables processor-affinity | ||
1130 | * scheduling on SMP without a TSC. | ||
1131 | */ | ||
1132 | return; | ||
1133 | } else { | ||
1134 | cachesize = boot_cpu_data.x86_cache_size; | 1139 | cachesize = boot_cpu_data.x86_cache_size; |
1135 | if (cachesize == -1) { | 1140 | |
1136 | cachesize = 16; /* Pentiums, 2x8kB cache */ | 1141 | if (cachesize > 0) |
1137 | bandwidth = 100; | 1142 | max_cache_size = cachesize * 1024; |
1138 | } | ||
1139 | max_cache_size = cachesize * 1024; | ||
1140 | } | 1143 | } |
1141 | } | 1144 | } |
1142 | 1145 | ||
@@ -1462,6 +1465,12 @@ int __devinit __cpu_up(unsigned int cpu) | |||
1462 | cpu_set(cpu, smp_commenced_mask); | 1465 | cpu_set(cpu, smp_commenced_mask); |
1463 | while (!cpu_isset(cpu, cpu_online_map)) | 1466 | while (!cpu_isset(cpu, cpu_online_map)) |
1464 | cpu_relax(); | 1467 | cpu_relax(); |
1468 | |||
1469 | #ifdef CONFIG_X86_GENERICARCH | ||
1470 | if (num_online_cpus() > 8 && genapic == &apic_default) | ||
1471 | panic("Default flat APIC routing can't be used with > 8 cpus\n"); | ||
1472 | #endif | ||
1473 | |||
1465 | return 0; | 1474 | return 0; |
1466 | } | 1475 | } |
1467 | 1476 | ||