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