diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-08-12 15:38:56 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-08-12 15:39:04 -0400 |
commit | f46a6804135795f77d096ab0128f27531c7d051c (patch) | |
tree | 7cd33f69e3661327739ae4c96e5a8389e7fc912e /arch/x86/kernel/cpu/topology.c | |
parent | b3e84ffa21f916e3354a12a7f19169c9febe96d0 (diff) | |
parent | ad41a1e0cab07c5125456e8d38e5b1ab148d04aa (diff) |
Merge branch 'linus' into perf/urgent
Merge reason: Fix upstream breakage introduced by:
de5d9bf: Move list types from <linux/list.h> to <linux/types.h>.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/cpu/topology.c')
-rw-r--r-- | arch/x86/kernel/cpu/topology.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c new file mode 100644 index 000000000000..4397e987a1cf --- /dev/null +++ b/arch/x86/kernel/cpu/topology.c | |||
@@ -0,0 +1,99 @@ | |||
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 | */ | ||
29 | void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) | ||
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 | */ | ||
85 | c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); | ||
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 | } | ||