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