1 /* $NetBSD: i386.c,v 1.9 2008/05/31 12:48:41 christos 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 #ifndef lint 60 __RCSID("$NetBSD: i386.c,v 1.9 2008/05/31 12:48:41 christos Exp $"); 61 #endif /* not lint */ 62 63 #include <sys/types.h> 64 #include <sys/param.h> 65 #include <sys/bitops.h> 66 #include <sys/sysctl.h> 67 68 #include <string.h> 69 #include <stdio.h> 70 #include <stdlib.h> 71 #include <err.h> 72 #include <assert.h> 73 #include <math.h> 74 75 #include <machine/specialreg.h> 76 #include <machine/cpu.h> 77 78 #include <x86/cpuvar.h> 79 #include <x86/cputypes.h> 80 #include <x86/cacheinfo.h> 81 82 #include "../cpuctl.h" 83 84 /* Size of buffer for printing humanized numbers */ 85 #define HUMAN_BUFSIZE 5 86 87 #define x86_cpuid(a,b) x86_cpuid2((a),0,(b)) 88 89 void x86_cpuid2(uint32_t, uint32_t, uint32_t *); 90 void x86_identify(void); 91 92 struct cpu_info { 93 const char *ci_dev; 94 int32_t ci_cpuid_level; 95 uint32_t ci_signature; /* X86 cpuid type */ 96 uint32_t ci_feature_flags;/* X86 %edx CPUID feature bits */ 97 uint32_t ci_feature2_flags;/* X86 %ecx CPUID feature bits */ 98 uint32_t ci_feature3_flags;/* X86 extended feature bits */ 99 uint32_t ci_padlock_flags;/* VIA PadLock feature bits */ 100 uint32_t ci_cpu_class; /* CPU class */ 101 uint32_t ci_brand_id; /* Intel brand id */ 102 uint32_t ci_vendor[4]; /* vendor string */ 103 uint32_t ci_cpu_serial[3]; /* PIII serial number */ 104 uint64_t ci_tsc_freq; /* cpu cycles/second */ 105 uint8_t ci_packageid; 106 uint8_t ci_coreid; 107 uint8_t ci_smtid; 108 uint32_t ci_initapicid; 109 struct x86_cache_info ci_cinfo[CAI_COUNT]; 110 void (*ci_info)(struct cpu_info *); 111 }; 112 113 struct cpu_nocpuid_nameclass { 114 int cpu_vendor; 115 const char *cpu_vendorname; 116 const char *cpu_name; 117 int cpu_class; 118 void (*cpu_setup)(struct cpu_info *); 119 void (*cpu_cacheinfo)(struct cpu_info *); 120 void (*cpu_info)(struct cpu_info *); 121 }; 122 123 124 struct cpu_cpuid_nameclass { 125 const char *cpu_id; 126 int cpu_vendor; 127 const char *cpu_vendorname; 128 struct cpu_cpuid_family { 129 int cpu_class; 130 const char *cpu_models[CPU_MAXMODEL+2]; 131 void (*cpu_setup)(struct cpu_info *); 132 void (*cpu_probe)(struct cpu_info *); 133 void (*cpu_info)(struct cpu_info *); 134 } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1]; 135 }; 136 137 static const struct x86_cache_info intel_cpuid_cache_info[] = INTEL_CACHE_INFO; 138 139 /* 140 * Map Brand ID from cpuid instruction to brand name. 141 * Source: Intel Processor Identification and the CPUID Instruction, AP-485 142 */ 143 static const char * const i386_intel_brand[] = { 144 "", /* Unsupported */ 145 "Celeron", /* Intel (R) Celeron (TM) processor */ 146 "Pentium III", /* Intel (R) Pentium (R) III processor */ 147 "Pentium III Xeon", /* Intel (R) Pentium (R) III Xeon (TM) processor */ 148 "Pentium III", /* Intel (R) Pentium (R) III processor */ 149 "", /* Reserved */ 150 "Mobile Pentium III", /* Mobile Intel (R) Pentium (R) III processor-M */ 151 "Mobile Celeron", /* Mobile Intel (R) Celeron (R) processor */ 152 "Pentium 4", /* Intel (R) Pentium (R) 4 processor */ 153 "Pentium 4", /* Intel (R) Pentium (R) 4 processor */ 154 "Celeron", /* Intel (R) Celeron (TM) processor */ 155 "Xeon", /* Intel (R) Xeon (TM) processor */ 156 "Xeon MP", /* Intel (R) Xeon (TM) processor MP */ 157 "", /* Reserved */ 158 "Mobile Pentium 4", /* Mobile Intel (R) Pentium (R) 4 processor-M */ 159 "Mobile Celeron", /* Mobile Intel (R) Celeron (R) processor */ 160 }; 161 162 /* 163 * AMD processors don't have Brand IDs, so we need these names for probe. 164 */ 165 static const char * const amd_brand[] = { 166 "", 167 "Duron", /* AMD Duron(tm) */ 168 "MP", /* AMD Athlon(tm) MP */ 169 "XP", /* AMD Athlon(tm) XP */ 170 "4" /* AMD Athlon(tm) 4 */ 171 }; 172 173 static int cpu_vendor; 174 static char cpu_brand_string[49]; 175 static char amd_brand_name[48]; 176 177 static void via_cpu_probe(struct cpu_info *); 178 static void amd_family6_probe(struct cpu_info *); 179 static void intel_family_new_probe(struct cpu_info *); 180 static const char *intel_family6_name(struct cpu_info *); 181 static const char *amd_amd64_name(struct cpu_info *); 182 static void amd_family5_setup(struct cpu_info *); 183 static void transmeta_cpu_info(struct cpu_info *); 184 static const char *print_cache_config(struct cpu_info *, int, const char *, 185 const char *); 186 static const char *print_tlb_config(struct cpu_info *, int, const char *, 187 const char *); 188 static void amd_cpu_cacheinfo(struct cpu_info *); 189 static void via_cpu_cacheinfo(struct cpu_info *); 190 static void x86_print_cacheinfo(struct cpu_info *); 191 static const struct x86_cache_info *cache_info_lookup( 192 const struct x86_cache_info *, uint8_t); 193 static void cyrix6x86_cpu_setup(struct cpu_info *); 194 static void winchip_cpu_setup(struct cpu_info *); 195 static void amd_family5_setup(struct cpu_info *); 196 static void powernow_probe(struct cpu_info *); 197 198 /* 199 * Info for CTL_HW 200 */ 201 static char cpu_model[120]; 202 203 /* 204 * Note: these are just the ones that may not have a cpuid instruction. 205 * We deal with the rest in a different way. 206 */ 207 const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = { 208 { CPUVENDOR_INTEL, "Intel", "386SX", CPUCLASS_386, 209 NULL, NULL, NULL }, /* CPU_386SX */ 210 { CPUVENDOR_INTEL, "Intel", "386DX", CPUCLASS_386, 211 NULL, NULL, NULL }, /* CPU_386 */ 212 { CPUVENDOR_INTEL, "Intel", "486SX", CPUCLASS_486, 213 NULL, NULL, NULL }, /* CPU_486SX */ 214 { CPUVENDOR_INTEL, "Intel", "486DX", CPUCLASS_486, 215 NULL, NULL, NULL }, /* CPU_486 */ 216 { CPUVENDOR_CYRIX, "Cyrix", "486DLC", CPUCLASS_486, 217 NULL, NULL, NULL }, /* CPU_486DLC */ 218 { CPUVENDOR_CYRIX, "Cyrix", "6x86", CPUCLASS_486, 219 NULL, NULL, NULL }, /* CPU_6x86 */ 220 { CPUVENDOR_NEXGEN,"NexGen","586", CPUCLASS_386, 221 NULL, NULL, NULL }, /* CPU_NX586 */ 222 }; 223 224 const char *classnames[] = { 225 "386", 226 "486", 227 "586", 228 "686" 229 }; 230 231 const char *modifiers[] = { 232 "", 233 "OverDrive", 234 "Dual", 235 "" 236 }; 237 238 const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = { 239 { 240 "GenuineIntel", 241 CPUVENDOR_INTEL, 242 "Intel", 243 /* Family 4 */ 244 { { 245 CPUCLASS_486, 246 { 247 "486DX", "486DX", "486SX", "486DX2", "486SL", 248 "486SX2", 0, "486DX2 W/B Enhanced", 249 "486DX4", 0, 0, 0, 0, 0, 0, 0, 250 "486" /* Default */ 251 }, 252 NULL, 253 NULL, 254 NULL, 255 }, 256 /* Family 5 */ 257 { 258 CPUCLASS_586, 259 { 260 "Pentium (P5 A-step)", "Pentium (P5)", 261 "Pentium (P54C)", "Pentium (P24T)", 262 "Pentium/MMX", "Pentium", 0, 263 "Pentium (P54C)", "Pentium/MMX (Tillamook)", 264 0, 0, 0, 0, 0, 0, 0, 265 "Pentium" /* Default */ 266 }, 267 NULL, 268 NULL, 269 NULL, 270 }, 271 /* Family 6 */ 272 { 273 CPUCLASS_686, 274 { 275 "Pentium Pro (A-step)", "Pentium Pro", 0, 276 "Pentium II (Klamath)", "Pentium Pro", 277 "Pentium II/Celeron (Deschutes)", 278 "Celeron (Mendocino)", 279 "Pentium III (Katmai)", 280 "Pentium III (Coppermine)", 281 "Pentium M (Banias)", 282 "Pentium III Xeon (Cascades)", 283 "Pentium III (Tualatin)", 0, 284 "Pentium M (Dothan)", 285 "Pentium M (Yonah)", 286 "Core 2 (Merom)", 287 "Pentium Pro, II or III" /* Default */ 288 }, 289 NULL, 290 intel_family_new_probe, 291 NULL, 292 }, 293 /* Family > 6 */ 294 { 295 CPUCLASS_686, 296 { 297 0, 0, 0, 0, 0, 0, 0, 0, 298 0, 0, 0, 0, 0, 0, 0, 0, 299 "Pentium 4" /* Default */ 300 }, 301 NULL, 302 intel_family_new_probe, 303 NULL, 304 } } 305 }, 306 { 307 "AuthenticAMD", 308 CPUVENDOR_AMD, 309 "AMD", 310 /* Family 4 */ 311 { { 312 CPUCLASS_486, 313 { 314 0, 0, 0, "Am486DX2 W/T", 315 0, 0, 0, "Am486DX2 W/B", 316 "Am486DX4 W/T or Am5x86 W/T 150", 317 "Am486DX4 W/B or Am5x86 W/B 150", 0, 0, 318 0, 0, "Am5x86 W/T 133/160", 319 "Am5x86 W/B 133/160", 320 "Am486 or Am5x86" /* Default */ 321 }, 322 NULL, 323 NULL, 324 NULL, 325 }, 326 /* Family 5 */ 327 { 328 CPUCLASS_586, 329 { 330 "K5", "K5", "K5", "K5", 0, 0, "K6", 331 "K6", "K6-2", "K6-III", "Geode LX", 0, 0, 332 "K6-2+/III+", 0, 0, 333 "K5 or K6" /* Default */ 334 }, 335 amd_family5_setup, 336 NULL, 337 amd_cpu_cacheinfo, 338 }, 339 /* Family 6 */ 340 { 341 CPUCLASS_686, 342 { 343 0, "Athlon Model 1", "Athlon Model 2", 344 "Duron", "Athlon Model 4 (Thunderbird)", 345 0, "Athlon", "Duron", "Athlon", 0, 346 "Athlon", 0, 0, 0, 0, 0, 347 "K7 (Athlon)" /* Default */ 348 }, 349 NULL, 350 amd_family6_probe, 351 amd_cpu_cacheinfo, 352 }, 353 /* Family > 6 */ 354 { 355 CPUCLASS_686, 356 { 357 0, 0, 0, 0, 0, 0, 0, 0, 358 0, 0, 0, 0, 0, 0, 0, 0, 359 "Unknown K8 (Athlon)" /* Default */ 360 }, 361 NULL, 362 amd_family6_probe, 363 amd_cpu_cacheinfo, 364 } } 365 }, 366 { 367 "CyrixInstead", 368 CPUVENDOR_CYRIX, 369 "Cyrix", 370 /* Family 4 */ 371 { { 372 CPUCLASS_486, 373 { 374 0, 0, 0, 375 "MediaGX", 376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 377 "486" /* Default */ 378 }, 379 cyrix6x86_cpu_setup, /* XXX ?? */ 380 NULL, 381 NULL, 382 }, 383 /* Family 5 */ 384 { 385 CPUCLASS_586, 386 { 387 0, 0, "6x86", 0, 388 "MMX-enhanced MediaGX (GXm)", /* or Geode? */ 389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 390 "6x86" /* Default */ 391 }, 392 cyrix6x86_cpu_setup, 393 NULL, 394 NULL, 395 }, 396 /* Family 6 */ 397 { 398 CPUCLASS_686, 399 { 400 "6x86MX", 0, 0, 0, 0, 0, 0, 0, 401 0, 0, 0, 0, 0, 0, 0, 0, 402 "6x86MX" /* Default */ 403 }, 404 cyrix6x86_cpu_setup, 405 NULL, 406 NULL, 407 }, 408 /* Family > 6 */ 409 { 410 CPUCLASS_686, 411 { 412 0, 0, 0, 0, 0, 0, 0, 0, 413 0, 0, 0, 0, 0, 0, 0, 0, 414 "Unknown 6x86MX" /* Default */ 415 }, 416 NULL, 417 NULL, 418 NULL, 419 } } 420 }, 421 { /* MediaGX is now owned by National Semiconductor */ 422 "Geode by NSC", 423 CPUVENDOR_CYRIX, /* XXX */ 424 "National Semiconductor", 425 /* Family 4, NSC never had any of these */ 426 { { 427 CPUCLASS_486, 428 { 429 0, 0, 0, 0, 0, 0, 0, 0, 430 0, 0, 0, 0, 0, 0, 0, 0, 431 "486 compatible" /* Default */ 432 }, 433 NULL, 434 NULL, 435 NULL, 436 }, 437 /* Family 5: Geode family, formerly MediaGX */ 438 { 439 CPUCLASS_586, 440 { 441 0, 0, 0, 0, 442 "Geode GX1", 443 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444 "Geode" /* Default */ 445 }, 446 cyrix6x86_cpu_setup, 447 NULL, 448 amd_cpu_cacheinfo, 449 }, 450 /* Family 6, not yet available from NSC */ 451 { 452 CPUCLASS_686, 453 { 454 0, 0, 0, 0, 0, 0, 0, 0, 455 0, 0, 0, 0, 0, 0, 0, 0, 456 "Pentium Pro compatible" /* Default */ 457 }, 458 NULL, 459 NULL, 460 NULL, 461 }, 462 /* Family > 6, not yet available from NSC */ 463 { 464 CPUCLASS_686, 465 { 466 0, 0, 0, 0, 0, 0, 0, 0, 467 0, 0, 0, 0, 0, 0, 0, 0, 468 "Pentium Pro compatible" /* Default */ 469 }, 470 NULL, 471 NULL, 472 NULL, 473 } } 474 }, 475 { 476 "CentaurHauls", 477 CPUVENDOR_IDT, 478 "IDT", 479 /* Family 4, IDT never had any of these */ 480 { { 481 CPUCLASS_486, 482 { 483 0, 0, 0, 0, 0, 0, 0, 0, 484 0, 0, 0, 0, 0, 0, 0, 0, 485 "486 compatible" /* Default */ 486 }, 487 NULL, 488 NULL, 489 NULL, 490 }, 491 /* Family 5 */ 492 { 493 CPUCLASS_586, 494 { 495 0, 0, 0, 0, "WinChip C6", 0, 0, 0, 496 "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0, 497 "WinChip" /* Default */ 498 }, 499 winchip_cpu_setup, 500 NULL, 501 NULL, 502 }, 503 /* Family 6, VIA acquired IDT Centaur design subsidiary */ 504 { 505 CPUCLASS_686, 506 { 507 0, 0, 0, 0, 0, 0, "C3 Samuel", 508 "C3 Samuel 2/Ezra", "C3 Ezra-T", 509 "C3 Nehemiah", "C7 Esther", 0, 0, 0, 0, 0, 510 "C3" /* Default */ 511 }, 512 NULL, 513 via_cpu_probe, 514 via_cpu_cacheinfo, 515 }, 516 /* Family > 6, not yet available from VIA */ 517 { 518 CPUCLASS_686, 519 { 520 0, 0, 0, 0, 0, 0, 0, 0, 521 0, 0, 0, 0, 0, 0, 0, 0, 522 "Pentium Pro compatible" /* Default */ 523 }, 524 NULL, 525 NULL, 526 NULL, 527 } } 528 }, 529 { 530 "GenuineTMx86", 531 CPUVENDOR_TRANSMETA, 532 "Transmeta", 533 /* Family 4, Transmeta never had any of these */ 534 { { 535 CPUCLASS_486, 536 { 537 0, 0, 0, 0, 0, 0, 0, 0, 538 0, 0, 0, 0, 0, 0, 0, 0, 539 "486 compatible" /* Default */ 540 }, 541 NULL, 542 NULL, 543 NULL, 544 }, 545 /* Family 5 */ 546 { 547 CPUCLASS_586, 548 { 549 0, 0, 0, 0, 0, 0, 0, 0, 550 0, 0, 0, 0, 0, 0, 0, 0, 551 "Crusoe" /* Default */ 552 }, 553 NULL, 554 NULL, 555 transmeta_cpu_info, 556 }, 557 /* Family 6, not yet available from Transmeta */ 558 { 559 CPUCLASS_686, 560 { 561 0, 0, 0, 0, 0, 0, 0, 0, 562 0, 0, 0, 0, 0, 0, 0, 0, 563 "Pentium Pro compatible" /* Default */ 564 }, 565 NULL, 566 NULL, 567 NULL, 568 }, 569 /* Family > 6, not yet available from Transmeta */ 570 { 571 CPUCLASS_686, 572 { 573 0, 0, 0, 0, 0, 0, 0, 0, 574 0, 0, 0, 0, 0, 0, 0, 0, 575 "Pentium Pro compatible" /* Default */ 576 }, 577 NULL, 578 NULL, 579 NULL, 580 } } 581 } 582 }; 583 584 /* 585 * disable the TSC such that we don't use the TSC in microtime(9) 586 * because some CPUs got the implementation wrong. 587 */ 588 static void 589 disable_tsc(struct cpu_info *ci) 590 { 591 if (ci->ci_feature_flags & CPUID_TSC) { 592 ci->ci_feature_flags &= ~CPUID_TSC; 593 aprint_error("WARNING: broken TSC disabled\n"); 594 } 595 } 596 597 static void 598 cyrix6x86_cpu_setup(struct cpu_info *ci) 599 { 600 601 /* 602 * Do not disable the TSC on the Geode GX, it's reported to 603 * work fine. 604 */ 605 if (ci->ci_signature != 0x552) 606 disable_tsc(ci); 607 } 608 609 void 610 winchip_cpu_setup(struct cpu_info *ci) 611 { 612 switch (CPUID2MODEL(ci->ci_signature)) { /* model */ 613 case 4: /* WinChip C6 */ 614 disable_tsc(ci); 615 } 616 } 617 618 619 static void 620 identifycpu_cpuids(struct cpu_info *ci) 621 { 622 const char *cpuname = ci->ci_dev; 623 u_int lp_max = 1; /* logical processors per package */ 624 u_int smt_max; /* smt per core */ 625 u_int core_max = 1; /* core per package */ 626 int smt_bits, core_bits; 627 uint32_t descs[4]; 628 629 aprint_verbose("%s: Initial APIC ID %u\n", cpuname, ci->ci_initapicid); 630 ci->ci_packageid = ci->ci_initapicid; 631 ci->ci_coreid = 0; 632 ci->ci_smtid = 0; 633 if (cpu_vendor != CPUVENDOR_INTEL) { 634 return; 635 } 636 637 /* 638 * 253668.pdf 7.10.2 639 */ 640 641 if ((ci->ci_feature_flags & CPUID_HTT) != 0) { 642 x86_cpuid(1, descs); 643 lp_max = (descs[1] >> 16) & 0xff; 644 } 645 x86_cpuid(0, descs); 646 if (descs[0] >= 4) { 647 x86_cpuid2(4, 0, descs); 648 core_max = (descs[0] >> 26) + 1; 649 } 650 assert(lp_max >= core_max); 651 smt_max = lp_max / core_max; 652 smt_bits = ilog2(smt_max - 1) + 1; 653 core_bits = ilog2(core_max - 1) + 1; 654 if (smt_bits + core_bits) { 655 ci->ci_packageid = ci->ci_initapicid >> (smt_bits + core_bits); 656 } 657 aprint_verbose("%s: Cluster/Package ID %u\n", cpuname, 658 ci->ci_packageid); 659 if (core_bits) { 660 u_int core_mask = __BITS(smt_bits, smt_bits + core_bits - 1); 661 662 ci->ci_coreid = 663 __SHIFTOUT(ci->ci_initapicid, core_mask); 664 aprint_verbose("%s: Core ID %u\n", cpuname, ci->ci_coreid); 665 } 666 if (smt_bits) { 667 u_int smt_mask = __BITS(0, smt_bits - 1); 668 669 ci->ci_smtid = __SHIFTOUT(ci->ci_initapicid, smt_mask); 670 aprint_verbose("%s: SMT ID %u\n", cpuname, ci->ci_smtid); 671 } 672 } 673 674 static void 675 via_cpu_probe(struct cpu_info *ci) 676 { 677 u_int model = CPUID2MODEL(ci->ci_signature); 678 u_int stepping = CPUID2STEPPING(ci->ci_signature); 679 u_int descs[4]; 680 u_int lfunc; 681 682 /* 683 * Determine the largest extended function value. 684 */ 685 x86_cpuid(0x80000000, descs); 686 lfunc = descs[0]; 687 688 /* 689 * Determine the extended feature flags. 690 */ 691 if (lfunc >= 0x80000001) { 692 x86_cpuid(0x80000001, descs); 693 ci->ci_feature_flags |= descs[3]; 694 } 695 696 if (model < 0x9) 697 return; 698 699 /* Nehemiah or Esther */ 700 x86_cpuid(0xc0000000, descs); 701 lfunc = descs[0]; 702 if (lfunc < 0xc0000001) /* no ACE, no RNG */ 703 return; 704 705 x86_cpuid(0xc0000001, descs); 706 lfunc = descs[3]; 707 if (model > 0x9 || stepping >= 8) { /* ACE */ 708 if (lfunc & CPUID_VIA_HAS_ACE) { 709 ci->ci_padlock_flags = lfunc; 710 } 711 } 712 } 713 714 static const char * 715 intel_family6_name(struct cpu_info *ci) 716 { 717 int model = CPUID2MODEL(ci->ci_signature); 718 const char *ret = NULL; 719 u_int l2cache = ci->ci_cinfo[CAI_L2CACHE].cai_totalsize; 720 721 if (model == 5) { 722 switch (l2cache) { 723 case 0: 724 case 128 * 1024: 725 ret = "Celeron (Covington)"; 726 break; 727 case 256 * 1024: 728 ret = "Mobile Pentium II (Dixon)"; 729 break; 730 case 512 * 1024: 731 ret = "Pentium II"; 732 break; 733 case 1 * 1024 * 1024: 734 case 2 * 1024 * 1024: 735 ret = "Pentium II Xeon"; 736 break; 737 } 738 } else if (model == 6) { 739 switch (l2cache) { 740 case 256 * 1024: 741 case 512 * 1024: 742 ret = "Mobile Pentium II"; 743 break; 744 } 745 } else if (model == 7) { 746 switch (l2cache) { 747 case 512 * 1024: 748 ret = "Pentium III"; 749 break; 750 case 1 * 1024 * 1024: 751 case 2 * 1024 * 1024: 752 ret = "Pentium III Xeon"; 753 break; 754 } 755 } else if (model >= 8) { 756 if (ci->ci_brand_id && ci->ci_brand_id < 0x10) { 757 switch (ci->ci_brand_id) { 758 case 0x3: 759 if (ci->ci_signature == 0x6B1) 760 ret = "Celeron"; 761 break; 762 case 0x8: 763 if (ci->ci_signature >= 0xF13) 764 ret = "genuine processor"; 765 break; 766 case 0xB: 767 if (ci->ci_signature >= 0xF13) 768 ret = "Xeon MP"; 769 break; 770 case 0xE: 771 if (ci->ci_signature < 0xF13) 772 ret = "Xeon"; 773 break; 774 } 775 if (ret == NULL) 776 ret = i386_intel_brand[ci->ci_brand_id]; 777 } 778 } 779 780 return ret; 781 } 782 783 /* 784 * Identify AMD64 CPU names from cpuid. 785 * 786 * Based on: 787 * "Revision Guide for AMD Athlon 64 and AMD Opteron Processors" 788 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf 789 * "Revision Guide for AMD NPT Family 0Fh Processors" 790 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf 791 * and other miscellaneous reports. 792 */ 793 static const char * 794 amd_amd64_name(struct cpu_info *ci) 795 { 796 int extfamily, extmodel, model; 797 const char *ret = NULL; 798 799 model = CPUID2MODEL(ci->ci_signature); 800 extfamily = CPUID2EXTFAMILY(ci->ci_signature); 801 extmodel = CPUID2EXTMODEL(ci->ci_signature); 802 803 switch (extfamily) { 804 case 0x00: 805 switch (model) { 806 case 0x1: 807 switch (extmodel) { 808 case 0x2: /* rev JH-E1/E6 */ 809 case 0x4: /* rev JH-F2 */ 810 ret = "Dual-Core Opteron"; 811 break; 812 } 813 break; 814 case 0x3: 815 switch (extmodel) { 816 case 0x2: /* rev JH-E6 (Toledo) */ 817 ret = "Dual-Core Opteron or Athlon 64 X2"; 818 break; 819 case 0x4: /* rev JH-F2 (Windsor) */ 820 ret = "Athlon 64 FX or Athlon 64 X2"; 821 break; 822 } 823 break; 824 case 0x4: 825 switch (extmodel) { 826 case 0x0: /* rev SH-B0/C0/CG (ClawHammer) */ 827 case 0x1: /* rev SH-D0 */ 828 ret = "Athlon 64"; 829 break; 830 case 0x2: /* rev SH-E5 (Lancaster?) */ 831 ret = "Mobile Athlon 64 or Turion 64"; 832 break; 833 } 834 break; 835 case 0x5: 836 switch (extmodel) { 837 case 0x0: /* rev SH-B0/B3/C0/CG (SledgeHammer?) */ 838 ret = "Opteron or Athlon 64 FX"; 839 break; 840 case 0x1: /* rev SH-D0 */ 841 case 0x2: /* rev SH-E4 */ 842 ret = "Opteron"; 843 break; 844 } 845 break; 846 case 0x7: 847 switch (extmodel) { 848 case 0x0: /* rev SH-CG (ClawHammer) */ 849 case 0x1: /* rev SH-D0 */ 850 ret = "Athlon 64"; 851 break; 852 case 0x2: /* rev DH-E4, SH-E4 */ 853 ret = "Athlon 64 or Athlon 64 FX or Opteron"; 854 break; 855 } 856 break; 857 case 0x8: 858 switch (extmodel) { 859 case 0x0: /* rev CH-CG */ 860 case 0x1: /* rev CH-D0 */ 861 ret = "Athlon 64 or Sempron"; 862 break; 863 case 0x4: /* rev BH-F2 */ 864 ret = "Turion 64 X2"; 865 break; 866 } 867 break; 868 case 0xb: 869 switch (extmodel) { 870 case 0x0: /* rev CH-CG */ 871 case 0x1: /* rev CH-D0 */ 872 ret = "Athlon 64"; 873 break; 874 case 0x2: /* rev BH-E4 (Manchester) */ 875 case 0x4: /* rev BH-F2 (Windsor) */ 876 ret = "Athlon 64 X2"; 877 break; 878 case 0x6: /* rev BH-G1 (Brisbane) */ 879 ret = "Athlon X2 or Athlon 64 X2"; 880 break; 881 } 882 break; 883 case 0xc: 884 switch (extmodel) { 885 case 0x0: /* rev DH-CG (Newcastle) */ 886 case 0x1: /* rev DH-D0 (Winchester) */ 887 case 0x2: /* rev DH-E3/E6 */ 888 ret = "Athlon 64 or Sempron"; 889 break; 890 } 891 break; 892 case 0xe: 893 switch (extmodel) { 894 case 0x0: /* rev DH-CG (Newcastle?) */ 895 ret = "Athlon 64 or Sempron"; 896 break; 897 } 898 break; 899 case 0xf: 900 switch (extmodel) { 901 case 0x0: /* rev DH-CG (Newcastle/Paris) */ 902 case 0x1: /* rev DH-D0 (Winchester/Victoria) */ 903 case 0x2: /* rev DH-E3/E6 (Venice/Palermo) */ 904 case 0x4: /* rev DH-F2 (Orleans/Manila) */ 905 case 0x5: /* rev DH-F2 (Orleans/Manila) */ 906 case 0x6: /* rev DH-G1 */ 907 ret = "Athlon 64 or Sempron"; 908 break; 909 } 910 break; 911 default: 912 ret = "Unknown AMD64 CPU"; 913 } 914 break; 915 case 0x01: 916 switch (model) { 917 case 0x02: 918 ret = "Family 10h"; 919 break; 920 default: 921 ret = "Unknown AMD64 CPU"; 922 break; 923 } 924 break; 925 } 926 927 return ret; 928 } 929 930 static void 931 cpu_probe_base_features(struct cpu_info *ci) 932 { 933 const struct x86_cache_info *cai; 934 u_int descs[4]; 935 int iterations, i, j; 936 uint8_t desc; 937 uint32_t miscbytes; 938 uint32_t brand[12]; 939 940 if (ci->ci_cpuid_level < 0) 941 return; 942 943 x86_cpuid(0, descs); 944 ci->ci_cpuid_level = descs[0]; 945 ci->ci_vendor[0] = descs[1]; 946 ci->ci_vendor[2] = descs[2]; 947 ci->ci_vendor[1] = descs[3]; 948 ci->ci_vendor[3] = 0; 949 950 x86_cpuid(0x80000000, brand); 951 if (brand[0] >= 0x80000004) { 952 x86_cpuid(0x80000002, brand); 953 x86_cpuid(0x80000003, brand + 4); 954 x86_cpuid(0x80000004, brand + 8); 955 for (i = 0; i < 48; i++) 956 if (((char *) brand)[i] != ' ') 957 break; 958 memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); 959 } 960 961 if (ci->ci_cpuid_level < 1) 962 return; 963 964 x86_cpuid(1, descs); 965 ci->ci_signature = descs[0]; 966 miscbytes = descs[1]; 967 ci->ci_feature2_flags = descs[2]; 968 ci->ci_feature_flags = descs[3]; 969 970 /* Brand is low order 8 bits of ebx */ 971 ci->ci_brand_id = miscbytes & 0xff; 972 ci->ci_initapicid = (miscbytes >> 24) & 0xff; 973 if (ci->ci_cpuid_level < 2) 974 return; 975 976 /* 977 * Parse the cache info from `cpuid', if we have it. 978 * XXX This is kinda ugly, but hey, so is the architecture... 979 */ 980 981 x86_cpuid(2, descs); 982 983 iterations = descs[0] & 0xff; 984 while (iterations-- > 0) { 985 for (i = 0; i < 4; i++) { 986 if (descs[i] & 0x80000000) 987 continue; 988 for (j = 0; j < 4; j++) { 989 if (i == 0 && j == 0) 990 continue; 991 desc = (descs[i] >> (j * 8)) & 0xff; 992 if (desc == 0) 993 continue; 994 cai = cache_info_lookup(intel_cpuid_cache_info, 995 desc); 996 if (cai != NULL) 997 ci->ci_cinfo[cai->cai_index] = *cai; 998 } 999 } 1000 x86_cpuid(2, descs); 1001 } 1002 1003 if (ci->ci_cpuid_level < 3) 1004 return; 1005 1006 /* 1007 * If the processor serial number misfeature is present and supported, 1008 * extract it here. 1009 */ 1010 if ((ci->ci_feature_flags & CPUID_PN) != 0) { 1011 ci->ci_cpu_serial[0] = ci->ci_signature; 1012 x86_cpuid(3, descs); 1013 ci->ci_cpu_serial[2] = descs[2]; 1014 ci->ci_cpu_serial[1] = descs[3]; 1015 } 1016 } 1017 1018 static void 1019 cpu_probe_features(struct cpu_info *ci) 1020 { 1021 const struct cpu_cpuid_nameclass *cpup = NULL; 1022 int i, xmax, family; 1023 1024 cpu_probe_base_features(ci); 1025 1026 if (ci->ci_cpuid_level < 1) 1027 return; 1028 1029 xmax = __arraycount(i386_cpuid_cpus); 1030 for (i = 0; i < xmax; i++) { 1031 if (!strncmp((char *)ci->ci_vendor, 1032 i386_cpuid_cpus[i].cpu_id, 12)) { 1033 cpup = &i386_cpuid_cpus[i]; 1034 break; 1035 } 1036 } 1037 1038 if (cpup == NULL) 1039 return; 1040 1041 family = (ci->ci_signature >> 8) & 0xf; 1042 1043 if (family > CPU_MAXFAMILY) { 1044 family = CPU_MAXFAMILY; 1045 } 1046 i = family - CPU_MINFAMILY; 1047 1048 if (cpup->cpu_family[i].cpu_probe == NULL) 1049 return; 1050 1051 (*cpup->cpu_family[i].cpu_probe)(ci); 1052 } 1053 1054 static void 1055 intel_family_new_probe(struct cpu_info *ci) 1056 { 1057 uint32_t descs[4]; 1058 1059 x86_cpuid(0x80000000, descs); 1060 1061 /* 1062 * Determine extended feature flags. 1063 */ 1064 if (descs[0] >= 0x80000001) { 1065 x86_cpuid(0x80000001, descs); 1066 ci->ci_feature3_flags |= descs[3]; 1067 } 1068 } 1069 1070 static void 1071 amd_family6_probe(struct cpu_info *ci) 1072 { 1073 uint32_t descs[4]; 1074 char *p; 1075 int i; 1076 1077 x86_cpuid(0x80000000, descs); 1078 1079 /* 1080 * Determine the extended feature flags. 1081 */ 1082 if (descs[0] >= 0x80000001) { 1083 x86_cpuid(0x80000001, descs); 1084 ci->ci_feature_flags |= descs[3]; 1085 } 1086 1087 if (*cpu_brand_string == '\0') 1088 return; 1089 1090 for (i = 1; i < __arraycount(amd_brand); i++) 1091 if ((p = strstr(cpu_brand_string, amd_brand[i])) != NULL) { 1092 ci->ci_brand_id = i; 1093 strlcpy(amd_brand_name, p, sizeof(amd_brand_name)); 1094 break; 1095 } 1096 } 1097 1098 static void 1099 amd_family5_setup(struct cpu_info *ci) 1100 { 1101 1102 switch (CPUID2MODEL(ci->ci_signature)) { 1103 case 0: /* AMD-K5 Model 0 */ 1104 /* 1105 * According to the AMD Processor Recognition App Note, 1106 * the AMD-K5 Model 0 uses the wrong bit to indicate 1107 * support for global PTEs, instead using bit 9 (APIC) 1108 * rather than bit 13 (i.e. "0x200" vs. 0x2000". Oops!). 1109 */ 1110 if (ci->ci_feature_flags & CPUID_APIC) 1111 ci->ci_feature_flags = (ci->ci_feature_flags & ~CPUID_APIC) | CPUID_PGE; 1112 /* 1113 * XXX But pmap_pg_g is already initialized -- need to kick 1114 * XXX the pmap somehow. How does the MP branch do this? 1115 */ 1116 break; 1117 } 1118 } 1119 1120 static void 1121 tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage) 1122 { 1123 u_int descs[4]; 1124 1125 x86_cpuid(0x80860007, descs); 1126 *frequency = descs[0]; 1127 *voltage = descs[1]; 1128 *percentage = descs[2]; 1129 } 1130 1131 static void 1132 transmeta_cpu_info(struct cpu_info *ci) 1133 { 1134 u_int descs[4], nreg; 1135 u_int frequency, voltage, percentage; 1136 1137 x86_cpuid(0x80860000, descs); 1138 nreg = descs[0]; 1139 if (nreg >= 0x80860001) { 1140 x86_cpuid(0x80860001, descs); 1141 aprint_verbose_dev(ci->ci_dev, "Processor revision %u.%u.%u.%u\n", 1142 (descs[1] >> 24) & 0xff, 1143 (descs[1] >> 16) & 0xff, 1144 (descs[1] >> 8) & 0xff, 1145 descs[1] & 0xff); 1146 } 1147 if (nreg >= 0x80860002) { 1148 x86_cpuid(0x80860002, descs); 1149 aprint_verbose_dev(ci->ci_dev, "Code Morphing Software Rev: %u.%u.%u-%u-%u\n", 1150 (descs[1] >> 24) & 0xff, 1151 (descs[1] >> 16) & 0xff, 1152 (descs[1] >> 8) & 0xff, 1153 descs[1] & 0xff, 1154 descs[2]); 1155 } 1156 if (nreg >= 0x80860006) { 1157 union { 1158 char text[65]; 1159 u_int descs[4][4]; 1160 } info; 1161 int i; 1162 1163 for (i=0; i<4; i++) { 1164 x86_cpuid(0x80860003 + i, info.descs[i]); 1165 } 1166 info.text[64] = '\0'; 1167 aprint_verbose_dev(ci->ci_dev, "%s\n", info.text); 1168 } 1169 1170 if (nreg >= 0x80860007) { 1171 tmx86_get_longrun_status(&frequency, 1172 &voltage, &percentage); 1173 aprint_verbose_dev(ci->ci_dev, "LongRun <%dMHz %dmV %d%%>\n", 1174 frequency, voltage, percentage); 1175 } 1176 } 1177 1178 void 1179 identifycpu(const char *cpuname) 1180 { 1181 const char *name, *modifier, *vendorname, *brand = ""; 1182 int class = CPUCLASS_386, i, xmax; 1183 int modif, family, model; 1184 const struct cpu_cpuid_nameclass *cpup = NULL; 1185 const struct cpu_cpuid_family *cpufam; 1186 char *buf; 1187 const char *feature_str[3]; 1188 struct cpu_info *ci, cistore; 1189 extern int cpu; 1190 extern int cpu_info_level; 1191 size_t sz; 1192 1193 ci = &cistore; 1194 memset(ci, 0, sizeof(*ci)); 1195 ci->ci_dev = cpuname; 1196 1197 x86_identify(); 1198 ci->ci_cpuid_level = cpu_info_level; 1199 cpu_probe_features(ci); 1200 1201 buf = malloc(MAXPATHLEN); 1202 if (ci->ci_cpuid_level == -1) { 1203 if (cpu < 0 || cpu >= __arraycount(i386_nocpuid_cpus)) 1204 errx(1, "unknown cpu type %d", cpu); 1205 name = i386_nocpuid_cpus[cpu].cpu_name; 1206 cpu_vendor = i386_nocpuid_cpus[cpu].cpu_vendor; 1207 vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname; 1208 class = i386_nocpuid_cpus[cpu].cpu_class; 1209 ci->ci_info = i386_nocpuid_cpus[cpu].cpu_info; 1210 modifier = ""; 1211 } else { 1212 xmax = __arraycount(i386_cpuid_cpus); 1213 modif = (ci->ci_signature >> 12) & 0x3; 1214 family = CPUID2FAMILY(ci->ci_signature); 1215 if (family < CPU_MINFAMILY) 1216 errx(1, "identifycpu: strange family value"); 1217 model = CPUID2MODEL(ci->ci_signature); 1218 1219 for (i = 0; i < xmax; i++) { 1220 if (!strncmp((char *)ci->ci_vendor, 1221 i386_cpuid_cpus[i].cpu_id, 12)) { 1222 cpup = &i386_cpuid_cpus[i]; 1223 break; 1224 } 1225 } 1226 1227 if (cpup == NULL) { 1228 cpu_vendor = CPUVENDOR_UNKNOWN; 1229 if (ci->ci_vendor[0] != '\0') 1230 vendorname = (char *)&ci->ci_vendor[0]; 1231 else 1232 vendorname = "Unknown"; 1233 if (family >= CPU_MAXFAMILY) 1234 family = CPU_MINFAMILY; 1235 class = family - 3; 1236 modifier = ""; 1237 name = ""; 1238 ci->ci_info = NULL; 1239 } else { 1240 cpu_vendor = cpup->cpu_vendor; 1241 vendorname = cpup->cpu_vendorname; 1242 modifier = modifiers[modif]; 1243 if (family > CPU_MAXFAMILY) { 1244 family = CPU_MAXFAMILY; 1245 model = CPU_DEFMODEL; 1246 } else if (model > CPU_MAXMODEL) 1247 model = CPU_DEFMODEL; 1248 cpufam = &cpup->cpu_family[family - CPU_MINFAMILY]; 1249 name = cpufam->cpu_models[model]; 1250 if (name == NULL) 1251 name = cpufam->cpu_models[CPU_DEFMODEL]; 1252 class = cpufam->cpu_class; 1253 ci->ci_info = cpufam->cpu_info; 1254 1255 if (cpu_vendor == CPUVENDOR_INTEL) { 1256 if (family == 6 && model >= 5) { 1257 const char *tmp; 1258 tmp = intel_family6_name(ci); 1259 if (tmp != NULL) 1260 name = tmp; 1261 } 1262 if (family == CPU_MAXFAMILY && 1263 ci->ci_brand_id < 1264 __arraycount(i386_intel_brand) && 1265 i386_intel_brand[ci->ci_brand_id]) 1266 name = 1267 i386_intel_brand[ci->ci_brand_id]; 1268 } 1269 1270 if (cpu_vendor == CPUVENDOR_AMD) { 1271 if (family == 6 && model >= 6) { 1272 if (ci->ci_brand_id == 1) 1273 /* 1274 * It's Duron. We override the 1275 * name, since it might have 1276 * been misidentified as Athlon. 1277 */ 1278 name = 1279 amd_brand[ci->ci_brand_id]; 1280 else 1281 brand = amd_brand_name; 1282 } 1283 if (CPUID2FAMILY(ci->ci_signature) == 0xf) { 1284 /* 1285 * Identify AMD64 CPU names. 1286 * Note family value is clipped by 1287 * CPU_MAXFAMILY. 1288 */ 1289 const char *tmp; 1290 tmp = amd_amd64_name(ci); 1291 if (tmp != NULL) 1292 name = tmp; 1293 } 1294 } 1295 1296 if (cpu_vendor == CPUVENDOR_IDT && family >= 6) 1297 vendorname = "VIA"; 1298 } 1299 } 1300 1301 ci->ci_cpu_class = class; 1302 1303 sz = sizeof(ci->ci_tsc_freq); 1304 (void)sysctlbyname("machdep.tsc_freq", &ci->ci_tsc_freq, &sz, NULL, 0); 1305 1306 snprintf(cpu_model, sizeof(cpu_model), "%s%s%s%s%s%s%s (%s-class)", 1307 vendorname, 1308 *modifier ? " " : "", modifier, 1309 *name ? " " : "", name, 1310 *brand ? " " : "", brand, 1311 classnames[class]); 1312 aprint_normal("%s: %s", cpuname, cpu_model); 1313 1314 if (ci->ci_tsc_freq != 0) 1315 aprint_normal(", %qd.%02qd MHz", 1316 (ci->ci_tsc_freq + 4999) / 1000000, 1317 ((ci->ci_tsc_freq + 4999) / 10000) % 100); 1318 if (ci->ci_signature != 0) 1319 aprint_normal(", id 0x%x", ci->ci_signature); 1320 aprint_normal("\n"); 1321 1322 if (ci->ci_info) 1323 (*ci->ci_info)(ci); 1324 1325 if (cpu_vendor == CPUVENDOR_INTEL) { 1326 feature_str[0] = CPUID_FLAGS1; 1327 feature_str[1] = CPUID_FLAGS2; 1328 feature_str[2] = CPUID_FLAGS3; 1329 } else { 1330 feature_str[0] = CPUID_FLAGS1; 1331 feature_str[1] = CPUID_EXT_FLAGS2; 1332 feature_str[2] = CPUID_EXT_FLAGS3; 1333 } 1334 1335 if (ci->ci_feature_flags) { 1336 if ((ci->ci_feature_flags & CPUID_MASK1) != 0) { 1337 bitmask_snprintf(ci->ci_feature_flags, 1338 feature_str[0], buf, MAXPATHLEN); 1339 aprint_verbose("%s: features %s\n", cpuname, buf); 1340 } 1341 if ((ci->ci_feature_flags & CPUID_MASK2) != 0) { 1342 bitmask_snprintf(ci->ci_feature_flags, 1343 feature_str[1], buf, MAXPATHLEN); 1344 aprint_verbose("%s: features %s\n", cpuname, buf); 1345 } 1346 if ((ci->ci_feature_flags & CPUID_MASK3) != 0) { 1347 bitmask_snprintf(ci->ci_feature_flags, 1348 feature_str[2], buf, MAXPATHLEN); 1349 aprint_verbose("%s: features %s\n", cpuname, buf); 1350 } 1351 } 1352 1353 if (ci->ci_feature2_flags) { 1354 bitmask_snprintf(ci->ci_feature2_flags, 1355 CPUID2_FLAGS, buf, MAXPATHLEN); 1356 aprint_verbose("%s: features2 %s\n", cpuname, buf); 1357 } 1358 1359 if (ci->ci_feature3_flags) { 1360 bitmask_snprintf(ci->ci_feature3_flags, 1361 CPUID_FLAGS4, buf, MAXPATHLEN); 1362 aprint_verbose("%s: features3 %s\n", cpuname, buf); 1363 } 1364 1365 if (ci->ci_padlock_flags) { 1366 bitmask_snprintf(ci->ci_padlock_flags, 1367 CPUID_FLAGS_PADLOCK, buf, MAXPATHLEN); 1368 aprint_verbose("%s: padlock features %s\n", cpuname, buf); 1369 } 1370 1371 free(buf); 1372 1373 if (*cpu_brand_string != '\0') 1374 aprint_normal("%s: \"%s\"\n", cpuname, cpu_brand_string); 1375 1376 x86_print_cacheinfo(ci); 1377 1378 if (ci->ci_cpuid_level >= 3 && (ci->ci_feature_flags & CPUID_PN)) { 1379 aprint_verbose("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n", 1380 cpuname, 1381 ci->ci_cpu_serial[0] / 65536, ci->ci_cpu_serial[0] % 65536, 1382 ci->ci_cpu_serial[1] / 65536, ci->ci_cpu_serial[1] % 65536, 1383 ci->ci_cpu_serial[2] / 65536, ci->ci_cpu_serial[2] % 65536); 1384 } 1385 1386 if (ci->ci_cpu_class == CPUCLASS_386) { 1387 errx(1, "NetBSD requires an 80486 or later processor"); 1388 } 1389 1390 if (cpu == CPU_486DLC) { 1391 #ifndef CYRIX_CACHE_WORKS 1392 aprint_error("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n"); 1393 #else 1394 #ifndef CYRIX_CACHE_REALLY_WORKS 1395 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n"); 1396 #else 1397 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED.\n"); 1398 #endif 1399 #endif 1400 } 1401 1402 /* 1403 * Everything past this point requires a Pentium or later. 1404 */ 1405 if (ci->ci_cpuid_level < 0) 1406 return; 1407 1408 identifycpu_cpuids(ci); 1409 1410 #ifdef INTEL_CORETEMP 1411 if (cpu_vendor == CPUVENDOR_INTEL && ci->ci_cpuid_level >= 0x06) 1412 coretemp_register(ci); 1413 #endif 1414 1415 if (cpu_vendor == CPUVENDOR_AMD) { 1416 powernow_probe(ci); 1417 } 1418 1419 #ifdef INTEL_ONDEMAND_CLOCKMOD 1420 clockmod_init(); 1421 #endif 1422 1423 aprint_normal_dev(ci->ci_dev, "family %02x model %02x " 1424 "extfamily %02x extmodel %02x\n", CPUID2FAMILY(ci->ci_signature), 1425 CPUID2MODEL(ci->ci_signature), CPUID2EXTFAMILY(ci->ci_signature), 1426 CPUID2EXTMODEL(ci->ci_signature)); 1427 } 1428 1429 static const char * 1430 print_cache_config(struct cpu_info *ci, int cache_tag, const char *name, 1431 const char *sep) 1432 { 1433 struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag]; 1434 char human_num[HUMAN_BUFSIZE]; 1435 1436 if (cai->cai_totalsize == 0) 1437 return sep; 1438 1439 if (sep == NULL) 1440 aprint_verbose_dev(ci->ci_dev, ""); 1441 else 1442 aprint_verbose("%s", sep); 1443 if (name != NULL) 1444 aprint_verbose("%s ", name); 1445 1446 if (cai->cai_string != NULL) { 1447 aprint_verbose("%s ", cai->cai_string); 1448 } else { 1449 (void)humanize_number(human_num, sizeof(human_num), 1450 cai->cai_totalsize, "B", HN_AUTOSCALE, HN_NOSPACE); 1451 aprint_verbose("%s %dB/line ", human_num, cai->cai_linesize); 1452 } 1453 switch (cai->cai_associativity) { 1454 case 0: 1455 aprint_verbose("disabled"); 1456 break; 1457 case 1: 1458 aprint_verbose("direct-mapped"); 1459 break; 1460 case 0xff: 1461 aprint_verbose("fully associative"); 1462 break; 1463 default: 1464 aprint_verbose("%d-way", cai->cai_associativity); 1465 break; 1466 } 1467 return ", "; 1468 } 1469 1470 static const char * 1471 print_tlb_config(struct cpu_info *ci, int cache_tag, const char *name, 1472 const char *sep) 1473 { 1474 struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag]; 1475 char human_num[HUMAN_BUFSIZE]; 1476 1477 if (cai->cai_totalsize == 0) 1478 return sep; 1479 1480 if (sep == NULL) 1481 aprint_verbose_dev(ci->ci_dev, ""); 1482 else 1483 aprint_verbose("%s", sep); 1484 if (name != NULL) 1485 aprint_verbose("%s ", name); 1486 1487 if (cai->cai_string != NULL) { 1488 aprint_verbose("%s", cai->cai_string); 1489 } else { 1490 (void)humanize_number(human_num, sizeof(human_num), 1491 cai->cai_linesize, "B", HN_AUTOSCALE, HN_NOSPACE); 1492 aprint_verbose("%d %s entries ", cai->cai_totalsize, 1493 human_num); 1494 switch (cai->cai_associativity) { 1495 case 0: 1496 aprint_verbose("disabled"); 1497 break; 1498 case 1: 1499 aprint_verbose("direct-mapped"); 1500 break; 1501 case 0xff: 1502 aprint_verbose("fully associative"); 1503 break; 1504 default: 1505 aprint_verbose("%d-way", cai->cai_associativity); 1506 break; 1507 } 1508 } 1509 return ", "; 1510 } 1511 1512 static const struct x86_cache_info * 1513 cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc) 1514 { 1515 int i; 1516 1517 for (i = 0; cai[i].cai_desc != 0; i++) { 1518 if (cai[i].cai_desc == desc) 1519 return (&cai[i]); 1520 } 1521 1522 return (NULL); 1523 } 1524 1525 static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = 1526 AMD_L2CACHE_INFO; 1527 1528 static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] = 1529 AMD_L3CACHE_INFO; 1530 1531 static void 1532 amd_cpu_cacheinfo(struct cpu_info *ci) 1533 { 1534 const struct x86_cache_info *cp; 1535 struct x86_cache_info *cai; 1536 int family, model; 1537 u_int descs[4]; 1538 u_int lfunc; 1539 1540 family = (ci->ci_signature >> 8) & 15; 1541 model = CPUID2MODEL(ci->ci_signature); 1542 1543 /* 1544 * K5 model 0 has none of this info. 1545 */ 1546 if (family == 5 && model == 0) 1547 return; 1548 1549 /* 1550 * Get extended values for K8 and up. 1551 */ 1552 if (family == 0xf) { 1553 family += CPUID2EXTFAMILY(ci->ci_signature); 1554 model += CPUID2EXTMODEL(ci->ci_signature); 1555 } 1556 1557 /* 1558 * Determine the largest extended function value. 1559 */ 1560 x86_cpuid(0x80000000, descs); 1561 lfunc = descs[0]; 1562 1563 /* 1564 * Determine L1 cache/TLB info. 1565 */ 1566 if (lfunc < 0x80000005) { 1567 /* No L1 cache info available. */ 1568 return; 1569 } 1570 1571 x86_cpuid(0x80000005, descs); 1572 1573 /* 1574 * K6-III and higher have large page TLBs. 1575 */ 1576 if ((family == 5 && model >= 9) || family >= 6) { 1577 cai = &ci->ci_cinfo[CAI_ITLB2]; 1578 cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]); 1579 cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]); 1580 cai->cai_linesize = (4 * 1024 * 1024); 1581 1582 cai = &ci->ci_cinfo[CAI_DTLB2]; 1583 cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]); 1584 cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]); 1585 cai->cai_linesize = (4 * 1024 * 1024); 1586 } 1587 1588 cai = &ci->ci_cinfo[CAI_ITLB]; 1589 cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]); 1590 cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]); 1591 cai->cai_linesize = (4 * 1024); 1592 1593 cai = &ci->ci_cinfo[CAI_DTLB]; 1594 cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]); 1595 cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]); 1596 cai->cai_linesize = (4 * 1024); 1597 1598 cai = &ci->ci_cinfo[CAI_DCACHE]; 1599 cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]); 1600 cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]); 1601 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]); 1602 1603 cai = &ci->ci_cinfo[CAI_ICACHE]; 1604 cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]); 1605 cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]); 1606 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]); 1607 1608 /* 1609 * Determine L2 cache/TLB info. 1610 */ 1611 if (lfunc < 0x80000006) { 1612 /* No L2 cache info available. */ 1613 return; 1614 } 1615 1616 x86_cpuid(0x80000006, descs); 1617 1618 cai = &ci->ci_cinfo[CAI_L2CACHE]; 1619 cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]); 1620 cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]); 1621 cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]); 1622 1623 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1624 cai->cai_associativity); 1625 if (cp != NULL) 1626 cai->cai_associativity = cp->cai_associativity; 1627 else 1628 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1629 1630 /* 1631 * Determine L3 cache info on AMD Family 10h processors 1632 */ 1633 if (family == 0x10) { 1634 cai = &ci->ci_cinfo[CAI_L3CACHE]; 1635 cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]); 1636 cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]); 1637 cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]); 1638 1639 cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info, 1640 cai->cai_associativity); 1641 if (cp != NULL) 1642 cai->cai_associativity = cp->cai_associativity; 1643 else 1644 cai->cai_associativity = 0; /* XXX Unkn/Rsvd */ 1645 } 1646 } 1647 1648 static void 1649 via_cpu_cacheinfo(struct cpu_info *ci) 1650 { 1651 struct x86_cache_info *cai; 1652 int family, model, stepping; 1653 u_int descs[4]; 1654 u_int lfunc; 1655 1656 family = (ci->ci_signature >> 8) & 15; 1657 model = CPUID2MODEL(ci->ci_signature); 1658 stepping = CPUID2STEPPING(ci->ci_signature); 1659 1660 /* 1661 * Determine the largest extended function value. 1662 */ 1663 x86_cpuid(0x80000000, descs); 1664 lfunc = descs[0]; 1665 1666 /* 1667 * Determine L1 cache/TLB info. 1668 */ 1669 if (lfunc < 0x80000005) { 1670 /* No L1 cache info available. */ 1671 return; 1672 } 1673 1674 x86_cpuid(0x80000005, descs); 1675 1676 cai = &ci->ci_cinfo[CAI_ITLB]; 1677 cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]); 1678 cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]); 1679 cai->cai_linesize = (4 * 1024); 1680 1681 cai = &ci->ci_cinfo[CAI_DTLB]; 1682 cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]); 1683 cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]); 1684 cai->cai_linesize = (4 * 1024); 1685 1686 cai = &ci->ci_cinfo[CAI_DCACHE]; 1687 cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]); 1688 cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]); 1689 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]); 1690 if (model == 9 && stepping == 8) { 1691 /* Erratum: stepping 8 reports 4 when it should be 2 */ 1692 cai->cai_associativity = 2; 1693 } 1694 1695 cai = &ci->ci_cinfo[CAI_ICACHE]; 1696 cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]); 1697 cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]); 1698 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]); 1699 if (model == 9 && stepping == 8) { 1700 /* Erratum: stepping 8 reports 4 when it should be 2 */ 1701 cai->cai_associativity = 2; 1702 } 1703 1704 /* 1705 * Determine L2 cache/TLB info. 1706 */ 1707 if (lfunc < 0x80000006) { 1708 /* No L2 cache info available. */ 1709 return; 1710 } 1711 1712 x86_cpuid(0x80000006, descs); 1713 1714 cai = &ci->ci_cinfo[CAI_L2CACHE]; 1715 if (model >= 9) { 1716 cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]); 1717 cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]); 1718 cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]); 1719 } else { 1720 cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]); 1721 cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]); 1722 cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]); 1723 } 1724 } 1725 1726 static void 1727 x86_print_cacheinfo(struct cpu_info *ci) 1728 { 1729 const char *sep; 1730 1731 if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 || 1732 ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) { 1733 sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL); 1734 sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep); 1735 if (sep != NULL) 1736 aprint_verbose("\n"); 1737 } 1738 if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) { 1739 sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", NULL); 1740 if (sep != NULL) 1741 aprint_verbose("\n"); 1742 } 1743 if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) { 1744 sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL); 1745 sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep); 1746 if (sep != NULL) 1747 aprint_verbose("\n"); 1748 } 1749 if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) { 1750 sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL); 1751 sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep); 1752 if (sep != NULL) 1753 aprint_verbose("\n"); 1754 } 1755 if (ci->ci_cinfo[CAI_L3CACHE].cai_totalsize != 0) { 1756 sep = print_cache_config(ci, CAI_L3CACHE, "L3 cache", NULL); 1757 if (sep != NULL) 1758 aprint_verbose("\n"); 1759 } 1760 } 1761 1762 static void 1763 powernow_probe(struct cpu_info *ci) 1764 { 1765 uint32_t regs[4]; 1766 char line[256]; 1767 1768 x86_cpuid(0x80000000, regs); 1769 1770 /* We need CPUID(0x80000007) */ 1771 if (regs[0] < 0x80000007) 1772 return; 1773 x86_cpuid(0x80000007, regs); 1774 1775 1776 1777 bitmask_snprintf(regs[3], "\20\11TscInv\10HwPState\7Clk100MHz" 1778 "\6STC\5TM\4TTP\3VID\2FID\1TS", line, sizeof(line)); 1779 aprint_normal_dev(ci->ci_dev, "AMD Power Management features: %s\n", 1780 line); 1781 } 1782