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 2020 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 * Second index by (model & 0x3) for family 0fh,
92 * CPUID pkg bits (Fn8000_0001_EBX[31:28]) for later families.
93 */
94static uint32_t amd_skts[18][8] = {
95	/*
96	 * Family 0xf revisions B through E
97	 */
98#define	A_SKTS_0			0
99	{
100		X86_SOCKET_754,		/* 0b000 */
101		X86_SOCKET_940,		/* 0b001 */
102		X86_SOCKET_754,		/* 0b010 */
103		X86_SOCKET_939,		/* 0b011 */
104		X86_SOCKET_UNKNOWN,	/* 0b100 */
105		X86_SOCKET_UNKNOWN,	/* 0b101 */
106		X86_SOCKET_UNKNOWN,	/* 0b110 */
107		X86_SOCKET_UNKNOWN	/* 0b111 */
108	},
109	/*
110	 * Family 0xf revisions F and G
111	 */
112#define	A_SKTS_1			1
113	{
114		X86_SOCKET_S1g1,	/* 0b000 */
115		X86_SOCKET_F1207,	/* 0b001 */
116		X86_SOCKET_UNKNOWN,	/* 0b010 */
117		X86_SOCKET_AM2,		/* 0b011 */
118		X86_SOCKET_UNKNOWN,	/* 0b100 */
119		X86_SOCKET_UNKNOWN,	/* 0b101 */
120		X86_SOCKET_UNKNOWN,	/* 0b110 */
121		X86_SOCKET_UNKNOWN	/* 0b111 */
122	},
123	/*
124	 * Family 0x10
125	 */
126#define	A_SKTS_2			2
127	{
128		X86_SOCKET_F1207,	/* 0b000 */
129		X86_SOCKET_AM2R2,	/* 0b001 */
130		X86_SOCKET_S1g3,	/* 0b010 */
131		X86_SOCKET_G34,		/* 0b011 */
132		X86_SOCKET_ASB2,	/* 0b100 */
133		X86_SOCKET_C32,		/* 0b101 */
134		X86_SOCKET_UNKNOWN,	/* 0b110 */
135		X86_SOCKET_UNKNOWN	/* 0b111 */
136	},
137
138	/*
139	 * Family 0x11
140	 */
141#define	A_SKTS_3			3
142	{
143		X86_SOCKET_UNKNOWN,	/* 0b000 */
144		X86_SOCKET_UNKNOWN,	/* 0b001 */
145		X86_SOCKET_S1g2,	/* 0b010 */
146		X86_SOCKET_UNKNOWN,	/* 0b011 */
147		X86_SOCKET_UNKNOWN,	/* 0b100 */
148		X86_SOCKET_UNKNOWN,	/* 0b101 */
149		X86_SOCKET_UNKNOWN,	/* 0b110 */
150		X86_SOCKET_UNKNOWN	/* 0b111 */
151	},
152
153	/*
154	 * Family 0x12
155	 */
156#define	A_SKTS_4			4
157	{
158		X86_SOCKET_UNKNOWN,	/* 0b000 */
159		X86_SOCKET_FS1,		/* 0b001 */
160		X86_SOCKET_FM1,		/* 0b010 */
161		X86_SOCKET_UNKNOWN,	/* 0b011 */
162		X86_SOCKET_UNKNOWN,	/* 0b100 */
163		X86_SOCKET_UNKNOWN,	/* 0b101 */
164		X86_SOCKET_UNKNOWN,	/* 0b110 */
165		X86_SOCKET_UNKNOWN	/* 0b111 */
166	},
167
168	/*
169	 * Family 0x14
170	 */
171#define	A_SKTS_5			5
172	{
173		X86_SOCKET_FT1,		/* 0b000 */
174		X86_SOCKET_UNKNOWN,	/* 0b001 */
175		X86_SOCKET_UNKNOWN,	/* 0b010 */
176		X86_SOCKET_UNKNOWN,	/* 0b011 */
177		X86_SOCKET_UNKNOWN,	/* 0b100 */
178		X86_SOCKET_UNKNOWN,	/* 0b101 */
179		X86_SOCKET_UNKNOWN,	/* 0b110 */
180		X86_SOCKET_UNKNOWN	/* 0b111 */
181	},
182
183	/*
184	 * Family 0x15 models 00 - 0f
185	 */
186#define	A_SKTS_6			6
187	{
188		X86_SOCKET_UNKNOWN,	/* 0b000 */
189		X86_SOCKET_AM3R2,	/* 0b001 */
190		X86_SOCKET_UNKNOWN,	/* 0b010 */
191		X86_SOCKET_G34,		/* 0b011 */
192		X86_SOCKET_UNKNOWN,	/* 0b100 */
193		X86_SOCKET_C32,		/* 0b101 */
194		X86_SOCKET_UNKNOWN,	/* 0b110 */
195		X86_SOCKET_UNKNOWN	/* 0b111 */
196	},
197
198	/*
199	 * Family 0x15 models 10 - 1f
200	 */
201#define	A_SKTS_7			7
202	{
203		X86_SOCKET_FP2,		/* 0b000 */
204		X86_SOCKET_FS1R2,	/* 0b001 */
205		X86_SOCKET_FM2,		/* 0b010 */
206		X86_SOCKET_UNKNOWN,	/* 0b011 */
207		X86_SOCKET_UNKNOWN,	/* 0b100 */
208		X86_SOCKET_UNKNOWN,	/* 0b101 */
209		X86_SOCKET_UNKNOWN,	/* 0b110 */
210		X86_SOCKET_UNKNOWN	/* 0b111 */
211	},
212
213	/*
214	 * Family 0x15 models 30-3f
215	 */
216#define	A_SKTS_8			8
217	{
218		X86_SOCKET_FP3,		/* 0b000 */
219		X86_SOCKET_FM2R2,	/* 0b001 */
220		X86_SOCKET_UNKNOWN,	/* 0b010 */
221		X86_SOCKET_UNKNOWN,	/* 0b011 */
222		X86_SOCKET_UNKNOWN,	/* 0b100 */
223		X86_SOCKET_UNKNOWN,	/* 0b101 */
224		X86_SOCKET_UNKNOWN,	/* 0b110 */
225		X86_SOCKET_UNKNOWN	/* 0b111 */
226	},
227
228	/*
229	 * Family 0x15 models 60-6f
230	 */
231#define	A_SKTS_9			9
232	{
233		X86_SOCKET_FP4,		/* 0b000 */
234		X86_SOCKET_UNKNOWN,	/* 0b001 */
235		X86_SOCKET_AM4,		/* 0b010 */
236		X86_SOCKET_FM2R2,	/* 0b011 */
237		X86_SOCKET_UNKNOWN,	/* 0b100 */
238		X86_SOCKET_UNKNOWN,	/* 0b101 */
239		X86_SOCKET_UNKNOWN,	/* 0b110 */
240		X86_SOCKET_UNKNOWN	/* 0b111 */
241	},
242
243	/*
244	 * Family 0x15 models 70-7f
245	 */
246#define	A_SKTS_10			10
247	{
248		X86_SOCKET_FP4,		/* 0b000 */
249		X86_SOCKET_UNKNOWN,	/* 0b001 */
250		X86_SOCKET_AM4,		/* 0b010 */
251		X86_SOCKET_UNKNOWN,	/* 0b011 */
252		X86_SOCKET_FT4,		/* 0b100 */
253		X86_SOCKET_UNKNOWN,	/* 0b101 */
254		X86_SOCKET_UNKNOWN,	/* 0b110 */
255		X86_SOCKET_UNKNOWN	/* 0b111 */
256	},
257
258	/*
259	 * Family 0x16 models 00-0f
260	 */
261#define	A_SKTS_11			11
262	{
263		X86_SOCKET_FT3,		/* 0b000 */
264		X86_SOCKET_FS1B,	/* 0b001 */
265		X86_SOCKET_UNKNOWN,	/* 0b010 */
266		X86_SOCKET_UNKNOWN,	/* 0b011 */
267		X86_SOCKET_UNKNOWN,	/* 0b100 */
268		X86_SOCKET_UNKNOWN,	/* 0b101 */
269		X86_SOCKET_UNKNOWN,	/* 0b110 */
270		X86_SOCKET_UNKNOWN	/* 0b111 */
271	},
272
273	/*
274	 * Family 0x16 models 30-3f
275	 */
276#define	A_SKTS_12			12
277	{
278		X86_SOCKET_FT3B,	/* 0b000 */
279		X86_SOCKET_UNKNOWN,	/* 0b001 */
280		X86_SOCKET_UNKNOWN,	/* 0b010 */
281		X86_SOCKET_FP4,		/* 0b011 */
282		X86_SOCKET_UNKNOWN,	/* 0b100 */
283		X86_SOCKET_UNKNOWN,	/* 0b101 */
284		X86_SOCKET_UNKNOWN,	/* 0b110 */
285		X86_SOCKET_UNKNOWN	/* 0b111 */
286	},
287
288	/*
289	 * Family 0x17 models 00-0f	(Zen 1 - Naples, Ryzen)
290	 */
291#define	A_SKTS_13			13
292	{
293		X86_SOCKET_UNKNOWN,	/* 0b000 */
294		X86_SOCKET_UNKNOWN,	/* 0b001 */
295		X86_SOCKET_AM4,		/* 0b010 */
296		X86_SOCKET_UNKNOWN,	/* 0b011 */
297		X86_SOCKET_SP3,		/* 0b100 */
298		X86_SOCKET_UNKNOWN,	/* 0b101 */
299		X86_SOCKET_UNKNOWN,	/* 0b110 */
300		X86_SOCKET_SP3R2	/* 0b111 */
301	},
302
303	/*
304	 * Family 0x17 models 10-2f	(Zen 1 - APU: Raven Ridge)
305	 *				(Zen 1 - APU: Banded Kestrel)
306	 *				(Zen 1 - APU: Dali)
307	 */
308#define	A_SKTS_14			14
309	{
310		X86_SOCKET_FP5,		/* 0b000 */
311		X86_SOCKET_UNKNOWN,	/* 0b001 */
312		X86_SOCKET_AM4,		/* 0b010 */
313		X86_SOCKET_UNKNOWN,	/* 0b011 */
314		X86_SOCKET_UNKNOWN,	/* 0b100 */
315		X86_SOCKET_UNKNOWN,	/* 0b101 */
316		X86_SOCKET_UNKNOWN,	/* 0b110 */
317		X86_SOCKET_UNKNOWN	/* 0b111 */
318	},
319
320	/*
321	 * Family 0x17 models 30-3f	(Zen 2 - Rome)
322	 */
323#define	A_SKTS_15			15
324	{
325		X86_SOCKET_UNKNOWN,	/* 0b000 */
326		X86_SOCKET_UNKNOWN,	/* 0b001 */
327		X86_SOCKET_UNKNOWN,	/* 0b010 */
328		X86_SOCKET_UNKNOWN,	/* 0b011 */
329		X86_SOCKET_SP3,		/* 0b100 */
330		X86_SOCKET_UNKNOWN,	/* 0b101 */
331		X86_SOCKET_UNKNOWN,	/* 0b110 */
332		X86_SOCKET_SP3R2	/* 0b111 */
333	},
334
335	/*
336	 * Family 0x17 models 60-6f	(Zen 2 - Renoir)
337	 */
338#define	A_SKTS_16			16
339	{
340		X86_SOCKET_FP6,		/* 0b000 */
341		X86_SOCKET_UNKNOWN,	/* 0b001 */
342		X86_SOCKET_AM4,		/* 0b010 */
343		X86_SOCKET_UNKNOWN,	/* 0b011 */
344		X86_SOCKET_UNKNOWN,	/* 0b100 */
345		X86_SOCKET_UNKNOWN,	/* 0b101 */
346		X86_SOCKET_UNKNOWN,	/* 0b110 */
347		X86_SOCKET_UNKNOWN	/* 0b111 */
348	},
349
350	/*
351	 * Family 0x17 models 70-7f	(Zen 2 - Matisse)
352	 */
353#define	A_SKTS_17			17
354	{
355		X86_SOCKET_UNKNOWN,	/* 0b000 */
356		X86_SOCKET_UNKNOWN,	/* 0b001 */
357		X86_SOCKET_AM4,		/* 0b010 */
358		X86_SOCKET_UNKNOWN,	/* 0b011 */
359		X86_SOCKET_UNKNOWN,	/* 0b100 */
360		X86_SOCKET_UNKNOWN,	/* 0b101 */
361		X86_SOCKET_UNKNOWN,	/* 0b110 */
362		X86_SOCKET_UNKNOWN	/* 0b111 */
363	},
364};
365
366struct amd_sktmap_s {
367	uint32_t	skt_code;
368	char		sktstr[16];
369};
370static struct amd_sktmap_s amd_sktmap_strs[X86_NUM_SOCKETS_AMD + 1] = {
371	{ X86_SOCKET_754,	"754" },
372	{ X86_SOCKET_939,	"939" },
373	{ X86_SOCKET_940,	"940" },
374	{ X86_SOCKET_S1g1,	"S1g1" },
375	{ X86_SOCKET_AM2,	"AM2" },
376	{ X86_SOCKET_F1207,	"F(1207)" },
377	{ X86_SOCKET_S1g2,	"S1g2" },
378	{ X86_SOCKET_S1g3,	"S1g3" },
379	{ X86_SOCKET_AM,	"AM" },
380	{ X86_SOCKET_AM2R2,	"AM2r2" },
381	{ X86_SOCKET_AM3,	"AM3" },
382	{ X86_SOCKET_G34,	"G34" },
383	{ X86_SOCKET_ASB2,	"ASB2" },
384	{ X86_SOCKET_C32,	"C32" },
385	{ X86_SOCKET_FT1,	"FT1" },
386	{ X86_SOCKET_FM1,	"FM1" },
387	{ X86_SOCKET_FS1,	"FS1" },
388	{ X86_SOCKET_AM3R2,	"AM3r2" },
389	{ X86_SOCKET_FP2,	"FP2" },
390	{ X86_SOCKET_FS1R2,	"FS1r2" },
391	{ X86_SOCKET_FM2,	"FM2" },
392	{ X86_SOCKET_FP3,	"FP3" },
393	{ X86_SOCKET_FM2R2,	"FM2r2" },
394	{ X86_SOCKET_FP4,	"FP4" },
395	{ X86_SOCKET_AM4,	"AM4" },
396	{ X86_SOCKET_FT3,	"FT3" },
397	{ X86_SOCKET_FT4,	"FT4" },
398	{ X86_SOCKET_FS1B,	"FS1b" },
399	{ X86_SOCKET_FT3B,	"FT3b" },
400	{ X86_SOCKET_SP3,	"SP3" },
401	{ X86_SOCKET_SP3R2,	"SP3r2" },
402	{ X86_SOCKET_FP5,	"FP5" },
403	{ X86_SOCKET_FP6,	"FP6" },
404	{ X86_SOCKET_UNKNOWN,	"Unknown" }
405};
406
407static const struct amd_skt_mapent {
408	uint_t sm_family;
409	uint_t sm_modello;
410	uint_t sm_modelhi;
411	uint_t sm_sktidx;
412} amd_sktmap[] = {
413	{ 0x10, 0x00, 0xff, A_SKTS_2 },
414	{ 0x11, 0x00, 0xff, A_SKTS_3 },
415	{ 0x12, 0x00, 0xff, A_SKTS_4 },
416	{ 0x14, 0x00, 0x0f, A_SKTS_5 },
417	{ 0x15, 0x00, 0x0f, A_SKTS_6 },
418	{ 0x15, 0x10, 0x1f, A_SKTS_7 },
419	{ 0x15, 0x30, 0x3f, A_SKTS_8 },
420	{ 0x15, 0x60, 0x6f, A_SKTS_9 },
421	{ 0x15, 0x70, 0x7f, A_SKTS_10 },
422	{ 0x16, 0x00, 0x0f, A_SKTS_11 },
423	{ 0x16, 0x30, 0x3f, A_SKTS_12 },
424	{ 0x17, 0x00, 0x0f, A_SKTS_13 },
425	{ 0x17, 0x10, 0x2f, A_SKTS_14 },
426	{ 0x17, 0x30, 0x3f, A_SKTS_15 },
427	{ 0x17, 0x60, 0x6f, A_SKTS_16 },
428	{ 0x17, 0x70, 0x7f, A_SKTS_17 }
429};
430
431/*
432 * Table for mapping AMD Family 0xf and AMD Family 0x10 model/stepping
433 * combination to chip "revision" and socket type.
434 *
435 * The first member of this array that matches a given family, extended model
436 * plus model range, and stepping range will be considered a match.
437 */
438static const struct amd_rev_mapent {
439	uint_t rm_family;
440	uint_t rm_modello;
441	uint_t rm_modelhi;
442	uint_t rm_steplo;
443	uint_t rm_stephi;
444	uint32_t rm_chiprev;
445	const char *rm_chiprevstr;
446	uint_t rm_sktidx;
447} amd_revmap[] = {
448	/*
449	 * =============== AuthenticAMD Family 0xf ===============
450	 */
451
452	/*
453	 * Rev B includes model 0x4 stepping 0 and model 0x5 stepping 0 and 1.
454	 */
455	{ 0xf, 0x04, 0x04, 0x0, 0x0, X86_CHIPREV_AMD_F_REV_B, "B", A_SKTS_0 },
456	{ 0xf, 0x05, 0x05, 0x0, 0x1, X86_CHIPREV_AMD_F_REV_B, "B", A_SKTS_0 },
457	/*
458	 * Rev C0 includes model 0x4 stepping 8 and model 0x5 stepping 8
459	 */
460	{ 0xf, 0x04, 0x05, 0x8, 0x8, X86_CHIPREV_AMD_F_REV_C0, "C0", A_SKTS_0 },
461	/*
462	 * Rev CG is the rest of extended model 0x0 - i.e., everything
463	 * but the rev B and C0 combinations covered above.
464	 */
465	{ 0xf, 0x00, 0x0f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_CG, "CG", A_SKTS_0 },
466	/*
467	 * Rev D has extended model 0x1.
468	 */
469	{ 0xf, 0x10, 0x1f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_D, "D", A_SKTS_0 },
470	/*
471	 * Rev E has extended model 0x2.
472	 * Extended model 0x3 is unused but available to grow into.
473	 */
474	{ 0xf, 0x20, 0x3f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_E, "E", A_SKTS_0 },
475	/*
476	 * Rev F has extended models 0x4 and 0x5.
477	 */
478	{ 0xf, 0x40, 0x5f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_F, "F", A_SKTS_1 },
479	/*
480	 * Rev G has extended model 0x6.
481	 */
482	{ 0xf, 0x60, 0x6f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_G, "G", A_SKTS_1 },
483
484	/*
485	 * =============== AuthenticAMD Family 0x10 ===============
486	 */
487
488	/*
489	 * Rev A has model 0 and stepping 0/1/2 for DR-{A0,A1,A2}.
490	 * Give all of model 0 stepping range to rev A.
491	 */
492	{ 0x10, 0x00, 0x00, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_A, "A", A_SKTS_2 },
493
494	/*
495	 * Rev B has model 2 and steppings 0/1/0xa/2 for DR-{B0,B1,BA,B2}.
496	 * Give all of model 2 stepping range to rev B.
497	 */
498	{ 0x10, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_B, "B", A_SKTS_2 },
499
500	/*
501	 * Rev C has models 4-6 (depending on L3 cache configuration)
502	 * Give all of models 4-6 stepping range 0-2 to rev C2.
503	 */
504	{ 0x10, 0x4, 0x6, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_C2, "C2", A_SKTS_2 },
505
506	/*
507	 * Rev C has models 4-6 (depending on L3 cache configuration)
508	 * Give all of models 4-6 stepping range >= 3 to rev C3.
509	 */
510	{ 0x10, 0x4, 0x6, 0x3, 0xf, X86_CHIPREV_AMD_10_REV_C3, "C3", A_SKTS_2 },
511
512	/*
513	 * Rev D has models 8 and 9
514	 * Give all of model 8 and 9 stepping 0 to rev D0.
515	 */
516	{ 0x10, 0x8, 0x9, 0x0, 0x0, X86_CHIPREV_AMD_10_REV_D0, "D0", A_SKTS_2 },
517
518	/*
519	 * Rev D has models 8 and 9
520	 * Give all of model 8 and 9 stepping range >= 1 to rev D1.
521	 */
522	{ 0x10, 0x8, 0x9, 0x1, 0xf, X86_CHIPREV_AMD_10_REV_D1, "D1", A_SKTS_2 },
523
524	/*
525	 * Rev E has models A and stepping 0
526	 * Give all of model A stepping range to rev E.
527	 */
528	{ 0x10, 0xA, 0xA, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_E, "E", A_SKTS_2 },
529
530	/*
531	 * =============== AuthenticAMD Family 0x11 ===============
532	 */
533	{ 0x11, 0x03, 0x03, 0x0, 0xf, X86_CHIPREV_AMD_11_REV_B, "B", A_SKTS_3 },
534
535	/*
536	 * =============== AuthenticAMD Family 0x12 ===============
537	 */
538	{ 0x12, 0x01, 0x01, 0x0, 0xf, X86_CHIPREV_AMD_12_REV_B, "B", A_SKTS_4 },
539
540	/*
541	 * =============== AuthenticAMD Family 0x14 ===============
542	 */
543	{ 0x14, 0x01, 0x01, 0x0, 0xf, X86_CHIPREV_AMD_14_REV_B, "B", A_SKTS_5 },
544	{ 0x14, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_14_REV_C, "C", A_SKTS_5 },
545
546	/*
547	 * =============== AuthenticAMD Family 0x15 ===============
548	 */
549	{ 0x15, 0x01, 0x01, 0x2, 0x2, X86_CHIPREV_AMD_15OR_REV_B2, "OR-B2",
550	    A_SKTS_6 },
551	{ 0x15, 0x02, 0x02, 0x0, 0x0, X86_CHIPREV_AMD_150R_REV_C0, "OR-C0",
552	    A_SKTS_6 },
553	{ 0x15, 0x10, 0x10, 0x1, 0x1, X86_CHIPREV_AMD_15TN_REV_A1, "TN-A1",
554	    A_SKTS_7 },
555	{ 0x15, 0x30, 0x30, 0x1, 0x1, X86_CHIPREV_AMD_15KV_REV_A1, "KV-A1",
556	    A_SKTS_8 },
557	/*
558	 * There is no Family 15 Models 60-6f revision guide available, so at
559	 * least get the socket information.
560	 */
561	{ 0x15, 0x60, 0x6f, 0x0, 0xf, X86_CHIPREV_AMD_15F60, "??",
562	    A_SKTS_9 },
563	{ 0x15, 0x70, 0x70, 0x0, 0x0, X86_CHIPREV_AMD_15ST_REV_A0, "ST-A0",
564	    A_SKTS_10 },
565
566	/*
567	 * =============== AuthenticAMD Family 0x16 ===============
568	 */
569	{ 0x16, 0x00, 0x00, 0x1, 0x1, X86_CHIPREV_AMD_16_KB_A1, "KB-A1",
570	    A_SKTS_11 },
571	{ 0x16, 0x30, 0x30, 0x1, 0x1, X86_CHIPREV_AMD_16_ML_A1, "ML-A1",
572	    A_SKTS_12 },
573
574	/*
575	 * =============== AuthenticAMD Family 0x17 ===============
576	 */
577	{ 0x17, 0x01, 0x01, 0x1, 0x1, X86_CHIPREV_AMD_17_ZP_B1, "ZP-B1",
578	    A_SKTS_13 },
579	{ 0x17, 0x01, 0x01, 0x2, 0x2, X86_CHIPREV_AMD_17_ZP_B2, "ZP-B2",
580	    A_SKTS_13 },
581	{ 0x17, 0x01, 0x01, 0x1, 0x1, X86_CHIPREV_AMD_17_PiR_B2, "PiR-B2",
582	    A_SKTS_13 },
583
584	{ 0x17, 0x11, 0x11, 0x0, 0x0, X86_CHIPREV_AMD_17_RV_B0, "RV-B0",
585	    A_SKTS_14 },
586	{ 0x17, 0x11, 0x11, 0x1, 0x1, X86_CHIPREV_AMD_17_RV_B1, "RV-B1",
587	    A_SKTS_14 },
588	{ 0x17, 0x18, 0x18, 0x1, 0x1, X86_CHIPREV_AMD_17_PCO_B1, "PCO-B1",
589	    A_SKTS_14 },
590
591	{ 0x17, 0x30, 0x30, 0x0, 0x0, X86_CHIPREV_AMD_17_SSP_A0, "SSP-A0",
592	    A_SKTS_15 },
593	{ 0x17, 0x31, 0x31, 0x0, 0x0, X86_CHIPREV_AMD_17_SSP_B0, "SSP-B0",
594	    A_SKTS_15 },
595
596	{ 0x17, 0x71, 0x71, 0x0, 0x0, X86_CHIPREV_AMD_17_MTS_B0, "MTS-B0",
597	    A_SKTS_17 }
598};
599
600/*
601 * AMD keeps the socket type in CPUID Fn8000_0001_EBX, bits 31:28.
602 */
603static uint32_t
604synth_amd_skt_cpuid(uint_t family, uint_t sktid)
605{
606	struct cpuid_regs cp;
607	uint_t idx;
608
609	cp.cp_eax = 0x80000001;
610	(void) __cpuid_insn(&cp);
611
612	/* PkgType bits */
613	idx = BITX(cp.cp_ebx, 31, 28);
614
615	if (idx > 7) {
616		return (X86_SOCKET_UNKNOWN);
617	}
618
619	if (family == 0x10) {
620		uint32_t val;
621
622		val = pci_getl_func(0, 24, 2, 0x94);
623		if (BITX(val, 8, 8)) {
624			if (amd_skts[sktid][idx] == X86_SOCKET_AM2R2) {
625				return (X86_SOCKET_AM3);
626			} else if (amd_skts[sktid][idx] == X86_SOCKET_S1g3) {
627				return (X86_SOCKET_S1g4);
628			}
629		}
630	}
631
632	return (amd_skts[sktid][idx]);
633}
634
635static void
636synth_amd_skt(uint_t family, uint_t model, uint32_t *skt_p)
637{
638	int platform;
639	const struct amd_skt_mapent *skt;
640	uint_t i;
641
642	if (skt_p == NULL || family < 0xf)
643		return;
644
645#ifdef __xpv
646	/* PV guest */
647	if (!is_controldom()) {
648		*skt_p = X86_SOCKET_UNKNOWN;
649		return;
650	}
651#endif
652	platform = get_hwenv();
653
654	if ((platform & HW_VIRTUAL) != 0) {
655		*skt_p = X86_SOCKET_UNKNOWN;
656		return;
657	}
658
659	for (i = 0, skt = amd_sktmap; i < ARRAY_SIZE(amd_sktmap);
660	    i++, skt++) {
661		if (family == skt->sm_family &&
662		    model >= skt->sm_modello && model <= skt->sm_modelhi) {
663			*skt_p = synth_amd_skt_cpuid(family, skt->sm_sktidx);
664		}
665	}
666}
667
668static void
669synth_amd_info(uint_t family, uint_t model, uint_t step,
670    uint32_t *skt_p, uint32_t *chiprev_p, const char **chiprevstr_p)
671{
672	const struct amd_rev_mapent *rmp;
673	int found = 0;
674	int i;
675
676	if (family < 0xf)
677		return;
678
679	for (i = 0, rmp = amd_revmap; i < ARRAY_SIZE(amd_revmap); i++, rmp++) {
680		if (family == rmp->rm_family &&
681		    model >= rmp->rm_modello && model <= rmp->rm_modelhi &&
682		    step >= rmp->rm_steplo && step <= rmp->rm_stephi) {
683			found = 1;
684			break;
685		}
686	}
687
688	if (!found) {
689		synth_amd_skt(family, model, skt_p);
690		return;
691	}
692
693	if (chiprev_p != NULL)
694		*chiprev_p = rmp->rm_chiprev;
695	if (chiprevstr_p != NULL)
696		*chiprevstr_p = rmp->rm_chiprevstr;
697
698	if (skt_p != NULL) {
699		int platform;
700
701#ifdef __xpv
702		/* PV guest */
703		if (!is_controldom()) {
704			*skt_p = X86_SOCKET_UNKNOWN;
705			return;
706		}
707#endif
708		platform = get_hwenv();
709
710		if ((platform & HW_VIRTUAL) != 0) {
711			*skt_p = X86_SOCKET_UNKNOWN;
712		} else if (family == 0xf) {
713			*skt_p = amd_skts[rmp->rm_sktidx][model & 0x3];
714		} else {
715			*skt_p = synth_amd_skt_cpuid(family, rmp->rm_sktidx);
716		}
717	}
718}
719
720uint32_t
721_cpuid_skt(uint_t vendor, uint_t family, uint_t model, uint_t step)
722{
723	uint32_t skt = X86_SOCKET_UNKNOWN;
724
725	switch (vendor) {
726	case X86_VENDOR_AMD:
727		synth_amd_info(family, model, step, &skt, NULL, NULL);
728		break;
729
730	default:
731		break;
732
733	}
734
735	return (skt);
736}
737
738const char *
739_cpuid_sktstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
740{
741	const char *sktstr = "Unknown";
742	struct amd_sktmap_s *sktmapp;
743	uint32_t skt = X86_SOCKET_UNKNOWN;
744
745	switch (vendor) {
746	case X86_VENDOR_AMD:
747		synth_amd_info(family, model, step, &skt, NULL, NULL);
748
749		sktmapp = amd_sktmap_strs;
750		while (sktmapp->skt_code != X86_SOCKET_UNKNOWN) {
751			if (sktmapp->skt_code == skt)
752				break;
753			sktmapp++;
754		}
755		sktstr = sktmapp->sktstr;
756		break;
757
758	default:
759		break;
760
761	}
762
763	return (sktstr);
764}
765
766uint32_t
767_cpuid_chiprev(uint_t vendor, uint_t family, uint_t model, uint_t step)
768{
769	uint32_t chiprev = X86_CHIPREV_UNKNOWN;
770
771	switch (vendor) {
772	case X86_VENDOR_AMD:
773		synth_amd_info(family, model, step, NULL, &chiprev, NULL);
774		break;
775
776	default:
777		break;
778
779	}
780
781	return (chiprev);
782}
783
784const char *
785_cpuid_chiprevstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
786{
787	const char *revstr = "Unknown";
788
789	switch (vendor) {
790	case X86_VENDOR_AMD:
791		synth_amd_info(family, model, step, NULL, NULL, &revstr);
792		break;
793
794	default:
795		break;
796
797	}
798
799	return (revstr);
800
801}
802
803/*
804 * CyrixInstead is a variable used by the Cyrix detection code
805 * in locore.
806 */
807const char CyrixInstead[] = X86_VENDORSTR_CYRIX;
808
809/*
810 * Map the vendor string to a type code
811 */
812uint_t
813_cpuid_vendorstr_to_vendorcode(char *vendorstr)
814{
815	if (strcmp(vendorstr, X86_VENDORSTR_Intel) == 0)
816		return (X86_VENDOR_Intel);
817	else if (strcmp(vendorstr, X86_VENDORSTR_AMD) == 0)
818		return (X86_VENDOR_AMD);
819	else if (strcmp(vendorstr, X86_VENDORSTR_TM) == 0)
820		return (X86_VENDOR_TM);
821	else if (strcmp(vendorstr, CyrixInstead) == 0)
822		return (X86_VENDOR_Cyrix);
823	else if (strcmp(vendorstr, X86_VENDORSTR_UMC) == 0)
824		return (X86_VENDOR_UMC);
825	else if (strcmp(vendorstr, X86_VENDORSTR_NexGen) == 0)
826		return (X86_VENDOR_NexGen);
827	else if (strcmp(vendorstr, X86_VENDORSTR_Centaur) == 0)
828		return (X86_VENDOR_Centaur);
829	else if (strcmp(vendorstr, X86_VENDORSTR_Rise) == 0)
830		return (X86_VENDOR_Rise);
831	else if (strcmp(vendorstr, X86_VENDORSTR_SiS) == 0)
832		return (X86_VENDOR_SiS);
833	else if (strcmp(vendorstr, X86_VENDORSTR_NSC) == 0)
834		return (X86_VENDOR_NSC);
835	else
836		return (X86_VENDOR_IntelClone);
837}
838