1 /* $NetBSD: identcpu.c,v 1.7 2008/05/13 11:22:15 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden, and by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /*- 33 * Copyright (c)2008 YAMAMOTO Takashi, 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58 #include <sys/cdefs.h> 59 __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.7 2008/05/13 11:22:15 ad Exp $"); 60 61 #include "opt_enhanced_speedstep.h" 62 #include "opt_intel_odcm.h" 63 #include "opt_intel_coretemp.h" 64 #include "opt_powernow_k8.h" 65 #include "opt_xen.h" 66 #ifdef i386 /* XXX */ 67 #include "opt_powernow_k7.h" 68 #endif 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/malloc.h> 73 #include <sys/bitops.h> 74 75 #include <uvm/uvm_extern.h> 76 77 #include <machine/specialreg.h> 78 #include <machine/pio.h> 79 #include <machine/cpu.h> 80 81 #include <x86/cputypes.h> 82 #include <x86/cacheinfo.h> 83 #include <x86/cpuvar.h> 84 #include <x86/cpu_msr.h> 85 #include <x86/powernow.h> 86 87 static const struct x86_cache_info intel_cpuid_cache_info[] = { 88 { CAI_ITLB, 0x01, 4, 32, 4 * 1024 }, 89 { CAI_ITLB, 0xb0, 4,128, 4 * 1024 }, 90 { CAI_ITLB2, 0x02, 0xff, 2, 4 * 1024 * 1024 }, 91 { CAI_DTLB, 0x03, 4, 64, 4 * 1024 }, 92 { CAI_DTLB, 0xb3, 4,128, 4 * 1024 }, 93 { CAI_DTLB, 0xb4, 4,256, 4 * 1024 }, 94 { CAI_DTLB2, 0x04, 4, 8, 4 * 1024 * 1024 }, 95 { CAI_DTLB2, 0x05, 4, 32, 4 * 1024 * 1024 }, 96 { CAI_ITLB, 0x50, 0xff, 64, 4 * 1024 }, 97 { CAI_ITLB, 0x51, 0xff, 64, 4 * 1024 }, 98 { CAI_ITLB, 0x52, 0xff, 64, 4 * 1024 }, 99 { CAI_DTLB, 0x5b, 0xff, 64, 4 * 1024 }, 100 { CAI_DTLB, 0x5c, 0xff,128, 4 * 1024 }, 101 { CAI_DTLB, 0x5d, 0xff,256, 4 * 1024 }, 102 { CAI_ICACHE, 0x06, 4, 8 * 1024, 32 }, 103 { CAI_ICACHE, 0x08, 4, 16 * 1024, 32 }, 104 { CAI_ICACHE, 0x30, 8, 32 * 1024, 64 }, 105 { CAI_DCACHE, 0x0a, 2, 8 * 1024, 32 }, 106 { CAI_DCACHE, 0x0c, 4, 16 * 1024, 32 }, 107 { CAI_L2CACHE, 0x39, 4, 128 * 1024, 64 }, 108 { CAI_L2CACHE, 0x3a, 6, 192 * 1024, 64 }, 109 { CAI_L2CACHE, 0x3b, 2, 128 * 1024, 64 }, 110 { CAI_L2CACHE, 0x3c, 4, 256 * 1024, 64 }, 111 { CAI_L2CACHE, 0x3d, 6, 384 * 1024, 64 }, 112 { CAI_L2CACHE, 0x3e, 4, 512 * 1024, 64 }, 113 { CAI_L2CACHE, 0x40, 0, 0, 0 }, 114 { CAI_L2CACHE, 0x41, 4, 128 * 1024, 32 }, 115 { CAI_L2CACHE, 0x42, 4, 256 * 1024, 32 }, 116 { CAI_L2CACHE, 0x43, 4, 512 * 1024, 32 }, 117 { CAI_L2CACHE, 0x44, 4, 1 * 1024 * 1024, 32 }, 118 { CAI_L2CACHE, 0x45, 4, 2 * 1024 * 1024, 32 }, 119 { CAI_L2CACHE, 0x49, 16, 4 * 1024 * 1024, 64 }, 120 { CAI_L2CACHE, 0x4e, 24, 6 * 1024 * 1024, 64 }, 121 { CAI_DCACHE, 0x60, 8, 16 * 1024, 64 }, 122 { CAI_DCACHE, 0x66, 4, 8 * 1024, 64 }, 123 { CAI_DCACHE, 0x67, 4, 16 * 1024, 64 }, 124 { CAI_DCACHE, 0x2c, 8, 32 * 1024, 64 }, 125 { CAI_DCACHE, 0x68, 4, 32 * 1024, 64 }, 126 { CAI_ICACHE, 0x70, 8, 12 * 1024, 64 }, 127 { CAI_ICACHE, 0x71, 8, 16 * 1024, 64 }, 128 { CAI_ICACHE, 0x72, 8, 32 * 1024, 64 }, 129 { CAI_ICACHE, 0x73, 8, 64 * 1024, 64 }, 130 { CAI_L2CACHE, 0x78, 4, 1 * 1024 * 1024, 64 }, 131 { CAI_L2CACHE, 0x79, 8, 128 * 1024, 64 }, 132 { CAI_L2CACHE, 0x7a, 8, 256 * 1024, 64 }, 133 { CAI_L2CACHE, 0x7b, 8, 512 * 1024, 64 }, 134 { CAI_L2CACHE, 0x7c, 8, 1 * 1024 * 1024, 64 }, 135 { CAI_L2CACHE, 0x7d, 8, 2 * 1024 * 1024, 64 }, 136 { CAI_L2CACHE, 0x7f, 2, 512 * 1024, 64 }, 137 { CAI_L2CACHE, 0x82, 8, 256 * 1024, 32 }, 138 { CAI_L2CACHE, 0x83, 8, 512 * 1024, 32 }, 139 { CAI_L2CACHE, 0x84, 8, 1 * 1024 * 1024, 32 }, 140 { CAI_L2CACHE, 0x85, 8, 2 * 1024 * 1024, 32 }, 141 { CAI_L2CACHE, 0x86, 4, 512 * 1024, 64 }, 142 { CAI_L2CACHE, 0x87, 8, 1 * 1024 * 1024, 64 }, 143 { 0, 0, 0, 0, 0 }, 144 }; 145 146 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = { 147 { 0, 0x01, 1, 0, 0 }, 148 { 0, 0x02, 2, 0, 0 }, 149 { 0, 0x04, 4, 0, 0 }, 150 { 0, 0x06, 8, 0, 0 }, 151 { 0, 0x08, 16, 0, 0 }, 152 { 0, 0x0a, 32, 0, 0 }, 153 { 0, 0x0b, 48, 0, 0 }, 154 { 0, 0x0c, 64, 0, 0 }, 155 { 0, 0x0d, 96, 0, 0 }, 156 { 0, 0x0e, 128, 0, 0 }, 157 { 0, 0x0f, 0xff, 0, 0 }, 158 { 0, 0x00, 0, 0, 0 }, 159 }; 160 161 static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] = { 162 { 0, 0x00, 0, 0, 0 }, 163 { 0, 0x01, 1, 0, 0 }, 164 { 0, 0x02, 2, 0, 0 }, 165 { 0, 0x04, 4, 0, 0 }, 166 { 0, 0x06, 8, 0, 0 }, 167 { 0, 0x08, 16, 0, 0 }, 168 { 0, 0x0a, 32, 0, 0 }, 169 { 0, 0x0b, 48, 0, 0 }, 170 { 0, 0x0c, 64, 0, 0 }, 171 { 0, 0x0d, 96, 0, 0 }, 172 { 0, 0x0e, 128, 0, 0 }, 173 { 0, 0x0f, 0xff, 0, 0 }, 174 { 0, 0x00, 0, 0, 0 }, 175 }; 176 177 int cpu_vendor; 178 char cpu_brand_string[49]; 179 180 /* 181 * Info for CTL_HW 182 */ 183 char cpu_model[120]; 184 185 /* 186 * Note: these are just the ones that may not have a cpuid instruction. 187 * We deal with the rest in a different way. 188 */ 189 const int i386_nocpuid_cpus[] = { 190 CPUVENDOR_INTEL, CPUCLASS_386, /* CPU_386SX */ 191 CPUVENDOR_INTEL, CPUCLASS_386, /* CPU_386 */ 192 CPUVENDOR_INTEL, CPUCLASS_486, /* CPU_486SX */ 193 CPUVENDOR_INTEL, CPUCLASS_486, /* CPU_486 */ 194 CPUVENDOR_CYRIX, CPUCLASS_486, /* CPU_486DLC */ 195 CPUVENDOR_CYRIX, CPUCLASS_486, /* CPU_6x86 */ 196 CPUVENDOR_NEXGEN, CPUCLASS_386, /* CPU_NX586 */ 197 }; 198 199 static const char cpu_vendor_names[][10] = { 200 "Unknown", "Intel", "NS/Cyrix", "NexGen", "AMD", "IDT/VIA", "Transmeta" 201 }; 202 203 static const struct x86_cache_info * 204 cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc) 205 { 206 int i; 207 208 for (i = 0; cai[i].cai_desc != 0; i++) { 209 if (cai[i].cai_desc == desc) 210 return (&cai[i]); 211 } 212 213 return (NULL); 214 } 215 216 static void 217 cpu_probe_p6(struct cpu_info *ci) 218 { 219 u_int lp_max = 1; /* logical processors per package */ 220 u_int smt_max; /* smt per core */ 221 u_int core_max = 1; /* core per package */ 222 int smt_bits, core_bits; 223 uint32_t descs[4]; 224 225 if (cpu_vendor != CPUVENDOR_INTEL || 226 CPUID2FAMILY(ci->ci_signature) < 6) 227 return; 228 229 /* Determine extended feature flags. */ 230 x86_cpuid(0x80000000, descs); 231 if (descs[0] >= 0x80000001) { 232 x86_cpuid(0x80000001, descs); 233 ci->ci_feature3_flags |= descs[3]; 234 } 235 236 /* Determine topology. 253668.pdf 7.10.2. */ 237 ci->ci_packageid = ci->ci_initapicid; 238 ci->ci_coreid = 0; 239 ci->ci_smtid = 0; 240 if ((ci->ci_feature_flags & CPUID_HTT) != 0) { 241 x86_cpuid(1, descs); 242 lp_max = (descs[1] >> 16) & 0xff; 243 } 244 x86_cpuid(0, descs); 245 if (descs[0] >= 4) { 246 x86_cpuid2(4, 0, descs); 247 core_max = (descs[0] >> 26) + 1; 248 } 249 KASSERT(lp_max >= core_max); 250 smt_max = lp_max / core_max; 251 smt_bits = ilog2(smt_max - 1) + 1; 252 core_bits = ilog2(core_max - 1) + 1; 253 if (smt_bits + core_bits) { 254 ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits); 255 } 256 if (core_bits) { 257 u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1); 258 ci->ci_coreid = __SHIFTOUT(ci->ci_initapicid, core_mask); 259 } 260 if (smt_bits) { 261 u_int smt_mask = __BITS(0, smt_bits - 1); 262 ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask); 263 } 264 } 265 266 static void 267 cpu_probe_amd_cache(struct cpu_info *ci) 268 { 269 const struct x86_cache_info *cp; 270 struct x86_cache_info *cai; 271 int family, model; 272 u_int descs[4]; 273 u_int lfunc; 274 275 family = CPUID2FAMILY(ci->ci_signature); 276 model = CPUID2MODEL(ci->ci_signature); 277 278 /* 279 * K5 model 0 has none of this info. 280 */ 281 if (family == 5 && model == 0) 282 return; 283 284 /* 285 * Get extended values for K8 and up. 286 */ 287 if (family == 0xf) { 288 family += CPUID2EXTFAMILY(ci->ci_signature); 289 model += CPUID2EXTMODEL(ci->ci_signature); 290 } 291 292 /* 293 * Determine the largest extended function value. 294 */ 295 x86_cpuid(0x80000000, descs); 296 lfunc = descs[0]; 297 298 /* 299 * Determine L1 cache/TLB info. 300 */ 301 if (lfunc < 0x80000005) { 302 /* No L1 cache info available. */ 303 return; 304 } 305 306 x86_cpuid(0x80000005, descs); 307 308 /* 309 * K6-III and higher have large page TLBs. 310 */ 311 if ((family == 5 && model >= 9) || family >= 6) { 312 cai = &ci->ci_cinfo[CAI_ITLB2]; 313 cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]); 314 cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]); 315 cai->cai_linesize = (4 * 1024 * 1024); 316 317 cai = &ci->ci_cinfo[CAI_DTLB2]; 318 cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]); 319 cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]); 320 cai->cai_linesize = (4 * 1024 * 1024); 321 } 322 323 cai = &ci->ci_cinfo[CAI_ITLB]; 324 cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]); 325 cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]); 326 cai->cai_linesize = (4 * 1024); 327 328 cai = &ci->ci_cinfo[CAI_DTLB]; 329 cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]); 330 cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]); 331 cai->cai_linesize = (4 * 1024); 332 333 cai = &ci->ci_cinfo[CAI_DCACHE]; 334 cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]); 335 cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]); 336 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]); 337 338 cai = &ci->ci_cinfo[CAI_ICACHE]; 339 cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]); 340 cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]); 341 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]); 342 343 /* 344 * Determine L2 cache/TLB info. 345 */ 346 if (lfunc < 0x80000006) { 347 /* No L2 cache info available. */ 348 return; 349 } 350 351 x86_cpuid(0x80000006, descs); 352 353 cai = &ci->ci_cinfo[CAI_L2CACHE]; 354 cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]); 355 cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]); 356 cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]); 357 358 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 359 cai->cai_associativity); 360 if (cp != NULL) 361 cai->cai_associativity = cp->cai_associativity; 362 else 363 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 364 365 if (family < 0xf) { 366 /* No L3 cache info available. */ 367 return; 368 } 369 370 cai = &ci->ci_cinfo[CAI_L3CACHE]; 371 cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]); 372 cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]); 373 cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]); 374 375 cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info, 376 cai->cai_associativity); 377 if (cp != NULL) 378 cai->cai_associativity = cp->cai_associativity; 379 else 380 cai->cai_associativity = 0; /* XXX Unknown reserved */ 381 382 if (lfunc < 0x80000019) { 383 /* No 1GB Page TLB */ 384 return; 385 } 386 387 x86_cpuid(0x80000019, descs); 388 389 cai = &ci->ci_cinfo[CAI_L1_1GBDTLB]; 390 cai->cai_totalsize = AMD_L1_1GB_EAX_DTLB_ENTRIES(descs[1]); 391 cai->cai_associativity = AMD_L1_1GB_EAX_DTLB_ASSOC(descs[1]); 392 cai->cai_linesize = (1 * 1024); 393 394 cai = &ci->ci_cinfo[CAI_L1_1GBITLB]; 395 cai->cai_totalsize = AMD_L1_1GB_EAX_IUTLB_ENTRIES(descs[0]); 396 cai->cai_associativity = AMD_L1_1GB_EAX_IUTLB_ASSOC(descs[0]); 397 cai->cai_linesize = (1 * 1024); 398 399 cai = &ci->ci_cinfo[CAI_L2_1GBDTLB]; 400 cai->cai_totalsize = AMD_L2_1GB_EBX_DUTLB_ENTRIES(descs[1]); 401 cai->cai_associativity = AMD_L2_1GB_EBX_DUTLB_ASSOC(descs[1]); 402 cai->cai_linesize = (1 * 1024); 403 404 cai = &ci->ci_cinfo[CAI_L2_1GBITLB]; 405 cai->cai_totalsize = AMD_L2_1GB_EBX_IUTLB_ENTRIES(descs[0]); 406 cai->cai_associativity = AMD_L2_1GB_EBX_IUTLB_ASSOC(descs[0]); 407 cai->cai_linesize = (1 * 1024); 408 } 409 410 static void 411 cpu_probe_k5(struct cpu_info *ci) 412 { 413 int flag; 414 415 if (cpu_vendor != CPUVENDOR_AMD || 416 CPUID2FAMILY(ci->ci_signature) != 5) 417 return; 418 419 if (CPUID2MODEL(ci->ci_signature) == 0) { 420 /* 421 * According to the AMD Processor Recognition App Note, 422 * the AMD-K5 Model 0 uses the wrong bit to indicate 423 * support for global PTEs, instead using bit 9 (APIC) 424 * rather than bit 13 (i.e. "0x200" vs. 0x2000". Oops!). 425 */ 426 flag = ci->ci_feature_flags; 427 if ((flag & CPUID_APIC) != 0) 428 flag = (flag & ~CPUID_APIC) | CPUID_PGE; 429 ci->ci_feature_flags = flag; 430 } 431 432 cpu_probe_amd_cache(ci); 433 } 434 435 static void 436 cpu_probe_k678(struct cpu_info *ci) 437 { 438 uint32_t descs[4]; 439 440 if (cpu_vendor != CPUVENDOR_AMD || 441 CPUID2FAMILY(ci->ci_signature) < 6) 442 return; 443 444 /* Determine the extended feature flags. */ 445 x86_cpuid(0x80000000, descs); 446 if (descs[0] >= 0x80000001) { 447 x86_cpuid(0x80000001, descs); 448 ci->ci_feature_flags |= descs[3]; 449 } 450 451 cpu_probe_amd_cache(ci); 452 } 453 454 static inline uint8_t 455 cyrix_read_reg(uint8_t reg) 456 { 457 458 outb(0x22, reg); 459 return inb(0x23); 460 } 461 462 static inline void 463 cyrix_write_reg(uint8_t reg, uint8_t data) 464 { 465 466 outb(0x22, reg); 467 outb(0x23, data); 468 } 469 470 static void 471 cpu_probe_cyrix_cmn(struct cpu_info *ci) 472 { 473 /* 474 * i8254 latch check routine: 475 * National Geode (formerly Cyrix MediaGX) has a serious bug in 476 * its built-in i8254-compatible clock module (cs5510 cs5520). 477 * Set the variable 'clock_broken_latch' to indicate it. 478 * 479 * This bug is not present in the cs5530, and the flag 480 * is disabled again in sys/arch/i386/pci/pcib.c if this later 481 * model device is detected. Ideally, this work-around should not 482 * even be in here, it should be in there. XXX 483 */ 484 uint8_t c3; 485 #ifndef XEN 486 extern int clock_broken_latch; 487 488 switch (ci->ci_signature) { 489 case 0x440: /* Cyrix MediaGX */ 490 case 0x540: /* GXm */ 491 clock_broken_latch = 1; 492 break; 493 } 494 #endif 495 496 /* set up various cyrix registers */ 497 /* 498 * Enable suspend on halt (powersave mode). 499 * When powersave mode is enabled, the TSC stops counting 500 * while the CPU is halted in idle() waiting for an interrupt. 501 * This means we can't use the TSC for interval time in 502 * microtime(9), and thus it is disabled here. 503 * 504 * It still makes a perfectly good cycle counter 505 * for program profiling, so long as you remember you're 506 * counting cycles, and not time. Further, if you don't 507 * mind not using powersave mode, the TSC works just fine, 508 * so this should really be optional. XXX 509 */ 510 cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08); 511 512 /* 513 * Do not disable the TSC on the Geode GX, it's reported to 514 * work fine. 515 */ 516 if (ci->ci_signature != 0x552) 517 ci->ci_feature_flags &= ~CPUID_TSC; 518 519 /* enable access to ccr4/ccr5 */ 520 c3 = cyrix_read_reg(0xC3); 521 cyrix_write_reg(0xC3, c3 | 0x10); 522 /* cyrix's workaround for the "coma bug" */ 523 cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8); 524 cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f); 525 cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff); 526 cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87); 527 /* disable access to ccr4/ccr5 */ 528 cyrix_write_reg(0xC3, c3); 529 530 /* 531 * XXX disable page zero in the idle loop, it seems to 532 * cause panics on these CPUs. 533 */ 534 vm_page_zero_enable = FALSE; 535 } 536 537 static void 538 cpu_probe_cyrix(struct cpu_info *ci) 539 { 540 541 if (cpu_vendor != CPUVENDOR_CYRIX || 542 CPUID2FAMILY(ci->ci_signature) < 4 || 543 CPUID2FAMILY(ci->ci_signature) > 6) 544 return; 545 546 cpu_probe_cyrix_cmn(ci); 547 } 548 549 static void 550 cpu_probe_winchip(struct cpu_info *ci) 551 { 552 553 if (cpu_vendor != CPUVENDOR_IDT || 554 CPUID2FAMILY(ci->ci_signature) != 5) 555 return; 556 557 if (CPUID2MODEL(ci->ci_signature) == 4) { 558 /* WinChip C6 */ 559 ci->ci_feature_flags &= ~CPUID_TSC; 560 } 561 } 562 563 static void 564 cpu_probe_c3(struct cpu_info *ci) 565 { 566 u_int family, model, stepping, descs[4], lfunc, msr; 567 struct x86_cache_info *cai; 568 569 if (cpu_vendor != CPUVENDOR_IDT || 570 CPUID2FAMILY(ci->ci_signature) != 5) 571 return; 572 573 family = CPUID2FAMILY(ci->ci_signature); 574 model = CPUID2MODEL(ci->ci_signature); 575 stepping = CPUID2STEPPING(ci->ci_signature); 576 577 /* Determine the largest extended function value. */ 578 x86_cpuid(0x80000000, descs); 579 lfunc = descs[0]; 580 581 /* Determine the extended feature flags. */ 582 if (lfunc >= 0x80000001) { 583 x86_cpuid(0x80000001, descs); 584 ci->ci_feature_flags |= descs[3]; 585 } 586 587 if (model >= 0x9) { 588 /* Nehemiah or Esther */ 589 x86_cpuid(0xc0000000, descs); 590 lfunc = descs[0]; 591 if (lfunc >= 0xc0000001) { /* has ACE, RNG */ 592 x86_cpuid(0xc0000001, descs); 593 lfunc = descs[3]; 594 if (model > 0x9 || stepping >= 8) { /* ACE */ 595 if (lfunc & CPUID_VIA_HAS_ACE) { 596 ci->ci_padlock_flags = lfunc; 597 if ((lfunc & CPUID_VIA_DO_ACE) == 0) { 598 msr = rdmsr(MSR_VIA_ACE); 599 wrmsr(MSR_VIA_ACE, msr | 600 MSR_VIA_ACE_ENABLE); 601 ci->ci_padlock_flags |= 602 CPUID_VIA_DO_ACE; 603 } 604 } 605 } 606 } 607 } 608 609 /* 610 * Determine L1 cache/TLB info. 611 */ 612 if (lfunc < 0x80000005) { 613 /* No L1 cache info available. */ 614 return; 615 } 616 617 x86_cpuid(0x80000005, descs); 618 619 cai = &ci->ci_cinfo[CAI_ITLB]; 620 cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]); 621 cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]); 622 cai->cai_linesize = (4 * 1024); 623 624 cai = &ci->ci_cinfo[CAI_DTLB]; 625 cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]); 626 cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]); 627 cai->cai_linesize = (4 * 1024); 628 629 cai = &ci->ci_cinfo[CAI_DCACHE]; 630 cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]); 631 cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]); 632 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]); 633 if (model == 9 && stepping == 8) { 634 /* Erratum: stepping 8 reports 4 when it should be 2 */ 635 cai->cai_associativity = 2; 636 } 637 638 cai = &ci->ci_cinfo[CAI_ICACHE]; 639 cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]); 640 cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]); 641 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]); 642 if (model == 9 && stepping == 8) { 643 /* Erratum: stepping 8 reports 4 when it should be 2 */ 644 cai->cai_associativity = 2; 645 } 646 647 /* 648 * Determine L2 cache/TLB info. 649 */ 650 if (lfunc < 0x80000006) { 651 /* No L2 cache info available. */ 652 return; 653 } 654 655 x86_cpuid(0x80000006, descs); 656 657 cai = &ci->ci_cinfo[CAI_L2CACHE]; 658 if (model >= 9) { 659 cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]); 660 cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]); 661 cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]); 662 } else { 663 cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]); 664 cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]); 665 cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]); 666 } 667 } 668 669 static void 670 cpu_probe_geode(struct cpu_info *ci) 671 { 672 673 if (memcmp("Geode by NSC", ci->ci_vendor, 12) != 0 || 674 CPUID2FAMILY(ci->ci_signature) != 5) 675 return; 676 677 cpu_probe_cyrix_cmn(ci); 678 cpu_probe_amd_cache(ci); 679 } 680 681 void 682 cpu_probe(struct cpu_info *ci) 683 { 684 const struct x86_cache_info *cai; 685 u_int descs[4]; 686 int iterations, i, j; 687 uint8_t desc; 688 uint32_t miscbytes; 689 uint32_t brand[12]; 690 691 cpu_vendor = i386_nocpuid_cpus[cpu << 1]; 692 cpu_class = i386_nocpuid_cpus[(cpu << 1) + 1]; 693 694 if (cpuid_level < 0) 695 return; 696 697 x86_cpuid(0, descs); 698 cpuid_level = descs[0]; 699 ci->ci_vendor[0] = descs[1]; 700 ci->ci_vendor[2] = descs[2]; 701 ci->ci_vendor[1] = descs[3]; 702 ci->ci_vendor[3] = 0; 703 704 if (memcmp(ci->ci_vendor, "GenuineIntel", 12) == 0) 705 cpu_vendor = CPUVENDOR_INTEL; 706 else if (memcmp(ci->ci_vendor, "AuthenticAMD", 12) == 0) 707 cpu_vendor = CPUVENDOR_AMD; 708 else if (memcmp(ci->ci_vendor, "CyrixInstead", 12) == 0) 709 cpu_vendor = CPUVENDOR_CYRIX; 710 else if (memcmp(ci->ci_vendor, "Geode by NSC", 12) == 0) 711 cpu_vendor = CPUVENDOR_CYRIX; 712 else if (memcmp(ci->ci_vendor, "CentaurHauls", 12) == 0) 713 cpu_vendor = CPUVENDOR_IDT; 714 else if (memcmp(ci->ci_vendor, "GenuineTMx86", 12) == 0) 715 cpu_vendor = CPUVENDOR_TRANSMETA; 716 else 717 cpu_vendor = CPUVENDOR_UNKNOWN; 718 719 x86_cpuid(0x80000000, brand); 720 if (brand[0] >= 0x80000004) { 721 x86_cpuid(0x80000002, brand); 722 x86_cpuid(0x80000003, brand + 4); 723 x86_cpuid(0x80000004, brand + 8); 724 for (i = 0; i < 48; i++) { 725 if (((char *) brand)[i] != ' ') 726 break; 727 } 728 memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); 729 } 730 731 if (cpuid_level >= 1) { 732 x86_cpuid(1, descs); 733 ci->ci_signature = descs[0]; 734 miscbytes = descs[1]; 735 ci->ci_feature2_flags = descs[2]; 736 ci->ci_feature_flags = descs[3]; 737 738 /* Determine family + class. */ 739 cpu_class = CPUID2FAMILY(ci->ci_signature) + (CPUCLASS_386 - 3); 740 if (cpu_class > CPUCLASS_686) 741 cpu_class = CPUCLASS_686; 742 743 /* CLFLUSH line size is next 8 bits */ 744 if (ci->ci_feature_flags & CPUID_CFLUSH) 745 ci->ci_cflush_lsize = ((miscbytes >> 8) & 0xff) << 3; 746 ci->ci_initapicid = (miscbytes >> 24) & 0xff; 747 } 748 749 if (cpuid_level >= 2) { 750 /* Parse the cache info from `cpuid', if we have it. */ 751 x86_cpuid(2, descs); 752 iterations = descs[0] & 0xff; 753 while (iterations-- > 0) { 754 for (i = 0; i < 4; i++) { 755 if (descs[i] & 0x80000000) 756 continue; 757 for (j = 0; j < 4; j++) { 758 if (i == 0 && j == 0) 759 continue; 760 desc = (descs[i] >> (j * 8)) & 0xff; 761 if (desc == 0) 762 continue; 763 cai = cache_info_lookup( 764 intel_cpuid_cache_info, desc); 765 if (cai != NULL) { 766 ci->ci_cinfo[cai->cai_index] = 767 *cai; 768 } 769 } 770 } 771 } 772 } 773 774 cpu_probe_p6(ci); 775 cpu_probe_k5(ci); 776 cpu_probe_k678(ci); 777 cpu_probe_cyrix(ci); 778 cpu_probe_winchip(ci); 779 cpu_probe_c3(ci); 780 cpu_probe_geode(ci); 781 782 if (cpu_vendor != CPUVENDOR_AMD && (ci->ci_feature_flags & CPUID_TM) && 783 (rdmsr(MSR_MISC_ENABLE) & (1 << 3)) == 0) { 784 /* Enable thermal monitor 1. */ 785 wrmsr(MSR_MISC_ENABLE, rdmsr(MSR_MISC_ENABLE) | (1<<3)); 786 } 787 788 if ((cpu_feature | cpu_feature2) == 0) { 789 /* If first. */ 790 cpu_feature = ci->ci_feature_flags; 791 cpu_feature2 = ci->ci_feature2_flags; 792 } else { 793 /* If not first. */ 794 cpu_feature &= ci->ci_feature_flags; 795 cpu_feature2 &= ci->ci_feature2_flags; 796 } 797 } 798 799 void 800 cpu_identify(struct cpu_info *ci) 801 { 802 803 snprintf(cpu_model, sizeof(cpu_model), "%s %d86-class", 804 cpu_vendor_names[cpu_vendor], cpu_class + 3); 805 aprint_normal(": %s", cpu_model); 806 if (ci->ci_data.cpu_cc_freq != 0) 807 aprint_normal(", %dMHz", (int)(ci->ci_data.cpu_cc_freq / 1000000)); 808 if (ci->ci_signature != 0) 809 aprint_normal(", id 0x%x", ci->ci_signature); 810 aprint_normal("\n"); 811 812 if (cpu_brand_string[0] == '\0') { 813 strlcpy(cpu_brand_string, cpu_model, sizeof(cpu_brand_string)); 814 } 815 if (cpu_class == CPUCLASS_386) { 816 panic("NetBSD requires an 80486DX or later processor"); 817 } 818 if (cpu == CPU_486DLC) { 819 aprint_error("WARNING: BUGGY CYRIX CACHE\n"); 820 } 821 822 #ifdef i386 /* XXX for now */ 823 if (cpu_vendor == CPUVENDOR_TRANSMETA) { 824 u_int descs[4]; 825 x86_cpuid(0x80860000, descs); 826 if (descs[0] >= 0x80860007) 827 tmx86_init_longrun(); 828 } 829 830 /* If we have FXSAVE/FXRESTOR, use them. */ 831 if (cpu_feature & CPUID_FXSR) { 832 i386_use_fxsave = 1; 833 /* 834 * If we have SSE/SSE2, enable XMM exceptions, and 835 * notify userland. 836 */ 837 if (cpu_feature & CPUID_SSE) 838 i386_has_sse = 1; 839 if (cpu_feature & CPUID_SSE2) 840 i386_has_sse2 = 1; 841 } else 842 i386_use_fxsave = 0; 843 #endif /* i386 */ 844 845 #ifdef ENHANCED_SPEEDSTEP 846 if (cpu_feature2 & CPUID2_EST) { 847 if (rdmsr(MSR_MISC_ENABLE) & (1 << 16)) 848 est_init(cpu_vendor); 849 } 850 #endif /* ENHANCED_SPEEDSTEP */ 851 852 #ifdef INTEL_CORETEMP 853 if (cpu_vendor == CPUVENDOR_INTEL && cpuid_level >= 0x06) 854 coretemp_register(ci); 855 #endif 856 857 #if defined(POWERNOW_K7) || defined(POWERNOW_K8) 858 if (cpu_vendor == CPUVENDOR_AMD && powernow_probe(ci)) { 859 switch (CPUID2FAMILY(ci->ci_signature)) { 860 #ifdef POWERNOW_K7 861 case 6: 862 k7_powernow_init(); 863 break; 864 #endif 865 #ifdef POWERNOW_K8 866 case 15: 867 k8_powernow_init(); 868 break; 869 #endif 870 default: 871 break; 872 } 873 } 874 #endif /* POWERNOW_K7 || POWERNOW_K8 */ 875 876 #ifdef INTEL_ONDEMAND_CLOCKMOD 877 if (cpuid_level >= 1) { 878 clockmod_init(); 879 } 880 #endif 881 } 882