Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/kernel/cpu/topology.c
10699 views
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
}
100
101