diff options
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 27 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 99 |
2 files changed, 79 insertions, 47 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a4bcbacdbe0b..a135239badb7 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
| @@ -1221,17 +1221,6 @@ static void dbg_restore_debug_regs(void) | |||
| 1221 | #define dbg_restore_debug_regs() | 1221 | #define dbg_restore_debug_regs() |
| 1222 | #endif /* ! CONFIG_KGDB */ | 1222 | #endif /* ! CONFIG_KGDB */ |
| 1223 | 1223 | ||
| 1224 | static void wait_for_master_cpu(int cpu) | ||
| 1225 | { | ||
| 1226 | /* | ||
| 1227 | * wait for ACK from master CPU before continuing | ||
| 1228 | * with AP initialization | ||
| 1229 | */ | ||
| 1230 | WARN_ON(cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)); | ||
| 1231 | while (!cpumask_test_cpu(cpu, cpu_callout_mask)) | ||
| 1232 | cpu_relax(); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | /* | 1224 | /* |
| 1236 | * cpu_init() initializes state that is per-CPU. Some data is already | 1225 | * cpu_init() initializes state that is per-CPU. Some data is already |
| 1237 | * initialized (naturally) in the bootstrap process, such as the GDT | 1226 | * initialized (naturally) in the bootstrap process, such as the GDT |
| @@ -1247,17 +1236,16 @@ void cpu_init(void) | |||
| 1247 | struct task_struct *me; | 1236 | struct task_struct *me; |
| 1248 | struct tss_struct *t; | 1237 | struct tss_struct *t; |
| 1249 | unsigned long v; | 1238 | unsigned long v; |
| 1250 | int cpu = stack_smp_processor_id(); | 1239 | int cpu; |
| 1251 | int i; | 1240 | int i; |
| 1252 | 1241 | ||
| 1253 | wait_for_master_cpu(cpu); | ||
| 1254 | |||
| 1255 | /* | 1242 | /* |
| 1256 | * Load microcode on this cpu if a valid microcode is available. | 1243 | * Load microcode on this cpu if a valid microcode is available. |
| 1257 | * This is early microcode loading procedure. | 1244 | * This is early microcode loading procedure. |
| 1258 | */ | 1245 | */ |
| 1259 | load_ucode_ap(); | 1246 | load_ucode_ap(); |
| 1260 | 1247 | ||
| 1248 | cpu = stack_smp_processor_id(); | ||
| 1261 | t = &per_cpu(init_tss, cpu); | 1249 | t = &per_cpu(init_tss, cpu); |
| 1262 | oist = &per_cpu(orig_ist, cpu); | 1250 | oist = &per_cpu(orig_ist, cpu); |
| 1263 | 1251 | ||
| @@ -1269,6 +1257,9 @@ void cpu_init(void) | |||
| 1269 | 1257 | ||
| 1270 | me = current; | 1258 | me = current; |
| 1271 | 1259 | ||
| 1260 | if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) | ||
| 1261 | panic("CPU#%d already initialized!\n", cpu); | ||
| 1262 | |||
| 1272 | pr_debug("Initializing CPU#%d\n", cpu); | 1263 | pr_debug("Initializing CPU#%d\n", cpu); |
| 1273 | 1264 | ||
| 1274 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | 1265 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); |
| @@ -1345,10 +1336,14 @@ void cpu_init(void) | |||
| 1345 | struct tss_struct *t = &per_cpu(init_tss, cpu); | 1336 | struct tss_struct *t = &per_cpu(init_tss, cpu); |
| 1346 | struct thread_struct *thread = &curr->thread; | 1337 | struct thread_struct *thread = &curr->thread; |
| 1347 | 1338 | ||
| 1348 | wait_for_master_cpu(cpu); | ||
| 1349 | |||
| 1350 | show_ucode_info_early(); | 1339 | show_ucode_info_early(); |
| 1351 | 1340 | ||
| 1341 | if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) { | ||
| 1342 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); | ||
| 1343 | for (;;) | ||
| 1344 | local_irq_enable(); | ||
| 1345 | } | ||
| 1346 | |||
| 1352 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); | 1347 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); |
| 1353 | 1348 | ||
| 1354 | if (cpu_has_vme || cpu_has_tsc || cpu_has_de) | 1349 | if (cpu_has_vme || cpu_has_tsc || cpu_has_de) |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index bc52fac39dd3..ae2fd975b782 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -111,6 +111,7 @@ atomic_t init_deasserted; | |||
| 111 | static void smp_callin(void) | 111 | static void smp_callin(void) |
| 112 | { | 112 | { |
| 113 | int cpuid, phys_id; | 113 | int cpuid, phys_id; |
| 114 | unsigned long timeout; | ||
| 114 | 115 | ||
| 115 | /* | 116 | /* |
| 116 | * If waken up by an INIT in an 82489DX configuration | 117 | * If waken up by an INIT in an 82489DX configuration |
| @@ -129,6 +130,37 @@ static void smp_callin(void) | |||
| 129 | * (This works even if the APIC is not enabled.) | 130 | * (This works even if the APIC is not enabled.) |
| 130 | */ | 131 | */ |
| 131 | phys_id = read_apic_id(); | 132 | phys_id = read_apic_id(); |
| 133 | if (cpumask_test_cpu(cpuid, cpu_callin_mask)) { | ||
| 134 | panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, | ||
| 135 | phys_id, cpuid); | ||
| 136 | } | ||
| 137 | pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); | ||
| 138 | |||
| 139 | /* | ||
| 140 | * STARTUP IPIs are fragile beasts as they might sometimes | ||
| 141 | * trigger some glue motherboard logic. Complete APIC bus | ||
| 142 | * silence for 1 second, this overestimates the time the | ||
| 143 | * boot CPU is spending to send the up to 2 STARTUP IPIs | ||
| 144 | * by a factor of two. This should be enough. | ||
| 145 | */ | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Waiting 2s total for startup (udelay is not yet working) | ||
| 149 | */ | ||
| 150 | timeout = jiffies + 2*HZ; | ||
| 151 | while (time_before(jiffies, timeout)) { | ||
| 152 | /* | ||
| 153 | * Has the boot CPU finished it's STARTUP sequence? | ||
| 154 | */ | ||
| 155 | if (cpumask_test_cpu(cpuid, cpu_callout_mask)) | ||
| 156 | break; | ||
| 157 | cpu_relax(); | ||
| 158 | } | ||
| 159 | |||
| 160 | if (!time_before(jiffies, timeout)) { | ||
| 161 | panic("%s: CPU%d started up but did not get a callout!\n", | ||
| 162 | __func__, cpuid); | ||
| 163 | } | ||
| 132 | 164 | ||
| 133 | /* | 165 | /* |
| 134 | * the boot CPU has finished the init stage and is spinning | 166 | * the boot CPU has finished the init stage and is spinning |
| @@ -718,8 +750,8 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
| 718 | unsigned long start_ip = real_mode_header->trampoline_start; | 750 | unsigned long start_ip = real_mode_header->trampoline_start; |
| 719 | 751 | ||
| 720 | unsigned long boot_error = 0; | 752 | unsigned long boot_error = 0; |
| 753 | int timeout; | ||
| 721 | int cpu0_nmi_registered = 0; | 754 | int cpu0_nmi_registered = 0; |
| 722 | unsigned long timeout; | ||
| 723 | 755 | ||
| 724 | /* Just in case we booted with a single CPU. */ | 756 | /* Just in case we booted with a single CPU. */ |
| 725 | alternatives_enable_smp(); | 757 | alternatives_enable_smp(); |
| @@ -767,15 +799,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
| 767 | } | 799 | } |
| 768 | 800 | ||
| 769 | /* | 801 | /* |
| 770 | * AP might wait on cpu_callout_mask in cpu_init() with | ||
| 771 | * cpu_initialized_mask set if previous attempt to online | ||
| 772 | * it timed-out. Clear cpu_initialized_mask so that after | ||
| 773 | * INIT/SIPI it could start with a clean state. | ||
| 774 | */ | ||
| 775 | cpumask_clear_cpu(cpu, cpu_initialized_mask); | ||
| 776 | smp_mb(); | ||
| 777 | |||
| 778 | /* | ||
| 779 | * Wake up a CPU in difference cases: | 802 | * Wake up a CPU in difference cases: |
| 780 | * - Use the method in the APIC driver if it's defined | 803 | * - Use the method in the APIC driver if it's defined |
| 781 | * Otherwise, | 804 | * Otherwise, |
| @@ -787,41 +810,55 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
| 787 | boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid, | 810 | boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid, |
| 788 | &cpu0_nmi_registered); | 811 | &cpu0_nmi_registered); |
| 789 | 812 | ||
| 790 | |||
| 791 | if (!boot_error) { | 813 | if (!boot_error) { |
| 792 | /* | 814 | /* |
| 793 | * Wait 10s total for a response from AP | 815 | * allow APs to start initializing. |
| 794 | */ | 816 | */ |
| 795 | boot_error = -1; | 817 | pr_debug("Before Callout %d\n", cpu); |
| 796 | timeout = jiffies + 10*HZ; | 818 | cpumask_set_cpu(cpu, cpu_callout_mask); |
| 797 | while (time_before(jiffies, timeout)) { | 819 | pr_debug("After Callout %d\n", cpu); |
| 798 | if (cpumask_test_cpu(cpu, cpu_initialized_mask)) { | ||
| 799 | /* | ||
| 800 | * Tell AP to proceed with initialization | ||
| 801 | */ | ||
| 802 | cpumask_set_cpu(cpu, cpu_callout_mask); | ||
| 803 | boot_error = 0; | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | udelay(100); | ||
| 807 | schedule(); | ||
| 808 | } | ||
| 809 | } | ||
| 810 | 820 | ||
| 811 | if (!boot_error) { | ||
| 812 | /* | 821 | /* |
| 813 | * Wait till AP completes initial initialization | 822 | * Wait 5s total for a response |
| 814 | */ | 823 | */ |
| 815 | while (!cpumask_test_cpu(cpu, cpu_callin_mask)) { | 824 | for (timeout = 0; timeout < 50000; timeout++) { |
| 825 | if (cpumask_test_cpu(cpu, cpu_callin_mask)) | ||
| 826 | break; /* It has booted */ | ||
| 827 | udelay(100); | ||
| 816 | /* | 828 | /* |
| 817 | * Allow other tasks to run while we wait for the | 829 | * Allow other tasks to run while we wait for the |
| 818 | * AP to come online. This also gives a chance | 830 | * AP to come online. This also gives a chance |
| 819 | * for the MTRR work(triggered by the AP coming online) | 831 | * for the MTRR work(triggered by the AP coming online) |
| 820 | * to be completed in the stop machine context. | 832 | * to be completed in the stop machine context. |
| 821 | */ | 833 | */ |
| 822 | udelay(100); | ||
| 823 | schedule(); | 834 | schedule(); |
| 824 | } | 835 | } |
| 836 | |||
| 837 | if (cpumask_test_cpu(cpu, cpu_callin_mask)) { | ||
| 838 | print_cpu_msr(&cpu_data(cpu)); | ||
| 839 | pr_debug("CPU%d: has booted.\n", cpu); | ||
| 840 | } else { | ||
| 841 | boot_error = 1; | ||
| 842 | if (*trampoline_status == 0xA5A5A5A5) | ||
| 843 | /* trampoline started but...? */ | ||
| 844 | pr_err("CPU%d: Stuck ??\n", cpu); | ||
| 845 | else | ||
| 846 | /* trampoline code not run */ | ||
| 847 | pr_err("CPU%d: Not responding\n", cpu); | ||
| 848 | if (apic->inquire_remote_apic) | ||
| 849 | apic->inquire_remote_apic(apicid); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | if (boot_error) { | ||
| 854 | /* Try to put things back the way they were before ... */ | ||
| 855 | numa_remove_cpu(cpu); /* was set by numa_add_cpu */ | ||
| 856 | |||
| 857 | /* was set by do_boot_cpu() */ | ||
| 858 | cpumask_clear_cpu(cpu, cpu_callout_mask); | ||
| 859 | |||
| 860 | /* was set by cpu_init() */ | ||
| 861 | cpumask_clear_cpu(cpu, cpu_initialized_mask); | ||
| 825 | } | 862 | } |
| 826 | 863 | ||
| 827 | /* mark "stuck" area as not stuck */ | 864 | /* mark "stuck" area as not stuck */ |
