xref: /illumos-gate/usr/src/uts/intel/os/cpuid_subr.c (revision b8f43eb65c2ac2ff69cf1a69aabc90c27cdb859e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
27  */
28 
29 /*
30  * Portions Copyright 2009 Advanced Micro Devices, Inc.
31  */
32 
33 /*
34  * Copyright 2012 Jens Elkner <jel+illumos@cs.uni-magdeburg.de>
35  * Copyright 2012 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
36  * Copyright 2019 Joyent, Inc.
37  * Copyright 2021 Oxide Computer Company
38  */
39 
40 /*
41  * Support functions that interpret CPUID and similar information.
42  * These should not be used from anywhere other than cpuid.c and
43  * cmi_hw.c - as such we will not list them in any header file
44  * such as x86_archext.h.
45  *
46  * In cpuid.c we process CPUID information for each cpu_t instance
47  * we're presented with, and stash this raw information and material
48  * derived from it in per-cpu_t structures.
49  *
50  * If we are virtualized then the CPUID information derived from CPUID
51  * instructions executed in the guest is based on whatever the hypervisor
52  * wanted to make things look like, and the cpu_t are not necessarily in 1:1
53  * or fixed correspondence with real processor execution resources.  In cmi_hw.c
54  * we are interested in the native properties of a processor - for fault
55  * management (and potentially other, such as power management) purposes;
56  * it will tunnel through to real hardware information, and use the
57  * functionality provided in this file to process it.
58  */
59 
60 #include <sys/types.h>
61 #include <sys/systm.h>
62 #include <sys/bitmap.h>
63 #include <sys/x86_archext.h>
64 #include <sys/pci_cfgspace.h>
65 #include <sys/sysmacros.h>
66 #ifdef __xpv
67 #include <sys/hypervisor.h>
68 #endif
69 
70 /*
71  * AMD socket types.
72  * First index :
73  *		0 for family 0xf, revs B thru E
74  *		1 for family 0xf, revs F and G
75  *		2 for family 0x10
76  *		3 for family 0x11
77  *		4 for family 0x12
78  *		5 for family 0x14
79  *		6 for family 0x15, models 00 - 0f
80  *		7 for family 0x15, models 10 - 1f
81  *		8 for family 0x15, models 30 - 3f
82  *		9 for family 0x15, models 60 - 6f
83  *		10 for family 0x15, models 70 - 7f
84  *		11 for family 0x16, models 00 - 0f
85  *		12 for family 0x16, models 30 - 3f
86  *		13 for family 0x17, models 00 - 0f
87  *		14 for family 0x17, models 10 - 2f
88  *		15 for family 0x17, models 30 - 3f
89  *		16 for family 0x17, models 60 - 6f
90  *		17 for family 0x17, models 70 - 7f
91  *		18 for family 0x18, models 00 - 0f
92  *		19 for family 0x19, models 00 - 0f
93  *		20 for family 0x19, models 20 - 2f
94  *		21 for family 0x19, models 50 - 5f
95  * Second index by (model & 0x3) for family 0fh,
96  * CPUID pkg bits (Fn8000_0001_EBX[31:28]) for later families.
97  */
98 static uint32_t amd_skts[22][8] = {
99 	/*
100 	 * Family 0xf revisions B through E
101 	 */
102 #define	A_SKTS_0			0
103 	{
104 		X86_SOCKET_754,		/* 0b000 */
105 		X86_SOCKET_940,		/* 0b001 */
106 		X86_SOCKET_754,		/* 0b010 */
107 		X86_SOCKET_939,		/* 0b011 */
108 		X86_SOCKET_UNKNOWN,	/* 0b100 */
109 		X86_SOCKET_UNKNOWN,	/* 0b101 */
110 		X86_SOCKET_UNKNOWN,	/* 0b110 */
111 		X86_SOCKET_UNKNOWN	/* 0b111 */
112 	},
113 	/*
114 	 * Family 0xf revisions F and G
115 	 */
116 #define	A_SKTS_1			1
117 	{
118 		X86_SOCKET_S1g1,	/* 0b000 */
119 		X86_SOCKET_F1207,	/* 0b001 */
120 		X86_SOCKET_UNKNOWN,	/* 0b010 */
121 		X86_SOCKET_AM2,		/* 0b011 */
122 		X86_SOCKET_UNKNOWN,	/* 0b100 */
123 		X86_SOCKET_UNKNOWN,	/* 0b101 */
124 		X86_SOCKET_UNKNOWN,	/* 0b110 */
125 		X86_SOCKET_UNKNOWN	/* 0b111 */
126 	},
127 	/*
128 	 * Family 0x10
129 	 */
130 #define	A_SKTS_2			2
131 	{
132 		X86_SOCKET_F1207,	/* 0b000 */
133 		X86_SOCKET_AM2R2,	/* 0b001 */
134 		X86_SOCKET_S1g3,	/* 0b010 */
135 		X86_SOCKET_G34,		/* 0b011 */
136 		X86_SOCKET_ASB2,	/* 0b100 */
137 		X86_SOCKET_C32,		/* 0b101 */
138 		X86_SOCKET_UNKNOWN,	/* 0b110 */
139 		X86_SOCKET_UNKNOWN	/* 0b111 */
140 	},
141 
142 	/*
143 	 * Family 0x11
144 	 */
145 #define	A_SKTS_3			3
146 	{
147 		X86_SOCKET_UNKNOWN,	/* 0b000 */
148 		X86_SOCKET_UNKNOWN,	/* 0b001 */
149 		X86_SOCKET_S1g2,	/* 0b010 */
150 		X86_SOCKET_UNKNOWN,	/* 0b011 */
151 		X86_SOCKET_UNKNOWN,	/* 0b100 */
152 		X86_SOCKET_UNKNOWN,	/* 0b101 */
153 		X86_SOCKET_UNKNOWN,	/* 0b110 */
154 		X86_SOCKET_UNKNOWN	/* 0b111 */
155 	},
156 
157 	/*
158 	 * Family 0x12
159 	 */
160 #define	A_SKTS_4			4
161 	{
162 		X86_SOCKET_UNKNOWN,	/* 0b000 */
163 		X86_SOCKET_FS1,		/* 0b001 */
164 		X86_SOCKET_FM1,		/* 0b010 */
165 		X86_SOCKET_UNKNOWN,	/* 0b011 */
166 		X86_SOCKET_UNKNOWN,	/* 0b100 */
167 		X86_SOCKET_UNKNOWN,	/* 0b101 */
168 		X86_SOCKET_UNKNOWN,	/* 0b110 */
169 		X86_SOCKET_UNKNOWN	/* 0b111 */
170 	},
171 
172 	/*
173 	 * Family 0x14
174 	 */
175 #define	A_SKTS_5			5
176 	{
177 		X86_SOCKET_FT1,		/* 0b000 */
178 		X86_SOCKET_UNKNOWN,	/* 0b001 */
179 		X86_SOCKET_UNKNOWN,	/* 0b010 */
180 		X86_SOCKET_UNKNOWN,	/* 0b011 */
181 		X86_SOCKET_UNKNOWN,	/* 0b100 */
182 		X86_SOCKET_UNKNOWN,	/* 0b101 */
183 		X86_SOCKET_UNKNOWN,	/* 0b110 */
184 		X86_SOCKET_UNKNOWN	/* 0b111 */
185 	},
186 
187 	/*
188 	 * Family 0x15 models 00 - 0f
189 	 */
190 #define	A_SKTS_6			6
191 	{
192 		X86_SOCKET_UNKNOWN,	/* 0b000 */
193 		X86_SOCKET_AM3R2,	/* 0b001 */
194 		X86_SOCKET_UNKNOWN,	/* 0b010 */
195 		X86_SOCKET_G34,		/* 0b011 */
196 		X86_SOCKET_UNKNOWN,	/* 0b100 */
197 		X86_SOCKET_C32,		/* 0b101 */
198 		X86_SOCKET_UNKNOWN,	/* 0b110 */
199 		X86_SOCKET_UNKNOWN	/* 0b111 */
200 	},
201 
202 	/*
203 	 * Family 0x15 models 10 - 1f
204 	 */
205 #define	A_SKTS_7			7
206 	{
207 		X86_SOCKET_FP2,		/* 0b000 */
208 		X86_SOCKET_FS1R2,	/* 0b001 */
209 		X86_SOCKET_FM2,		/* 0b010 */
210 		X86_SOCKET_UNKNOWN,	/* 0b011 */
211 		X86_SOCKET_UNKNOWN,	/* 0b100 */
212 		X86_SOCKET_UNKNOWN,	/* 0b101 */
213 		X86_SOCKET_UNKNOWN,	/* 0b110 */
214 		X86_SOCKET_UNKNOWN	/* 0b111 */
215 	},
216 
217 	/*
218 	 * Family 0x15 models 30-3f
219 	 */
220 #define	A_SKTS_8			8
221 	{
222 		X86_SOCKET_FP3,		/* 0b000 */
223 		X86_SOCKET_FM2R2,	/* 0b001 */
224 		X86_SOCKET_UNKNOWN,	/* 0b010 */
225 		X86_SOCKET_UNKNOWN,	/* 0b011 */
226 		X86_SOCKET_UNKNOWN,	/* 0b100 */
227 		X86_SOCKET_UNKNOWN,	/* 0b101 */
228 		X86_SOCKET_UNKNOWN,	/* 0b110 */
229 		X86_SOCKET_UNKNOWN	/* 0b111 */
230 	},
231 
232 	/*
233 	 * Family 0x15 models 60-6f
234 	 */
235 #define	A_SKTS_9			9
236 	{
237 		X86_SOCKET_FP4,		/* 0b000 */
238 		X86_SOCKET_UNKNOWN,	/* 0b001 */
239 		X86_SOCKET_AM4,		/* 0b010 */
240 		X86_SOCKET_FM2R2,	/* 0b011 */
241 		X86_SOCKET_UNKNOWN,	/* 0b100 */
242 		X86_SOCKET_UNKNOWN,	/* 0b101 */
243 		X86_SOCKET_UNKNOWN,	/* 0b110 */
244 		X86_SOCKET_UNKNOWN	/* 0b111 */
245 	},
246 
247 	/*
248 	 * Family 0x15 models 70-7f
249 	 */
250 #define	A_SKTS_10			10
251 	{
252 		X86_SOCKET_FP4,		/* 0b000 */
253 		X86_SOCKET_UNKNOWN,	/* 0b001 */
254 		X86_SOCKET_AM4,		/* 0b010 */
255 		X86_SOCKET_UNKNOWN,	/* 0b011 */
256 		X86_SOCKET_FT4,		/* 0b100 */
257 		X86_SOCKET_UNKNOWN,	/* 0b101 */
258 		X86_SOCKET_UNKNOWN,	/* 0b110 */
259 		X86_SOCKET_UNKNOWN	/* 0b111 */
260 	},
261 
262 	/*
263 	 * Family 0x16 models 00-0f
264 	 */
265 #define	A_SKTS_11			11
266 	{
267 		X86_SOCKET_FT3,		/* 0b000 */
268 		X86_SOCKET_FS1B,	/* 0b001 */
269 		X86_SOCKET_UNKNOWN,	/* 0b010 */
270 		X86_SOCKET_UNKNOWN,	/* 0b011 */
271 		X86_SOCKET_UNKNOWN,	/* 0b100 */
272 		X86_SOCKET_UNKNOWN,	/* 0b101 */
273 		X86_SOCKET_UNKNOWN,	/* 0b110 */
274 		X86_SOCKET_UNKNOWN	/* 0b111 */
275 	},
276 
277 	/*
278 	 * Family 0x16 models 30-3f
279 	 */
280 #define	A_SKTS_12			12
281 	{
282 		X86_SOCKET_FT3B,	/* 0b000 */
283 		X86_SOCKET_UNKNOWN,	/* 0b001 */
284 		X86_SOCKET_UNKNOWN,	/* 0b010 */
285 		X86_SOCKET_FP4,		/* 0b011 */
286 		X86_SOCKET_UNKNOWN,	/* 0b100 */
287 		X86_SOCKET_UNKNOWN,	/* 0b101 */
288 		X86_SOCKET_UNKNOWN,	/* 0b110 */
289 		X86_SOCKET_UNKNOWN	/* 0b111 */
290 	},
291 
292 	/*
293 	 * Family 0x17 models 00-0f	(Zen 1 - Naples, Ryzen)
294 	 */
295 #define	A_SKTS_13			13
296 	{
297 		X86_SOCKET_UNKNOWN,	/* 0b000 */
298 		X86_SOCKET_UNKNOWN,	/* 0b001 */
299 		X86_SOCKET_AM4,		/* 0b010 */
300 		X86_SOCKET_UNKNOWN,	/* 0b011 */
301 		X86_SOCKET_SP3,		/* 0b100 */
302 		X86_SOCKET_UNKNOWN,	/* 0b101 */
303 		X86_SOCKET_UNKNOWN,	/* 0b110 */
304 		X86_SOCKET_SP3R2	/* 0b111 */
305 	},
306 
307 	/*
308 	 * Family 0x17 models 10-2f	(Zen 1 - APU: Raven Ridge)
309 	 *				(Zen 1 - APU: Banded Kestrel)
310 	 *				(Zen 1 - APU: Dali)
311 	 */
312 #define	A_SKTS_14			14
313 	{
314 		X86_SOCKET_FP5,		/* 0b000 */
315 		X86_SOCKET_UNKNOWN,	/* 0b001 */
316 		X86_SOCKET_AM4,		/* 0b010 */
317 		X86_SOCKET_UNKNOWN,	/* 0b011 */
318 		X86_SOCKET_UNKNOWN,	/* 0b100 */
319 		X86_SOCKET_UNKNOWN,	/* 0b101 */
320 		X86_SOCKET_UNKNOWN,	/* 0b110 */
321 		X86_SOCKET_UNKNOWN	/* 0b111 */
322 	},
323 
324 	/*
325 	 * Family 0x17 models 30-3f	(Zen 2 - Rome)
326 	 */
327 #define	A_SKTS_15			15
328 	{
329 		X86_SOCKET_UNKNOWN,	/* 0b000 */
330 		X86_SOCKET_UNKNOWN,	/* 0b001 */
331 		X86_SOCKET_UNKNOWN,	/* 0b010 */
332 		X86_SOCKET_UNKNOWN,	/* 0b011 */
333 		X86_SOCKET_SP3,		/* 0b100 */
334 		X86_SOCKET_UNKNOWN,	/* 0b101 */
335 		X86_SOCKET_UNKNOWN,	/* 0b110 */
336 		X86_SOCKET_SP3R2	/* 0b111 */
337 	},
338 
339 	/*
340 	 * Family 0x17 models 60-6f	(Zen 2 - Renoir)
341 	 */
342 #define	A_SKTS_16			16
343 	{
344 		X86_SOCKET_FP6,		/* 0b000 */
345 		X86_SOCKET_UNKNOWN,	/* 0b001 */
346 		X86_SOCKET_AM4,		/* 0b010 */
347 		X86_SOCKET_UNKNOWN,	/* 0b011 */
348 		X86_SOCKET_UNKNOWN,	/* 0b100 */
349 		X86_SOCKET_UNKNOWN,	/* 0b101 */
350 		X86_SOCKET_UNKNOWN,	/* 0b110 */
351 		X86_SOCKET_UNKNOWN	/* 0b111 */
352 	},
353 
354 	/*
355 	 * Family 0x17 models 70-7f	(Zen 2 - Matisse)
356 	 */
357 #define	A_SKTS_17			17
358 	{
359 		X86_SOCKET_UNKNOWN,	/* 0b000 */
360 		X86_SOCKET_UNKNOWN,	/* 0b001 */
361 		X86_SOCKET_AM4,		/* 0b010 */
362 		X86_SOCKET_UNKNOWN,	/* 0b011 */
363 		X86_SOCKET_UNKNOWN,	/* 0b100 */
364 		X86_SOCKET_UNKNOWN,	/* 0b101 */
365 		X86_SOCKET_UNKNOWN,	/* 0b110 */
366 		X86_SOCKET_UNKNOWN	/* 0b111 */
367 	},
368 
369 	/*
370 	 * Family 0x18 models 00-0f	(Dhyana)
371 	 */
372 #define	A_SKTS_18			18
373 	{
374 		X86_SOCKET_UNKNOWN,	/* 0b000 */
375 		X86_SOCKET_UNKNOWN,	/* 0b001 */
376 		X86_SOCKET_UNKNOWN,	/* 0b010 */
377 		X86_SOCKET_UNKNOWN,	/* 0b011 */
378 		X86_SOCKET_SL1,		/* 0b100 */
379 		X86_SOCKET_UNKNOWN,	/* 0b101 */
380 		X86_SOCKET_DM1,		/* 0b110 */
381 		X86_SOCKET_SL1R2	/* 0b111 */
382 	},
383 
384 	/*
385 	 * Family 0x19 models 00-0f	(Zen 3 - Milan)
386 	 */
387 #define	A_SKTS_19			19
388 	{
389 		X86_SOCKET_UNKNOWN,	/* 0b000 */
390 		X86_SOCKET_UNKNOWN,	/* 0b001 */
391 		X86_SOCKET_UNKNOWN,	/* 0b010 */
392 		X86_SOCKET_UNKNOWN,	/* 0b011 */
393 		X86_SOCKET_SP3,		/* 0b100 */
394 		X86_SOCKET_UNKNOWN,	/* 0b101 */
395 		X86_SOCKET_UNKNOWN,	/* 0b110 */
396 		X86_SOCKET_STRX4	/* 0b111 */
397 	},
398 
399 	/*
400 	 * Family 0x19 models 20-2f	(Zen 3 - Vermeer)
401 	 */
402 #define	A_SKTS_20			20
403 	{
404 		X86_SOCKET_UNKNOWN,	/* 0b000 */
405 		X86_SOCKET_UNKNOWN,	/* 0b001 */
406 		X86_SOCKET_AM4,		/* 0b010 */
407 		X86_SOCKET_UNKNOWN,	/* 0b011 */
408 		X86_SOCKET_UNKNOWN,	/* 0b100 */
409 		X86_SOCKET_UNKNOWN,	/* 0b101 */
410 		X86_SOCKET_UNKNOWN,	/* 0b110 */
411 		X86_SOCKET_UNKNOWN	/* 0b111 */
412 	},
413 
414 	/*
415 	 * Family 0x19 models 50-5f	(Zen 3 - Cezanne)
416 	 */
417 #define	A_SKTS_21			21
418 	{
419 		X86_SOCKET_FP6,		/* 0b000 */
420 		X86_SOCKET_UNKNOWN,	/* 0b001 */
421 		X86_SOCKET_AM4,		/* 0b010 */
422 		X86_SOCKET_UNKNOWN,	/* 0b011 */
423 		X86_SOCKET_UNKNOWN,	/* 0b100 */
424 		X86_SOCKET_UNKNOWN,	/* 0b101 */
425 		X86_SOCKET_UNKNOWN,	/* 0b110 */
426 		X86_SOCKET_UNKNOWN	/* 0b111 */
427 	},
428 };
429 
430 struct amd_sktmap_s {
431 	uint32_t	skt_code;
432 	char		sktstr[16];
433 };
434 static struct amd_sktmap_s amd_sktmap_strs[X86_NUM_SOCKETS + 1] = {
435 	{ X86_SOCKET_754,	"754" },
436 	{ X86_SOCKET_939,	"939" },
437 	{ X86_SOCKET_940,	"940" },
438 	{ X86_SOCKET_S1g1,	"S1g1" },
439 	{ X86_SOCKET_AM2,	"AM2" },
440 	{ X86_SOCKET_F1207,	"F(1207)" },
441 	{ X86_SOCKET_S1g2,	"S1g2" },
442 	{ X86_SOCKET_S1g3,	"S1g3" },
443 	{ X86_SOCKET_AM,	"AM" },
444 	{ X86_SOCKET_AM2R2,	"AM2r2" },
445 	{ X86_SOCKET_AM3,	"AM3" },
446 	{ X86_SOCKET_G34,	"G34" },
447 	{ X86_SOCKET_ASB2,	"ASB2" },
448 	{ X86_SOCKET_C32,	"C32" },
449 	{ X86_SOCKET_FT1,	"FT1" },
450 	{ X86_SOCKET_FM1,	"FM1" },
451 	{ X86_SOCKET_FS1,	"FS1" },
452 	{ X86_SOCKET_AM3R2,	"AM3r2" },
453 	{ X86_SOCKET_FP2,	"FP2" },
454 	{ X86_SOCKET_FS1R2,	"FS1r2" },
455 	{ X86_SOCKET_FM2,	"FM2" },
456 	{ X86_SOCKET_FP3,	"FP3" },
457 	{ X86_SOCKET_FM2R2,	"FM2r2" },
458 	{ X86_SOCKET_FP4,	"FP4" },
459 	{ X86_SOCKET_AM4,	"AM4" },
460 	{ X86_SOCKET_FT3,	"FT3" },
461 	{ X86_SOCKET_FT4,	"FT4" },
462 	{ X86_SOCKET_FS1B,	"FS1b" },
463 	{ X86_SOCKET_FT3B,	"FT3b" },
464 	{ X86_SOCKET_SP3,	"SP3" },
465 	{ X86_SOCKET_SP3R2,	"SP3r2" },
466 	{ X86_SOCKET_FP5,	"FP5" },
467 	{ X86_SOCKET_FP6,	"FP6" },
468 	{ X86_SOCKET_STRX4,	"sTRX4" },
469 	{ X86_SOCKET_SL1,	"SL1" },
470 	{ X86_SOCKET_SL1R2,	"SL1R2" },
471 	{ X86_SOCKET_DM1,	"DM1" },
472 	{ X86_SOCKET_UNKNOWN,	"Unknown" }
473 };
474 
475 static const struct amd_skt_mapent {
476 	uint_t sm_family;
477 	uint_t sm_modello;
478 	uint_t sm_modelhi;
479 	uint_t sm_sktidx;
480 } amd_sktmap[] = {
481 	{ 0x10, 0x00, 0xff, A_SKTS_2 },
482 	{ 0x11, 0x00, 0xff, A_SKTS_3 },
483 	{ 0x12, 0x00, 0xff, A_SKTS_4 },
484 	{ 0x14, 0x00, 0x0f, A_SKTS_5 },
485 	{ 0x15, 0x00, 0x0f, A_SKTS_6 },
486 	{ 0x15, 0x10, 0x1f, A_SKTS_7 },
487 	{ 0x15, 0x30, 0x3f, A_SKTS_8 },
488 	{ 0x15, 0x60, 0x6f, A_SKTS_9 },
489 	{ 0x15, 0x70, 0x7f, A_SKTS_10 },
490 	{ 0x16, 0x00, 0x0f, A_SKTS_11 },
491 	{ 0x16, 0x30, 0x3f, A_SKTS_12 },
492 	{ 0x17, 0x00, 0x0f, A_SKTS_13 },
493 	{ 0x17, 0x10, 0x2f, A_SKTS_14 },
494 	{ 0x17, 0x30, 0x3f, A_SKTS_15 },
495 	{ 0x17, 0x60, 0x6f, A_SKTS_16 },
496 	{ 0x17, 0x70, 0x7f, A_SKTS_17 },
497 	{ 0x18, 0x00, 0x0f, A_SKTS_18 },
498 	{ 0x19, 0x00, 0x0f, A_SKTS_19 },
499 	{ 0x19, 0x20, 0x2f, A_SKTS_20 },
500 	{ 0x19, 0x50, 0x5f, A_SKTS_21 }
501 };
502 
503 /*
504  * Table for mapping AMD Family 0xf and AMD Family 0x10 model/stepping
505  * combination to chip "revision" and socket type.
506  *
507  * The first member of this array that matches a given family, extended model
508  * plus model range, and stepping range will be considered a match.
509  */
510 static const struct amd_rev_mapent {
511 	uint_t rm_family;
512 	uint_t rm_modello;
513 	uint_t rm_modelhi;
514 	uint_t rm_steplo;
515 	uint_t rm_stephi;
516 	uint32_t rm_chiprev;
517 	const char *rm_chiprevstr;
518 	uint_t rm_sktidx;
519 } amd_revmap[] = {
520 	/*
521 	 * =============== AuthenticAMD Family 0xf ===============
522 	 */
523 
524 	/*
525 	 * Rev B includes model 0x4 stepping 0 and model 0x5 stepping 0 and 1.
526 	 */
527 	{ 0xf, 0x04, 0x04, 0x0, 0x0, X86_CHIPREV_AMD_F_REV_B, "B", A_SKTS_0 },
528 	{ 0xf, 0x05, 0x05, 0x0, 0x1, X86_CHIPREV_AMD_F_REV_B, "B", A_SKTS_0 },
529 	/*
530 	 * Rev C0 includes model 0x4 stepping 8 and model 0x5 stepping 8
531 	 */
532 	{ 0xf, 0x04, 0x05, 0x8, 0x8, X86_CHIPREV_AMD_F_REV_C0, "C0", A_SKTS_0 },
533 	/*
534 	 * Rev CG is the rest of extended model 0x0 - i.e., everything
535 	 * but the rev B and C0 combinations covered above.
536 	 */
537 	{ 0xf, 0x00, 0x0f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_CG, "CG", A_SKTS_0 },
538 	/*
539 	 * Rev D has extended model 0x1.
540 	 */
541 	{ 0xf, 0x10, 0x1f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_D, "D", A_SKTS_0 },
542 	/*
543 	 * Rev E has extended model 0x2.
544 	 * Extended model 0x3 is unused but available to grow into.
545 	 */
546 	{ 0xf, 0x20, 0x3f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_E, "E", A_SKTS_0 },
547 	/*
548 	 * Rev F has extended models 0x4 and 0x5.
549 	 */
550 	{ 0xf, 0x40, 0x5f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_F, "F", A_SKTS_1 },
551 	/*
552 	 * Rev G has extended model 0x6.
553 	 */
554 	{ 0xf, 0x60, 0x6f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_G, "G", A_SKTS_1 },
555 
556 	/*
557 	 * =============== AuthenticAMD Family 0x10 ===============
558 	 */
559 
560 	/*
561 	 * Rev A has model 0 and stepping 0/1/2 for DR-{A0,A1,A2}.
562 	 * Give all of model 0 stepping range to rev A.
563 	 */
564 	{ 0x10, 0x00, 0x00, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_A, "A", A_SKTS_2 },
565 
566 	/*
567 	 * Rev B has model 2 and steppings 0/1/0xa/2 for DR-{B0,B1,BA,B2}.
568 	 * Give all of model 2 stepping range to rev B.
569 	 */
570 	{ 0x10, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_B, "B", A_SKTS_2 },
571 
572 	/*
573 	 * Rev C has models 4-6 (depending on L3 cache configuration)
574 	 * Give all of models 4-6 stepping range 0-2 to rev C2.
575 	 */
576 	{ 0x10, 0x4, 0x6, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_C2, "C2", A_SKTS_2 },
577 
578 	/*
579 	 * Rev C has models 4-6 (depending on L3 cache configuration)
580 	 * Give all of models 4-6 stepping range >= 3 to rev C3.
581 	 */
582 	{ 0x10, 0x4, 0x6, 0x3, 0xf, X86_CHIPREV_AMD_10_REV_C3, "C3", A_SKTS_2 },
583 
584 	/*
585 	 * Rev D has models 8 and 9
586 	 * Give all of model 8 and 9 stepping 0 to rev D0.
587 	 */
588 	{ 0x10, 0x8, 0x9, 0x0, 0x0, X86_CHIPREV_AMD_10_REV_D0, "D0", A_SKTS_2 },
589 
590 	/*
591 	 * Rev D has models 8 and 9
592 	 * Give all of model 8 and 9 stepping range >= 1 to rev D1.
593 	 */
594 	{ 0x10, 0x8, 0x9, 0x1, 0xf, X86_CHIPREV_AMD_10_REV_D1, "D1", A_SKTS_2 },
595 
596 	/*
597 	 * Rev E has models A and stepping 0
598 	 * Give all of model A stepping range to rev E.
599 	 */
600 	{ 0x10, 0xA, 0xA, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_E, "E", A_SKTS_2 },
601 
602 	/*
603 	 * =============== AuthenticAMD Family 0x11 ===============
604 	 */
605 	{ 0x11, 0x03, 0x03, 0x0, 0xf, X86_CHIPREV_AMD_11_REV_B, "B", A_SKTS_3 },
606 
607 	/*
608 	 * =============== AuthenticAMD Family 0x12 ===============
609 	 */
610 	{ 0x12, 0x01, 0x01, 0x0, 0xf, X86_CHIPREV_AMD_12_REV_B, "B", A_SKTS_4 },
611 
612 	/*
613 	 * =============== AuthenticAMD Family 0x14 ===============
614 	 */
615 	{ 0x14, 0x01, 0x01, 0x0, 0xf, X86_CHIPREV_AMD_14_REV_B, "B", A_SKTS_5 },
616 	{ 0x14, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_14_REV_C, "C", A_SKTS_5 },
617 
618 	/*
619 	 * =============== AuthenticAMD Family 0x15 ===============
620 	 */
621 	{ 0x15, 0x01, 0x01, 0x2, 0x2, X86_CHIPREV_AMD_15OR_REV_B2, "OR-B2",
622 	    A_SKTS_6 },
623 	{ 0x15, 0x02, 0x02, 0x0, 0x0, X86_CHIPREV_AMD_150R_REV_C0, "OR-C0",
624 	    A_SKTS_6 },
625 	{ 0x15, 0x10, 0x10, 0x1, 0x1, X86_CHIPREV_AMD_15TN_REV_A1, "TN-A1",
626 	    A_SKTS_7 },
627 	{ 0x15, 0x30, 0x30, 0x1, 0x1, X86_CHIPREV_AMD_15KV_REV_A1, "KV-A1",
628 	    A_SKTS_8 },
629 	/*
630 	 * There is no Family 15 Models 60-6f revision guide available, so at
631 	 * least get the socket information.
632 	 */
633 	{ 0x15, 0x60, 0x6f, 0x0, 0xf, X86_CHIPREV_AMD_15F60, "??",
634 	    A_SKTS_9 },
635 	{ 0x15, 0x70, 0x70, 0x0, 0x0, X86_CHIPREV_AMD_15ST_REV_A0, "ST-A0",
636 	    A_SKTS_10 },
637 
638 	/*
639 	 * =============== AuthenticAMD Family 0x16 ===============
640 	 */
641 	{ 0x16, 0x00, 0x00, 0x1, 0x1, X86_CHIPREV_AMD_16_KB_A1, "KB-A1",
642 	    A_SKTS_11 },
643 	{ 0x16, 0x30, 0x30, 0x1, 0x1, X86_CHIPREV_AMD_16_ML_A1, "ML-A1",
644 	    A_SKTS_12 },
645 
646 	/*
647 	 * =============== AuthenticAMD Family 0x17 ===============
648 	 */
649 	{ 0x17, 0x01, 0x01, 0x1, 0x1, X86_CHIPREV_AMD_17_ZP_B1, "ZP-B1",
650 	    A_SKTS_13 },
651 	{ 0x17, 0x01, 0x01, 0x2, 0x2, X86_CHIPREV_AMD_17_ZP_B2, "ZP-B2",
652 	    A_SKTS_13 },
653 	{ 0x17, 0x01, 0x01, 0x1, 0x1, X86_CHIPREV_AMD_17_PiR_B2, "PiR-B2",
654 	    A_SKTS_13 },
655 
656 	{ 0x17, 0x11, 0x11, 0x0, 0x0, X86_CHIPREV_AMD_17_RV_B0, "RV-B0",
657 	    A_SKTS_14 },
658 	{ 0x17, 0x11, 0x11, 0x1, 0x1, X86_CHIPREV_AMD_17_RV_B1, "RV-B1",
659 	    A_SKTS_14 },
660 	{ 0x17, 0x18, 0x18, 0x1, 0x1, X86_CHIPREV_AMD_17_PCO_B1, "PCO-B1",
661 	    A_SKTS_14 },
662 
663 	{ 0x17, 0x30, 0x30, 0x0, 0x0, X86_CHIPREV_AMD_17_SSP_A0, "SSP-A0",
664 	    A_SKTS_15 },
665 	{ 0x17, 0x31, 0x31, 0x0, 0x0, X86_CHIPREV_AMD_17_SSP_B0, "SSP-B0",
666 	    A_SKTS_15 },
667 
668 	{ 0x17, 0x71, 0x71, 0x0, 0x0, X86_CHIPREV_AMD_17_MTS_B0, "MTS-B0",
669 	    A_SKTS_17 },
670 
671 	/*
672 	 * =============== HygonGenuine Family 0x18 ===============
673 	 */
674 	{ 0x18, 0x00, 0x00, 0x1, 0x1, X86_CHIPREV_HYGON_18_DN_A1, "DN_A1",
675 	    A_SKTS_18 },
676 
677 	/*
678 	 * =============== AuthenticAMD Family 0x19 ===============
679 	 */
680 	{ 0x19, 0x00, 0x00, 0x0, 0x0, X86_CHIPREV_AMD_19_GN_A0, "GN-A0",
681 	    A_SKTS_19 },
682 	{ 0x19, 0x01, 0x01, 0x0, 0x0, X86_CHIPREV_AMD_19_GN_B0, "GN-B0",
683 	    A_SKTS_19 },
684 	{ 0x19, 0x01, 0x01, 0x1, 0x1, X86_CHIPREV_AMD_19_GN_B1, "GN-B1",
685 	    A_SKTS_19 },
686 
687 	{ 0x19, 0x21, 0x21, 0x0, 0x0, X86_CHIPREV_AMD_19_VMR_B0, "VMR-B0",
688 	    A_SKTS_20 },
689 	{ 0x19, 0x21, 0x21, 0x2, 0x2, X86_CHIPREV_AMD_19_VMR_B1, "VMR-B1",
690 	    A_SKTS_20 },
691 };
692 
693 /*
694  * AMD keeps the socket type in CPUID Fn8000_0001_EBX, bits 31:28.
695  */
696 static uint32_t
697 synth_amd_skt_cpuid(uint_t family, uint_t sktid)
698 {
699 	struct cpuid_regs cp;
700 	uint_t idx;
701 
702 	cp.cp_eax = 0x80000001;
703 	(void) __cpuid_insn(&cp);
704 
705 	/* PkgType bits */
706 	idx = BITX(cp.cp_ebx, 31, 28);
707 
708 	if (idx > 7) {
709 		return (X86_SOCKET_UNKNOWN);
710 	}
711 
712 	if (family == 0x10) {
713 		uint32_t val;
714 
715 		val = pci_getl_func(0, 24, 2, 0x94);
716 		if (BITX(val, 8, 8)) {
717 			if (amd_skts[sktid][idx] == X86_SOCKET_AM2R2) {
718 				return (X86_SOCKET_AM3);
719 			} else if (amd_skts[sktid][idx] == X86_SOCKET_S1g3) {
720 				return (X86_SOCKET_S1g4);
721 			}
722 		}
723 	}
724 
725 	return (amd_skts[sktid][idx]);
726 }
727 
728 static void
729 synth_amd_skt(uint_t family, uint_t model, uint32_t *skt_p)
730 {
731 	int platform;
732 	const struct amd_skt_mapent *skt;
733 	uint_t i;
734 
735 	if (skt_p == NULL || family < 0xf)
736 		return;
737 
738 #ifdef __xpv
739 	/* PV guest */
740 	if (!is_controldom()) {
741 		*skt_p = X86_SOCKET_UNKNOWN;
742 		return;
743 	}
744 #endif
745 	platform = get_hwenv();
746 
747 	if ((platform & HW_VIRTUAL) != 0) {
748 		*skt_p = X86_SOCKET_UNKNOWN;
749 		return;
750 	}
751 
752 	for (i = 0, skt = amd_sktmap; i < ARRAY_SIZE(amd_sktmap);
753 	    i++, skt++) {
754 		if (family == skt->sm_family &&
755 		    model >= skt->sm_modello && model <= skt->sm_modelhi) {
756 			*skt_p = synth_amd_skt_cpuid(family, skt->sm_sktidx);
757 		}
758 	}
759 }
760 
761 static void
762 synth_amd_info(uint_t family, uint_t model, uint_t step,
763     uint32_t *skt_p, uint32_t *chiprev_p, const char **chiprevstr_p)
764 {
765 	const struct amd_rev_mapent *rmp;
766 	int found = 0;
767 	int i;
768 
769 	if (family < 0xf)
770 		return;
771 
772 	for (i = 0, rmp = amd_revmap; i < ARRAY_SIZE(amd_revmap); i++, rmp++) {
773 		if (family == rmp->rm_family &&
774 		    model >= rmp->rm_modello && model <= rmp->rm_modelhi &&
775 		    step >= rmp->rm_steplo && step <= rmp->rm_stephi) {
776 			found = 1;
777 			break;
778 		}
779 	}
780 
781 	if (!found) {
782 		synth_amd_skt(family, model, skt_p);
783 		return;
784 	}
785 
786 	if (chiprev_p != NULL)
787 		*chiprev_p = rmp->rm_chiprev;
788 	if (chiprevstr_p != NULL)
789 		*chiprevstr_p = rmp->rm_chiprevstr;
790 
791 	if (skt_p != NULL) {
792 		int platform;
793 
794 #ifdef __xpv
795 		/* PV guest */
796 		if (!is_controldom()) {
797 			*skt_p = X86_SOCKET_UNKNOWN;
798 			return;
799 		}
800 #endif
801 		platform = get_hwenv();
802 
803 		if ((platform & HW_VIRTUAL) != 0) {
804 			*skt_p = X86_SOCKET_UNKNOWN;
805 		} else if (family == 0xf) {
806 			*skt_p = amd_skts[rmp->rm_sktidx][model & 0x3];
807 		} else {
808 			*skt_p = synth_amd_skt_cpuid(family, rmp->rm_sktidx);
809 		}
810 	}
811 }
812 
813 uint32_t
814 _cpuid_skt(uint_t vendor, uint_t family, uint_t model, uint_t step)
815 {
816 	uint32_t skt = X86_SOCKET_UNKNOWN;
817 
818 	switch (vendor) {
819 	case X86_VENDOR_AMD:
820 	case X86_VENDOR_HYGON:
821 		synth_amd_info(family, model, step, &skt, NULL, NULL);
822 		break;
823 
824 	default:
825 		break;
826 
827 	}
828 
829 	return (skt);
830 }
831 
832 const char *
833 _cpuid_sktstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
834 {
835 	const char *sktstr = "Unknown";
836 	struct amd_sktmap_s *sktmapp;
837 	uint32_t skt = X86_SOCKET_UNKNOWN;
838 
839 	switch (vendor) {
840 	case X86_VENDOR_AMD:
841 	case X86_VENDOR_HYGON:
842 		synth_amd_info(family, model, step, &skt, NULL, NULL);
843 
844 		sktmapp = amd_sktmap_strs;
845 		while (sktmapp->skt_code != X86_SOCKET_UNKNOWN) {
846 			if (sktmapp->skt_code == skt)
847 				break;
848 			sktmapp++;
849 		}
850 		sktstr = sktmapp->sktstr;
851 		break;
852 
853 	default:
854 		break;
855 
856 	}
857 
858 	return (sktstr);
859 }
860 
861 uint32_t
862 _cpuid_chiprev(uint_t vendor, uint_t family, uint_t model, uint_t step)
863 {
864 	uint32_t chiprev = X86_CHIPREV_UNKNOWN;
865 
866 	switch (vendor) {
867 	case X86_VENDOR_AMD:
868 	case X86_VENDOR_HYGON:
869 		synth_amd_info(family, model, step, NULL, &chiprev, NULL);
870 		break;
871 
872 	default:
873 		break;
874 
875 	}
876 
877 	return (chiprev);
878 }
879 
880 const char *
881 _cpuid_chiprevstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
882 {
883 	const char *revstr = "Unknown";
884 
885 	switch (vendor) {
886 	case X86_VENDOR_AMD:
887 	case X86_VENDOR_HYGON:
888 		synth_amd_info(family, model, step, NULL, NULL, &revstr);
889 		break;
890 
891 	default:
892 		break;
893 
894 	}
895 
896 	return (revstr);
897 
898 }
899 
900 /*
901  * Map the vendor string to a type code
902  */
903 uint_t
904 _cpuid_vendorstr_to_vendorcode(char *vendorstr)
905 {
906 	if (strcmp(vendorstr, X86_VENDORSTR_Intel) == 0)
907 		return (X86_VENDOR_Intel);
908 	else if (strcmp(vendorstr, X86_VENDORSTR_AMD) == 0)
909 		return (X86_VENDOR_AMD);
910 	else if (strcmp(vendorstr, X86_VENDORSTR_HYGON) == 0)
911 		return (X86_VENDOR_HYGON);
912 	else if (strcmp(vendorstr, X86_VENDORSTR_TM) == 0)
913 		return (X86_VENDOR_TM);
914 	else if (strcmp(vendorstr, X86_VENDORSTR_CYRIX) == 0)
915 		return (X86_VENDOR_Cyrix);
916 	else if (strcmp(vendorstr, X86_VENDORSTR_UMC) == 0)
917 		return (X86_VENDOR_UMC);
918 	else if (strcmp(vendorstr, X86_VENDORSTR_NexGen) == 0)
919 		return (X86_VENDOR_NexGen);
920 	else if (strcmp(vendorstr, X86_VENDORSTR_Centaur) == 0)
921 		return (X86_VENDOR_Centaur);
922 	else if (strcmp(vendorstr, X86_VENDORSTR_Rise) == 0)
923 		return (X86_VENDOR_Rise);
924 	else if (strcmp(vendorstr, X86_VENDORSTR_SiS) == 0)
925 		return (X86_VENDOR_SiS);
926 	else if (strcmp(vendorstr, X86_VENDORSTR_NSC) == 0)
927 		return (X86_VENDOR_NSC);
928 	else
929 		return (X86_VENDOR_IntelClone);
930 }
931