identcpu.c revision 48571
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.65 1999/06/24 20:08:56 jlemon 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 case 0x590: 299 strcat(cpu_model, "K6-III"); 300 break; 301 default: 302 strcat(cpu_model, "Unknown"); 303 break; 304 } 305#if defined(I586_CPU) && defined(CPU_WT_ALLOC) 306 if ((cpu_id & 0xf00) == 0x500) { 307 if (((cpu_id & 0x0f0) > 0) 308 && ((cpu_id & 0x0f0) < 0x60) 309 && ((cpu_id & 0x00f) > 3)) 310 enable_K5_wt_alloc(); 311 else if (((cpu_id & 0x0f0) > 0x80) 312 || (((cpu_id & 0x0f0) == 0x80) 313 && (cpu_id & 0x00f) > 0x07)) 314 enable_K6_2_wt_alloc(); 315 else if ((cpu_id & 0x0f0) > 0x50) 316 enable_K6_wt_alloc(); 317 } 318#endif 319 do_cpuid(0x80000000, regs); 320 nreg = regs[0]; 321 if (nreg >= 0x80000004) { 322 do_cpuid(0x80000002, regs); 323 memcpy(cpu_model, regs, sizeof regs); 324 do_cpuid(0x80000003, regs); 325 memcpy(cpu_model+16, regs, sizeof regs); 326 do_cpuid(0x80000004, regs); 327 memcpy(cpu_model+32, regs, sizeof regs); 328 } 329 } else if (strcmp(cpu_vendor,"CyrixInstead") == 0) { 330 strcpy(cpu_model, "Cyrix "); 331 switch (cpu_id & 0xff0) { 332 case 0x440: 333 strcat(cpu_model, "MediaGX"); 334 break; 335 case 0x520: 336 strcat(cpu_model, "6x86"); 337 break; 338 case 0x540: 339 cpu_class = CPUCLASS_586; 340 strcat(cpu_model, "GXm"); 341 break; 342 case 0x600: 343 strcat(cpu_model, "6x86MX"); 344 break; 345 default: 346 /* 347 * Even though CPU supports the cpuid 348 * instruction, it can be disabled. 349 * Therefore, this routine supports all Cyrix 350 * CPUs. 351 */ 352 switch (cyrix_did & 0xf0) { 353 case 0x00: 354 switch (cyrix_did & 0x0f) { 355 case 0x00: 356 strcat(cpu_model, "486SLC"); 357 break; 358 case 0x01: 359 strcat(cpu_model, "486DLC"); 360 break; 361 case 0x02: 362 strcat(cpu_model, "486SLC2"); 363 break; 364 case 0x03: 365 strcat(cpu_model, "486DLC2"); 366 break; 367 case 0x04: 368 strcat(cpu_model, "486SRx"); 369 break; 370 case 0x05: 371 strcat(cpu_model, "486DRx"); 372 break; 373 case 0x06: 374 strcat(cpu_model, "486SRx2"); 375 break; 376 case 0x07: 377 strcat(cpu_model, "486DRx2"); 378 break; 379 case 0x08: 380 strcat(cpu_model, "486SRu"); 381 break; 382 case 0x09: 383 strcat(cpu_model, "486DRu"); 384 break; 385 case 0x0a: 386 strcat(cpu_model, "486SRu2"); 387 break; 388 case 0x0b: 389 strcat(cpu_model, "486DRu2"); 390 break; 391 default: 392 strcat(cpu_model, "Unknown"); 393 break; 394 } 395 break; 396 case 0x10: 397 switch (cyrix_did & 0x0f) { 398 case 0x00: 399 strcat(cpu_model, "486S"); 400 break; 401 case 0x01: 402 strcat(cpu_model, "486S2"); 403 break; 404 case 0x02: 405 strcat(cpu_model, "486Se"); 406 break; 407 case 0x03: 408 strcat(cpu_model, "486S2e"); 409 break; 410 case 0x0a: 411 strcat(cpu_model, "486DX"); 412 break; 413 case 0x0b: 414 strcat(cpu_model, "486DX2"); 415 break; 416 case 0x0f: 417 strcat(cpu_model, "486DX4"); 418 break; 419 default: 420 strcat(cpu_model, "Unknown"); 421 break; 422 } 423 break; 424 case 0x20: 425 if ((cyrix_did & 0x0f) < 8) 426 strcat(cpu_model, "6x86"); /* Where did you get it? */ 427 else 428 strcat(cpu_model, "5x86"); 429 break; 430 case 0x30: 431 strcat(cpu_model, "6x86"); 432 break; 433 case 0x40: 434 if ((cyrix_did & 0xf000) == 0x3000) { 435 cpu_class = CPUCLASS_586; 436 strcat(cpu_model, "GXm"); 437 } else 438 strcat(cpu_model, "MediaGX"); 439 break; 440 case 0x50: 441 strcat(cpu_model, "6x86MX"); 442 break; 443 case 0xf0: 444 switch (cyrix_did & 0x0f) { 445 case 0x0d: 446 strcat(cpu_model, "Overdrive CPU"); 447 case 0x0e: 448 strcpy(cpu_model, "Texas Instruments 486SXL"); 449 break; 450 case 0x0f: 451 strcat(cpu_model, "486SLC/DLC"); 452 break; 453 default: 454 strcat(cpu_model, "Unknown"); 455 break; 456 } 457 break; 458 default: 459 strcat(cpu_model, "Unknown"); 460 break; 461 } 462 break; 463 } 464 } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) { 465 strcpy(cpu_model, "Rise "); 466 switch (cpu_id & 0xff0) { 467 case 0x500: 468 strcat(cpu_model, "mP6"); 469 break; 470 default: 471 strcat(cpu_model, "Unknown"); 472 } 473 } else if (strcmp(cpu_vendor, "IBM") == 0) 474 strcpy(cpu_model, "Blue Lightning CPU"); 475#endif 476 477 printf("%s (", cpu_model); 478 switch(cpu_class) { 479 case CPUCLASS_286: 480 printf("286"); 481 break; 482#if defined(I386_CPU) 483 case CPUCLASS_386: 484 printf("386"); 485 break; 486#endif 487#if defined(I486_CPU) 488 case CPUCLASS_486: 489 printf("486"); 490 bzero = i486_bzero; 491 break; 492#endif 493#if defined(I586_CPU) 494 case CPUCLASS_586: 495#ifndef SMP 496 printf("%d.%02d-MHz ", 497 (tsc_freq + 4999) / 1000000, 498 ((tsc_freq + 4999) / 10000) % 100); 499#endif 500 printf("586"); 501 break; 502#endif 503#if defined(I686_CPU) 504 case CPUCLASS_686: 505#ifndef SMP 506 printf("%d.%02d-MHz ", 507 (tsc_freq + 4999) / 1000000, 508 ((tsc_freq + 4999) / 10000) % 100); 509#endif 510 printf("686"); 511 break; 512#endif 513 default: 514 printf("unknown"); /* will panic below... */ 515 } 516 printf("-class CPU)\n"); 517#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 518 if(*cpu_vendor) 519 printf(" Origin = \"%s\"",cpu_vendor); 520 if(cpu_id) 521 printf(" Id = 0x%x", cpu_id); 522 523 if (strcmp(cpu_vendor, "GenuineIntel") == 0 || 524 strcmp(cpu_vendor, "AuthenticAMD") == 0 || 525 strcmp(cpu_vendor, "RiseRiseRise") == 0 || 526 ((strcmp(cpu_vendor, "CyrixInstead") == 0) && 527 ((cpu_id & 0xf00) > 0x500))) { 528 printf(" Stepping=%u", cpu_id & 0xf); 529 if (strcmp(cpu_vendor, "CyrixInstead") == 0) 530 printf(" DIR=0x%04x", cyrix_did); 531 if (cpu_high > 0) { 532 /* 533 * Here we should probably set up flags indicating 534 * whether or not various features are available. 535 * The interesting ones are probably VME, PSE, PAE, 536 * and PGE. The code already assumes without bothering 537 * to check that all CPUs >= Pentium have a TSC and 538 * MSRs. 539 */ 540 printf("\n Features=0x%b", cpu_feature, 541 "\020" 542 "\001FPU" 543 "\002VME" 544 "\003DE" 545 "\004PSE" 546 "\005TSC" 547 "\006MSR" 548 "\007PAE" 549 "\010MCE" 550 "\011CX8" 551 "\012APIC" 552 "\013oldMTRR" 553 "\014SEP" 554 "\015MTRR" 555 "\016PGE" 556 "\017MCA" 557 "\020CMOV" 558 "\021PAT" 559 "\022PSE36" 560 "\023<b18>" 561 "\024<b19>" 562 "\025<b20>" 563 "\026<b21>" 564 "\027<b22>" 565 "\030MMX" 566 "\031FXSR" 567 "\032<b25>" 568 "\033<b26>" 569 "\034<b27>" 570 "\035<b28>" 571 "\036<b29>" 572 "\037<b30>" 573 "\040<b31>" 574 ); 575 } 576 } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { 577 printf(" DIR=0x%04x", cyrix_did); 578 printf(" Stepping=%u", (cyrix_did & 0xf000) >> 12); 579 printf(" Revision=%u", (cyrix_did & 0x0f00) >> 8); 580#ifndef CYRIX_CACHE_REALLY_WORKS 581 if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700) 582 printf("\n CPU cache: write-through mode"); 583#endif 584 } 585 /* Avoid ugly blank lines: only print newline when we have to. */ 586 if (*cpu_vendor || cpu_id) 587 printf("\n"); 588 589#endif 590 if (!bootverbose) 591 return; 592 593 if (strcmp(cpu_vendor, "AuthenticAMD") == 0) 594 print_AMD_info(); 595#ifdef I686_CPU 596 /* 597 * XXX - Do PPro CPUID level=2 stuff here? 598 * 599 * No, but maybe in a print_Intel_info() function called from here. 600 */ 601#endif 602} 603 604void 605panicifcpuunsupported(void) 606{ 607 608 /* 609 * Now that we have told the user what they have, 610 * let them know if that machine type isn't configured. 611 */ 612 switch (cpu_class) { 613 case CPUCLASS_286: /* a 286 should not make it this far, anyway */ 614#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU) 615#error This kernel is not configured for one of the supported CPUs 616#endif 617#if !defined(I386_CPU) 618 case CPUCLASS_386: 619#endif 620#if !defined(I486_CPU) 621 case CPUCLASS_486: 622#endif 623#if !defined(I586_CPU) 624 case CPUCLASS_586: 625#endif 626#if !defined(I686_CPU) 627 case CPUCLASS_686: 628#endif 629 panic("CPU class not configured"); 630 default: 631 break; 632 } 633} 634 635 636static volatile u_int trap_by_rdmsr; 637 638/* 639 * Special exception 6 handler. 640 * The rdmsr instruction generates invalid opcodes fault on 486-class 641 * Cyrix CPU. Stacked eip register points the rdmsr instruction in the 642 * function identblue() when this handler is called. Stacked eip should 643 * be advanced. 644 */ 645inthand_t bluetrap6; 646__asm 647(" 648 .text 649 .p2align 2,0x90 650 .type " __XSTRING(CNAME(bluetrap6)) ",@function 651" __XSTRING(CNAME(bluetrap6)) ": 652 ss 653 movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " 654 addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. 655 iret 656"); 657 658/* 659 * Special exception 13 handler. 660 * Accessing non-existent MSR generates general protection fault. 661 */ 662inthand_t bluetrap13; 663__asm 664(" 665 .text 666 .p2align 2,0x90 667 .type " __XSTRING(CNAME(bluetrap13)) ",@function 668" __XSTRING(CNAME(bluetrap13)) ": 669 ss 670 movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " 671 popl %eax # discard errorcode. 672 addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. 673 iret 674"); 675 676/* 677 * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not 678 * support cpuid instruction. This function should be called after 679 * loading interrupt descriptor table register. 680 * 681 * I don't like this method that handles fault, but I couldn't get 682 * information for any other methods. Does blue giant know? 683 */ 684static int 685identblue(void) 686{ 687 688 trap_by_rdmsr = 0; 689 690 /* 691 * Cyrix 486-class CPU does not support rdmsr instruction. 692 * The rdmsr instruction generates invalid opcode fault, and exception 693 * will be trapped by bluetrap6() on Cyrix 486-class CPU. The 694 * bluetrap6() set the magic number to trap_by_rdmsr. 695 */ 696 setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 697 698 /* 699 * Certain BIOS disables cpuid instructnion of Cyrix 6x86MX CPU. 700 * In this case, rdmsr generates general protection fault, and 701 * exception will be trapped by bluetrap13(). 702 */ 703 setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 704 705 rdmsr(0x1002); /* Cyrix CPU generates fault. */ 706 707 if (trap_by_rdmsr == 0xa8c1d) 708 return IDENTBLUE_CYRIX486; 709 else if (trap_by_rdmsr == 0xa89c4) 710 return IDENTBLUE_CYRIXM2; 711 return IDENTBLUE_IBMCPU; 712} 713 714 715/* 716 * identifycyrix() set lower 16 bits of cyrix_did as follows: 717 * 718 * F E D C B A 9 8 7 6 5 4 3 2 1 0 719 * +-------+-------+---------------+ 720 * | SID | RID | Device ID | 721 * | (DIR 1) | (DIR 0) | 722 * +-------+-------+---------------+ 723 */ 724static void 725identifycyrix(void) 726{ 727 u_int eflags; 728 int ccr2_test = 0, dir_test = 0; 729 u_char ccr2, ccr3; 730 731 eflags = read_eflags(); 732 disable_intr(); 733 734 ccr2 = read_cyrix_reg(CCR2); 735 write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW); 736 read_cyrix_reg(CCR2); 737 if (read_cyrix_reg(CCR2) != ccr2) 738 ccr2_test = 1; 739 write_cyrix_reg(CCR2, ccr2); 740 741 ccr3 = read_cyrix_reg(CCR3); 742 write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3); 743 read_cyrix_reg(CCR3); 744 if (read_cyrix_reg(CCR3) != ccr3) 745 dir_test = 1; /* CPU supports DIRs. */ 746 write_cyrix_reg(CCR3, ccr3); 747 748 if (dir_test) { 749 /* Device ID registers are available. */ 750 cyrix_did = read_cyrix_reg(DIR1) << 8; 751 cyrix_did += read_cyrix_reg(DIR0); 752 } else if (ccr2_test) 753 cyrix_did = 0x0010; /* 486S A-step */ 754 else 755 cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */ 756 757 write_eflags(eflags); 758} 759 760/* 761 * Final stage of CPU identification. -- Should I check TI? 762 */ 763void 764finishidentcpu(void) 765{ 766 int isblue = 0; 767 u_char ccr3; 768 u_int regs[4]; 769 770 if (strcmp(cpu_vendor, "CyrixInstead") == 0) { 771 if (cpu == CPU_486) { 772 /* 773 * These conditions are equivalent to: 774 * - CPU does not support cpuid instruction. 775 * - Cyrix/IBM CPU is detected. 776 */ 777 isblue = identblue(); 778 if (isblue == IDENTBLUE_IBMCPU) { 779 strcpy(cpu_vendor, "IBM"); 780 cpu = CPU_BLUE; 781 return; 782 } 783 } 784 switch (cpu_id & 0xf00) { 785 case 0x600: 786 /* 787 * Cyrix's datasheet does not describe DIRs. 788 * Therefor, I assume it does not have them 789 * and use the result of the cpuid instruction. 790 * XXX they seem to have it for now at least. -Peter 791 */ 792 identifycyrix(); 793 cpu = CPU_M2; 794 break; 795 default: 796 identifycyrix(); 797 /* 798 * This routine contains a trick. 799 * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now. 800 */ 801 switch (cyrix_did & 0x00f0) { 802 case 0x00: 803 case 0xf0: 804 cpu = CPU_486DLC; 805 break; 806 case 0x10: 807 cpu = CPU_CY486DX; 808 break; 809 case 0x20: 810 if ((cyrix_did & 0x000f) < 8) 811 cpu = CPU_M1; 812 else 813 cpu = CPU_M1SC; 814 break; 815 case 0x30: 816 cpu = CPU_M1; 817 break; 818 case 0x40: 819 /* MediaGX CPU */ 820 cpu = CPU_M1SC; 821 break; 822 default: 823 /* M2 and later CPUs are treated as M2. */ 824 cpu = CPU_M2; 825 826 /* 827 * enable cpuid instruction. 828 */ 829 ccr3 = read_cyrix_reg(CCR3); 830 write_cyrix_reg(CCR3, CCR3_MAPEN0); 831 write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID); 832 write_cyrix_reg(CCR3, ccr3); 833 834 do_cpuid(0, regs); 835 cpu_high = regs[0]; /* eax */ 836 do_cpuid(1, regs); 837 cpu_id = regs[0]; /* eax */ 838 cpu_feature = regs[3]; /* edx */ 839 break; 840 } 841 } 842 } 843} 844 845/* 846 * This routine is called specifically to set up cpu_class before 847 * startrtclock() uses it. Probably this should be rearranged so that 848 * startrtclock() doesn't need to run until after identifycpu() has been 849 * called. Another alternative formulation would be for this routine 850 * to do all the identification work, and make identifycpu() into a 851 * printing-only routine. 852 */ 853void 854earlysetcpuclass(void) 855{ 856 857 cpu_class = i386_cpus[cpu].cpu_class; 858} 859 860static void 861print_AMD_assoc(int i) 862{ 863 if (i == 255) 864 printf(", fully associative\n"); 865 else 866 printf(", %d-way associative\n", i); 867} 868 869static void 870print_AMD_info(void) 871{ 872 u_int regs[4], amd_maxregs; 873 quad_t amd_whcr; 874 875 do_cpuid(0x80000000, regs); 876 amd_maxregs = regs[0]; 877 878 if (amd_maxregs >= 0x80000001) { 879 do_cpuid(0x80000001, regs); 880 printf(" AMD Features=0x%b\n", regs[3], 881 "\020" /* in hex */ 882 "\001FPU" 883 "\002VME" 884 "\003DE" 885 "\004PSE" 886 "\005TSC" 887 "\006MSR" 888 "\007<b6>" 889 "\010MCE" 890 "\011CX8" 891 "\012<b9>" 892 "\013<b10>" 893 "\014SYSCALL" 894 "\015<b12>" 895 "\016PGE" 896 "\017<b14>" 897 "\020ICMOV" 898 "\021FCMOV" 899 "\022<b17>" 900 "\023<b18>" 901 "\024<b19>" 902 "\025<b20>" 903 "\026<b21>" 904 "\027<b22>" 905 "\030MMX" 906 "\031<b24>" 907 "\032<b25>" 908 "\033<b26>" 909 "\034<b27>" 910 "\035<b28>" 911 "\036<b29>" 912 "\037<b30>" 913 "\0403DNow!" 914 ); 915 } 916 if (amd_maxregs >= 0x80000005) { 917 do_cpuid(0x80000005, regs); 918 printf("Data TLB: %d entries", (regs[1] >> 16) & 0xff); 919 print_AMD_assoc(regs[1] >> 24); 920 printf("Instruction TLB: %d entries", regs[1] & 0xff); 921 print_AMD_assoc((regs[1] >> 8) & 0xff); 922 printf("L1 data cache: %d kbytes", regs[2] >> 24); 923 printf(", %d bytes/line", regs[2] & 0xff); 924 printf(", %d lines/tag", (regs[2] >> 8) & 0xff); 925 print_AMD_assoc((regs[2] >> 16) & 0xff); 926 printf("L1 instruction cache: %d kbytes", regs[3] >> 24); 927 printf(", %d bytes/line", regs[3] & 0xff); 928 printf(", %d lines/tag", (regs[3] >> 8) & 0xff); 929 print_AMD_assoc((regs[3] >> 16) & 0xff); 930 if (amd_maxregs >= 0x80000006) { /* K6-III only */ 931 do_cpuid(0x80000006, regs); 932 printf("L2 internal cache: %d kbytes", regs[2] >> 16); 933 printf(", %d bytes/line", regs[2] & 0xff); 934 printf(", %d lines/tag", (regs[2] >> 8) & 0x0f); 935 print_AMD_assoc((regs[2] >> 12) & 0x0f); 936 } 937 } 938 if (((cpu_id & 0xf00) == 0x500) 939 && (((cpu_id & 0x0f0) > 0x80) 940 || (((cpu_id & 0x0f0) == 0x80) 941 && (cpu_id & 0x00f) > 0x07))) { 942 /* K6-2(new core [Stepping 8-F]), K6-III or later */ 943 amd_whcr = rdmsr(0xc0000082); 944 if (!(amd_whcr & (0x3ff << 22))) { 945 printf("Write Allocate Disable\n"); 946 } else { 947 printf("Write Allocate Enable Limit: %dM bytes\n", 948 (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4); 949 printf("Write Allocate 15-16M bytes: %s\n", 950 (amd_whcr & (1 << 16)) ? "Enable" : "Disable"); 951 } 952 } else if (((cpu_id & 0xf00) == 0x500) 953 && ((cpu_id & 0x0f0) > 0x50)) { 954 /* K6, K6-2(old core) */ 955 amd_whcr = rdmsr(0xc0000082); 956 if (!(amd_whcr & (0x7f << 1))) { 957 printf("Write Allocate Disable\n"); 958 } else { 959 printf("Write Allocate Enable Limit: %dM bytes\n", 960 (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4); 961 printf("Write Allocate 15-16M bytes: %s\n", 962 (amd_whcr & 0x0001) ? "Enable" : "Disable"); 963 printf("Hardware Write Allocate Control: %s\n", 964 (amd_whcr & 0x0100) ? "Enable" : "Disable"); 965 } 966 } 967} 968