aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/smpboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/smpboot.c')
-rw-r--r--arch/ia64/kernel/smpboot.c294
1 files changed, 261 insertions, 33 deletions
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 5318f0cbfc26..0d5ee57c9865 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -1,14 +1,25 @@
1/* 1/*
2 * SMP boot-related support 2 * SMP boot-related support
3 * 3 *
4 * Copyright (C) 1998-2003 Hewlett-Packard Co 4 * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com> 5 * David Mosberger-Tang <davidm@hpl.hp.com>
6 * Copyright (C) 2001, 2004-2005 Intel Corp
7 * Rohit Seth <rohit.seth@intel.com>
8 * Suresh Siddha <suresh.b.siddha@intel.com>
9 * Gordon Jin <gordon.jin@intel.com>
10 * Ashok Raj <ashok.raj@intel.com>
6 * 11 *
7 * 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here. 12 * 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here.
8 * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code. 13 * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code.
9 * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence. 14 * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence.
10 * smp_boot_cpus()/smp_commence() is replaced by 15 * smp_boot_cpus()/smp_commence() is replaced by
11 * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). 16 * smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
17 * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
18 * 04/12/26 Jin Gordon <gordon.jin@intel.com>
19 * 04/12/26 Rohit Seth <rohit.seth@intel.com>
20 * Add multi-threading and multi-core detection
21 * 05/01/30 Suresh Siddha <suresh.b.siddha@intel.com>
22 * Setup cpu_sibling_map and cpu_core_map
12 */ 23 */
13#include <linux/config.h> 24#include <linux/config.h>
14 25
@@ -58,6 +69,37 @@
58#define Dprintk(x...) 69#define Dprintk(x...)
59#endif 70#endif
60 71
72#ifdef CONFIG_HOTPLUG_CPU
73/*
74 * Store all idle threads, this can be reused instead of creating
75 * a new thread. Also avoids complicated thread destroy functionality
76 * for idle threads.
77 */
78struct task_struct *idle_thread_array[NR_CPUS];
79
80/*
81 * Global array allocated for NR_CPUS at boot time
82 */
83struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
84
85/*
86 * start_ap in head.S uses this to store current booting cpu
87 * info.
88 */
89struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
90
91#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
92
93#define get_idle_for_cpu(x) (idle_thread_array[(x)])
94#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
95
96#else
97
98#define get_idle_for_cpu(x) (NULL)
99#define set_idle_for_cpu(x,p)
100#define set_brendez_area(x)
101#endif
102
61 103
62/* 104/*
63 * ITC synchronization related stuff: 105 * ITC synchronization related stuff:
@@ -90,6 +132,11 @@ EXPORT_SYMBOL(cpu_online_map);
90cpumask_t cpu_possible_map; 132cpumask_t cpu_possible_map;
91EXPORT_SYMBOL(cpu_possible_map); 133EXPORT_SYMBOL(cpu_possible_map);
92 134
135cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
136cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
137int smp_num_siblings = 1;
138int smp_num_cpucores = 1;
139
93/* which logical CPU number maps to which CPU (physical APIC ID) */ 140/* which logical CPU number maps to which CPU (physical APIC ID) */
94volatile int ia64_cpu_to_sapicid[NR_CPUS]; 141volatile int ia64_cpu_to_sapicid[NR_CPUS];
95EXPORT_SYMBOL(ia64_cpu_to_sapicid); 142EXPORT_SYMBOL(ia64_cpu_to_sapicid);
@@ -124,7 +171,8 @@ sync_master (void *arg)
124 local_irq_save(flags); 171 local_irq_save(flags);
125 { 172 {
126 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) { 173 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
127 while (!go[MASTER]); 174 while (!go[MASTER])
175 cpu_relax();
128 go[MASTER] = 0; 176 go[MASTER] = 0;
129 go[SLAVE] = ia64_get_itc(); 177 go[SLAVE] = ia64_get_itc();
130 } 178 }
@@ -147,7 +195,8 @@ get_delta (long *rt, long *master)
147 for (i = 0; i < NUM_ITERS; ++i) { 195 for (i = 0; i < NUM_ITERS; ++i) {
148 t0 = ia64_get_itc(); 196 t0 = ia64_get_itc();
149 go[MASTER] = 1; 197 go[MASTER] = 1;
150 while (!(tm = go[SLAVE])); 198 while (!(tm = go[SLAVE]))
199 cpu_relax();
151 go[SLAVE] = 0; 200 go[SLAVE] = 0;
152 t1 = ia64_get_itc(); 201 t1 = ia64_get_itc();
153 202
@@ -226,7 +275,8 @@ ia64_sync_itc (unsigned int master)
226 return; 275 return;
227 } 276 }
228 277
229 while (go[MASTER]); /* wait for master to be ready */ 278 while (go[MASTER])
279 cpu_relax(); /* wait for master to be ready */
230 280
231 spin_lock_irqsave(&itc_sync_lock, flags); 281 spin_lock_irqsave(&itc_sync_lock, flags);
232 { 282 {
@@ -345,7 +395,6 @@ start_secondary (void *unused)
345{ 395{
346 /* Early console may use I/O ports */ 396 /* Early console may use I/O ports */
347 ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase)); 397 ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
348
349 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); 398 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
350 efi_map_pal_code(); 399 efi_map_pal_code();
351 cpu_init(); 400 cpu_init();
@@ -384,6 +433,13 @@ do_boot_cpu (int sapicid, int cpu)
384 .done = COMPLETION_INITIALIZER(c_idle.done), 433 .done = COMPLETION_INITIALIZER(c_idle.done),
385 }; 434 };
386 DECLARE_WORK(work, do_fork_idle, &c_idle); 435 DECLARE_WORK(work, do_fork_idle, &c_idle);
436
437 c_idle.idle = get_idle_for_cpu(cpu);
438 if (c_idle.idle) {
439 init_idle(c_idle.idle, cpu);
440 goto do_rest;
441 }
442
387 /* 443 /*
388 * We can't use kernel_thread since we must avoid to reschedule the child. 444 * We can't use kernel_thread since we must avoid to reschedule the child.
389 */ 445 */
@@ -396,10 +452,15 @@ do_boot_cpu (int sapicid, int cpu)
396 452
397 if (IS_ERR(c_idle.idle)) 453 if (IS_ERR(c_idle.idle))
398 panic("failed fork for CPU %d", cpu); 454 panic("failed fork for CPU %d", cpu);
455
456 set_idle_for_cpu(cpu, c_idle.idle);
457
458do_rest:
399 task_for_booting_cpu = c_idle.idle; 459 task_for_booting_cpu = c_idle.idle;
400 460
401 Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); 461 Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
402 462
463 set_brendez_area(cpu);
403 platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); 464 platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
404 465
405 /* 466 /*
@@ -552,19 +613,70 @@ void __devinit smp_prepare_boot_cpu(void)
552 cpu_set(smp_processor_id(), cpu_callin_map); 613 cpu_set(smp_processor_id(), cpu_callin_map);
553} 614}
554 615
616/*
617 * mt_info[] is a temporary store for all info returned by
618 * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
619 * specific cpu comes.
620 */
621static struct {
622 __u32 socket_id;
623 __u16 core_id;
624 __u16 thread_id;
625 __u16 proc_fixed_addr;
626 __u8 valid;
627}mt_info[NR_CPUS] __devinit;
628
555#ifdef CONFIG_HOTPLUG_CPU 629#ifdef CONFIG_HOTPLUG_CPU
556extern void fixup_irqs(void); 630static inline void
557/* must be called with cpucontrol mutex held */ 631remove_from_mtinfo(int cpu)
558static int __devinit cpu_enable(unsigned int cpu)
559{ 632{
560 per_cpu(cpu_state,cpu) = CPU_UP_PREPARE; 633 int i;
561 wmb();
562 634
563 while (!cpu_online(cpu)) 635 for_each_cpu(i)
564 cpu_relax(); 636 if (mt_info[i].valid && mt_info[i].socket_id ==
565 return 0; 637 cpu_data(cpu)->socket_id)
638 mt_info[i].valid = 0;
639}
640
641static inline void
642clear_cpu_sibling_map(int cpu)
643{
644 int i;
645
646 for_each_cpu_mask(i, cpu_sibling_map[cpu])
647 cpu_clear(cpu, cpu_sibling_map[i]);
648 for_each_cpu_mask(i, cpu_core_map[cpu])
649 cpu_clear(cpu, cpu_core_map[i]);
650
651 cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
652}
653
654static void
655remove_siblinginfo(int cpu)
656{
657 int last = 0;
658
659 if (cpu_data(cpu)->threads_per_core == 1 &&
660 cpu_data(cpu)->cores_per_socket == 1) {
661 cpu_clear(cpu, cpu_core_map[cpu]);
662 cpu_clear(cpu, cpu_sibling_map[cpu]);
663 return;
664 }
665
666 last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0);
667
668 /* remove it from all sibling map's */
669 clear_cpu_sibling_map(cpu);
670
671 /* if this cpu is the last in the core group, remove all its info
672 * from mt_info structure
673 */
674 if (last)
675 remove_from_mtinfo(cpu);
566} 676}
567 677
678extern void fixup_irqs(void);
679/* must be called with cpucontrol mutex held */
568int __cpu_disable(void) 680int __cpu_disable(void)
569{ 681{
570 int cpu = smp_processor_id(); 682 int cpu = smp_processor_id();
@@ -575,9 +687,10 @@ int __cpu_disable(void)
575 if (cpu == 0) 687 if (cpu == 0)
576 return -EBUSY; 688 return -EBUSY;
577 689
690 remove_siblinginfo(cpu);
578 fixup_irqs(); 691 fixup_irqs();
579 local_flush_tlb_all(); 692 local_flush_tlb_all();
580 printk ("Disabled cpu %u\n", smp_processor_id()); 693 cpu_clear(cpu, cpu_callin_map);
581 return 0; 694 return 0;
582} 695}
583 696
@@ -589,12 +702,7 @@ void __cpu_die(unsigned int cpu)
589 /* They ack this in play_dead by setting CPU_DEAD */ 702 /* They ack this in play_dead by setting CPU_DEAD */
590 if (per_cpu(cpu_state, cpu) == CPU_DEAD) 703 if (per_cpu(cpu_state, cpu) == CPU_DEAD)
591 { 704 {
592 /* 705 printk ("CPU %d is now offline\n", cpu);
593 * TBD: Enable this when physical removal
594 * or when we put the processor is put in
595 * SAL_BOOT_RENDEZ mode
596 * cpu_clear(cpu, cpu_callin_map);
597 */
598 return; 706 return;
599 } 707 }
600 msleep(100); 708 msleep(100);
@@ -602,11 +710,6 @@ void __cpu_die(unsigned int cpu)
602 printk(KERN_ERR "CPU %u didn't die...\n", cpu); 710 printk(KERN_ERR "CPU %u didn't die...\n", cpu);
603} 711}
604#else /* !CONFIG_HOTPLUG_CPU */ 712#else /* !CONFIG_HOTPLUG_CPU */
605static int __devinit cpu_enable(unsigned int cpu)
606{
607 return 0;
608}
609
610int __cpu_disable(void) 713int __cpu_disable(void)
611{ 714{
612 return -ENOSYS; 715 return -ENOSYS;
@@ -637,6 +740,23 @@ smp_cpus_done (unsigned int dummy)
637 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); 740 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
638} 741}
639 742
743static inline void __devinit
744set_cpu_sibling_map(int cpu)
745{
746 int i;
747
748 for_each_online_cpu(i) {
749 if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
750 cpu_set(i, cpu_core_map[cpu]);
751 cpu_set(cpu, cpu_core_map[i]);
752 if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
753 cpu_set(i, cpu_sibling_map[cpu]);
754 cpu_set(cpu, cpu_sibling_map[i]);
755 }
756 }
757 }
758}
759
640int __devinit 760int __devinit
641__cpu_up (unsigned int cpu) 761__cpu_up (unsigned int cpu)
642{ 762{
@@ -648,21 +768,26 @@ __cpu_up (unsigned int cpu)
648 return -EINVAL; 768 return -EINVAL;
649 769
650 /* 770 /*
651 * Already booted.. just enable and get outa idle lool 771 * Already booted cpu? not valid anymore since we dont
772 * do idle loop tightspin anymore.
652 */ 773 */
653 if (cpu_isset(cpu, cpu_callin_map)) 774 if (cpu_isset(cpu, cpu_callin_map))
654 { 775 return -EINVAL;
655 cpu_enable(cpu); 776
656 local_irq_enable();
657 while (!cpu_isset(cpu, cpu_online_map))
658 mb();
659 return 0;
660 }
661 /* Processor goes to start_secondary(), sets online flag */ 777 /* Processor goes to start_secondary(), sets online flag */
662 ret = do_boot_cpu(sapicid, cpu); 778 ret = do_boot_cpu(sapicid, cpu);
663 if (ret < 0) 779 if (ret < 0)
664 return ret; 780 return ret;
665 781
782 if (cpu_data(cpu)->threads_per_core == 1 &&
783 cpu_data(cpu)->cores_per_socket == 1) {
784 cpu_set(cpu, cpu_sibling_map[cpu]);
785 cpu_set(cpu, cpu_core_map[cpu]);
786 return 0;
787 }
788
789 set_cpu_sibling_map(cpu);
790
666 return 0; 791 return 0;
667} 792}
668 793
@@ -690,3 +815,106 @@ init_smp_config(void)
690 ia64_sal_strerror(sal_ret)); 815 ia64_sal_strerror(sal_ret));
691} 816}
692 817
818static inline int __devinit
819check_for_mtinfo_index(void)
820{
821 int i;
822
823 for_each_cpu(i)
824 if (!mt_info[i].valid)
825 return i;
826
827 return -1;
828}
829
830/*
831 * Search the mt_info to find out if this socket's cid/tid information is
832 * cached or not. If the socket exists, fill in the core_id and thread_id
833 * in cpuinfo
834 */
835static int __devinit
836check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
837{
838 int i;
839 __u32 sid = c->socket_id;
840
841 for_each_cpu(i) {
842 if (mt_info[i].valid && mt_info[i].proc_fixed_addr == logical_address
843 && mt_info[i].socket_id == sid) {
844 c->core_id = mt_info[i].core_id;
845 c->thread_id = mt_info[i].thread_id;
846 return 1; /* not a new socket */
847 }
848 }
849 return 0;
850}
851
852/*
853 * identify_siblings(cpu) gets called from identify_cpu. This populates the
854 * information related to logical execution units in per_cpu_data structure.
855 */
856void __devinit
857identify_siblings(struct cpuinfo_ia64 *c)
858{
859 s64 status;
860 u16 pltid;
861 u64 proc_fixed_addr;
862 int count, i;
863 pal_logical_to_physical_t info;
864
865 if (smp_num_cpucores == 1 && smp_num_siblings == 1)
866 return;
867
868 if ((status = ia64_pal_logical_to_phys(0, &info)) != PAL_STATUS_SUCCESS) {
869 printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
870 status);
871 return;
872 }
873 if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
874 printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
875 return;
876 }
877 if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != PAL_STATUS_SUCCESS) {
878 printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", status);
879 return;
880 }
881
882 c->socket_id = (pltid << 8) | info.overview_ppid;
883 c->cores_per_socket = info.overview_cpp;
884 c->threads_per_core = info.overview_tpc;
885 count = c->num_log = info.overview_num_log;
886
887 /* If the thread and core id information is already cached, then
888 * we will simply update cpu_info and return. Otherwise, we will
889 * do the PAL calls and cache core and thread id's of all the siblings.
890 */
891 if (check_for_new_socket(proc_fixed_addr, c))
892 return;
893
894 for (i = 0; i < count; i++) {
895 int index;
896
897 if (i && (status = ia64_pal_logical_to_phys(i, &info))
898 != PAL_STATUS_SUCCESS) {
899 printk(KERN_ERR "ia64_pal_logical_to_phys failed"
900 " with %ld\n", status);
901 return;
902 }
903 if (info.log2_la == proc_fixed_addr) {
904 c->core_id = info.log1_cid;
905 c->thread_id = info.log1_tid;
906 }
907
908 index = check_for_mtinfo_index();
909 /* We will not do the mt_info caching optimization in this case.
910 */
911 if (index < 0)
912 continue;
913
914 mt_info[index].valid = 1;
915 mt_info[index].socket_id = c->socket_id;
916 mt_info[index].core_id = info.log1_cid;
917 mt_info[index].thread_id = info.log1_tid;
918 mt_info[index].proc_fixed_addr = info.log2_la;
919 }
920}