identcpu.c revision 47592
1/* 2 * Copyright (c) 1992 Terrence R. Lambert. 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * Copyright (c) 1997 KATO Takenori. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * William Jolitz. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp 39 * $Id: identcpu.c,v 1.62 1999/05/10 10:51:25 bde Exp $ 40 */ 41 42#include "opt_cpu.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/sysctl.h> 48 49#include <machine/asmacros.h> 50#include <machine/clock.h> 51#include <machine/cputypes.h> 52#include <machine/segments.h> 53#include <machine/specialreg.h> 54#include <machine/md_var.h> 55 56#include <i386/isa/intr_machdep.h> 57 58#define IDENTBLUE_CYRIX486 0 59#define IDENTBLUE_IBMCPU 1 60#define IDENTBLUE_CYRIXM2 2 61 62/* XXX - should be in header file: */ 63void printcpuinfo(void); 64void finishidentcpu(void); 65void earlysetcpuclass(void); 66#if defined(I586_CPU) && defined(CPU_WT_ALLOC) 67void enable_K5_wt_alloc(void); 68void enable_K6_wt_alloc(void); 69void enable_K6_2_wt_alloc(void); 70#endif 71void panicifcpuunsupported(void); 72 73static void identifycyrix(void); 74static void print_AMD_info(void); 75static void print_AMD_assoc(int i); 76static void do_cpuid(u_int ax, u_int *p); 77 78u_int cyrix_did; /* Device ID of Cyrix CPU */ 79int cpu_class = CPUCLASS_386; /* least common denominator */ 80char machine[] = "i386"; 81SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, 82 machine, 0, "Machine class"); 83 84static char cpu_model[128]; 85SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, 86 cpu_model, 0, "Machine model"); 87 88static struct cpu_nameclass i386_cpus[] = { 89 { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */ 90 { "i386SX", CPUCLASS_386 }, /* CPU_386SX */ 91 { "i386DX", CPUCLASS_386 }, /* CPU_386 */ 92 { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ 93 { "i486DX", CPUCLASS_486 }, /* CPU_486 */ 94 { "Pentium", CPUCLASS_586 }, /* CPU_586 */ 95 { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */ 96 { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ 97 { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */ 98 { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */ 99 { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */ 100 { "Cyrix 6x86MX", CPUCLASS_686 }, /* CPU_M2 */ 101 { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */ 102 { "Cyrix 486S/DX", CPUCLASS_486 }, /* CPU_CY486DX */ 103 { "Pentium II", CPUCLASS_686 }, /* CPU_PII */ 104 { "Pentium III", CPUCLASS_686 }, /* CPU_PIII */ 105}; 106 107static void 108do_cpuid(u_int ax, u_int *p) 109{ 110 __asm __volatile( 111 ".byte 0x0f, 0xa2;" 112 "movl %%eax, (%2);" 113 "movl %%ebx, 4(%2);" 114 "movl %%ecx, 8(%2);" 115 "movl %%edx, 12(%2);" 116 : "=a" (ax) 117 : "0" (ax), "S" (p) 118 : "bx", "cx", "dx" 119 ); 120} 121 122#if defined(I586_CPU) && !defined(NO_F00F_HACK) 123int has_f00f_bug = 0; 124#endif 125 126void 127printcpuinfo(void) 128{ 129 130 u_int regs[4], nreg; 131 cpu_class = i386_cpus[cpu].cpu_class; 132 printf("CPU: "); 133 strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); 134 135#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 136 if (strcmp(cpu_vendor,"GenuineIntel") == 0) { 137 if ((cpu_id & 0xf00) > 0x300) { 138 cpu_model[0] = '\0'; 139 140 switch (cpu_id & 0x3000) { 141 case 0x1000: 142 strcpy(cpu_model, "Overdrive "); 143 break; 144 case 0x2000: 145 strcpy(cpu_model, "Dual "); 146 break; 147 } 148 149 switch (cpu_id & 0xf00) { 150 case 0x400: 151 strcat(cpu_model, "i486 "); 152 break; 153 case 0x500: 154 /* Check the particular flavor of 586 */ 155 strcat(cpu_model, "Pentium"); 156 switch (cpu_id & 0xf0) { 157 case 0x00: 158 strcat(cpu_model, " A-step"); 159 break; 160 case 0x10: 161 strcat(cpu_model, "/P5"); 162 break; 163 case 0x20: 164 strcat(cpu_model, "/P54C"); 165 break; 166 case 0x30: 167 strcat(cpu_model, "/P54T Overdrive"); 168 break; 169 case 0x40: 170 strcat(cpu_model, "/P55C"); 171 break; 172 case 0x70: 173 strcat(cpu_model, "/P54C"); 174 break; 175 case 0x80: 176 strcat(cpu_model, "/P55C (quarter-micron)"); 177 break; 178 default: 179 /* nothing */ 180 break; 181 } 182#if defined(I586_CPU) && !defined(NO_F00F_HACK) 183 /* 184 * XXX - If/when Intel fixes the bug, this 185 * should also check the version of the 186 * CPU, not just that it's a Pentium. 187 */ 188 has_f00f_bug = 1; 189#endif 190 break; 191 case 0x600: 192 /* Check the particular flavor of 686 */ 193 switch (cpu_id & 0xf0) { 194 case 0x00: 195 strcat(cpu_model, "Pentium Pro A-step"); 196 break; 197 case 0x10: 198 strcat(cpu_model, "Pentium Pro"); 199 break; 200 case 0x30: 201 strcat(cpu_model, "Pentium II"); 202 cpu = CPU_PII; 203 break; 204 case 0x50: 205 strcat(cpu_model, "Pentium II/Xeon/Celeron"); 206 cpu = CPU_PII; 207 break; 208 case 0x60: 209 strcat(cpu_model, "Celeron"); 210 cpu = CPU_PII; 211 break; 212 case 0x70: 213 strcat(cpu_model, "Pentium III"); 214 cpu = CPU_PIII; 215 break; 216 default: 217 strcat(cpu_model, "Unknown 80686"); 218 break; 219 } 220 break; 221 default: 222 strcat(cpu_model, "unknown"); 223 break; 224 } 225 226 switch (cpu_id & 0xff0) { 227 case 0x400: 228 strcat(cpu_model, "DX"); break; 229 case 0x410: 230 strcat(cpu_model, "DX"); break; 231 case 0x420: 232 strcat(cpu_model, "SX"); break; 233 case 0x430: 234 strcat(cpu_model, "DX2"); break; 235 case 0x440: 236 strcat(cpu_model, "SL"); break; 237 case 0x450: 238 strcat(cpu_model, "SX2"); break; 239 case 0x470: 240 strcat(cpu_model, "DX2 Write-Back Enhanced"); 241 break; 242 case 0x480: 243 strcat(cpu_model, "DX4"); break; 244 break; 245 } 246 } 247 } else if (strcmp(cpu_vendor,"AuthenticAMD") == 0) { 248 /* 249 * Values taken from AMD Processor Recognition 250 * http://www.amd.com/K6/k6docs/pdf/20734g.pdf 251 * (also describes ``Features'' encodings. 252 */ 253 strcpy(cpu_model, "AMD "); 254 switch (cpu_id & 0xFF0) { 255 case 0x410: 256 strcat(cpu_model, "Standard Am486DX"); 257 break; 258 case 0x430: 259 strcat(cpu_model, "Am486DX2/4 Write-Through"); 260 break; 261 case 0x470: 262 strcat(cpu_model, "Enhanced Am486DX4 Write-Back"); 263 break; 264 case 0x480: 265 strcat(cpu_model, "Enhanced Am486DX4 Write-Through"); 266 break; 267 case 0x490: 268 strcat(cpu_model, "Enhanced Am486DX4 Write-Back"); 269 break; 270 case 0x4E0: 271 strcat(cpu_model, "Am5x86 Write-Through"); 272 break; 273 case 0x4F0: 274 strcat(cpu_model, "Am5x86 Write-Back"); 275 break; 276 case 0x500: 277 strcat(cpu_model, "K5 model 0"); 278 tsc_is_broken = 1; 279 break; 280 case 0x510: 281 strcat(cpu_model, "K5 model 1"); 282 break; 283 case 0x520: 284 strcat(cpu_model, "K5 PR166 (model 2)"); 285 break; 286 case 0x530: 287 strcat(cpu_model, "K5 PR200 (model 3)"); 288 break; 289 case 0x560: 290 strcat(cpu_model, "K6"); 291 break; 292 case 0x570: 293 strcat(cpu_model, "K6 266 (model 1)"); 294 break; 295 case 0x580: 296 strcat(cpu_model, "K6-2"); 297 break; 298 default: 299 strcat(cpu_model, "Unknown"); 300 break; 301 } 302#ifdef CPU_WT_ALLOC 303 if ((cpu_id & 0xf00) == 0x500) { 304 if (((cpu_id & 0x0f0) > 0) 305 && ((cpu_id & 0x0f0) < 0x60) 306 && ((cpu_id & 0x00f) > 3)) 307 enable_K5_wt_alloc(); 308 else if (((cpu_id & 0x0f0) > 0x80) 309 || (((cpu_id & 0x0f0) == 0x80) 310 && (cpu_id & 0x00f) > 0x07)) 311 enable_K6_2_wt_alloc(); 312 else if ((cpu_id & 0x0f0) > 0x50) 313 enable_K6_wt_alloc(); 314 } 315#endif 316 do_cpuid(0x80000000, regs); 317 nreg = regs[0]; 318 if (nreg >= 0x80000004) { 319 do_cpuid(0x80000002, regs); 320 memcpy(cpu_model, regs, sizeof regs); 321 do_cpuid(0x80000003, regs); 322 memcpy(cpu_model+16, regs, sizeof regs); 323 do_cpuid(0x80000004, regs); 324 memcpy(cpu_model+32, regs, sizeof regs); 325 } 326 } else if (strcmp(cpu_vendor,"CyrixInstead") == 0) { 327 strcpy(cpu_model, "Cyrix "); 328 switch (cpu_id & 0xff0) { 329 case 0x440: 330 strcat(cpu_model, "MediaGX"); 331 break; 332 case 0x520: 333 strcat(cpu_model, "6x86"); 334 break; 335 case 0x540: 336 cpu_class = CPUCLASS_586; 337 strcat(cpu_model, "GXm"); 338 break; 339 case 0x600: 340 strcat(cpu_model, "6x86MX"); 341 break; 342 default: 343 /* 344 * Even though CPU supports the cpuid 345 * instruction, it can be disabled. 346 * Therefore, this routine supports all Cyrix 347 * CPUs. 348 */ 349 switch (cyrix_did & 0xf0) { 350 case 0x00: 351 switch (cyrix_did & 0x0f) { 352 case 0x00: 353 strcat(cpu_model, "486SLC"); 354 break; 355 case 0x01: 356 strcat(cpu_model, "486DLC"); 357 break; 358 case 0x02: 359 strcat(cpu_model, "486SLC2"); 360 break; 361 case 0x03: 362 strcat(cpu_model, "486DLC2"); 363 break; 364 case 0x04: 365 strcat(cpu_model, "486SRx"); 366 break; 367 case 0x05: 368 strcat(cpu_model, "486DRx"); 369 break; 370 case 0x06: 371 strcat(cpu_model, "486SRx2"); 372 break; 373 case 0x07: 374 strcat(cpu_model, "486DRx2"); 375 break; 376 case 0x08: 377 strcat(cpu_model, "486SRu"); 378 break; 379 case 0x09: 380 strcat(cpu_model, "486DRu"); 381 break; 382 case 0x0a: 383 strcat(cpu_model, "486SRu2"); 384 break; 385 case 0x0b: 386 strcat(cpu_model, "486DRu2"); 387 break; 388 default: 389 strcat(cpu_model, "Unknown"); 390 break; 391 } 392 break; 393 case 0x10: 394 switch (cyrix_did & 0x0f) { 395 case 0x00: 396 strcat(cpu_model, "486S"); 397 break; 398 case 0x01: 399 strcat(cpu_model, "486S2"); 400 break; 401 case 0x02: 402 strcat(cpu_model, "486Se"); 403 break; 404 case 0x03: 405 strcat(cpu_model, "486S2e"); 406 break; 407 case 0x0a: 408 strcat(cpu_model, "486DX"); 409 break; 410 case 0x0b: 411 strcat(cpu_model, "486DX2"); 412 break; 413 case 0x0f: 414 strcat(cpu_model, "486DX4"); 415 break; 416 default: 417 strcat(cpu_model, "Unknown"); 418 break; 419 } 420 break; 421 case 0x20: 422 if ((cyrix_did & 0x0f) < 8) 423 strcat(cpu_model, "6x86"); /* Where did you get it? */ 424 else 425 strcat(cpu_model, "5x86"); 426 break; 427 case 0x30: 428 strcat(cpu_model, "6x86"); 429 break; 430 case 0x40: 431 if ((cyrix_did & 0xf000) == 0x3000) { 432 cpu_class = CPUCLASS_586; 433 strcat(cpu_model, "GXm"); 434 } else 435 strcat(cpu_model, "MediaGX"); 436 break; 437 case 0x50: 438 strcat(cpu_model, "6x86MX"); 439 break; 440 case 0xf0: 441 switch (cyrix_did & 0x0f) { 442 case 0x0d: 443 strcat(cpu_model, "Overdrive CPU"); 444 case 0x0e: 445 strcpy(cpu_model, "Texas Instruments 486SXL"); 446 break; 447 case 0x0f: 448 strcat(cpu_model, "486SLC/DLC"); 449 break; 450 default: 451 strcat(cpu_model, "Unknown"); 452 break; 453 } 454 break; 455 default: 456 strcat(cpu_model, "Unknown"); 457 break; 458 } 459 break; 460 } 461 } else if (strcmp(cpu_vendor,"IBM") == 0) 462 strcpy(cpu_model, "Blue Lightning CPU"); 463#endif 464 465 printf("%s (", cpu_model); 466 switch(cpu_class) { 467 case CPUCLASS_286: 468 printf("286"); 469 break; 470#if defined(I386_CPU) 471 case CPUCLASS_386: 472 printf("386"); 473 break; 474#endif 475#if defined(I486_CPU) 476 case CPUCLASS_486: 477 printf("486"); 478 bzero = i486_bzero; 479 break; 480#endif 481#if defined(I586_CPU) 482 case CPUCLASS_586: 483#ifndef SMP 484 printf("%d.%02d-MHz ", 485 (tsc_freq + 4999) / 1000000, 486 ((tsc_freq + 4999) / 10000) % 100); 487#endif 488 printf("586"); 489 break; 490#endif 491#if defined(I686_CPU) 492 case CPUCLASS_686: 493#ifndef SMP 494 printf("%d.%02d-MHz ", 495 (tsc_freq + 4999) / 1000000, 496 ((tsc_freq + 4999) / 10000) % 100); 497#endif 498 printf("686"); 499 break; 500#endif 501 default: 502 printf("unknown"); /* will panic below... */ 503 } 504 printf("-class CPU)\n"); 505#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 506 if(*cpu_vendor) 507 printf(" Origin = \"%s\"",cpu_vendor); 508 if(cpu_id) 509 printf(" Id = 0x%x", cpu_id); 510 511 if (strcmp(cpu_vendor, "GenuineIntel") == 0 || 512 strcmp(cpu_vendor, "AuthenticAMD") == 0 || 513 ((strcmp(cpu_vendor, "CyrixInstead") == 0) && 514 ((cpu_id & 0xf00) > 0x500))) { 515 printf(" Stepping=%u", cpu_id & 0xf); 516 if (strcmp(cpu_vendor, "CyrixInstead") == 0) 517 printf(" DIR=0x%04x", cyrix_did); 518 if (cpu_high > 0) { 519 /* 520 * Here we should probably set up flags indicating 521 * whether or not various features are available. 522 * The interesting ones are probably VME, PSE, PAE, 523 * and PGE. The code already assumes without bothering 524 * to check that all CPUs >= Pentium have a TSC and 525 * MSRs. 526 */ 527 printf("\n Features=0x%b", cpu_feature, 528 "\020" 529 "\001FPU" 530 "\002VME" 531 "\003DE" 532 "\004PSE" 533 "\005TSC" 534 "\006MSR" 535 "\007PAE" 536 "\010MCE" 537 "\011CX8" 538 "\012APIC" 539 "\013oldMTRR" 540 "\014SEP" 541 "\015MTRR" 542 "\016PGE" 543 "\017MCA" 544 "\020CMOV" 545 "\021PAT" 546 "\022PSE36" 547 "\023<b18>" 548 "\024<b19>" 549 "\025<b20>" 550 "\026<b21>" 551 "\027<b22>" 552 "\030MMX" 553 "\031FXSR" 554 "\032<b25>" 555 "\033<b26>" 556 "\034<b27>" 557 "\035<b28>" 558 "\036<b29>" 559 "\037<b30>" 560 "\040<b31>" 561 ); 562 } 563 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { 564 printf(" DIR=0x%04x", cyrix_did); 565 printf(" Stepping=%u", (cyrix_did & 0xf000) >> 12); 566 printf(" Revision=%u", (cyrix_did & 0x0f00) >> 8); 567#ifndef CYRIX_CACHE_REALLY_WORKS 568 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700) 569 printf("\n CPU cache: write-through mode"); 570#endif 571 } 572 /* Avoid ugly blank lines: only print newline when we have to. */ 573 if (*cpu_vendor || cpu_id) 574 printf("\n"); 575 576#endif 577 if (!bootverbose) 578 return; 579 580 if (strcmp(cpu_vendor, "AuthenticAMD") == 0) 581 print_AMD_info(); 582#ifdef I686_CPU 583 /* 584 * XXX - Do PPro CPUID level=2 stuff here? 585 * 586 * No, but maybe in a print_Intel_info() function called from here. 587 */ 588#endif 589} 590 591void 592panicifcpuunsupported(void) 593{ 594 595 /* 596 * Now that we have told the user what they have, 597 * let them know if that machine type isn't configured. 598 */ 599 switch (cpu_class) { 600 case CPUCLASS_286: /* a 286 should not make it this far, anyway */ 601#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU) 602#error This kernel is not configured for one of the supported CPUs 603#endif 604#if !defined(I386_CPU) 605 case CPUCLASS_386: 606#endif 607#if !defined(I486_CPU) 608 case CPUCLASS_486: 609#endif 610#if !defined(I586_CPU) 611 case CPUCLASS_586: 612#endif 613#if !defined(I686_CPU) 614 case CPUCLASS_686: 615#endif 616 panic("CPU class not configured"); 617 default: 618 break; 619 } 620} 621 622 623static volatile u_int trap_by_rdmsr; 624 625/* 626 * Special exception 6 handler. 627 * The rdmsr instruction generates invalid opcodes fault on 486-class 628 * Cyrix CPU. Stacked eip register points the rdmsr instruction in the 629 * function identblue() when this handler is called. Stacked eip should 630 * be advanced. 631 */ 632inthand_t bluetrap6; 633__asm 634(" 635 .text 636 .p2align 2,0x90 637 .type " __XSTRING(CNAME(bluetrap6)) ",@function 638" __XSTRING(CNAME(bluetrap6)) ": 639 ss 640 movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " 641 addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. 642 iret 643"); 644 645/* 646 * Special exception 13 handler. 647 * Accessing non-existent MSR generates general protection fault. 648 */ 649inthand_t bluetrap13; 650__asm 651(" 652 .text 653 .p2align 2,0x90 654 .type " __XSTRING(CNAME(bluetrap13)) ",@function 655" __XSTRING(CNAME(bluetrap13)) ": 656 ss 657 movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " 658 popl %eax # discard errorcode. 659 addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. 660 iret 661"); 662 663/* 664 * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not 665 * support cpuid instruction. This function should be called after 666 * loading interrupt descriptor table register. 667 * 668 * I don't like this method that handles fault, but I couldn't get 669 * information for any other methods. Does blue giant know? 670 */ 671static int 672identblue(void) 673{ 674 675 trap_by_rdmsr = 0; 676 677 /* 678 * Cyrix 486-class CPU does not support rdmsr instruction. 679 * The rdmsr instruction generates invalid opcode fault, and exception 680 * will be trapped by bluetrap6() on Cyrix 486-class CPU. The 681 * bluetrap6() set the magic number to trap_by_rdmsr. 682 */ 683 setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 684 685 /* 686 * Certain BIOS disables cpuid instructnion of Cyrix 6x86MX CPU. 687 * In this case, rdmsr generates general protection fault, and 688 * exception will be trapped by bluetrap13(). 689 */ 690 setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 691 692 rdmsr(0x1002); /* Cyrix CPU generates fault. */ 693 694 if (trap_by_rdmsr == 0xa8c1d) 695 return IDENTBLUE_CYRIX486; 696 else if (trap_by_rdmsr == 0xa89c4) 697 return IDENTBLUE_CYRIXM2; 698 return IDENTBLUE_IBMCPU; 699} 700 701 702/* 703 * identifycyrix() set lower 16 bits of cyrix_did as follows: 704 * 705 * F E D C B A 9 8 7 6 5 4 3 2 1 0 706 * +-------+-------+---------------+ 707 * | SID | RID | Device ID | 708 * | (DIR 1) | (DIR 0) | 709 * +-------+-------+---------------+ 710 */ 711static void 712identifycyrix(void) 713{ 714 u_int eflags; 715 int ccr2_test = 0, dir_test = 0; 716 u_char ccr2, ccr3; 717 718 eflags = read_eflags(); 719 disable_intr(); 720 721 ccr2 = read_cyrix_reg(CCR2); 722 write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW); 723 read_cyrix_reg(CCR2); 724 if (read_cyrix_reg(CCR2) != ccr2) 725 ccr2_test = 1; 726 write_cyrix_reg(CCR2, ccr2); 727 728 ccr3 = read_cyrix_reg(CCR3); 729 write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3); 730 read_cyrix_reg(CCR3); 731 if (read_cyrix_reg(CCR3) != ccr3) 732 dir_test = 1; /* CPU supports DIRs. */ 733 write_cyrix_reg(CCR3, ccr3); 734 735 if (dir_test) { 736 /* Device ID registers are available. */ 737 cyrix_did = read_cyrix_reg(DIR1) << 8; 738 cyrix_did += read_cyrix_reg(DIR0); 739 } else if (ccr2_test) 740 cyrix_did = 0x0010; /* 486S A-step */ 741 else 742 cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */ 743 744 write_eflags(eflags); 745} 746 747/* 748 * Final stage of CPU identification. -- Should I check TI? 749 */ 750void 751finishidentcpu(void) 752{ 753 int isblue = 0; 754 u_char ccr3; 755 u_int regs[4]; 756 757 if (strcmp(cpu_vendor, "CyrixInstead") == 0) { 758 if (cpu == CPU_486) { 759 /* 760 * These conditions are equivalent to: 761 * - CPU does not support cpuid instruction. 762 * - Cyrix/IBM CPU is detected. 763 */ 764 isblue = identblue(); 765 if (isblue == IDENTBLUE_IBMCPU) { 766 strcpy(cpu_vendor, "IBM"); 767 cpu = CPU_BLUE; 768 return; 769 } 770 } 771 switch (cpu_id & 0xf00) { 772 case 0x600: 773 /* 774 * Cyrix's datasheet does not describe DIRs. 775 * Therefor, I assume it does not have them 776 * and use the result of the cpuid instruction. 777 * XXX they seem to have it for now at least. -Peter 778 */ 779 identifycyrix(); 780 cpu = CPU_M2; 781 break; 782 default: 783 identifycyrix(); 784 /* 785 * This routine contains a trick. 786 * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now. 787 */ 788 switch (cyrix_did & 0x00f0) { 789 case 0x00: 790 case 0xf0: 791 cpu = CPU_486DLC; 792 break; 793 case 0x10: 794 cpu = CPU_CY486DX; 795 break; 796 case 0x20: 797 if ((cyrix_did & 0x000f) < 8) 798 cpu = CPU_M1; 799 else 800 cpu = CPU_M1SC; 801 break; 802 case 0x30: 803 cpu = CPU_M1; 804 break; 805 case 0x40: 806 /* MediaGX CPU */ 807 cpu = CPU_M1SC; 808 break; 809 default: 810 /* M2 and later CPUs are treated as M2. */ 811 cpu = CPU_M2; 812 813 /* 814 * enable cpuid instruction. 815 */ 816 ccr3 = read_cyrix_reg(CCR3); 817 write_cyrix_reg(CCR3, CCR3_MAPEN0); 818 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID); 819 write_cyrix_reg(CCR3, ccr3); 820 821 do_cpuid(0, regs); 822 cpu_high = regs[0]; /* eax */ 823 do_cpuid(1, regs); 824 cpu_id = regs[0]; /* eax */ 825 cpu_feature = regs[3]; /* edx */ 826 break; 827 } 828 } 829 } 830} 831 832/* 833 * This routine is called specifically to set up cpu_class before 834 * startrtclock() uses it. Probably this should be rearranged so that 835 * startrtclock() doesn't need to run until after identifycpu() has been 836 * called. Another alternative formulation would be for this routine 837 * to do all the identification work, and make identifycpu() into a 838 * printing-only routine. 839 */ 840void 841earlysetcpuclass(void) 842{ 843 844 cpu_class = i386_cpus[cpu].cpu_class; 845} 846 847static void 848print_AMD_assoc(int i) 849{ 850 if (i == 255) 851 printf(", fully associative\n"); 852 else 853 printf(", %d-way associative\n", i); 854} 855 856static void 857print_AMD_info(void) 858{ 859 u_int regs[4]; 860 quad_t amd_whcr; 861 862 do_cpuid(0x80000000, regs); 863 if (regs[0] >= 0x80000005) { 864 do_cpuid(0x80000005, regs); 865 printf("Data TLB: %d entries", (regs[1] >> 16) & 0xff); 866 print_AMD_assoc(regs[1] >> 24); 867 printf("Instruction TLB: %d entries", regs[1] & 0xff); 868 print_AMD_assoc((regs[1] >> 8) & 0xff); 869 printf("L1 data cache: %d kbytes", regs[2] >> 24); 870 printf(", %d bytes/line", regs[2] & 0xff); 871 printf(", %d lines/tag", (regs[2] >> 8) & 0xff); 872 print_AMD_assoc((regs[2] >> 16) & 0xff); 873 printf("L1 instruction cache: %d kbytes", regs[3] >> 24); 874 printf(", %d bytes/line", regs[3] & 0xff); 875 printf(", %d lines/tag", (regs[3] >> 8) & 0xff); 876 print_AMD_assoc((regs[3] >> 16) & 0xff); 877 } 878 if (((cpu_id & 0xf00) == 0x500) 879 && (((cpu_id & 0x0f0) > 0x80) 880 || (((cpu_id & 0x0f0) == 0x80) 881 && (cpu_id & 0x00f) > 0x07))) { 882 /* K6-2(new core [Stepping 8-F]), K6-3 or later */ 883 amd_whcr = rdmsr(0xc0000082); 884 if (!(amd_whcr & (0x3ff << 22))) { 885 printf("Write Allocate Disable\n"); 886 } else { 887 printf("Write Allocate Enable Limit: %dM bytes\n", 888 (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4); 889 printf("Write Allocate 15-16M bytes: %s\n", 890 (amd_whcr & (1 << 16)) ? "Enable" : "Disable"); 891 } 892 } else if (((cpu_id & 0xf00) == 0x500) 893 && ((cpu_id & 0x0f0) > 0x50)) { 894 /* K6, K6-2(old core) */ 895 amd_whcr = rdmsr(0xc0000082); 896 if (!(amd_whcr & (0x7f << 1))) { 897 printf("Write Allocate Disable\n"); 898 } else { 899 printf("Write Allocate Enable Limit: %dM bytes\n", 900 (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4); 901 printf("Write Allocate 15-16M bytes: %s\n", 902 (amd_whcr & 0x0001) ? "Enable" : "Disable"); 903 printf("Hardware Write Allocate Control: %s\n", 904 (amd_whcr & 0x0100) ? "Enable" : "Disable"); 905 } 906 } 907} 908