| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: identcpu.c,v 1.39 2013/12/23 11:40:57 msaitoh Exp $ */ | | 1 | /* $NetBSD: identcpu.c,v 1.40 2014/02/22 17:48:08 dsl Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Frank van der Linden, and by Jason R. Thorpe. | | 8 | * by Frank van der Linden, and by Jason R. Thorpe. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -20,27 +20,27 @@ | | | @@ -20,27 +20,27 @@ |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 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 | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.39 2013/12/23 11:40:57 msaitoh Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.40 2014/02/22 17:48:08 dsl Exp $"); |
34 | | | 34 | |
35 | #include "opt_xen.h" | | 35 | #include "opt_xen.h" |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/systm.h> | | 38 | #include <sys/systm.h> |
39 | #include <sys/device.h> | | 39 | #include <sys/device.h> |
40 | | | 40 | |
41 | #include <uvm/uvm_extern.h> | | 41 | #include <uvm/uvm_extern.h> |
42 | | | 42 | |
43 | #include <machine/specialreg.h> | | 43 | #include <machine/specialreg.h> |
44 | #include <machine/pio.h> | | 44 | #include <machine/pio.h> |
45 | #include <machine/cpu.h> | | 45 | #include <machine/cpu.h> |
46 | | | 46 | |
| @@ -125,27 +125,27 @@ cpu_probe_intel_cache(struct cpu_info *c | | | @@ -125,27 +125,27 @@ cpu_probe_intel_cache(struct cpu_info *c |
125 | ci->ci_cinfo[cai->cai_index] = | | 125 | ci->ci_cinfo[cai->cai_index] = |
126 | *cai; | | 126 | *cai; |
127 | } | | 127 | } |
128 | } | | 128 | } |
129 | } | | 129 | } |
130 | } | | 130 | } |
131 | } | | 131 | } |
132 | | | 132 | |
133 | if (cpuid_level >= 4) { | | 133 | if (cpuid_level >= 4) { |
134 | int type, level; | | 134 | int type, level; |
135 | int ways, partitions, linesize, sets; | | 135 | int ways, partitions, linesize, sets; |
136 | int caitype = -1; | | 136 | int caitype = -1; |
137 | int totalsize; | | 137 | int totalsize; |
138 | | | 138 | |
139 | /* Parse the cache info from `cpuid leaf 4', if we have it. */ | | 139 | /* Parse the cache info from `cpuid leaf 4', if we have it. */ |
140 | for (i = 0; ; i++) { | | 140 | for (i = 0; ; i++) { |
141 | x86_cpuid2(4, i, descs); | | 141 | x86_cpuid2(4, i, descs); |
142 | type = __SHIFTOUT(descs[0], CPUID_DCP_CACHETYPE); | | 142 | type = __SHIFTOUT(descs[0], CPUID_DCP_CACHETYPE); |
143 | if (type == CPUID_DCP_CACHETYPE_N) | | 143 | if (type == CPUID_DCP_CACHETYPE_N) |
144 | break; | | 144 | break; |
145 | level = __SHIFTOUT(descs[0], CPUID_DCP_CACHELEVEL); | | 145 | level = __SHIFTOUT(descs[0], CPUID_DCP_CACHELEVEL); |
146 | switch (level) { | | 146 | switch (level) { |
147 | case 1: | | 147 | case 1: |
148 | if (type == CPUID_DCP_CACHETYPE_I) | | 148 | if (type == CPUID_DCP_CACHETYPE_I) |
149 | caitype = CAI_ICACHE; | | 149 | caitype = CAI_ICACHE; |
150 | else if (type == CPUID_DCP_CACHETYPE_D) | | 150 | else if (type == CPUID_DCP_CACHETYPE_D) |
151 | caitype = CAI_DCACHE; | | 151 | caitype = CAI_DCACHE; |
| @@ -349,40 +349,31 @@ cpu_probe_k5(struct cpu_info *ci) | | | @@ -349,40 +349,31 @@ cpu_probe_k5(struct cpu_info *ci) |
349 | */ | | 349 | */ |
350 | flag = ci->ci_feat_val[0]; | | 350 | flag = ci->ci_feat_val[0]; |
351 | if ((flag & CPUID_APIC) != 0) | | 351 | if ((flag & CPUID_APIC) != 0) |
352 | flag = (flag & ~CPUID_APIC) | CPUID_PGE; | | 352 | flag = (flag & ~CPUID_APIC) | CPUID_PGE; |
353 | ci->ci_feat_val[0] = flag; | | 353 | ci->ci_feat_val[0] = flag; |
354 | } | | 354 | } |
355 | | | 355 | |
356 | cpu_probe_amd_cache(ci); | | 356 | cpu_probe_amd_cache(ci); |
357 | } | | 357 | } |
358 | | | 358 | |
359 | static void | | 359 | static void |
360 | cpu_probe_k678(struct cpu_info *ci) | | 360 | cpu_probe_k678(struct cpu_info *ci) |
361 | { | | 361 | { |
362 | uint32_t descs[4]; | | | |
363 | | | 362 | |
364 | if (cpu_vendor != CPUVENDOR_AMD || | | 363 | if (cpu_vendor != CPUVENDOR_AMD || |
365 | CPUID_TO_FAMILY(ci->ci_signature) < 6) | | 364 | CPUID_TO_FAMILY(ci->ci_signature) < 6) |
366 | return; | | 365 | return; |
367 | | | 366 | |
368 | /* Determine the extended feature flags. */ | | | |
369 | x86_cpuid(0x80000000, descs); | | | |
370 | if (descs[0] >= 0x80000001) { | | | |
371 | x86_cpuid(0x80000001, descs); | | | |
372 | ci->ci_feat_val[3] = descs[2]; /* %ecx */ | | | |
373 | ci->ci_feat_val[2] = descs[3]; /* %edx */ | | | |
374 | } | | | |
375 | | | | |
376 | cpu_probe_amd_cache(ci); | | 367 | cpu_probe_amd_cache(ci); |
377 | } | | 368 | } |
378 | | | 369 | |
379 | static inline uint8_t | | 370 | static inline uint8_t |
380 | cyrix_read_reg(uint8_t reg) | | 371 | cyrix_read_reg(uint8_t reg) |
381 | { | | 372 | { |
382 | | | 373 | |
383 | outb(0x22, reg); | | 374 | outb(0x22, reg); |
384 | return inb(0x23); | | 375 | return inb(0x23); |
385 | } | | 376 | } |
386 | | | 377 | |
387 | static inline void | | 378 | static inline void |
388 | cyrix_write_reg(uint8_t reg, uint8_t data) | | 379 | cyrix_write_reg(uint8_t reg, uint8_t data) |
| @@ -505,32 +496,26 @@ cpu_probe_c3(struct cpu_info *ci) | | | @@ -505,32 +496,26 @@ cpu_probe_c3(struct cpu_info *ci) |
505 | | | 496 | |
506 | if (cpu_vendor != CPUVENDOR_IDT || | | 497 | if (cpu_vendor != CPUVENDOR_IDT || |
507 | CPUID_TO_FAMILY(ci->ci_signature) < 6) | | 498 | CPUID_TO_FAMILY(ci->ci_signature) < 6) |
508 | return; | | 499 | return; |
509 | | | 500 | |
510 | family = CPUID_TO_FAMILY(ci->ci_signature); | | 501 | family = CPUID_TO_FAMILY(ci->ci_signature); |
511 | model = CPUID_TO_MODEL(ci->ci_signature); | | 502 | model = CPUID_TO_MODEL(ci->ci_signature); |
512 | stepping = CPUID_TO_STEPPING(ci->ci_signature); | | 503 | stepping = CPUID_TO_STEPPING(ci->ci_signature); |
513 | | | 504 | |
514 | /* Determine the largest extended function value. */ | | 505 | /* Determine the largest extended function value. */ |
515 | x86_cpuid(0x80000000, descs); | | 506 | x86_cpuid(0x80000000, descs); |
516 | lfunc = descs[0]; | | 507 | lfunc = descs[0]; |
517 | | | 508 | |
518 | /* Determine the extended feature flags. */ | | | |
519 | if (lfunc >= 0x80000001) { | | | |
520 | x86_cpuid(0x80000001, descs); | | | |
521 | ci->ci_feat_val[2] = descs[3]; | | | |
522 | } | | | |
523 | | | | |
524 | if (family > 6 || model > 0x9 || (model == 0x9 && stepping >= 3)) { | | 509 | if (family > 6 || model > 0x9 || (model == 0x9 && stepping >= 3)) { |
525 | /* Nehemiah or Esther */ | | 510 | /* Nehemiah or Esther */ |
526 | x86_cpuid(0xc0000000, descs); | | 511 | x86_cpuid(0xc0000000, descs); |
527 | lfunc = descs[0]; | | 512 | lfunc = descs[0]; |
528 | if (lfunc >= 0xc0000001) { /* has ACE, RNG */ | | 513 | if (lfunc >= 0xc0000001) { /* has ACE, RNG */ |
529 | int rng_enable = 0, ace_enable = 0; | | 514 | int rng_enable = 0, ace_enable = 0; |
530 | x86_cpuid(0xc0000001, descs); | | 515 | x86_cpuid(0xc0000001, descs); |
531 | lfunc = descs[3]; | | 516 | lfunc = descs[3]; |
532 | ci->ci_feat_val[4] = lfunc; | | 517 | ci->ci_feat_val[4] = lfunc; |
533 | /* Check for and enable RNG */ | | 518 | /* Check for and enable RNG */ |
534 | if (lfunc & CPUID_VIA_HAS_RNG) { | | 519 | if (lfunc & CPUID_VIA_HAS_RNG) { |
535 | if (!(lfunc & CPUID_VIA_DO_RNG)) { | | 520 | if (!(lfunc & CPUID_VIA_DO_RNG)) { |
536 | rng_enable++; | | 521 | rng_enable++; |
| @@ -565,27 +550,27 @@ cpu_probe_c3(struct cpu_info *ci) | | | @@ -565,27 +550,27 @@ cpu_probe_c3(struct cpu_info *ci) |
565 | ci->ci_feat_val[4] |= CPUID_VIA_DO_PMM; | | 550 | ci->ci_feat_val[4] |= CPUID_VIA_DO_PMM; |
566 | } | | 551 | } |
567 | } | | 552 | } |
568 | | | 553 | |
569 | /* Actually do the enables. */ | | 554 | /* Actually do the enables. */ |
570 | if (rng_enable) { | | 555 | if (rng_enable) { |
571 | msr = rdmsr(MSR_VIA_RNG); | | 556 | msr = rdmsr(MSR_VIA_RNG); |
572 | wrmsr(MSR_VIA_RNG, msr | MSR_VIA_RNG_ENABLE); | | 557 | wrmsr(MSR_VIA_RNG, msr | MSR_VIA_RNG_ENABLE); |
573 | } | | 558 | } |
574 | if (ace_enable) { | | 559 | if (ace_enable) { |
575 | msr = rdmsr(MSR_VIA_ACE); | | 560 | msr = rdmsr(MSR_VIA_ACE); |
576 | wrmsr(MSR_VIA_ACE, msr | MSR_VIA_ACE_ENABLE); | | 561 | wrmsr(MSR_VIA_ACE, msr | MSR_VIA_ACE_ENABLE); |
577 | } | | 562 | } |
578 | | | 563 | |
579 | } | | 564 | } |
580 | } | | 565 | } |
581 | | | 566 | |
582 | /* | | 567 | /* |
583 | * Determine L1 cache/TLB info. | | 568 | * Determine L1 cache/TLB info. |
584 | */ | | 569 | */ |
585 | if (lfunc < 0x80000005) { | | 570 | if (lfunc < 0x80000005) { |
586 | /* No L1 cache info available. */ | | 571 | /* No L1 cache info available. */ |
587 | return; | | 572 | return; |
588 | } | | 573 | } |
589 | | | 574 | |
590 | x86_cpuid(0x80000005, descs); | | 575 | x86_cpuid(0x80000005, descs); |
591 | | | 576 | |
| @@ -606,27 +591,27 @@ cpu_probe_c3(struct cpu_info *ci) | | | @@ -606,27 +591,27 @@ cpu_probe_c3(struct cpu_info *ci) |
606 | if (family == 6 && model == 9 && stepping == 8) { | | 591 | if (family == 6 && model == 9 && stepping == 8) { |
607 | /* Erratum: stepping 8 reports 4 when it should be 2 */ | | 592 | /* Erratum: stepping 8 reports 4 when it should be 2 */ |
608 | cai->cai_associativity = 2; | | 593 | cai->cai_associativity = 2; |
609 | } | | 594 | } |
610 | | | 595 | |
611 | cai = &ci->ci_cinfo[CAI_ICACHE]; | | 596 | cai = &ci->ci_cinfo[CAI_ICACHE]; |
612 | cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]); | | 597 | cai->cai_totalsize = VIA_L1_EDX_IC_SIZE(descs[3]); |
613 | cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]); | | 598 | cai->cai_associativity = VIA_L1_EDX_IC_ASSOC(descs[3]); |
614 | cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]); | | 599 | cai->cai_linesize = VIA_L1_EDX_IC_LS(descs[3]); |
615 | if (family == 6 && model == 9 && stepping == 8) { | | 600 | if (family == 6 && model == 9 && stepping == 8) { |
616 | /* Erratum: stepping 8 reports 4 when it should be 2 */ | | 601 | /* Erratum: stepping 8 reports 4 when it should be 2 */ |
617 | cai->cai_associativity = 2; | | 602 | cai->cai_associativity = 2; |
618 | } | | 603 | } |
619 | | | 604 | |
620 | /* | | 605 | /* |
621 | * Determine L2 cache/TLB info. | | 606 | * Determine L2 cache/TLB info. |
622 | */ | | 607 | */ |
623 | if (lfunc < 0x80000006) { | | 608 | if (lfunc < 0x80000006) { |
624 | /* No L2 cache info available. */ | | 609 | /* No L2 cache info available. */ |
625 | return; | | 610 | return; |
626 | } | | 611 | } |
627 | | | 612 | |
628 | x86_cpuid(0x80000006, descs); | | 613 | x86_cpuid(0x80000006, descs); |
629 | | | 614 | |
630 | cai = &ci->ci_cinfo[CAI_L2CACHE]; | | 615 | cai = &ci->ci_cinfo[CAI_L2CACHE]; |
631 | if (family > 6 || model >= 9) { | | 616 | if (family > 6 || model >= 9) { |
632 | cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]); | | 617 | cai->cai_totalsize = VIA_L2N_ECX_C_SIZE(descs[2]); |
| @@ -702,79 +687,99 @@ cpu_probe(struct cpu_info *ci) | | | @@ -702,79 +687,99 @@ cpu_probe(struct cpu_info *ci) |
702 | | | 687 | |
703 | cpu_vendor = i386_nocpuid_cpus[cputype << 1]; | | 688 | cpu_vendor = i386_nocpuid_cpus[cputype << 1]; |
704 | cpu_class = i386_nocpuid_cpus[(cputype << 1) + 1]; | | 689 | cpu_class = i386_nocpuid_cpus[(cputype << 1) + 1]; |
705 | | | 690 | |
706 | if (cpuid_level < 0) | | 691 | if (cpuid_level < 0) |
707 | return; | | 692 | return; |
708 | | | 693 | |
709 | for (i = 0; i < __arraycount(ci->ci_feat_val); i++) { | | 694 | for (i = 0; i < __arraycount(ci->ci_feat_val); i++) { |
710 | ci->ci_feat_val[i] = 0; | | 695 | ci->ci_feat_val[i] = 0; |
711 | } | | 696 | } |
712 | | | 697 | |
713 | x86_cpuid(0, descs); | | 698 | x86_cpuid(0, descs); |
714 | cpuid_level = descs[0]; | | 699 | cpuid_level = descs[0]; |
| | | 700 | ci->ci_max_cpuid = descs[0]; |
| | | 701 | |
715 | ci->ci_vendor[0] = descs[1]; | | 702 | ci->ci_vendor[0] = descs[1]; |
716 | ci->ci_vendor[2] = descs[2]; | | 703 | ci->ci_vendor[2] = descs[2]; |
717 | ci->ci_vendor[1] = descs[3]; | | 704 | ci->ci_vendor[1] = descs[3]; |
718 | ci->ci_vendor[3] = 0; | | 705 | ci->ci_vendor[3] = 0; |
719 | | | 706 | |
720 | if (memcmp(ci->ci_vendor, "GenuineIntel", 12) == 0) | | 707 | if (memcmp(ci->ci_vendor, "GenuineIntel", 12) == 0) |
721 | cpu_vendor = CPUVENDOR_INTEL; | | 708 | cpu_vendor = CPUVENDOR_INTEL; |
722 | else if (memcmp(ci->ci_vendor, "AuthenticAMD", 12) == 0) | | 709 | else if (memcmp(ci->ci_vendor, "AuthenticAMD", 12) == 0) |
723 | cpu_vendor = CPUVENDOR_AMD; | | 710 | cpu_vendor = CPUVENDOR_AMD; |
724 | else if (memcmp(ci->ci_vendor, "CyrixInstead", 12) == 0) | | 711 | else if (memcmp(ci->ci_vendor, "CyrixInstead", 12) == 0) |
725 | cpu_vendor = CPUVENDOR_CYRIX; | | 712 | cpu_vendor = CPUVENDOR_CYRIX; |
726 | else if (memcmp(ci->ci_vendor, "Geode by NSC", 12) == 0) | | 713 | else if (memcmp(ci->ci_vendor, "Geode by NSC", 12) == 0) |
727 | cpu_vendor = CPUVENDOR_CYRIX; | | 714 | cpu_vendor = CPUVENDOR_CYRIX; |
728 | else if (memcmp(ci->ci_vendor, "CentaurHauls", 12) == 0) | | 715 | else if (memcmp(ci->ci_vendor, "CentaurHauls", 12) == 0) |
729 | cpu_vendor = CPUVENDOR_IDT; | | 716 | cpu_vendor = CPUVENDOR_IDT; |
730 | else if (memcmp(ci->ci_vendor, "GenuineTMx86", 12) == 0) | | 717 | else if (memcmp(ci->ci_vendor, "GenuineTMx86", 12) == 0) |
731 | cpu_vendor = CPUVENDOR_TRANSMETA; | | 718 | cpu_vendor = CPUVENDOR_TRANSMETA; |
732 | else if (memcmp(ci->ci_vendor, "Vortex86 SoC", 12) == 0) | | 719 | else if (memcmp(ci->ci_vendor, "Vortex86 SoC", 12) == 0) |
733 | cpu_vendor = CPUVENDOR_VORTEX86; | | 720 | cpu_vendor = CPUVENDOR_VORTEX86; |
734 | else | | 721 | else |
735 | cpu_vendor = CPUVENDOR_UNKNOWN; | | 722 | cpu_vendor = CPUVENDOR_UNKNOWN; |
736 | | | 723 | |
737 | x86_cpuid(0x80000000, brand); | | | |
738 | if (brand[0] >= 0x80000004) { | | | |
739 | x86_cpuid(0x80000002, brand); | | | |
740 | x86_cpuid(0x80000003, brand + 4); | | | |
741 | x86_cpuid(0x80000004, brand + 8); | | | |
742 | for (i = 0; i < 48; i++) { | | | |
743 | if (((char *) brand)[i] != ' ') | | | |
744 | break; | | | |
745 | } | | | |
746 | memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); | | | |
747 | } | | | |
748 | | | | |
749 | if (cpuid_level >= 1) { | | 724 | if (cpuid_level >= 1) { |
750 | x86_cpuid(1, descs); | | 725 | x86_cpuid(1, descs); |
751 | ci->ci_signature = descs[0]; | | 726 | ci->ci_signature = descs[0]; |
752 | miscbytes = descs[1]; | | 727 | miscbytes = descs[1]; |
753 | ci->ci_feat_val[1] = descs[2]; | | 728 | ci->ci_feat_val[1] = descs[2]; |
754 | ci->ci_feat_val[0] = descs[3]; | | 729 | ci->ci_feat_val[0] = descs[3]; |
755 | | | 730 | |
756 | /* Determine family + class. */ | | 731 | /* Determine family + class. */ |
757 | cpu_class = CPUID_TO_FAMILY(ci->ci_signature) | | 732 | cpu_class = CPUID_TO_FAMILY(ci->ci_signature) |
758 | + (CPUCLASS_386 - 3); | | 733 | + (CPUCLASS_386 - 3); |
759 | if (cpu_class > CPUCLASS_686) | | 734 | if (cpu_class > CPUCLASS_686) |
760 | cpu_class = CPUCLASS_686; | | 735 | cpu_class = CPUCLASS_686; |
761 | | | 736 | |
762 | /* CLFLUSH line size is next 8 bits */ | | 737 | /* CLFLUSH line size is next 8 bits */ |
763 | if (ci->ci_feat_val[0] & CPUID_CFLUSH) | | 738 | if (ci->ci_feat_val[0] & CPUID_CFLUSH) |
764 | ci->ci_cflush_lsize = ((miscbytes >> 8) & 0xff) << 3; | | 739 | ci->ci_cflush_lsize = ((miscbytes >> 8) & 0xff) << 3; |
765 | ci->ci_initapicid = (miscbytes >> 24) & 0xff; | | 740 | ci->ci_initapicid = (miscbytes >> 24) & 0xff; |
766 | } | | 741 | } |
767 | | | 742 | |
| | | 743 | /* |
| | | 744 | * Get the basic information from the extended cpuid leafs. |
| | | 745 | * These were first implemented by amd, but most of the values |
| | | 746 | * match with those generated by modern intel cpus. |
| | | 747 | */ |
| | | 748 | x86_cpuid(0x80000000, descs); |
| | | 749 | if (descs[0] == 0x80000000) |
| | | 750 | ci->ci_max_ext_cpuid = descs[0]; |
| | | 751 | else |
| | | 752 | ci->ci_max_ext_cpuid = 0; |
| | | 753 | |
| | | 754 | if (ci->ci_max_ext_cpuid >= 0x80000001) { |
| | | 755 | /* Determine the extended feature flags. */ |
| | | 756 | x86_cpuid(0x80000001, descs); |
| | | 757 | ci->ci_feat_val[3] = descs[2]; /* %ecx */ |
| | | 758 | ci->ci_feat_val[2] = descs[3]; /* %edx */ |
| | | 759 | } |
| | | 760 | |
| | | 761 | if (ci->ci_max_ext_cpuid >= 0x80000004) { |
| | | 762 | x86_cpuid(0x80000002, brand); |
| | | 763 | x86_cpuid(0x80000003, brand + 4); |
| | | 764 | x86_cpuid(0x80000004, brand + 8); |
| | | 765 | /* Skip leading spaces on brand */ |
| | | 766 | for (i = 0; i < 48; i++) { |
| | | 767 | if (((char *) brand)[i] != ' ') |
| | | 768 | break; |
| | | 769 | } |
| | | 770 | memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i); |
| | | 771 | } |
| | | 772 | |
768 | cpu_probe_intel(ci); | | 773 | cpu_probe_intel(ci); |
769 | cpu_probe_k5(ci); | | 774 | cpu_probe_k5(ci); |
770 | cpu_probe_k678(ci); | | 775 | cpu_probe_k678(ci); |
771 | cpu_probe_cyrix(ci); | | 776 | cpu_probe_cyrix(ci); |
772 | cpu_probe_winchip(ci); | | 777 | cpu_probe_winchip(ci); |
773 | cpu_probe_c3(ci); | | 778 | cpu_probe_c3(ci); |
774 | cpu_probe_geode(ci); | | 779 | cpu_probe_geode(ci); |
775 | cpu_probe_vortex86(ci); | | 780 | cpu_probe_vortex86(ci); |
776 | | | 781 | |
777 | x86_cpu_topology(ci); | | 782 | x86_cpu_topology(ci); |
778 | | | 783 | |
779 | if (cpu_vendor != CPUVENDOR_AMD && (ci->ci_feat_val[0] & CPUID_TM) && | | 784 | if (cpu_vendor != CPUVENDOR_AMD && (ci->ci_feat_val[0] & CPUID_TM) && |
780 | (rdmsr(MSR_MISC_ENABLE) & (1 << 3)) == 0) { | | 785 | (rdmsr(MSR_MISC_ENABLE) & (1 << 3)) == 0) { |
| @@ -863,17 +868,23 @@ cpu_identify(struct cpu_info *ci) | | | @@ -863,17 +868,23 @@ cpu_identify(struct cpu_info *ci) |
863 | } | | 868 | } |
864 | | | 869 | |
865 | /* If we have FXSAVE/FXRESTOR, use them. */ | | 870 | /* If we have FXSAVE/FXRESTOR, use them. */ |
866 | if (cpu_feature[0] & CPUID_FXSR) { | | 871 | if (cpu_feature[0] & CPUID_FXSR) { |
867 | i386_use_fxsave = 1; | | 872 | i386_use_fxsave = 1; |
868 | /* | | 873 | /* |
869 | * If we have SSE/SSE2, enable XMM exceptions, and | | 874 | * If we have SSE/SSE2, enable XMM exceptions, and |
870 | * notify userland. | | 875 | * notify userland. |
871 | */ | | 876 | */ |
872 | if (cpu_feature[0] & CPUID_SSE) | | 877 | if (cpu_feature[0] & CPUID_SSE) |
873 | i386_has_sse = 1; | | 878 | i386_has_sse = 1; |
874 | if (cpu_feature[0] & CPUID_SSE2) | | 879 | if (cpu_feature[0] & CPUID_SSE2) |
875 | i386_has_sse2 = 1; | | 880 | i386_has_sse2 = 1; |
876 | } else | | 881 | } else { |
877 | i386_use_fxsave = 0; | | 882 | i386_use_fxsave = 0; |
| | | 883 | } |
| | | 884 | #else |
| | | 885 | /* |
| | | 886 | * i386_use_fxsave, i386_has_sse and i386_has_sse2 are |
| | | 887 | * #defined to 1. |
| | | 888 | */ |
878 | #endif /* i386 */ | | 889 | #endif /* i386 */ |
879 | } | | 890 | } |