1/* $NetBSD: i386.c,v 1.27.2.3 2012/04/06 17:46:41 riz 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.27.2.3 2012/04/06 17:46:41 riz 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 90void x86_cpuid2(uint32_t, uint32_t, uint32_t *); 91void x86_identify(void); 92 93struct 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 117struct 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 127struct cpu_extend_nameclass { 128 int ext_model; 129 const char *cpu_models[CPU_MAXMODEL+1]; 130}; 131 132struct 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 146static 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 */ 152static 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 */ 174static 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 182static int cpu_vendor; 183static char cpu_brand_string[49]; 184static char amd_brand_name[48]; 185static int use_pae, largepagesize; 186 187static void via_cpu_probe(struct cpu_info *); 188static void amd_family6_probe(struct cpu_info *); 189static void intel_family_new_probe(struct cpu_info *); 190static const char *intel_family6_name(struct cpu_info *); 191static const char *amd_amd64_name(struct cpu_info *); 192static void amd_family5_setup(struct cpu_info *); 193static void transmeta_cpu_info(struct cpu_info *); 194static const char *print_cache_config(struct cpu_info *, int, const char *, 195 const char *); 196static const char *print_tlb_config(struct cpu_info *, int, const char *, 197 const char *); 198static void amd_cpu_cacheinfo(struct cpu_info *); 199static void via_cpu_cacheinfo(struct cpu_info *); 200static void x86_print_cacheinfo(struct cpu_info *); 201static const struct x86_cache_info *cache_info_lookup( 202 const struct x86_cache_info *, uint8_t); 203static void cyrix6x86_cpu_setup(struct cpu_info *); 204static void winchip_cpu_setup(struct cpu_info *); 205static void amd_family5_setup(struct cpu_info *); 206static void powernow_probe(struct cpu_info *); 207 208/* 209 * Info for CTL_HW 210 */ 211static 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 */ 217const 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 234const char *classnames[] = { 235 "386", 236 "486", 237 "586", 238 "686" 239}; 240 241const char *modifiers[] = { 242 "", 243 "OverDrive", 244 "Dual", 245 "" 246}; 247 248struct 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 263const 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 */ 638static void 639disable_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 647static void 648cyrix6x86_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 659void 660winchip_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 669static void 670identifycpu_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 724static void 725via_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 760static const char * 761intel_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 */ 839static const char * 840amd_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 ret = "Family 10h"; 963 break; 964 case 0x02: 965 ret = "Family 11h"; 966 break; 967 case 0x03: 968 ret = "Family 12h"; 969 break; 970 case 0x05: 971 ret = "Family 14h"; 972 break; 973 case 0x06: 974 ret = "Family 15h"; 975 break; 976 default: 977 ret = "Unknown AMD64 CPU"; 978 break; 979 } 980 981 return ret; 982} 983 984static void 985cpu_probe_base_features(struct cpu_info *ci) 986{ 987 const struct x86_cache_info *cai; 988 u_int descs[4]; 989 int iterations, i, j; 990 uint8_t desc; 991 uint32_t miscbytes; 992 uint32_t brand[12]; 993 994 if (ci->ci_cpuid_level < 0) 995 return; 996 997 x86_cpuid(0, descs); 998 ci->ci_cpuid_level = descs[0]; 999 ci->ci_vendor[0] = descs[1]; 1000 ci->ci_vendor[2] = descs[2]; 1001 ci->ci_vendor[1] = descs[3]; 1002 ci->ci_vendor[3] = 0; 1003 1004 x86_cpuid(0x80000000, brand); 1005 if (brand[0] >= 0x80000004) { 1006 x86_cpuid(0x80000002, brand); 1007 x86_cpuid(0x80000003, brand + 4); 1008 x86_cpuid(0x80000004, brand + 8); 1009 for (i = 0; i < 48; i++) 1010 if (((char *) brand)[i] != ' ') 1011 break; 1012 memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); 1013 } 1014 1015 if (ci->ci_cpuid_level < 1) 1016 return; 1017 1018 x86_cpuid(1, descs); 1019 ci->ci_signature = descs[0]; 1020 miscbytes = descs[1]; 1021 ci->ci_feat_val[1] = descs[2]; 1022 ci->ci_feat_val[0] = descs[3]; 1023 1024 /* Brand is low order 8 bits of ebx */ 1025 ci->ci_brand_id = miscbytes & 0xff; 1026 ci->ci_initapicid = (miscbytes >> 24) & 0xff; 1027 if (ci->ci_cpuid_level < 2) 1028 return; 1029 1030 /* 1031 * Parse the cache info from `cpuid', if we have it. 1032 * XXX This is kinda ugly, but hey, so is the architecture... 1033 */ 1034 1035 x86_cpuid(2, descs); 1036 1037 iterations = descs[0] & 0xff; 1038 while (iterations-- > 0) { 1039 for (i = 0; i < 4; i++) { 1040 if (descs[i] & 0x80000000) 1041 continue; 1042 for (j = 0; j < 4; j++) { 1043 if (i == 0 && j == 0) 1044 continue; 1045 desc = (descs[i] >> (j * 8)) & 0xff; 1046 if (desc == 0) 1047 continue; 1048 cai = cache_info_lookup(intel_cpuid_cache_info, 1049 desc); 1050 if (cai != NULL) 1051 ci->ci_cinfo[cai->cai_index] = *cai; 1052 } 1053 } 1054 x86_cpuid(2, descs); 1055 } 1056 1057 if (ci->ci_cpuid_level < 3) 1058 return; 1059 1060 /* 1061 * If the processor serial number misfeature is present and supported, 1062 * extract it here. 1063 */ 1064 if ((ci->ci_feat_val[0] & CPUID_PN) != 0) { 1065 ci->ci_cpu_serial[0] = ci->ci_signature; 1066 x86_cpuid(3, descs); 1067 ci->ci_cpu_serial[2] = descs[2]; 1068 ci->ci_cpu_serial[1] = descs[3]; 1069 } 1070} 1071 1072static void 1073cpu_probe_features(struct cpu_info *ci) 1074{ 1075 const struct cpu_cpuid_nameclass *cpup = NULL; 1076 int i, xmax, family; 1077 1078 cpu_probe_base_features(ci); 1079 1080 if (ci->ci_cpuid_level < 1) 1081 return; 1082 1083 xmax = __arraycount(i386_cpuid_cpus); 1084 for (i = 0; i < xmax; i++) { 1085 if (!strncmp((char *)ci->ci_vendor, 1086 i386_cpuid_cpus[i].cpu_id, 12)) { 1087 cpup = &i386_cpuid_cpus[i]; 1088 break; 1089 } 1090 } 1091 1092 if (cpup == NULL) 1093 return; 1094 1095 family = (ci->ci_signature >> 8) & 0xf; 1096 1097 if (family > CPU_MAXFAMILY) { 1098 family = CPU_MAXFAMILY; 1099 } 1100 i = family - CPU_MINFAMILY; 1101 1102 if (cpup->cpu_family[i].cpu_probe == NULL) 1103 return; 1104 1105 (*cpup->cpu_family[i].cpu_probe)(ci); 1106} 1107 1108static void 1109intel_family_new_probe(struct cpu_info *ci) 1110{ 1111 uint32_t descs[4]; 1112 1113 x86_cpuid(0x80000000, descs); 1114 1115 /* 1116 * Determine extended feature flags. 1117 */ 1118 if (descs[0] >= 0x80000001) { 1119 x86_cpuid(0x80000001, descs); 1120 ci->ci_feat_val[2] |= descs[3]; 1121 ci->ci_feat_val[3] |= descs[2]; 1122 } 1123} 1124 1125static void 1126amd_family6_probe(struct cpu_info *ci) 1127{ 1128 uint32_t descs[4]; 1129 char *p; 1130 size_t i; 1131 1132 x86_cpuid(0x80000000, descs); 1133 1134 /* 1135 * Determine the extended feature flags. 1136 */ 1137 if (descs[0] >= 0x80000001) { 1138 x86_cpuid(0x80000001, descs); 1139 ci->ci_feat_val[2] |= descs[3]; /* %edx */ 1140 ci->ci_feat_val[3] = descs[2]; /* %ecx */ 1141 } 1142 1143 if (*cpu_brand_string == '\0') 1144 return; 1145 1146 for (i = 1; i < __arraycount(amd_brand); i++) 1147 if ((p = strstr(cpu_brand_string, amd_brand[i])) != NULL) { 1148 ci->ci_brand_id = i; 1149 strlcpy(amd_brand_name, p, sizeof(amd_brand_name)); 1150 break; 1151 } 1152} 1153 1154static void 1155amd_family5_setup(struct cpu_info *ci) 1156{ 1157 1158 switch (CPUID2MODEL(ci->ci_signature)) { 1159 case 0: /* AMD-K5 Model 0 */ 1160 /* 1161 * According to the AMD Processor Recognition App Note, 1162 * the AMD-K5 Model 0 uses the wrong bit to indicate 1163 * support for global PTEs, instead using bit 9 (APIC) 1164 * rather than bit 13 (i.e. "0x200" vs. 0x2000". Oops!). 1165 */ 1166 if (ci->ci_feat_val[0] & CPUID_APIC) 1167 ci->ci_feat_val[0] = 1168 (ci->ci_feat_val[0] & ~CPUID_APIC) | CPUID_PGE; 1169 /* 1170 * XXX But pmap_pg_g is already initialized -- need to kick 1171 * XXX the pmap somehow. How does the MP branch do this? 1172 */ 1173 break; 1174 } 1175} 1176 1177static void 1178tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage) 1179{ 1180 u_int descs[4]; 1181 1182 x86_cpuid(0x80860007, descs); 1183 *frequency = descs[0]; 1184 *voltage = descs[1]; 1185 *percentage = descs[2]; 1186} 1187 1188static void 1189transmeta_cpu_info(struct cpu_info *ci) 1190{ 1191 u_int descs[4], nreg; 1192 u_int frequency, voltage, percentage; 1193 1194 x86_cpuid(0x80860000, descs); 1195 nreg = descs[0]; 1196 if (nreg >= 0x80860001) { 1197 x86_cpuid(0x80860001, descs); 1198 aprint_verbose_dev(ci->ci_dev, "Processor revision %u.%u.%u.%u\n", 1199 (descs[1] >> 24) & 0xff, 1200 (descs[1] >> 16) & 0xff, 1201 (descs[1] >> 8) & 0xff, 1202 descs[1] & 0xff); 1203 } 1204 if (nreg >= 0x80860002) { 1205 x86_cpuid(0x80860002, descs); 1206 aprint_verbose_dev(ci->ci_dev, "Code Morphing Software Rev: %u.%u.%u-%u-%u\n", 1207 (descs[1] >> 24) & 0xff, 1208 (descs[1] >> 16) & 0xff, 1209 (descs[1] >> 8) & 0xff, 1210 descs[1] & 0xff, 1211 descs[2]); 1212 } 1213 if (nreg >= 0x80860006) { 1214 union { 1215 char text[65]; 1216 u_int descs[4][4]; 1217 } info; 1218 int i; 1219 1220 for (i=0; i<4; i++) { 1221 x86_cpuid(0x80860003 + i, info.descs[i]); 1222 } 1223 info.text[64] = '\0'; 1224 aprint_verbose_dev(ci->ci_dev, "%s\n", info.text); 1225 } 1226 1227 if (nreg >= 0x80860007) { 1228 tmx86_get_longrun_status(&frequency, 1229 &voltage, &percentage); 1230 aprint_verbose_dev(ci->ci_dev, "LongRun <%dMHz %dmV %d%%>\n", 1231 frequency, voltage, percentage); 1232 } 1233} 1234 1235void 1236identifycpu(const char *cpuname) 1237{ 1238 const char *name = "", *modifier, *vendorname, *brand = ""; 1239 int class = CPUCLASS_386, i, xmax; 1240 int modif, family, model, ext_model; 1241 const struct cpu_extend_nameclass *modlist; 1242 const struct cpu_cpuid_nameclass *cpup = NULL; 1243 const struct cpu_cpuid_family *cpufam; 1244 const char *feature_str[5]; 1245 struct cpu_info *ci, cistore; 1246 extern int cpu; 1247 extern int cpu_info_level; 1248 size_t sz; 1249 char buf[512]; 1250 char *bp; 1251 1252 ci = &cistore; 1253 memset(ci, 0, sizeof(*ci)); 1254 ci->ci_dev = cpuname; 1255 1256 x86_identify(); 1257 ci->ci_cpuid_level = cpu_info_level; 1258 cpu_probe_features(ci); 1259 1260 if (ci->ci_cpuid_level == -1) { 1261 if ((size_t)cpu >= __arraycount(i386_nocpuid_cpus)) 1262 errx(1, "unknown cpu type %d", cpu); 1263 name = i386_nocpuid_cpus[cpu].cpu_name; 1264 cpu_vendor = i386_nocpuid_cpus[cpu].cpu_vendor; 1265 vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname; 1266 class = i386_nocpuid_cpus[cpu].cpu_class; 1267 ci->ci_info = i386_nocpuid_cpus[cpu].cpu_info; 1268 modifier = ""; 1269 } else { 1270 xmax = __arraycount(i386_cpuid_cpus); 1271 modif = (ci->ci_signature >> 12) & 0x3; 1272 family = CPUID2FAMILY(ci->ci_signature); 1273 if (family < CPU_MINFAMILY) 1274 errx(1, "identifycpu: strange family value"); 1275 model = CPUID2MODEL(ci->ci_signature); 1276 ext_model = CPUID2EXTMODEL(ci->ci_signature); 1277 1278 for (i = 0; i < xmax; i++) { 1279 if (!strncmp((char *)ci->ci_vendor, 1280 i386_cpuid_cpus[i].cpu_id, 12)) { 1281 cpup = &i386_cpuid_cpus[i]; 1282 break; 1283 } 1284 } 1285 1286 if (cpup == NULL) { 1287 cpu_vendor = CPUVENDOR_UNKNOWN; 1288 if (ci->ci_vendor[0] != '\0') 1289 vendorname = (char *)&ci->ci_vendor[0]; 1290 else 1291 vendorname = "Unknown"; 1292 if (family >= CPU_MAXFAMILY) 1293 family = CPU_MINFAMILY; 1294 class = family - 3; 1295 modifier = ""; 1296 name = ""; 1297 ci->ci_info = NULL; 1298 } else { 1299 cpu_vendor = cpup->cpu_vendor; 1300 vendorname = cpup->cpu_vendorname; 1301 modifier = modifiers[modif]; 1302 if (family > CPU_MAXFAMILY) { 1303 family = CPU_MAXFAMILY; 1304 model = CPU_DEFMODEL; 1305 } else if (model > CPU_MAXMODEL) { 1306 model = CPU_DEFMODEL; 1307 ext_model = 0; 1308 } 1309 cpufam = &cpup->cpu_family[family - CPU_MINFAMILY]; 1310 if (cpufam->cpu_extended_names == NULL || 1311 ext_model == 0) 1312 name = cpufam->cpu_models[model]; 1313 else { 1314 /* 1315 * Scan list(s) of extended model names 1316 */ 1317 modlist = cpufam->cpu_extended_names; 1318 while (modlist->ext_model != 0) { 1319 if (modlist->ext_model == ext_model) { 1320 name = 1321 modlist->cpu_models[model]; 1322 break; 1323 } 1324 modlist++; 1325 } 1326 } 1327 if (name == NULL || *name == '\0') 1328 name = cpufam->cpu_models[CPU_DEFMODEL]; 1329 class = cpufam->cpu_class; 1330 ci->ci_info = cpufam->cpu_info; 1331 1332 if (cpu_vendor == CPUVENDOR_INTEL) { 1333 if (family == 6 && model >= 5) { 1334 const char *tmp; 1335 tmp = intel_family6_name(ci); 1336 if (tmp != NULL) 1337 name = tmp; 1338 } 1339 if (family == CPU_MAXFAMILY && 1340 ci->ci_brand_id < 1341 __arraycount(i386_intel_brand) && 1342 i386_intel_brand[ci->ci_brand_id]) 1343 name = 1344 i386_intel_brand[ci->ci_brand_id]; 1345 } 1346 1347 if (cpu_vendor == CPUVENDOR_AMD) { 1348 if (family == 6 && model >= 6) { 1349 if (ci->ci_brand_id == 1) 1350 /* 1351 * It's Duron. We override the 1352 * name, since it might have 1353 * been misidentified as Athlon. 1354 */ 1355 name = 1356 amd_brand[ci->ci_brand_id]; 1357 else 1358 brand = amd_brand_name; 1359 } 1360 if (CPUID2FAMILY(ci->ci_signature) == 0xf) { 1361 /* 1362 * Identify AMD64 CPU names. 1363 * Note family value is clipped by 1364 * CPU_MAXFAMILY. 1365 */ 1366 const char *tmp; 1367 tmp = amd_amd64_name(ci); 1368 if (tmp != NULL) 1369 name = tmp; 1370 } 1371 } 1372 1373 if (cpu_vendor == CPUVENDOR_IDT && family >= 6) 1374 vendorname = "VIA"; 1375 } 1376 } 1377 1378 ci->ci_cpu_class = class; 1379 1380 sz = sizeof(ci->ci_tsc_freq); 1381 (void)sysctlbyname("machdep.tsc_freq", &ci->ci_tsc_freq, &sz, NULL, 0); 1382 sz = sizeof(use_pae); 1383 (void)sysctlbyname("machdep.pae", &use_pae, &sz, NULL, 0); 1384 largepagesize = (use_pae ? 2 * 1024 * 1024 : 4 * 1024 * 1024); 1385 1386 snprintf(cpu_model, sizeof(cpu_model), "%s%s%s%s%s%s%s (%s-class)", 1387 vendorname, 1388 *modifier ? " " : "", modifier, 1389 *name ? " " : "", name, 1390 *brand ? " " : "", brand, 1391 classnames[class]); 1392 aprint_normal("%s: %s", cpuname, cpu_model); 1393 1394 if (ci->ci_tsc_freq != 0) 1395 aprint_normal(", %ju.%02ju MHz", 1396 ((uintmax_t)ci->ci_tsc_freq + 4999) / 1000000, 1397 (((uintmax_t)ci->ci_tsc_freq + 4999) / 10000) % 100); 1398 if (ci->ci_signature != 0) 1399 aprint_normal(", id 0x%x", ci->ci_signature); 1400 aprint_normal("\n"); 1401 1402 if (ci->ci_info) 1403 (*ci->ci_info)(ci); 1404 1405 /* 1406 * display CPU feature flags 1407 */ 1408 1409#define MAX_FEATURE_LEN 60 /* XXX Need to find a better way to set this */ 1410 1411 feature_str[0] = CPUID_FLAGS1; 1412 feature_str[1] = CPUID2_FLAGS1; 1413 feature_str[2] = CPUID_EXT_FLAGS; 1414 feature_str[3] = NULL; 1415 feature_str[4] = NULL; 1416 1417 switch (cpu_vendor) { 1418 case CPUVENDOR_AMD: 1419 feature_str[3] = CPUID_AMD_FLAGS4; 1420 break; 1421 case CPUVENDOR_INTEL: 1422 feature_str[2] = CPUID_INTEL_EXT_FLAGS; 1423 feature_str[3] = CPUID_INTEL_FLAGS4; 1424 break; 1425 case CPUVENDOR_IDT: 1426 feature_str[4] = CPUID_FLAGS_PADLOCK; 1427 break; 1428 default: 1429 break; 1430 } 1431 1432 for (i = 0; i <= 4; i++) { 1433 if (ci->ci_feat_val[i] && feature_str[i] != NULL) { 1434 snprintb_m(buf, sizeof(buf), feature_str[i], 1435 ci->ci_feat_val[i], MAX_FEATURE_LEN); 1436 bp = buf; 1437 while (*bp != '\0') { 1438 aprint_verbose("%s: %sfeatures%c %s\n", 1439 cpuname, (i == 4)?"padlock ":"", 1440 (i == 4 || i == 0)?' ':'1' + i, bp); 1441 bp += strlen(bp) + 1; 1442 } 1443 } 1444 } 1445 1446 if (*cpu_brand_string != '\0') 1447 aprint_normal("%s: \"%s\"\n", cpuname, cpu_brand_string); 1448 1449 x86_print_cacheinfo(ci); 1450 1451 if (ci->ci_cpuid_level >= 3 && (ci->ci_feat_val[0] & CPUID_PN)) { 1452 aprint_verbose("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n", 1453 cpuname, 1454 ci->ci_cpu_serial[0] / 65536, ci->ci_cpu_serial[0] % 65536, 1455 ci->ci_cpu_serial[1] / 65536, ci->ci_cpu_serial[1] % 65536, 1456 ci->ci_cpu_serial[2] / 65536, ci->ci_cpu_serial[2] % 65536); 1457 } 1458 1459 if (ci->ci_cpu_class == CPUCLASS_386) { 1460 errx(1, "NetBSD requires an 80486 or later processor"); 1461 } 1462 1463 if (cpu == CPU_486DLC) { 1464#ifndef CYRIX_CACHE_WORKS 1465 aprint_error("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n"); 1466#else 1467#ifndef CYRIX_CACHE_REALLY_WORKS 1468 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n"); 1469#else 1470 aprint_error("WARNING: CYRIX 486DLC CACHE ENABLED.\n"); 1471#endif 1472#endif 1473 } 1474 1475 /* 1476 * Everything past this point requires a Pentium or later. 1477 */ 1478 if (ci->ci_cpuid_level < 0) 1479 return; 1480 1481 identifycpu_cpuids(ci); 1482 1483#ifdef INTEL_CORETEMP 1484 if (cpu_vendor == CPUVENDOR_INTEL && ci->ci_cpuid_level >= 0x06) 1485 coretemp_register(ci); 1486#endif 1487 1488 if (cpu_vendor == CPUVENDOR_AMD) { 1489 uint32_t data[4]; 1490 1491 x86_cpuid(0x80000000, data); 1492 if (data[0] >= 0x80000007) 1493 powernow_probe(ci); 1494 1495 if ((data[0] >= 0x8000000a) 1496 && (ci->ci_feat_val[3] & CPUID_SVM) != 0) { 1497 1498 x86_cpuid(0x8000000a, data); 1499 aprint_verbose("%s: SVM Rev. %d\n", cpuname, 1500 data[0] & 0xf); 1501 aprint_verbose("%s: SVM NASID %d\n", cpuname, data[1]); 1502 snprintb_m(buf, sizeof(buf), CPUID_AMD_SVM_FLAGS, 1503 data[3], MAX_FEATURE_LEN); 1504 bp = buf; 1505 while (*bp != '\0') { 1506 aprint_verbose("%s: SVM features %s\n", 1507 cpuname, bp); 1508 bp += strlen(bp) + 1; 1509 } 1510 } 1511 } 1512 1513#ifdef INTEL_ONDEMAND_CLOCKMOD 1514 clockmod_init(); 1515#endif 1516 1517 aprint_normal_dev(ci->ci_dev, "family %02x model %02x " 1518 "extfamily %02x extmodel %02x stepping %02x\n", 1519 CPUID2FAMILY(ci->ci_signature), CPUID2MODEL(ci->ci_signature), 1520 CPUID2EXTFAMILY(ci->ci_signature), CPUID2EXTMODEL(ci->ci_signature), 1521 CPUID2STEPPING(ci->ci_signature)); 1522} 1523 1524static const char * 1525print_cache_config(struct cpu_info *ci, int cache_tag, const char *name, 1526 const char *sep) 1527{ 1528 struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag]; 1529 char human_num[HUMAN_BUFSIZE]; 1530 1531 if (cai->cai_totalsize == 0) 1532 return sep; 1533 1534 if (sep == NULL) 1535 aprint_verbose_dev(ci->ci_dev, ""); 1536 else 1537 aprint_verbose("%s", sep); 1538 if (name != NULL) 1539 aprint_verbose("%s ", name); 1540 1541 if (cai->cai_string != NULL) { 1542 aprint_verbose("%s ", cai->cai_string); 1543 } else { 1544 (void)humanize_number(human_num, sizeof(human_num), 1545 cai->cai_totalsize, "B", HN_AUTOSCALE, HN_NOSPACE); 1546 aprint_verbose("%s %dB/line ", human_num, cai->cai_linesize); 1547 } 1548 switch (cai->cai_associativity) { 1549 case 0: 1550 aprint_verbose("disabled"); 1551 break; 1552 case 1: 1553 aprint_verbose("direct-mapped"); 1554 break; 1555 case 0xff: 1556 aprint_verbose("fully associative"); 1557 break; 1558 default: 1559 aprint_verbose("%d-way", cai->cai_associativity); 1560 break; 1561 } 1562 return ", "; 1563} 1564 1565static const char * 1566print_tlb_config(struct cpu_info *ci, int cache_tag, const char *name, 1567 const char *sep) 1568{ 1569 struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag]; 1570 char human_num[HUMAN_BUFSIZE]; 1571 1572 if (cai->cai_totalsize == 0) 1573 return sep; 1574 1575 if (sep == NULL) 1576 aprint_verbose_dev(ci->ci_dev, ""); 1577 else 1578 aprint_verbose("%s", sep); 1579 if (name != NULL) 1580 aprint_verbose("%s ", name); 1581 1582 if (cai->cai_string != NULL) { 1583 aprint_verbose("%s", cai->cai_string); 1584 } else { 1585 (void)humanize_number(human_num, sizeof(human_num), 1586 cai->cai_linesize, "B", HN_AUTOSCALE, HN_NOSPACE); 1587 aprint_verbose("%d %s entries ", cai->cai_totalsize, 1588 human_num); 1589 switch (cai->cai_associativity) { 1590 case 0: 1591 aprint_verbose("disabled"); 1592 break; 1593 case 1: 1594 aprint_verbose("direct-mapped"); 1595 break; 1596 case 0xff: 1597 aprint_verbose("fully associative"); 1598 break; 1599 default: 1600 aprint_verbose("%d-way", cai->cai_associativity); 1601 break; 1602 } 1603 } 1604 return ", "; 1605} 1606 1607static const struct x86_cache_info * 1608cache_info_lookup(const struct x86_cache_info *cai, uint8_t desc) 1609{ 1610 int i; 1611 1612 for (i = 0; cai[i].cai_desc != 0; i++) { 1613 if (cai[i].cai_desc == desc) 1614 return (&cai[i]); 1615 } 1616 1617 return (NULL); 1618} 1619 1620static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = 1621 AMD_L2CACHE_INFO; 1622 1623static const struct x86_cache_info amd_cpuid_l3cache_assoc_info[] = 1624 AMD_L3CACHE_INFO; 1625 1626static void 1627amd_cpu_cacheinfo(struct cpu_info *ci) 1628{ 1629 const struct x86_cache_info *cp; 1630 struct x86_cache_info *cai; 1631 int family, model; 1632 u_int descs[4]; 1633 u_int lfunc; 1634 1635 family = (ci->ci_signature >> 8) & 15; 1636 model = CPUID2MODEL(ci->ci_signature); 1637 1638 /* 1639 * K5 model 0 has none of this info. 1640 */ 1641 if (family == 5 && model == 0) 1642 return; 1643 1644 /* 1645 * Get extended values for K8 and up. 1646 */ 1647 if (family == 0xf) { 1648 family += CPUID2EXTFAMILY(ci->ci_signature); 1649 model += CPUID2EXTMODEL(ci->ci_signature); 1650 } 1651 1652 /* 1653 * Determine the largest extended function value. 1654 */ 1655 x86_cpuid(0x80000000, descs); 1656 lfunc = descs[0]; 1657 1658 /* 1659 * Determine L1 cache/TLB info. 1660 */ 1661 if (lfunc < 0x80000005) { 1662 /* No L1 cache info available. */ 1663 return; 1664 } 1665 1666 x86_cpuid(0x80000005, descs); 1667 1668 /* 1669 * K6-III and higher have large page TLBs. 1670 */ 1671 if ((family == 5 && model >= 9) || family >= 6) { 1672 cai = &ci->ci_cinfo[CAI_ITLB2]; 1673 cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]); 1674 cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]); 1675 cai->cai_linesize = largepagesize; 1676 1677 cai = &ci->ci_cinfo[CAI_DTLB2]; 1678 cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]); 1679 cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]); 1680 cai->cai_linesize = largepagesize; 1681 } 1682 1683 cai = &ci->ci_cinfo[CAI_ITLB]; 1684 cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]); 1685 cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]); 1686 cai->cai_linesize = (4 * 1024); 1687 1688 cai = &ci->ci_cinfo[CAI_DTLB]; 1689 cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]); 1690 cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]); 1691 cai->cai_linesize = (4 * 1024); 1692 1693 cai = &ci->ci_cinfo[CAI_DCACHE]; 1694 cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]); 1695 cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]); 1696 cai->cai_linesize = AMD_L1_ECX_DC_LS(descs[2]); 1697 1698 cai = &ci->ci_cinfo[CAI_ICACHE]; 1699 cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]); 1700 cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]); 1701 cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]); 1702 1703 /* 1704 * Determine L2 cache/TLB info. 1705 */ 1706 if (lfunc < 0x80000006) { 1707 /* No L2 cache info available. */ 1708 return; 1709 } 1710 1711 x86_cpuid(0x80000006, descs); 1712 1713 cai = &ci->ci_cinfo[CAI_L2_ITLB]; 1714 cai->cai_totalsize = AMD_L2_EBX_IUTLB_ENTRIES(descs[1]); 1715 cai->cai_associativity = AMD_L2_EBX_IUTLB_ASSOC(descs[1]); 1716 cai->cai_linesize = (4 * 1024); 1717 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1718 cai->cai_associativity); 1719 if (cp != NULL) 1720 cai->cai_associativity = cp->cai_associativity; 1721 else 1722 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1723 1724 cai = &ci->ci_cinfo[CAI_L2_ITLB2]; 1725 cai->cai_totalsize = AMD_L2_EAX_IUTLB_ENTRIES(descs[0]); 1726 cai->cai_associativity = AMD_L2_EAX_IUTLB_ASSOC(descs[0]); 1727 cai->cai_linesize = largepagesize; 1728 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1729 cai->cai_associativity); 1730 if (cp != NULL) 1731 cai->cai_associativity = cp->cai_associativity; 1732 else 1733 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1734 1735 cai = &ci->ci_cinfo[CAI_L2_DTLB]; 1736 cai->cai_totalsize = AMD_L2_EBX_DTLB_ENTRIES(descs[1]); 1737 cai->cai_associativity = AMD_L2_EBX_DTLB_ASSOC(descs[1]); 1738 cai->cai_linesize = (4 * 1024); 1739 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1740 cai->cai_associativity); 1741 if (cp != NULL) 1742 cai->cai_associativity = cp->cai_associativity; 1743 else 1744 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1745 1746 cai = &ci->ci_cinfo[CAI_L2_DTLB2]; 1747 cai->cai_totalsize = AMD_L2_EAX_DTLB_ENTRIES(descs[0]); 1748 cai->cai_associativity = AMD_L2_EAX_DTLB_ASSOC(descs[0]); 1749 cai->cai_linesize = largepagesize; 1750 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1751 cai->cai_associativity); 1752 if (cp != NULL) 1753 cai->cai_associativity = cp->cai_associativity; 1754 else 1755 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1756 1757 cai = &ci->ci_cinfo[CAI_L2CACHE]; 1758 cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]); 1759 cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]); 1760 cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]); 1761 1762 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1763 cai->cai_associativity); 1764 if (cp != NULL) 1765 cai->cai_associativity = cp->cai_associativity; 1766 else 1767 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1768 1769 /* 1770 * Determine L3 cache info on AMD Family 10h and newer processors 1771 */ 1772 if (family >= 0x10) { 1773 cai = &ci->ci_cinfo[CAI_L3CACHE]; 1774 cai->cai_totalsize = AMD_L3_EDX_C_SIZE(descs[3]); 1775 cai->cai_associativity = AMD_L3_EDX_C_ASSOC(descs[3]); 1776 cai->cai_linesize = AMD_L3_EDX_C_LS(descs[3]); 1777 1778 cp = cache_info_lookup(amd_cpuid_l3cache_assoc_info, 1779 cai->cai_associativity); 1780 if (cp != NULL) 1781 cai->cai_associativity = cp->cai_associativity; 1782 else 1783 cai->cai_associativity = 0; /* XXX Unkn/Rsvd */ 1784 } 1785 1786 /* 1787 * Determine 1GB TLB info. 1788 */ 1789 if (lfunc < 0x80000019) { 1790 /* No 1GB TLB info available. */ 1791 return; 1792 } 1793 1794 x86_cpuid(0x80000019, descs); 1795 1796 cai = &ci->ci_cinfo[CAI_L1_1GBITLB]; 1797 cai->cai_totalsize = AMD_L1_1GB_EAX_IUTLB_ENTRIES(descs[0]); 1798 cai->cai_associativity = AMD_L1_1GB_EAX_IUTLB_ASSOC(descs[0]); 1799 cai->cai_linesize = (1024 * 1024 * 1024); 1800 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1801 cai->cai_associativity); 1802 if (cp != NULL) 1803 cai->cai_associativity = cp->cai_associativity; 1804 else 1805 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1806 1807 cai = &ci->ci_cinfo[CAI_L1_1GBDTLB]; 1808 cai->cai_totalsize = AMD_L1_1GB_EAX_DTLB_ENTRIES(descs[0]); 1809 cai->cai_associativity = AMD_L1_1GB_EAX_DTLB_ASSOC(descs[0]); 1810 cai->cai_linesize = (1024 * 1024 * 1024); 1811 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1812 cai->cai_associativity); 1813 if (cp != NULL) 1814 cai->cai_associativity = cp->cai_associativity; 1815 else 1816 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1817 1818 cai = &ci->ci_cinfo[CAI_L2_1GBITLB]; 1819 cai->cai_totalsize = AMD_L2_1GB_EBX_IUTLB_ENTRIES(descs[1]); 1820 cai->cai_associativity = AMD_L2_1GB_EBX_IUTLB_ASSOC(descs[1]); 1821 cai->cai_linesize = (1024 * 1024 * 1024); 1822 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1823 cai->cai_associativity); 1824 if (cp != NULL) 1825 cai->cai_associativity = cp->cai_associativity; 1826 else 1827 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1828 1829 cai = &ci->ci_cinfo[CAI_L2_1GBDTLB]; 1830 cai->cai_totalsize = AMD_L2_1GB_EBX_DUTLB_ENTRIES(descs[1]); 1831 cai->cai_associativity = AMD_L2_1GB_EBX_DUTLB_ASSOC(descs[1]); 1832 cai->cai_linesize = (1024 * 1024 * 1024); 1833 cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info, 1834 cai->cai_associativity); 1835 if (cp != NULL) 1836 cai->cai_associativity = cp->cai_associativity; 1837 else 1838 cai->cai_associativity = 0; /* XXX Unknown/reserved */ 1839} 1840 1841static void 1842via_cpu_cacheinfo(struct cpu_info *ci) 1843{ 1844 struct x86_cache_info *cai; 1845 int family, model, stepping; 1846 u_int descs[4]; 1847 u_int lfunc; 1848 1849 family = (ci->ci_signature >> 8) & 15; 1850 model = CPUID2MODEL(ci->ci_signature); 1851 stepping = CPUID2STEPPING(ci->ci_signature); 1852 1853 /* 1854 * Determine the largest extended function value. 1855 */ 1856 x86_cpuid(0x80000000, descs); 1857 lfunc = descs[0]; 1858 1859 /* 1860 * Determine L1 cache/TLB info. 1861 */ 1862 if (lfunc < 0x80000005) { 1863 /* No L1 cache info available. */ 1864 return; 1865 } 1866 1867 x86_cpuid(0x80000005, descs); 1868 1869 cai = &ci->ci_cinfo[CAI_ITLB]; 1870 cai->cai_totalsize = VIA_L1_EBX_ITLB_ENTRIES(descs[1]); 1871 cai->cai_associativity = VIA_L1_EBX_ITLB_ASSOC(descs[1]); 1872 cai->cai_linesize = (4 * 1024); 1873 1874 cai = &ci->ci_cinfo[CAI_DTLB]; 1875 cai->cai_totalsize = VIA_L1_EBX_DTLB_ENTRIES(descs[1]); 1876 cai->cai_associativity = VIA_L1_EBX_DTLB_ASSOC(descs[1]); 1877 cai->cai_linesize = (4 * 1024); 1878 1879 cai = &ci->ci_cinfo[CAI_DCACHE]; 1880 cai->cai_totalsize = VIA_L1_ECX_DC_SIZE(descs[2]); 1881 cai->cai_associativity = VIA_L1_ECX_DC_ASSOC(descs[2]); 1882 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[2]); 1883 if (model == 9 && stepping == 8) { 1884 /* Erratum: stepping 8 reports 4 when it should be 2 */ 1885 cai->cai_associativity = 2; 1886 } 1887 1888 cai = &ci->ci_cinfo[CAI_ICACHE]; 1889 cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]); 1890 cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]); 1891 cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]); 1892 if (model == 9 && stepping == 8) { 1893 /* Erratum: stepping 8 reports 4 when it should be 2 */ 1894 cai->cai_associativity = 2; 1895 } 1896 1897 /* 1898 * Determine L2 cache/TLB info. 1899 */ 1900 if (lfunc < 0x80000006) { 1901 /* No L2 cache info available. */ 1902 return; 1903 } 1904 1905 x86_cpuid(0x80000006, descs); 1906 1907 cai = &ci->ci_cinfo[CAI_L2CACHE]; 1908 if (model >= 9) { 1909 cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]); 1910 cai->cai_associativity = VIA_L2N_ECX_C_ASSOC(descs[2]); 1911 cai->cai_linesize = VIA_L2N_ECX_C_LS(descs[2]); 1912 } else { 1913 cai->cai_totalsize = VIA_L2_ECX_C_SIZE(descs[2]); 1914 cai->cai_associativity = VIA_L2_ECX_C_ASSOC(descs[2]); 1915 cai->cai_linesize = VIA_L2_ECX_C_LS(descs[2]); 1916 } 1917} 1918 1919static void 1920x86_print_cacheinfo(struct cpu_info *ci) 1921{ 1922 const char *sep; 1923 1924 if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 || 1925 ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) { 1926 sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL); 1927 sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep); 1928 if (sep != NULL) 1929 aprint_verbose("\n"); 1930 } 1931 if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) { 1932 sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", NULL); 1933 if (sep != NULL) 1934 aprint_verbose("\n"); 1935 } 1936 if (ci->ci_cinfo[CAI_L3CACHE].cai_totalsize != 0) { 1937 sep = print_cache_config(ci, CAI_L3CACHE, "L3 cache", NULL); 1938 if (sep != NULL) 1939 aprint_verbose("\n"); 1940 } 1941 if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) { 1942 sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL); 1943 sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep); 1944 if (sep != NULL) 1945 aprint_verbose("\n"); 1946 } 1947 if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) { 1948 sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL); 1949 sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep); 1950 if (sep != NULL) 1951 aprint_verbose("\n"); 1952 } 1953 if (ci->ci_cinfo[CAI_L2_ITLB].cai_totalsize != 0) { 1954 sep = print_tlb_config(ci, CAI_L2_ITLB, "L2 ITLB", NULL); 1955 sep = print_tlb_config(ci, CAI_L2_ITLB2, NULL, sep); 1956 if (sep != NULL) 1957 aprint_verbose("\n"); 1958 } 1959 if (ci->ci_cinfo[CAI_L2_DTLB].cai_totalsize != 0) { 1960 sep = print_tlb_config(ci, CAI_L2_DTLB, "L2 DTLB", NULL); 1961 sep = print_tlb_config(ci, CAI_L2_DTLB2, NULL, sep); 1962 if (sep != NULL) 1963 aprint_verbose("\n"); 1964 } 1965 if (ci->ci_cinfo[CAI_L1_1GBITLB].cai_totalsize != 0) { 1966 sep = print_tlb_config(ci, CAI_L1_1GBITLB, "L1 1GB page ITLB", NULL); 1967 if (sep != NULL) 1968 aprint_verbose("\n"); 1969 } 1970 if (ci->ci_cinfo[CAI_L1_1GBDTLB].cai_totalsize != 0) { 1971 sep = print_tlb_config(ci, CAI_L1_1GBDTLB, "L1 1GB page DTLB", NULL); 1972 if (sep != NULL) 1973 aprint_verbose("\n"); 1974 } 1975 if (ci->ci_cinfo[CAI_L2_1GBITLB].cai_totalsize != 0) { 1976 sep = print_tlb_config(ci, CAI_L2_1GBITLB, "L2 1GB page ITLB", NULL); 1977 if (sep != NULL) 1978 aprint_verbose("\n"); 1979 } 1980 if (ci->ci_cinfo[CAI_L2_1GBDTLB].cai_totalsize != 0) { 1981 sep = print_tlb_config(ci, CAI_L2_1GBDTLB, "L2 1GB page DTLB", NULL); 1982 if (sep != NULL) 1983 aprint_verbose("\n"); 1984 } 1985} 1986 1987static void 1988powernow_probe(struct cpu_info *ci) 1989{ 1990 uint32_t regs[4]; 1991 char buf[256]; 1992 1993 x86_cpuid(0x80000007, regs); 1994 1995 snprintb(buf, sizeof(buf), CPUID_APM_FLAGS, regs[3]); 1996 aprint_normal_dev(ci->ci_dev, "AMD Power Management features: %s\n", 1997 buf); 1998} 1999