1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/cpu.h>
3
4 #include <asm/apic.h>
5 #include <asm/memtype.h>
6 #include <asm/processor.h>
7
8 #include "cpu.h"
9
parse_8000_0008(struct topo_scan * tscan)10 static bool parse_8000_0008(struct topo_scan *tscan)
11 {
12 struct {
13 // ecx
14 u32 cpu_nthreads : 8, // Number of physical threads - 1
15 : 4, // Reserved
16 apicid_coreid_len : 4, // Number of thread core ID bits (shift) in APIC ID
17 perf_tsc_len : 2, // Performance time-stamp counter size
18 : 14; // Reserved
19 } ecx;
20 unsigned int sft;
21
22 if (tscan->c->extended_cpuid_level < 0x80000008)
23 return false;
24
25 cpuid_leaf_reg(0x80000008, CPUID_ECX, &ecx);
26
27 /* If the thread bits are 0, then get the shift value from ecx.cpu_nthreads */
28 sft = ecx.apicid_coreid_len;
29 if (!sft)
30 sft = get_count_order(ecx.cpu_nthreads + 1);
31
32 /*
33 * cpu_nthreads describes the number of threads in the package
34 * sft is the number of APIC ID bits per package
35 *
36 * As the number of actual threads per core is not described in
37 * this leaf, just set the CORE domain shift and let the later
38 * parsers set SMT shift. Assume one thread per core by default
39 * which is correct if there are no other CPUID leafs to parse.
40 */
41 topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
42 topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1);
43 return true;
44 }
45
store_node(struct topo_scan * tscan,u16 nr_nodes,u16 node_id)46 static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id)
47 {
48 /*
49 * Starting with Fam 17h the DIE domain could probably be used to
50 * retrieve the node info on AMD/HYGON. Analysis of CPUID dumps
51 * suggests it's the topmost bit(s) of the CPU cores area, but
52 * that's guess work and neither enumerated nor documented.
53 *
54 * Up to Fam 16h this does not work at all and the legacy node ID
55 * has to be used.
56 */
57 tscan->amd_nodes_per_pkg = nr_nodes;
58 tscan->amd_node_id = node_id;
59 }
60
parse_8000_001e(struct topo_scan * tscan,bool has_topoext)61 static bool parse_8000_001e(struct topo_scan *tscan, bool has_topoext)
62 {
63 struct {
64 // eax
65 u32 ext_apic_id : 32; // Extended APIC ID
66 // ebx
67 u32 core_id : 8, // Unique per-socket logical core unit ID
68 core_nthreads : 8, // #Threads per core (zero-based)
69 : 16; // Reserved
70 // ecx
71 u32 node_id : 8, // Node (die) ID of invoking logical CPU
72 nnodes_per_socket : 3, // #nodes in invoking logical CPU's package/socket
73 : 21; // Reserved
74 // edx
75 u32 : 32; // Reserved
76 } leaf;
77
78 if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
79 return false;
80
81 cpuid_leaf(0x8000001e, &leaf);
82
83 /*
84 * If leaf 0xb/0x26 is available, then the APIC ID and the domain
85 * shifts are set already.
86 */
87 if (!has_topoext) {
88 tscan->c->topo.initial_apicid = leaf.ext_apic_id;
89
90 /*
91 * Leaf 0x8000008 sets the CORE domain shift but not the
92 * SMT domain shift. On CPUs with family >= 0x17, there
93 * might be hyperthreads.
94 */
95 if (tscan->c->x86 >= 0x17) {
96 /* Update the SMT domain, but do not propagate it. */
97 unsigned int nthreads = leaf.core_nthreads + 1;
98
99 topology_update_dom(tscan, TOPO_SMT_DOMAIN,
100 get_count_order(nthreads), nthreads);
101 }
102 }
103
104 store_node(tscan, leaf.nnodes_per_socket + 1, leaf.node_id);
105
106 if (tscan->c->x86_vendor == X86_VENDOR_AMD) {
107 if (tscan->c->x86 == 0x15)
108 tscan->c->topo.cu_id = leaf.core_id;
109
110 cacheinfo_amd_init_llc_id(tscan->c, leaf.node_id);
111 } else {
112 /*
113 * Package ID is ApicId[6..] on certain Hygon CPUs. See
114 * commit e0ceeae708ce for explanation. The topology info
115 * is screwed up: The package shift is always 6 and the
116 * node ID is bit [4:5].
117 */
118 if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && tscan->c->x86_model <= 0x3) {
119 topology_set_dom(tscan, TOPO_CORE_DOMAIN, 6,
120 tscan->dom_ncpus[TOPO_CORE_DOMAIN]);
121 }
122 cacheinfo_hygon_init_llc_id(tscan->c);
123 }
124 return true;
125 }
126
parse_fam10h_node_id(struct topo_scan * tscan)127 static void parse_fam10h_node_id(struct topo_scan *tscan)
128 {
129 union {
130 struct {
131 u64 node_id : 3,
132 nodes_per_pkg : 3,
133 unused : 58;
134 };
135 u64 msr;
136 } nid;
137
138 if (!boot_cpu_has(X86_FEATURE_NODEID_MSR))
139 return;
140
141 rdmsrl(MSR_FAM10H_NODE_ID, nid.msr);
142 store_node(tscan, nid.nodes_per_pkg + 1, nid.node_id);
143 tscan->c->topo.llc_id = nid.node_id;
144 }
145
legacy_set_llc(struct topo_scan * tscan)146 static void legacy_set_llc(struct topo_scan *tscan)
147 {
148 unsigned int apicid = tscan->c->topo.initial_apicid;
149
150 /* If none of the parsers set LLC ID then use the die ID for it. */
151 if (tscan->c->topo.llc_id == BAD_APICID)
152 tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN];
153 }
154
topoext_fixup(struct topo_scan * tscan)155 static void topoext_fixup(struct topo_scan *tscan)
156 {
157 struct cpuinfo_x86 *c = tscan->c;
158 u64 msrval;
159
160 /* Try to re-enable TopologyExtensions if switched off by BIOS */
161 if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD ||
162 c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f)
163 return;
164
165 if (msr_set_bit(0xc0011005, 54) <= 0)
166 return;
167
168 rdmsrl(0xc0011005, msrval);
169 if (msrval & BIT_64(54)) {
170 set_cpu_cap(c, X86_FEATURE_TOPOEXT);
171 pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
172 }
173 }
174
parse_topology_amd(struct topo_scan * tscan)175 static void parse_topology_amd(struct topo_scan *tscan)
176 {
177 /*
178 * Try to get SMT, CORE, TILE, and DIE shifts from extended
179 * CPUID leaf 0x8000_0026 on supported processors first. If
180 * extended CPUID leaf 0x8000_0026 is not supported, try to
181 * get SMT and CORE shift from leaf 0xb. If either leaf is
182 * available, cpu_parse_topology_ext() will return true.
183 */
184 bool has_xtopology = cpu_parse_topology_ext(tscan);
185
186 /*
187 * If XTOPOLOGY leaves (0x26/0xb) are not available, try to
188 * get the CORE shift from leaf 0x8000_0008 first.
189 */
190 if (!has_xtopology && !parse_8000_0008(tscan))
191 return;
192
193 /*
194 * Prefer leaf 0x8000001e if available to get the SMT shift and
195 * the initial APIC ID if XTOPOLOGY leaves are not available.
196 */
197 if (parse_8000_001e(tscan, has_xtopology))
198 return;
199
200 /* Try the NODEID MSR */
201 parse_fam10h_node_id(tscan);
202 }
203
cpu_parse_topology_amd(struct topo_scan * tscan)204 void cpu_parse_topology_amd(struct topo_scan *tscan)
205 {
206 tscan->amd_nodes_per_pkg = 1;
207 topoext_fixup(tscan);
208 parse_topology_amd(tscan);
209 legacy_set_llc(tscan);
210
211 if (tscan->amd_nodes_per_pkg > 1)
212 set_cpu_cap(tscan->c, X86_FEATURE_AMD_DCM);
213 }
214
cpu_topology_fixup_amd(struct topo_scan * tscan)215 void cpu_topology_fixup_amd(struct topo_scan *tscan)
216 {
217 struct cpuinfo_x86 *c = tscan->c;
218
219 /*
220 * Adjust the core_id relative to the node when there is more than
221 * one node.
222 */
223 if (tscan->c->x86 < 0x17 && tscan->amd_nodes_per_pkg > 1)
224 c->topo.core_id %= tscan->dom_ncpus[TOPO_CORE_DOMAIN] / tscan->amd_nodes_per_pkg;
225 }
226