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