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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
30 * Portions Copyright 2009 Advanced Micro Devices, Inc.
34 * Copyright 2012 Jens Elkner <jel+illumos@cs.uni-magdeburg.de>
35 * Copyright 2012 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
39 * Support functions that interpret CPUID and similar information.
40 * These should not be used from anywhere other than cpuid.c and
41 * cmi_hw.c - as such we will not list them in any header file
42 * such as x86_archext.h.
44 * In cpuid.c we process CPUID information for each cpu_t instance
45 * we're presented with, and stash this raw information and material
46 * derived from it in per-cpu_t structures.
48 * If we are virtualized then the CPUID information derived from CPUID
49 * instructions executed in the guest is based on whatever the hypervisor
50 * wanted to make things look like, and the cpu_t are not necessarily in 1:1
51 * or fixed correspondence with real processor execution resources. In cmi_hw.c
52 * we are interested in the native properties of a processor - for fault
53 * management (and potentially other, such as power management) purposes;
54 * it will tunnel through to real hardware information, and use the
55 * functionality provided in this file to process it.
58 #include <sys/types.h>
59 #include <sys/systm.h>
60 #include <sys/bitmap.h>
61 #include <sys/x86_archext.h>
62 #include <sys/pci_cfgspace.h>
67 * 0 for family 0xf, revs B thru E
68 * 1 for family 0xf, revs F and G
73 * 6 for family 0x15, models 00 - 0f
74 * 7 for family 0x15, models 10 - 1f
75 * Second index by (model & 0x3) for family 0fh,
76 * CPUID pkg bits (Fn8000_0001_EBX[31:28]) for later families.
78 static uint32_t amd_skts
[8][8] = {
80 * Family 0xf revisions B through E
84 X86_SOCKET_754
, /* 0b000 */
85 X86_SOCKET_940
, /* 0b001 */
86 X86_SOCKET_754
, /* 0b010 */
87 X86_SOCKET_939
, /* 0b011 */
88 X86_SOCKET_UNKNOWN
, /* 0b100 */
89 X86_SOCKET_UNKNOWN
, /* 0b101 */
90 X86_SOCKET_UNKNOWN
, /* 0b110 */
91 X86_SOCKET_UNKNOWN
/* 0b111 */
94 * Family 0xf revisions F and G
98 X86_SOCKET_S1g1
, /* 0b000 */
99 X86_SOCKET_F1207
, /* 0b001 */
100 X86_SOCKET_UNKNOWN
, /* 0b010 */
101 X86_SOCKET_AM2
, /* 0b011 */
102 X86_SOCKET_UNKNOWN
, /* 0b100 */
103 X86_SOCKET_UNKNOWN
, /* 0b101 */
104 X86_SOCKET_UNKNOWN
, /* 0b110 */
105 X86_SOCKET_UNKNOWN
/* 0b111 */
112 X86_SOCKET_F1207
, /* 0b000 */
113 X86_SOCKET_AM2R2
, /* 0b001 */
114 X86_SOCKET_S1g3
, /* 0b010 */
115 X86_SOCKET_G34
, /* 0b011 */
116 X86_SOCKET_ASB2
, /* 0b100 */
117 X86_SOCKET_C32
, /* 0b101 */
118 X86_SOCKET_UNKNOWN
, /* 0b110 */
119 X86_SOCKET_UNKNOWN
/* 0b111 */
127 X86_SOCKET_UNKNOWN
, /* 0b000 */
128 X86_SOCKET_UNKNOWN
, /* 0b001 */
129 X86_SOCKET_S1g2
, /* 0b010 */
130 X86_SOCKET_UNKNOWN
, /* 0b011 */
131 X86_SOCKET_UNKNOWN
, /* 0b100 */
132 X86_SOCKET_UNKNOWN
, /* 0b101 */
133 X86_SOCKET_UNKNOWN
, /* 0b110 */
134 X86_SOCKET_UNKNOWN
/* 0b111 */
142 X86_SOCKET_UNKNOWN
, /* 0b000 */
143 X86_SOCKET_FS1
, /* 0b001 */
144 X86_SOCKET_FM1
, /* 0b010 */
145 X86_SOCKET_UNKNOWN
, /* 0b011 */
146 X86_SOCKET_UNKNOWN
, /* 0b100 */
147 X86_SOCKET_UNKNOWN
, /* 0b101 */
148 X86_SOCKET_UNKNOWN
, /* 0b110 */
149 X86_SOCKET_UNKNOWN
/* 0b111 */
157 X86_SOCKET_FT1
, /* 0b000 */
158 X86_SOCKET_UNKNOWN
, /* 0b001 */
159 X86_SOCKET_UNKNOWN
, /* 0b010 */
160 X86_SOCKET_UNKNOWN
, /* 0b011 */
161 X86_SOCKET_UNKNOWN
, /* 0b100 */
162 X86_SOCKET_UNKNOWN
, /* 0b101 */
163 X86_SOCKET_UNKNOWN
, /* 0b110 */
164 X86_SOCKET_UNKNOWN
/* 0b111 */
168 * Family 0x15 models 00 - 0f
172 X86_SOCKET_UNKNOWN
, /* 0b000 */
173 X86_SOCKET_AM3R2
, /* 0b001 */
174 X86_SOCKET_UNKNOWN
, /* 0b010 */
175 X86_SOCKET_G34
, /* 0b011 */
176 X86_SOCKET_UNKNOWN
, /* 0b100 */
177 X86_SOCKET_C32
, /* 0b101 */
178 X86_SOCKET_UNKNOWN
, /* 0b110 */
179 X86_SOCKET_UNKNOWN
/* 0b111 */
183 * Family 0x15 models 10 - 1f
187 X86_SOCKET_FP2
, /* 0b000 */
188 X86_SOCKET_FS1R2
, /* 0b001 */
189 X86_SOCKET_FM2
, /* 0b010 */
190 X86_SOCKET_UNKNOWN
, /* 0b011 */
191 X86_SOCKET_UNKNOWN
, /* 0b100 */
192 X86_SOCKET_UNKNOWN
, /* 0b101 */
193 X86_SOCKET_UNKNOWN
, /* 0b110 */
194 X86_SOCKET_UNKNOWN
/* 0b111 */
199 struct amd_sktmap_s
{
203 static struct amd_sktmap_s amd_sktmap
[23] = {
204 { X86_SOCKET_754
, "754" },
205 { X86_SOCKET_939
, "939" },
206 { X86_SOCKET_940
, "940" },
207 { X86_SOCKET_S1g1
, "S1g1" },
208 { X86_SOCKET_AM2
, "AM2" },
209 { X86_SOCKET_F1207
, "F(1207)" },
210 { X86_SOCKET_S1g2
, "S1g2" },
211 { X86_SOCKET_S1g3
, "S1g3" },
212 { X86_SOCKET_AM
, "AM" },
213 { X86_SOCKET_AM2R2
, "AM2r2" },
214 { X86_SOCKET_AM3
, "AM3" },
215 { X86_SOCKET_G34
, "G34" },
216 { X86_SOCKET_ASB2
, "ASB2" },
217 { X86_SOCKET_C32
, "C32" },
218 { X86_SOCKET_FT1
, "FT1" },
219 { X86_SOCKET_FM1
, "FM1" },
220 { X86_SOCKET_FS1
, "FS1" },
221 { X86_SOCKET_AM3R2
, "AM3r2" },
222 { X86_SOCKET_FP2
, "FP2" },
223 { X86_SOCKET_FS1R2
, "FS1r2" },
224 { X86_SOCKET_FM2
, "FM2" },
225 { X86_SOCKET_UNKNOWN
, "Unknown" }
229 * Table for mapping AMD Family 0xf and AMD Family 0x10 model/stepping
230 * combination to chip "revision" and socket type.
232 * The first member of this array that matches a given family, extended model
233 * plus model range, and stepping range will be considered a match.
235 static const struct amd_rev_mapent
{
242 const char *rm_chiprevstr
;
246 * =============== AuthenticAMD Family 0xf ===============
250 * Rev B includes model 0x4 stepping 0 and model 0x5 stepping 0 and 1.
252 { 0xf, 0x04, 0x04, 0x0, 0x0, X86_CHIPREV_AMD_F_REV_B
, "B", A_SKTS_0
},
253 { 0xf, 0x05, 0x05, 0x0, 0x1, X86_CHIPREV_AMD_F_REV_B
, "B", A_SKTS_0
},
255 * Rev C0 includes model 0x4 stepping 8 and model 0x5 stepping 8
257 { 0xf, 0x04, 0x05, 0x8, 0x8, X86_CHIPREV_AMD_F_REV_C0
, "C0", A_SKTS_0
},
259 * Rev CG is the rest of extended model 0x0 - i.e., everything
260 * but the rev B and C0 combinations covered above.
262 { 0xf, 0x00, 0x0f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_CG
, "CG", A_SKTS_0
},
264 * Rev D has extended model 0x1.
266 { 0xf, 0x10, 0x1f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_D
, "D", A_SKTS_0
},
268 * Rev E has extended model 0x2.
269 * Extended model 0x3 is unused but available to grow into.
271 { 0xf, 0x20, 0x3f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_E
, "E", A_SKTS_0
},
273 * Rev F has extended models 0x4 and 0x5.
275 { 0xf, 0x40, 0x5f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_F
, "F", A_SKTS_1
},
277 * Rev G has extended model 0x6.
279 { 0xf, 0x60, 0x6f, 0x0, 0xf, X86_CHIPREV_AMD_F_REV_G
, "G", A_SKTS_1
},
282 * =============== AuthenticAMD Family 0x10 ===============
286 * Rev A has model 0 and stepping 0/1/2 for DR-{A0,A1,A2}.
287 * Give all of model 0 stepping range to rev A.
289 { 0x10, 0x00, 0x00, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_A
, "A", A_SKTS_2
},
292 * Rev B has model 2 and steppings 0/1/0xa/2 for DR-{B0,B1,BA,B2}.
293 * Give all of model 2 stepping range to rev B.
295 { 0x10, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_B
, "B", A_SKTS_2
},
298 * Rev C has models 4-6 (depending on L3 cache configuration)
299 * Give all of models 4-6 stepping range 0-2 to rev C2.
301 { 0x10, 0x4, 0x6, 0x0, 0x2, X86_CHIPREV_AMD_10_REV_C2
, "C2", A_SKTS_2
},
304 * Rev C has models 4-6 (depending on L3 cache configuration)
305 * Give all of models 4-6 stepping range >= 3 to rev C3.
307 { 0x10, 0x4, 0x6, 0x3, 0xf, X86_CHIPREV_AMD_10_REV_C3
, "C3", A_SKTS_2
},
310 * Rev D has models 8 and 9
311 * Give all of model 8 and 9 stepping 0 to rev D0.
313 { 0x10, 0x8, 0x9, 0x0, 0x0, X86_CHIPREV_AMD_10_REV_D0
, "D0", A_SKTS_2
},
316 * Rev D has models 8 and 9
317 * Give all of model 8 and 9 stepping range >= 1 to rev D1.
319 { 0x10, 0x8, 0x9, 0x1, 0xf, X86_CHIPREV_AMD_10_REV_D1
, "D1", A_SKTS_2
},
322 * Rev E has models A and stepping 0
323 * Give all of model A stepping range to rev E.
325 { 0x10, 0xA, 0xA, 0x0, 0xf, X86_CHIPREV_AMD_10_REV_E
, "E", A_SKTS_2
},
328 * =============== AuthenticAMD Family 0x11 ===============
330 { 0x11, 0x03, 0x03, 0x0, 0xf, X86_CHIPREV_AMD_11_REV_B
, "B", A_SKTS_3
},
333 * =============== AuthenticAMD Family 0x12 ===============
335 { 0x12, 0x01, 0x01, 0x0, 0xf, X86_CHIPREV_AMD_12_REV_B
, "B", A_SKTS_4
},
338 * =============== AuthenticAMD Family 0x14 ===============
340 { 0x14, 0x01, 0x01, 0x0, 0xf, X86_CHIPREV_AMD_14_REV_B
, "B", A_SKTS_5
},
341 { 0x14, 0x02, 0x02, 0x0, 0xf, X86_CHIPREV_AMD_14_REV_C
, "C", A_SKTS_5
},
344 * =============== AuthenticAMD Family 0x15 ===============
346 { 0x15, 0x01, 0x01, 0x2, 0x2, X86_CHIPREV_AMD_15OR_REV_B2
, "B2",
348 { 0x15, 0x10, 0x10, 0x1, 0x1, X86_CHIPREV_AMD_15TN_REV_A1
, "A1",
353 synth_amd_info(uint_t family
, uint_t model
, uint_t step
,
354 uint32_t *skt_p
, uint32_t *chiprev_p
, const char **chiprevstr_p
)
356 const struct amd_rev_mapent
*rmp
;
363 for (i
= 0, rmp
= amd_revmap
; i
< sizeof (amd_revmap
) / sizeof (*rmp
);
365 if (family
== rmp
->rm_family
&&
366 model
>= rmp
->rm_modello
&& model
<= rmp
->rm_modelhi
&&
367 step
>= rmp
->rm_steplo
&& step
<= rmp
->rm_stephi
) {
376 if (chiprev_p
!= NULL
)
377 *chiprev_p
= rmp
->rm_chiprev
;
378 if (chiprevstr_p
!= NULL
)
379 *chiprevstr_p
= rmp
->rm_chiprevstr
;
384 platform
= get_hwenv();
386 if ((platform
& HW_VIRTUAL
) != 0) {
387 *skt_p
= X86_SOCKET_UNKNOWN
;
388 } else if (family
== 0xf) {
389 *skt_p
= amd_skts
[rmp
->rm_sktidx
][model
& 0x3];
392 * Starting with family 10h, socket type is stored in
393 * CPUID Fn8000_0001_EBX
395 struct cpuid_regs cp
;
398 cp
.cp_eax
= 0x80000001;
399 (void) __cpuid_insn(&cp
);
402 idx
= BITX(cp
.cp_ebx
, 31, 28);
406 *skt_p
= X86_SOCKET_UNKNOWN
;
408 *skt_p
= amd_skts
[rmp
->rm_sktidx
][idx
];
410 if (family
== 0x10) {
412 * Look at Ddr3Mode bit of DRAM Configuration
413 * High Register to decide whether this is
414 * actually AM3 or S1g4.
418 val
= pci_getl_func(0, 24, 2, 0x94);
419 if (BITX(val
, 8, 8)) {
420 if (*skt_p
== X86_SOCKET_AM2R2
)
421 *skt_p
= X86_SOCKET_AM3
;
422 else if (*skt_p
== X86_SOCKET_S1g3
)
423 *skt_p
= X86_SOCKET_S1g4
;
431 _cpuid_skt(uint_t vendor
, uint_t family
, uint_t model
, uint_t step
)
433 uint32_t skt
= X86_SOCKET_UNKNOWN
;
437 synth_amd_info(family
, model
, step
, &skt
, NULL
, NULL
);
449 _cpuid_sktstr(uint_t vendor
, uint_t family
, uint_t model
, uint_t step
)
451 const char *sktstr
= "Unknown";
452 struct amd_sktmap_s
*sktmapp
;
453 uint32_t skt
= X86_SOCKET_UNKNOWN
;
457 synth_amd_info(family
, model
, step
, &skt
, NULL
, NULL
);
459 sktmapp
= amd_sktmap
;
460 while (sktmapp
->skt_code
!= X86_SOCKET_UNKNOWN
) {
461 if (sktmapp
->skt_code
== skt
)
465 sktstr
= sktmapp
->sktstr
;
477 _cpuid_chiprev(uint_t vendor
, uint_t family
, uint_t model
, uint_t step
)
479 uint32_t chiprev
= X86_CHIPREV_UNKNOWN
;
483 synth_amd_info(family
, model
, step
, NULL
, &chiprev
, NULL
);
495 _cpuid_chiprevstr(uint_t vendor
, uint_t family
, uint_t model
, uint_t step
)
497 const char *revstr
= "Unknown";
501 synth_amd_info(family
, model
, step
, NULL
, NULL
, &revstr
);
514 * CyrixInstead is a variable used by the Cyrix detection code
517 const char CyrixInstead
[] = X86_VENDORSTR_CYRIX
;
520 * Map the vendor string to a type code
523 _cpuid_vendorstr_to_vendorcode(char *vendorstr
)
525 if (strcmp(vendorstr
, X86_VENDORSTR_Intel
) == 0)
526 return (X86_VENDOR_Intel
);
527 else if (strcmp(vendorstr
, X86_VENDORSTR_AMD
) == 0)
528 return (X86_VENDOR_AMD
);
529 else if (strcmp(vendorstr
, X86_VENDORSTR_TM
) == 0)
530 return (X86_VENDOR_TM
);
531 else if (strcmp(vendorstr
, CyrixInstead
) == 0)
532 return (X86_VENDOR_Cyrix
);
533 else if (strcmp(vendorstr
, X86_VENDORSTR_UMC
) == 0)
534 return (X86_VENDOR_UMC
);
535 else if (strcmp(vendorstr
, X86_VENDORSTR_NexGen
) == 0)
536 return (X86_VENDOR_NexGen
);
537 else if (strcmp(vendorstr
, X86_VENDORSTR_Centaur
) == 0)
538 return (X86_VENDOR_Centaur
);
539 else if (strcmp(vendorstr
, X86_VENDORSTR_Rise
) == 0)
540 return (X86_VENDOR_Rise
);
541 else if (strcmp(vendorstr
, X86_VENDORSTR_SiS
) == 0)
542 return (X86_VENDOR_SiS
);
543 else if (strcmp(vendorstr
, X86_VENDORSTR_NSC
) == 0)
544 return (X86_VENDOR_NSC
);
546 return (X86_VENDOR_IntelClone
);