xref: /linux/arch/x86/kernel/cpu/topology_common.c (revision 490cc3c5e724502667a104a4e818dc071faf5e77)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/cpu.h>
3 
4 #include <xen/xen.h>
5 
6 #include <asm/apic.h>
7 #include <asm/processor.h>
8 #include <asm/smp.h>
9 
10 #include "cpu.h"
11 
12 struct x86_topology_system x86_topo_system __ro_after_init;
13 
14 unsigned int __amd_nodes_per_pkg __ro_after_init;
15 EXPORT_SYMBOL_GPL(__amd_nodes_per_pkg);
16 
17 void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom,
18 		      unsigned int shift, unsigned int ncpus)
19 {
20 	topology_update_dom(tscan, dom, shift, ncpus);
21 
22 	/* Propagate to the upper levels */
23 	for (dom++; dom < TOPO_MAX_DOMAIN; dom++) {
24 		tscan->dom_shifts[dom] = tscan->dom_shifts[dom - 1];
25 		tscan->dom_ncpus[dom] = tscan->dom_ncpus[dom - 1];
26 	}
27 }
28 
29 static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c)
30 {
31 	struct {
32 		u32	cache_type	:  5,
33 			unused		: 21,
34 			ncores		:  6;
35 	} eax;
36 
37 	if (c->cpuid_level < 4)
38 		return 1;
39 
40 	cpuid_subleaf_reg(4, 0, CPUID_EAX, &eax);
41 	if (!eax.cache_type)
42 		return 1;
43 
44 	return eax.ncores + 1;
45 }
46 
47 static void parse_legacy(struct topo_scan *tscan)
48 {
49 	unsigned int cores, core_shift, smt_shift = 0;
50 	struct cpuinfo_x86 *c = tscan->c;
51 
52 	cores = parse_num_cores_legacy(c);
53 	core_shift = get_count_order(cores);
54 
55 	if (cpu_has(c, X86_FEATURE_HT)) {
56 		if (!WARN_ON_ONCE(tscan->ebx1_nproc_shift < core_shift))
57 			smt_shift = tscan->ebx1_nproc_shift - core_shift;
58 		/*
59 		 * The parser expects leaf 0xb/0x1f format, which means
60 		 * the number of logical processors at core level is
61 		 * counting threads.
62 		 */
63 		core_shift += smt_shift;
64 		cores <<= smt_shift;
65 	}
66 
67 	topology_set_dom(tscan, TOPO_SMT_DOMAIN, smt_shift, 1U << smt_shift);
68 	topology_set_dom(tscan, TOPO_CORE_DOMAIN, core_shift, cores);
69 }
70 
71 static bool fake_topology(struct topo_scan *tscan)
72 {
73 	/*
74 	 * Preset the CORE level shift for CPUID less systems and XEN_PV,
75 	 * which has useless CPUID information.
76 	 */
77 	topology_set_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
78 	topology_set_dom(tscan, TOPO_CORE_DOMAIN, 0, 1);
79 
80 	return tscan->c->cpuid_level < 1 || xen_pv_domain();
81 }
82 
83 static void parse_topology(struct topo_scan *tscan, bool early)
84 {
85 	const struct cpuinfo_topology topo_defaults = {
86 		.cu_id			= 0xff,
87 		.llc_id			= BAD_APICID,
88 		.l2c_id			= BAD_APICID,
89 	};
90 	struct cpuinfo_x86 *c = tscan->c;
91 	struct {
92 		u32	unused0		: 16,
93 			nproc		:  8,
94 			apicid		:  8;
95 	} ebx;
96 
97 	c->topo = topo_defaults;
98 
99 	if (fake_topology(tscan))
100 		return;
101 
102 	/* Preset Initial APIC ID from CPUID leaf 1 */
103 	cpuid_leaf_reg(1, CPUID_EBX, &ebx);
104 	c->topo.initial_apicid = ebx.apicid;
105 
106 	/*
107 	 * The initial invocation from early_identify_cpu() happens before
108 	 * the APIC is mapped or X2APIC enabled. For establishing the
109 	 * topology, that's not required. Use the initial APIC ID.
110 	 */
111 	if (early)
112 		c->topo.apicid = c->topo.initial_apicid;
113 	else
114 		c->topo.apicid = read_apic_id();
115 
116 	/* The above is sufficient for UP */
117 	if (!IS_ENABLED(CONFIG_SMP))
118 		return;
119 
120 	tscan->ebx1_nproc_shift = get_count_order(ebx.nproc);
121 
122 	switch (c->x86_vendor) {
123 	case X86_VENDOR_AMD:
124 		if (IS_ENABLED(CONFIG_CPU_SUP_AMD))
125 			cpu_parse_topology_amd(tscan);
126 		break;
127 	case X86_VENDOR_CENTAUR:
128 	case X86_VENDOR_ZHAOXIN:
129 		parse_legacy(tscan);
130 		break;
131 	case X86_VENDOR_INTEL:
132 		if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan))
133 			parse_legacy(tscan);
134 		break;
135 	case X86_VENDOR_HYGON:
136 		if (IS_ENABLED(CONFIG_CPU_SUP_HYGON))
137 			cpu_parse_topology_amd(tscan);
138 		break;
139 	}
140 }
141 
142 static void topo_set_ids(struct topo_scan *tscan)
143 {
144 	struct cpuinfo_x86 *c = tscan->c;
145 	u32 apicid = c->topo.apicid;
146 
147 	c->topo.pkg_id = topo_shift_apicid(apicid, TOPO_PKG_DOMAIN);
148 	c->topo.die_id = topo_shift_apicid(apicid, TOPO_DIE_DOMAIN);
149 
150 	/* Package relative core ID */
151 	c->topo.core_id = (apicid & topo_domain_mask(TOPO_PKG_DOMAIN)) >>
152 		x86_topo_system.dom_shifts[TOPO_SMT_DOMAIN];
153 
154 	c->topo.amd_node_id = tscan->amd_node_id;
155 
156 	if (c->x86_vendor == X86_VENDOR_AMD)
157 		cpu_topology_fixup_amd(tscan);
158 }
159 
160 static void topo_set_max_cores(struct topo_scan *tscan)
161 {
162 	/*
163 	 * Bug compatible for now. This is broken on hybrid systems:
164 	 * 8 cores SMT + 8 cores w/o SMT
165 	 * tscan.dom_ncpus[TOPO_DIEGRP_DOMAIN] = 24; 24 / 2 = 12 !!
166 	 *
167 	 * Cannot be fixed without further topology enumeration changes.
168 	 */
169 	tscan->c->x86_max_cores = tscan->dom_ncpus[TOPO_DIEGRP_DOMAIN] >>
170 		x86_topo_system.dom_shifts[TOPO_SMT_DOMAIN];
171 }
172 
173 void cpu_parse_topology(struct cpuinfo_x86 *c)
174 {
175 	unsigned int dom, cpu = smp_processor_id();
176 	struct topo_scan tscan = { .c = c, };
177 
178 	parse_topology(&tscan, false);
179 
180 	if (IS_ENABLED(CONFIG_X86_LOCAL_APIC)) {
181 		if (c->topo.initial_apicid != c->topo.apicid) {
182 			pr_err(FW_BUG "CPU%4u: APIC ID mismatch. CPUID: 0x%04x APIC: 0x%04x\n",
183 			       cpu, c->topo.initial_apicid, c->topo.apicid);
184 		}
185 
186 		if (c->topo.apicid != cpuid_to_apicid[cpu]) {
187 			pr_err(FW_BUG "CPU%4u: APIC ID mismatch. Firmware: 0x%04x APIC: 0x%04x\n",
188 			       cpu, cpuid_to_apicid[cpu], c->topo.apicid);
189 		}
190 	}
191 
192 	for (dom = TOPO_SMT_DOMAIN; dom < TOPO_MAX_DOMAIN; dom++) {
193 		if (tscan.dom_shifts[dom] == x86_topo_system.dom_shifts[dom])
194 			continue;
195 		pr_err(FW_BUG "CPU%d: Topology domain %u shift %u != %u\n", cpu, dom,
196 		       tscan.dom_shifts[dom], x86_topo_system.dom_shifts[dom]);
197 	}
198 
199 	/* Bug compatible with the existing parsers */
200 	if (tscan.dom_ncpus[TOPO_SMT_DOMAIN] > smp_num_siblings) {
201 		if (system_state == SYSTEM_BOOTING) {
202 			pr_warn_once("CPU%d: SMT detected and enabled late\n", cpu);
203 			smp_num_siblings = tscan.dom_ncpus[TOPO_SMT_DOMAIN];
204 		} else {
205 			pr_warn_once("CPU%d: SMT detected after init. Too late!\n", cpu);
206 		}
207 	}
208 
209 	topo_set_ids(&tscan);
210 	topo_set_max_cores(&tscan);
211 }
212 
213 void __init cpu_init_topology(struct cpuinfo_x86 *c)
214 {
215 	struct topo_scan tscan = { .c = c, };
216 	unsigned int dom, sft;
217 
218 	parse_topology(&tscan, true);
219 
220 	/* Copy the shift values and calculate the unit sizes. */
221 	memcpy(x86_topo_system.dom_shifts, tscan.dom_shifts, sizeof(x86_topo_system.dom_shifts));
222 
223 	dom = TOPO_SMT_DOMAIN;
224 	x86_topo_system.dom_size[dom] = 1U << x86_topo_system.dom_shifts[dom];
225 
226 	for (dom++; dom < TOPO_MAX_DOMAIN; dom++) {
227 		sft = x86_topo_system.dom_shifts[dom] - x86_topo_system.dom_shifts[dom - 1];
228 		x86_topo_system.dom_size[dom] = 1U << sft;
229 	}
230 
231 	topo_set_ids(&tscan);
232 	topo_set_max_cores(&tscan);
233 
234 	/*
235 	 * Bug compatible with the existing code. If the boot CPU does not
236 	 * have SMT this ends up with one sibling. This needs way deeper
237 	 * changes further down the road to get it right during early boot.
238 	 */
239 	smp_num_siblings = tscan.dom_ncpus[TOPO_SMT_DOMAIN];
240 
241 	/*
242 	 * Neither it's clear whether there are as many dies as the APIC
243 	 * space indicating die level is. But assume that the actual number
244 	 * of CPUs gives a proper indication for now to stay bug compatible.
245 	 */
246 	__max_die_per_package = tscan.dom_ncpus[TOPO_DIE_DOMAIN] /
247 		tscan.dom_ncpus[TOPO_DIE_DOMAIN - 1];
248 	/*
249 	 * AMD systems have Nodes per package which cannot be mapped to
250 	 * APIC ID.
251 	 */
252 	__amd_nodes_per_pkg = tscan.amd_nodes_per_pkg;
253 }
254