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