aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2005-04-25 16:25:06 -0400
committerTony Luck <tony.luck@intel.com>2005-04-25 16:25:06 -0400
commite927ecb05e1ce4bbb1e10f57008c94994e2160f5 (patch)
treebc8256cc074f02d557088696035982fa7ae0b301 /arch/ia64/kernel
parent6118ec847e8e35393efc0f88394c2f5dd48c3313 (diff)
[IA64] multi-core/multi-thread identification
Version 3 - rediffed to apply on top of Ashok's hotplug cpu patch. /proc/cpuinfo output in step with x86. This is an updated MC/MT identification patch based on the previous discussions on list. Add the Multi-core and Multi-threading detection for IPF. - Add new core and threading related fields in /proc/cpuinfo. Physical id Core id Thread id Siblings - setup the cpu_core_map and cpu_sibling_map appropriately - Handles Hot plug CPU Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Gordon Jin <gordon.jin@intel.com> Signed-off-by: Rohit Seth <rohit.seth@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/setup.c69
-rw-r--r--arch/ia64/kernel/smpboot.c206
2 files changed, 273 insertions, 2 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index f05650c801d2..88043841fb8a 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -4,10 +4,15 @@
4 * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co 4 * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com> 5 * David Mosberger-Tang <davidm@hpl.hp.com>
6 * Stephane Eranian <eranian@hpl.hp.com> 6 * Stephane Eranian <eranian@hpl.hp.com>
7 * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com> 7 * Copyright (C) 2000, 2004 Intel Corp
8 * Rohit Seth <rohit.seth@intel.com>
9 * Suresh Siddha <suresh.b.siddha@intel.com>
10 * Gordon Jin <gordon.jin@intel.com>
8 * Copyright (C) 1999 VA Linux Systems 11 * Copyright (C) 1999 VA Linux Systems
9 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> 12 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
10 * 13 *
14 * 12/26/04 S.Siddha, G.Jin, R.Seth
15 * Add multi-threading and multi-core detection
11 * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo(). 16 * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
12 * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map 17 * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
13 * 03/31/00 R.Seth cpu_initialized and current->processor fixes 18 * 03/31/00 R.Seth cpu_initialized and current->processor fixes
@@ -296,6 +301,34 @@ mark_bsp_online (void)
296#endif 301#endif
297} 302}
298 303
304#ifdef CONFIG_SMP
305static void
306check_for_logical_procs (void)
307{
308 pal_logical_to_physical_t info;
309 s64 status;
310
311 status = ia64_pal_logical_to_phys(0, &info);
312 if (status == -1) {
313 printk(KERN_INFO "No logical to physical processor mapping "
314 "available\n");
315 return;
316 }
317 if (status) {
318 printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
319 status);
320 return;
321 }
322 /*
323 * Total number of siblings that BSP has. Though not all of them
324 * may have booted successfully. The correct number of siblings
325 * booted is in info.overview_num_log.
326 */
327 smp_num_siblings = info.overview_tpc;
328 smp_num_cpucores = info.overview_cpp;
329}
330#endif
331
299void __init 332void __init
300setup_arch (char **cmdline_p) 333setup_arch (char **cmdline_p)
301{ 334{
@@ -356,6 +389,19 @@ setup_arch (char **cmdline_p)
356 389
357#ifdef CONFIG_SMP 390#ifdef CONFIG_SMP
358 cpu_physical_id(0) = hard_smp_processor_id(); 391 cpu_physical_id(0) = hard_smp_processor_id();
392
393 cpu_set(0, cpu_sibling_map[0]);
394 cpu_set(0, cpu_core_map[0]);
395
396 check_for_logical_procs();
397 if (smp_num_cpucores > 1)
398 printk(KERN_INFO
399 "cpu package is Multi-Core capable: number of cores=%d\n",
400 smp_num_cpucores);
401 if (smp_num_siblings > 1)
402 printk(KERN_INFO
403 "cpu package is Multi-Threading capable: number of siblings=%d\n",
404 smp_num_siblings);
359#endif 405#endif
360 406
361 cpu_init(); /* initialize the bootstrap CPU */ 407 cpu_init(); /* initialize the bootstrap CPU */
@@ -459,12 +505,23 @@ show_cpuinfo (struct seq_file *m, void *v)
459 "cpu regs : %u\n" 505 "cpu regs : %u\n"
460 "cpu MHz : %lu.%06lu\n" 506 "cpu MHz : %lu.%06lu\n"
461 "itc MHz : %lu.%06lu\n" 507 "itc MHz : %lu.%06lu\n"
462 "BogoMIPS : %lu.%02lu\n\n", 508 "BogoMIPS : %lu.%02lu\n",
463 cpunum, c->vendor, family, c->model, c->revision, c->archrev, 509 cpunum, c->vendor, family, c->model, c->revision, c->archrev,
464 features, c->ppn, c->number, 510 features, c->ppn, c->number,
465 c->proc_freq / 1000000, c->proc_freq % 1000000, 511 c->proc_freq / 1000000, c->proc_freq % 1000000,
466 c->itc_freq / 1000000, c->itc_freq % 1000000, 512 c->itc_freq / 1000000, c->itc_freq % 1000000,
467 lpj*HZ/500000, (lpj*HZ/5000) % 100); 513 lpj*HZ/500000, (lpj*HZ/5000) % 100);
514#ifdef CONFIG_SMP
515 if (c->threads_per_core > 1 || c->cores_per_socket > 1)
516 seq_printf(m,
517 "physical id: %u\n"
518 "core id : %u\n"
519 "thread id : %u\n",
520 c->socket_id, c->core_id, c->thread_id);
521 seq_printf(m, "siblings : %u\n", c->num_log);
522#endif
523 seq_printf(m,"\n");
524
468 return 0; 525 return 0;
469} 526}
470 527
@@ -533,6 +590,14 @@ identify_cpu (struct cpuinfo_ia64 *c)
533 memcpy(c->vendor, cpuid.field.vendor, 16); 590 memcpy(c->vendor, cpuid.field.vendor, 16);
534#ifdef CONFIG_SMP 591#ifdef CONFIG_SMP
535 c->cpu = smp_processor_id(); 592 c->cpu = smp_processor_id();
593
594 /* below default values will be overwritten by identify_siblings()
595 * for Multi-Threading/Multi-Core capable cpu's
596 */
597 c->threads_per_core = c->cores_per_socket = c->num_log = 1;
598 c->socket_id = -1;
599
600 identify_siblings(c);
536#endif 601#endif
537 c->ppn = cpuid.field.ppn; 602 c->ppn = cpuid.field.ppn;
538 c->number = cpuid.field.number; 603 c->number = cpuid.field.number;
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index dbc6b610cc64..0d5ee57c9865 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -3,6 +3,11 @@
3 * 3 *
4 * Copyright (C) 1998-2003, 2005 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.
@@ -10,6 +15,11 @@
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().
12 * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support 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
13 */ 23 */
14#include <linux/config.h> 24#include <linux/config.h>
15 25
@@ -122,6 +132,11 @@ EXPORT_SYMBOL(cpu_online_map);
122cpumask_t cpu_possible_map; 132cpumask_t cpu_possible_map;
123EXPORT_SYMBOL(cpu_possible_map); 133EXPORT_SYMBOL(cpu_possible_map);
124 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
125/* which logical CPU number maps to which CPU (physical APIC ID) */ 140/* which logical CPU number maps to which CPU (physical APIC ID) */
126volatile int ia64_cpu_to_sapicid[NR_CPUS]; 141volatile int ia64_cpu_to_sapicid[NR_CPUS];
127EXPORT_SYMBOL(ia64_cpu_to_sapicid); 142EXPORT_SYMBOL(ia64_cpu_to_sapicid);
@@ -598,7 +613,68 @@ void __devinit smp_prepare_boot_cpu(void)
598 cpu_set(smp_processor_id(), cpu_callin_map); 613 cpu_set(smp_processor_id(), cpu_callin_map);
599} 614}
600 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
601#ifdef CONFIG_HOTPLUG_CPU 629#ifdef CONFIG_HOTPLUG_CPU
630static inline void
631remove_from_mtinfo(int cpu)
632{
633 int i;
634
635 for_each_cpu(i)
636 if (mt_info[i].valid && mt_info[i].socket_id ==
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);
676}
677
602extern void fixup_irqs(void); 678extern void fixup_irqs(void);
603/* must be called with cpucontrol mutex held */ 679/* must be called with cpucontrol mutex held */
604int __cpu_disable(void) 680int __cpu_disable(void)
@@ -611,6 +687,7 @@ int __cpu_disable(void)
611 if (cpu == 0) 687 if (cpu == 0)
612 return -EBUSY; 688 return -EBUSY;
613 689
690 remove_siblinginfo(cpu);
614 fixup_irqs(); 691 fixup_irqs();
615 local_flush_tlb_all(); 692 local_flush_tlb_all();
616 cpu_clear(cpu, cpu_callin_map); 693 cpu_clear(cpu, cpu_callin_map);
@@ -663,6 +740,23 @@ smp_cpus_done (unsigned int dummy)
663 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); 740 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
664} 741}
665 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
666int __devinit 760int __devinit
667__cpu_up (unsigned int cpu) 761__cpu_up (unsigned int cpu)
668{ 762{
@@ -685,6 +779,15 @@ __cpu_up (unsigned int cpu)
685 if (ret < 0) 779 if (ret < 0)
686 return ret; 780 return ret;
687 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
688 return 0; 791 return 0;
689} 792}
690 793
@@ -712,3 +815,106 @@ init_smp_config(void)
712 ia64_sal_strerror(sal_ret)); 815 ia64_sal_strerror(sal_ret));
713} 816}
714 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}