xref: /titanic_52/usr/src/uts/i86pc/os/cpuid_subr.c (revision d9b365efa57e560c120a68d37339e584d8bf04c0)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Support functions that interpret CPUID and similar information.
29  * These should not be used from anywhere other than cpuid.c and
30  * cmi_hw.c - as such we will not list them in any header file
31  * such as x86_archext.h.
32  *
33  * In cpuid.c we process CPUID information for each cpu_t instance
34  * we're presented with, and stash this raw information and material
35  * derived from it in per-cpu_t structures.
36  *
37  * If we are virtualized then the CPUID information derived from CPUID
38  * instructions executed in the guest is based on whatever the hypervisor
39  * wanted to make things look like, and the cpu_t are not necessarily in 1:1
40  * or fixed correspondence with real processor execution resources.  In cmi_hw.c
41  * we are interested in the native properties of a processor - for fault
42  * management (and potentially other, such as power management) purposes;
43  * it will tunnel through to real hardware information, and use the
44  * functionality provided in this file to process it.
45  */
46 
47 #include <sys/types.h>
48 #include <sys/systm.h>
49 #include <sys/x86_archext.h>
50 
51 /*
52  * AMD family 0xf and family 0x10 socket types.
53  * First index :
54  *		0 for family 0xf, revs B thru E
55  *		1 for family 0xf, revs F and G
56  *		2 for family 0x10, rev B
57  * Second index by (model & 0x3)
58  */
59 static uint32_t amd_skts[3][4] = {
60 	/*
61 	 * Family 0xf revisions B through E
62 	 */
63 #define	A_SKTS_0			0
64 	{
65 		X86_SOCKET_754,		/* 0b00 */
66 		X86_SOCKET_940,		/* 0b01 */
67 		X86_SOCKET_754,		/* 0b10 */
68 		X86_SOCKET_939		/* 0b11 */
69 	},
70 	/*
71 	 * Family 0xf revisions F and G
72 	 */
73 #define	A_SKTS_1			1
74 	{
75 		X86_SOCKET_S1g1,	/* 0b00 */
76 		X86_SOCKET_F1207,	/* 0b01 */
77 		X86_SOCKET_UNKNOWN,	/* 0b10 */
78 		X86_SOCKET_AM2		/* 0b11 */
79 	},
80 	/*
81 	 * Family 0x10 revisions A and B
82 	 * It is not clear whether, as new sockets release, that
83 	 * model & 0x3 will id socket for this family
84 	 */
85 #define	A_SKTS_2			2
86 	{
87 		X86_SOCKET_F1207,	/* 0b00 */
88 		X86_SOCKET_F1207,	/* 0b01 */
89 		X86_SOCKET_F1207,	/* 0b10 */
90 		X86_SOCKET_F1207,	/* 0b11 */
91 	}
92 };
93 
94 /*
95  * Table for mapping AMD Family 0xf and AMD Family 0x10 model/stepping
96  * combination to chip "revision" and socket type.
97  *
98  * The first member of this array that matches a given family, extended model
99  * plus model range, and stepping range will be considered a match.
100  */
101 static const struct amd_rev_mapent {
102 	uint_t rm_family;
103 	uint_t rm_modello;
104 	uint_t rm_modelhi;
105 	uint_t rm_steplo;
106 	uint_t rm_stephi;
107 	uint32_t rm_chiprev;
108 	const char *rm_chiprevstr;
109 	int rm_sktidx;
110 } amd_revmap[] = {
111 	/*
112 	 * =============== AuthenticAMD Family 0xf ===============
113 	 */
114 
115 	/*
116 	 * Rev B includes model 0x4 stepping 0 and model 0x5 stepping 0 and 1.
117 	 */
118 	{ 0xf, 0x04, 0x04, 0x0, 0x0, X86_CHIPREV_AMD_F_REV_B, "B", A_SKTS_0 },
119 	{ 0xf, 0x05, 0x05, 0x0, 0x1, X86_CHIPREV_AMD_F_REV_B, "B", A_SKTS_0 },
120 	/*
121 	 * Rev C0 includes model 0x4 stepping 8 and model 0x5 stepping 8
122 	 */
123 	{ 0xf, 0x04, 0x05, 0x8, 0x8, X86_CHIPREV_AMD_F_REV_C0, "C0", A_SKTS_0 },
124 	/*
125 	 * Rev CG is the rest of extended model 0x0 - i.e., everything
126 	 * but the rev B and C0 combinations covered above.
127 	 */
128 	{ 0xf, 0x00, 0x0f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_CG, "CG", A_SKTS_0 },
129 	/*
130 	 * Rev D has extended model 0x1.
131 	 */
132 	{ 0xf, 0x10, 0x1f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_D, "D", A_SKTS_0 },
133 	/*
134 	 * Rev E has extended model 0x2.
135 	 * Extended model 0x3 is unused but available to grow into.
136 	 */
137 	{ 0xf, 0x20, 0x3f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_E, "E", A_SKTS_0 },
138 	/*
139 	 * Rev F has extended models 0x4 and 0x5.
140 	 */
141 	{ 0xf, 0x40, 0x5f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_F, "F", A_SKTS_1 },
142 	/*
143 	 * Rev G has extended model 0x6.
144 	 */
145 	{ 0xf, 0x60, 0x6f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_G, "G", A_SKTS_1 },
146 
147 	/*
148 	 * =============== AuthenticAMD Family 0x10 ===============
149 	 */
150 
151 	/*
152 	 * Rev A has model 0 and stepping 0/1/2 for DR-{A0,A1,A2}.
153 	 * Give all of model 0 stepping range to rev A.
154 	 */
155 	{ 0x10, 0x00, 0x00, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_A, "A", A_SKTS_2 },
156 
157 	/*
158 	 * Rev B has model 2 and steppings 0/1/0xa/2 for DR-{B0,B1,BA,B2}.
159 	 * Give all of model 2 stepping range to rev B.
160 	 */
161 	{ 0x10, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_B, "B", A_SKTS_2 },
162 };
163 
164 static void
165 synth_amd_info(uint_t family, uint_t model, uint_t step,
166     uint32_t *skt_p, uint32_t *chiprev_p, const char **chiprevstr_p)
167 {
168 	const struct amd_rev_mapent *rmp;
169 	int found = 0;
170 	int i;
171 
172 	/*
173 	 * Currently only AMD family 0xf and family 0x10 use these fields.
174 	 */
175 	if (family != 0xf && family != 0x10)
176 		return;
177 
178 	for (i = 0, rmp = amd_revmap; i < sizeof (amd_revmap) / sizeof (*rmp);
179 	    i++, rmp++) {
180 		if (family == rmp->rm_family &&
181 		    model >= rmp->rm_modello && model <= rmp->rm_modelhi &&
182 		    step >= rmp->rm_steplo && step <= rmp->rm_stephi) {
183 			found = 1;
184 			break;
185 		}
186 	}
187 
188 	if (found) {
189 		if (skt_p != NULL)
190 			*skt_p = amd_skts[rmp->rm_sktidx][model & 0x3];
191 		if (chiprev_p != NULL)
192 			*chiprev_p = rmp->rm_chiprev;
193 		if (chiprevstr_p != NULL)
194 			*chiprevstr_p = rmp->rm_chiprevstr;
195 	}
196 }
197 
198 uint32_t
199 _cpuid_skt(uint_t vendor, uint_t family, uint_t model, uint_t step)
200 {
201 	uint32_t skt = X86_SOCKET_UNKNOWN;
202 
203 	switch (vendor) {
204 	case X86_VENDOR_AMD:
205 		synth_amd_info(family, model, step, &skt, NULL, NULL);
206 		break;
207 
208 	default:
209 		break;
210 
211 	}
212 
213 	return (skt);
214 }
215 
216 uint32_t
217 _cpuid_chiprev(uint_t vendor, uint_t family, uint_t model, uint_t step)
218 {
219 	uint32_t chiprev = X86_CHIPREV_UNKNOWN;
220 
221 	switch (vendor) {
222 	case X86_VENDOR_AMD:
223 		synth_amd_info(family, model, step, NULL, &chiprev, NULL);
224 		break;
225 
226 	default:
227 		break;
228 
229 	}
230 
231 	return (chiprev);
232 }
233 
234 const char *
235 _cpuid_chiprevstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
236 {
237 	const char *revstr = "Unknown";
238 
239 	switch (vendor) {
240 	case X86_VENDOR_AMD:
241 		synth_amd_info(family, model, step, NULL, NULL, &revstr);
242 		break;
243 
244 	default:
245 		break;
246 
247 	}
248 
249 	return (revstr);
250 
251 }
252 
253 /*
254  * CyrixInstead is a variable used by the Cyrix detection code
255  * in locore.
256  */
257 const char CyrixInstead[] = X86_VENDORSTR_CYRIX;
258 
259 /*
260  * Map the vendor string to a type code
261  */
262 uint_t
263 _cpuid_vendorstr_to_vendorcode(char *vendorstr)
264 {
265 	if (strcmp(vendorstr, X86_VENDORSTR_Intel) == 0)
266 		return (X86_VENDOR_Intel);
267 	else if (strcmp(vendorstr, X86_VENDORSTR_AMD) == 0)
268 		return (X86_VENDOR_AMD);
269 	else if (strcmp(vendorstr, X86_VENDORSTR_TM) == 0)
270 		return (X86_VENDOR_TM);
271 	else if (strcmp(vendorstr, CyrixInstead) == 0)
272 		return (X86_VENDOR_Cyrix);
273 	else if (strcmp(vendorstr, X86_VENDORSTR_UMC) == 0)
274 		return (X86_VENDOR_UMC);
275 	else if (strcmp(vendorstr, X86_VENDORSTR_NexGen) == 0)
276 		return (X86_VENDOR_NexGen);
277 	else if (strcmp(vendorstr, X86_VENDORSTR_Centaur) == 0)
278 		return (X86_VENDOR_Centaur);
279 	else if (strcmp(vendorstr, X86_VENDORSTR_Rise) == 0)
280 		return (X86_VENDOR_Rise);
281 	else if (strcmp(vendorstr, X86_VENDORSTR_SiS) == 0)
282 		return (X86_VENDOR_SiS);
283 	else if (strcmp(vendorstr, X86_VENDORSTR_NSC) == 0)
284 		return (X86_VENDOR_NSC);
285 	else
286 		return (X86_VENDOR_IntelClone);
287 }
288