diff options
Diffstat (limited to 'arch/x86_64/kernel/smpboot.c')
-rw-r--r-- | arch/x86_64/kernel/smpboot.c | 91 |
1 files changed, 29 insertions, 62 deletions
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index b15761ff4101..e12d7baeb33e 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/mm.h> | 44 | #include <linux/mm.h> |
45 | #include <linux/kernel_stat.h> | 45 | #include <linux/kernel_stat.h> |
46 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
47 | #include <linux/irq.h> | ||
48 | #include <linux/bootmem.h> | 47 | #include <linux/bootmem.h> |
49 | #include <linux/thread_info.h> | 48 | #include <linux/thread_info.h> |
50 | #include <linux/module.h> | 49 | #include <linux/module.h> |
@@ -58,17 +57,19 @@ | |||
58 | #include <asm/tlbflush.h> | 57 | #include <asm/tlbflush.h> |
59 | #include <asm/proto.h> | 58 | #include <asm/proto.h> |
60 | #include <asm/nmi.h> | 59 | #include <asm/nmi.h> |
60 | #include <asm/irq.h> | ||
61 | #include <asm/hw_irq.h> | ||
61 | 62 | ||
62 | /* Number of siblings per CPU package */ | 63 | /* Number of siblings per CPU package */ |
63 | int smp_num_siblings = 1; | 64 | int smp_num_siblings = 1; |
64 | /* Package ID of each logical CPU */ | 65 | /* Package ID of each logical CPU */ |
65 | u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; | 66 | u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
66 | u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; | 67 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
67 | EXPORT_SYMBOL(phys_proc_id); | 68 | EXPORT_SYMBOL(phys_proc_id); |
68 | EXPORT_SYMBOL(cpu_core_id); | 69 | EXPORT_SYMBOL(cpu_core_id); |
69 | 70 | ||
70 | /* Bitmask of currently online CPUs */ | 71 | /* Bitmask of currently online CPUs */ |
71 | cpumask_t cpu_online_map; | 72 | cpumask_t cpu_online_map __read_mostly; |
72 | 73 | ||
73 | EXPORT_SYMBOL(cpu_online_map); | 74 | EXPORT_SYMBOL(cpu_online_map); |
74 | 75 | ||
@@ -88,8 +89,8 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; | |||
88 | /* Set when the idlers are all forked */ | 89 | /* Set when the idlers are all forked */ |
89 | int smp_threads_ready; | 90 | int smp_threads_ready; |
90 | 91 | ||
91 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; | 92 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
92 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; | 93 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
93 | EXPORT_SYMBOL(cpu_core_map); | 94 | EXPORT_SYMBOL(cpu_core_map); |
94 | 95 | ||
95 | /* | 96 | /* |
@@ -413,8 +414,13 @@ void __cpuinit smp_callin(void) | |||
413 | 414 | ||
414 | /* | 415 | /* |
415 | * Get our bogomips. | 416 | * Get our bogomips. |
417 | * | ||
418 | * Need to enable IRQs because it can take longer and then | ||
419 | * the NMI watchdog might kill us. | ||
416 | */ | 420 | */ |
421 | local_irq_enable(); | ||
417 | calibrate_delay(); | 422 | calibrate_delay(); |
423 | local_irq_disable(); | ||
418 | Dprintk("Stack at about %p\n",&cpuid); | 424 | Dprintk("Stack at about %p\n",&cpuid); |
419 | 425 | ||
420 | disable_APIC_timer(); | 426 | disable_APIC_timer(); |
@@ -492,6 +498,14 @@ void __cpuinit start_secondary(void) | |||
492 | */ | 498 | */ |
493 | set_cpu_sibling_map(smp_processor_id()); | 499 | set_cpu_sibling_map(smp_processor_id()); |
494 | 500 | ||
501 | /* | ||
502 | * Wait for TSC sync to not schedule things before. | ||
503 | * We still process interrupts, which could see an inconsistent | ||
504 | * time in that window unfortunately. | ||
505 | * Do this here because TSC sync has global unprotected state. | ||
506 | */ | ||
507 | tsc_sync_wait(); | ||
508 | |||
495 | /* | 509 | /* |
496 | * We need to hold call_lock, so there is no inconsistency | 510 | * We need to hold call_lock, so there is no inconsistency |
497 | * between the time smp_call_function() determines number of | 511 | * between the time smp_call_function() determines number of |
@@ -509,13 +523,6 @@ void __cpuinit start_secondary(void) | |||
509 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; | 523 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; |
510 | unlock_ipi_call_lock(); | 524 | unlock_ipi_call_lock(); |
511 | 525 | ||
512 | mb(); | ||
513 | |||
514 | /* Wait for TSC sync to not schedule things before. | ||
515 | We still process interrupts, which could see an inconsistent | ||
516 | time in that window unfortunately. */ | ||
517 | tsc_sync_wait(); | ||
518 | |||
519 | cpu_idle(); | 526 | cpu_idle(); |
520 | } | 527 | } |
521 | 528 | ||
@@ -539,8 +546,8 @@ static void inquire_remote_apic(int apicid) | |||
539 | */ | 546 | */ |
540 | apic_wait_icr_idle(); | 547 | apic_wait_icr_idle(); |
541 | 548 | ||
542 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); | 549 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); |
543 | apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); | 550 | apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]); |
544 | 551 | ||
545 | timeout = 0; | 552 | timeout = 0; |
546 | do { | 553 | do { |
@@ -573,12 +580,12 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta | |||
573 | /* | 580 | /* |
574 | * Turn INIT on target chip | 581 | * Turn INIT on target chip |
575 | */ | 582 | */ |
576 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | 583 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); |
577 | 584 | ||
578 | /* | 585 | /* |
579 | * Send IPI | 586 | * Send IPI |
580 | */ | 587 | */ |
581 | apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | 588 | apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT |
582 | | APIC_DM_INIT); | 589 | | APIC_DM_INIT); |
583 | 590 | ||
584 | Dprintk("Waiting for send to finish...\n"); | 591 | Dprintk("Waiting for send to finish...\n"); |
@@ -594,10 +601,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta | |||
594 | Dprintk("Deasserting INIT.\n"); | 601 | Dprintk("Deasserting INIT.\n"); |
595 | 602 | ||
596 | /* Target chip */ | 603 | /* Target chip */ |
597 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | 604 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); |
598 | 605 | ||
599 | /* Send IPI */ | 606 | /* Send IPI */ |
600 | apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); | 607 | apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); |
601 | 608 | ||
602 | Dprintk("Waiting for send to finish...\n"); | 609 | Dprintk("Waiting for send to finish...\n"); |
603 | timeout = 0; | 610 | timeout = 0; |
@@ -609,16 +616,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta | |||
609 | 616 | ||
610 | atomic_set(&init_deasserted, 1); | 617 | atomic_set(&init_deasserted, 1); |
611 | 618 | ||
612 | /* | 619 | num_starts = 2; |
613 | * Should we send STARTUP IPIs ? | ||
614 | * | ||
615 | * Determine this based on the APIC version. | ||
616 | * If we don't have an integrated APIC, don't send the STARTUP IPIs. | ||
617 | */ | ||
618 | if (APIC_INTEGRATED(apic_version[phys_apicid])) | ||
619 | num_starts = 2; | ||
620 | else | ||
621 | num_starts = 0; | ||
622 | 620 | ||
623 | /* | 621 | /* |
624 | * Run STARTUP IPI loop. | 622 | * Run STARTUP IPI loop. |
@@ -639,12 +637,11 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta | |||
639 | */ | 637 | */ |
640 | 638 | ||
641 | /* Target chip */ | 639 | /* Target chip */ |
642 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | 640 | apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); |
643 | 641 | ||
644 | /* Boot on the stack */ | 642 | /* Boot on the stack */ |
645 | /* Kick the second */ | 643 | /* Kick the second */ |
646 | apic_write_around(APIC_ICR, APIC_DM_STARTUP | 644 | apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12)); |
647 | | (start_rip >> 12)); | ||
648 | 645 | ||
649 | /* | 646 | /* |
650 | * Give the other CPU some time to accept the IPI. | 647 | * Give the other CPU some time to accept the IPI. |
@@ -863,17 +860,6 @@ static __cpuinit void smp_cleanup_boot(void) | |||
863 | * Reset trampoline flag | 860 | * Reset trampoline flag |
864 | */ | 861 | */ |
865 | *((volatile int *) phys_to_virt(0x467)) = 0; | 862 | *((volatile int *) phys_to_virt(0x467)) = 0; |
866 | |||
867 | #ifndef CONFIG_HOTPLUG_CPU | ||
868 | /* | ||
869 | * Free pages reserved for SMP bootup. | ||
870 | * When you add hotplug CPU support later remove this | ||
871 | * Note there is more work to be done for later CPU bootup. | ||
872 | */ | ||
873 | |||
874 | free_page((unsigned long) __va(PAGE_SIZE)); | ||
875 | free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE)); | ||
876 | #endif | ||
877 | } | 863 | } |
878 | 864 | ||
879 | /* | 865 | /* |
@@ -893,23 +879,6 @@ static __init void disable_smp(void) | |||
893 | cpu_set(0, cpu_core_map[0]); | 879 | cpu_set(0, cpu_core_map[0]); |
894 | } | 880 | } |
895 | 881 | ||
896 | /* | ||
897 | * Handle user cpus=... parameter. | ||
898 | */ | ||
899 | static __init void enforce_max_cpus(unsigned max_cpus) | ||
900 | { | ||
901 | int i, k; | ||
902 | k = 0; | ||
903 | for (i = 0; i < NR_CPUS; i++) { | ||
904 | if (!cpu_possible(i)) | ||
905 | continue; | ||
906 | if (++k > max_cpus) { | ||
907 | cpu_clear(i, cpu_possible_map); | ||
908 | cpu_clear(i, cpu_present_map); | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | |||
913 | #ifdef CONFIG_HOTPLUG_CPU | 882 | #ifdef CONFIG_HOTPLUG_CPU |
914 | /* | 883 | /* |
915 | * cpu_possible_map should be static, it cannot change as cpu's | 884 | * cpu_possible_map should be static, it cannot change as cpu's |
@@ -998,8 +967,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
998 | current_cpu_data = boot_cpu_data; | 967 | current_cpu_data = boot_cpu_data; |
999 | current_thread_info()->cpu = 0; /* needed? */ | 968 | current_thread_info()->cpu = 0; /* needed? */ |
1000 | 969 | ||
1001 | enforce_max_cpus(max_cpus); | ||
1002 | |||
1003 | #ifdef CONFIG_HOTPLUG_CPU | 970 | #ifdef CONFIG_HOTPLUG_CPU |
1004 | prefill_possible_map(); | 971 | prefill_possible_map(); |
1005 | #endif | 972 | #endif |