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