Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
topology.c
Go to the documentation of this file.
1 /*
2  * Check for extended topology enumeration cpuid leaf 0xb and if it
3  * exists, use it for populating initial_apicid and cpu topology
4  * detection.
5  */
6 
7 #include <linux/cpu.h>
8 #include <asm/apic.h>
9 #include <asm/pat.h>
10 #include <asm/processor.h>
11 
12 /* leaf 0xb SMT level */
13 #define SMT_LEVEL 0
14 
15 /* leaf 0xb sub-leaf types */
16 #define INVALID_TYPE 0
17 #define SMT_TYPE 1
18 #define CORE_TYPE 2
19 
20 #define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
21 #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
22 #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff)
23 
24 /*
25  * Check for extended topology enumeration cpuid leaf 0xb and if it
26  * exists, use it for populating initial_apicid and cpu topology
27  * detection.
28  */
30 {
31 #ifdef CONFIG_SMP
32  unsigned int eax, ebx, ecx, edx, sub_index;
33  unsigned int ht_mask_width, core_plus_mask_width;
34  unsigned int core_select_mask, core_level_siblings;
35  static bool printed;
36 
37  if (c->cpuid_level < 0xb)
38  return;
39 
40  cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
41 
42  /*
43  * check if the cpuid leaf 0xb is actually implemented.
44  */
45  if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
46  return;
47 
48  set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
49 
50  /*
51  * initial apic id, which also represents 32-bit extended x2apic id.
52  */
53  c->initial_apicid = edx;
54 
55  /*
56  * Populate HT related information from sub-leaf level 0.
57  */
58  core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
59  core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
60 
61  sub_index = 1;
62  do {
63  cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
64 
65  /*
66  * Check for the Core type in the implemented sub leaves.
67  */
68  if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
69  core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
70  core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
71  break;
72  }
73 
74  sub_index++;
75  } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
76 
77  core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
78 
79  c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width)
80  & core_select_mask;
81  c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width);
82  /*
83  * Reinit the apicid, now that we have extended initial_apicid.
84  */
86 
87  c->x86_max_cores = (core_level_siblings / smp_num_siblings);
88 
89  if (!printed) {
90  printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
91  c->phys_proc_id);
92  if (c->x86_max_cores > 1)
93  printk(KERN_INFO "CPU: Processor Core ID: %d\n",
94  c->cpu_core_id);
95  printed = 1;
96  }
97  return;
98 #endif
99 }