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