xref: /titanic_41/usr/src/uts/i86pc/os/cpuid_subr.c (revision ff5ca3bd17dee7e2bf2e4f2e3a2b354e0ecbd00d)
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 	 * Rev C has models 4-6 (depending on L3 cache configuration)
165 	 * Give all of model 2 stepping range to rev c.
166 	 */
167 	{ 0x10, 0x04, 0x06, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_C, "C", A_SKTS_2 },
168 };
169 
170 static void
171 synth_amd_info(uint_t family, uint_t model, uint_t step,
172     uint32_t *skt_p, uint32_t *chiprev_p, const char **chiprevstr_p)
173 {
174 	const struct amd_rev_mapent *rmp;
175 	int found = 0;
176 	int i;
177 
178 	/*
179 	 * Currently only AMD family 0xf and family 0x10 use these fields.
180 	 */
181 	if (family != 0xf && family != 0x10)
182 		return;
183 
184 	for (i = 0, rmp = amd_revmap; i < sizeof (amd_revmap) / sizeof (*rmp);
185 	    i++, rmp++) {
186 		if (family == rmp->rm_family &&
187 		    model >= rmp->rm_modello && model <= rmp->rm_modelhi &&
188 		    step >= rmp->rm_steplo && step <= rmp->rm_stephi) {
189 			found = 1;
190 			break;
191 		}
192 	}
193 
194 	if (found) {
195 		if (skt_p != NULL)
196 			*skt_p = amd_skts[rmp->rm_sktidx][model & 0x3];
197 		if (chiprev_p != NULL)
198 			*chiprev_p = rmp->rm_chiprev;
199 		if (chiprevstr_p != NULL)
200 			*chiprevstr_p = rmp->rm_chiprevstr;
201 	}
202 }
203 
204 uint32_t
205 _cpuid_skt(uint_t vendor, uint_t family, uint_t model, uint_t step)
206 {
207 	uint32_t skt = X86_SOCKET_UNKNOWN;
208 
209 	switch (vendor) {
210 	case X86_VENDOR_AMD:
211 		synth_amd_info(family, model, step, &skt, NULL, NULL);
212 		break;
213 
214 	default:
215 		break;
216 
217 	}
218 
219 	return (skt);
220 }
221 
222 uint32_t
223 _cpuid_chiprev(uint_t vendor, uint_t family, uint_t model, uint_t step)
224 {
225 	uint32_t chiprev = X86_CHIPREV_UNKNOWN;
226 
227 	switch (vendor) {
228 	case X86_VENDOR_AMD:
229 		synth_amd_info(family, model, step, NULL, &chiprev, NULL);
230 		break;
231 
232 	default:
233 		break;
234 
235 	}
236 
237 	return (chiprev);
238 }
239 
240 const char *
241 _cpuid_chiprevstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
242 {
243 	const char *revstr = "Unknown";
244 
245 	switch (vendor) {
246 	case X86_VENDOR_AMD:
247 		synth_amd_info(family, model, step, NULL, NULL, &revstr);
248 		break;
249 
250 	default:
251 		break;
252 
253 	}
254 
255 	return (revstr);
256 
257 }
258 
259 /*
260  * CyrixInstead is a variable used by the Cyrix detection code
261  * in locore.
262  */
263 const char CyrixInstead[] = X86_VENDORSTR_CYRIX;
264 
265 /*
266  * Map the vendor string to a type code
267  */
268 uint_t
269 _cpuid_vendorstr_to_vendorcode(char *vendorstr)
270 {
271 	if (strcmp(vendorstr, X86_VENDORSTR_Intel) == 0)
272 		return (X86_VENDOR_Intel);
273 	else if (strcmp(vendorstr, X86_VENDORSTR_AMD) == 0)
274 		return (X86_VENDOR_AMD);
275 	else if (strcmp(vendorstr, X86_VENDORSTR_TM) == 0)
276 		return (X86_VENDOR_TM);
277 	else if (strcmp(vendorstr, CyrixInstead) == 0)
278 		return (X86_VENDOR_Cyrix);
279 	else if (strcmp(vendorstr, X86_VENDORSTR_UMC) == 0)
280 		return (X86_VENDOR_UMC);
281 	else if (strcmp(vendorstr, X86_VENDORSTR_NexGen) == 0)
282 		return (X86_VENDOR_NexGen);
283 	else if (strcmp(vendorstr, X86_VENDORSTR_Centaur) == 0)
284 		return (X86_VENDOR_Centaur);
285 	else if (strcmp(vendorstr, X86_VENDORSTR_Rise) == 0)
286 		return (X86_VENDOR_Rise);
287 	else if (strcmp(vendorstr, X86_VENDORSTR_SiS) == 0)
288 		return (X86_VENDOR_SiS);
289 	else if (strcmp(vendorstr, X86_VENDORSTR_NSC) == 0)
290 		return (X86_VENDOR_NSC);
291 	else
292 		return (X86_VENDOR_IntelClone);
293 }
294