LCOV - code coverage report
Current view: top level - arch/x86/kernel/cpu - centaur.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 42 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 3 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : 
       3             : #include <linux/sched.h>
       4             : #include <linux/sched/clock.h>
       5             : 
       6             : #include <asm/cpu.h>
       7             : #include <asm/cpufeature.h>
       8             : #include <asm/e820/api.h>
       9             : #include <asm/mtrr.h>
      10             : #include <asm/msr.h>
      11             : 
      12             : #include "cpu.h"
      13             : 
      14             : #define ACE_PRESENT     (1 << 6)
      15             : #define ACE_ENABLED     (1 << 7)
      16             : #define ACE_FCR         (1 << 28) /* MSR_VIA_FCR */
      17             : 
      18             : #define RNG_PRESENT     (1 << 2)
      19             : #define RNG_ENABLED     (1 << 3)
      20             : #define RNG_ENABLE      (1 << 6)  /* MSR_VIA_RNG */
      21             : 
      22           0 : static void init_c3(struct cpuinfo_x86 *c)
      23             : {
      24           0 :         u32  lo, hi;
      25             : 
      26             :         /* Test for Centaur Extended Feature Flags presence */
      27           0 :         if (cpuid_eax(0xC0000000) >= 0xC0000001) {
      28           0 :                 u32 tmp = cpuid_edx(0xC0000001);
      29             : 
      30             :                 /* enable ACE unit, if present and disabled */
      31           0 :                 if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
      32           0 :                         rdmsr(MSR_VIA_FCR, lo, hi);
      33           0 :                         lo |= ACE_FCR;          /* enable ACE unit */
      34           0 :                         wrmsr(MSR_VIA_FCR, lo, hi);
      35           0 :                         pr_info("CPU: Enabled ACE h/w crypto\n");
      36             :                 }
      37             : 
      38             :                 /* enable RNG unit, if present and disabled */
      39           0 :                 if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
      40           0 :                         rdmsr(MSR_VIA_RNG, lo, hi);
      41           0 :                         lo |= RNG_ENABLE;       /* enable RNG unit */
      42           0 :                         wrmsr(MSR_VIA_RNG, lo, hi);
      43           0 :                         pr_info("CPU: Enabled h/w RNG\n");
      44             :                 }
      45             : 
      46             :                 /* store Centaur Extended Feature Flags as
      47             :                  * word 5 of the CPU capability bit array
      48             :                  */
      49           0 :                 c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001);
      50             :         }
      51             : #ifdef CONFIG_X86_32
      52             :         /* Cyrix III family needs CX8 & PGE explicitly enabled. */
      53             :         if (c->x86_model >= 6 && c->x86_model <= 13) {
      54             :                 rdmsr(MSR_VIA_FCR, lo, hi);
      55             :                 lo |= (1<<1 | 1<<7);
      56             :                 wrmsr(MSR_VIA_FCR, lo, hi);
      57             :                 set_cpu_cap(c, X86_FEATURE_CX8);
      58             :         }
      59             : 
      60             :         /* Before Nehemiah, the C3's had 3dNOW! */
      61             :         if (c->x86_model >= 6 && c->x86_model < 9)
      62             :                 set_cpu_cap(c, X86_FEATURE_3DNOW);
      63             : #endif
      64           0 :         if (c->x86 == 0x6 && c->x86_model >= 0xf) {
      65           0 :                 c->x86_cache_alignment = c->x86_clflush_size * 2;
      66           0 :                 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
      67             :         }
      68             : 
      69           0 :         if (c->x86 >= 7)
      70           0 :                 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
      71           0 : }
      72             : 
      73             : enum {
      74             :                 ECX8            = 1<<1,
      75             :                 EIERRINT        = 1<<2,
      76             :                 DPM             = 1<<3,
      77             :                 DMCE            = 1<<4,
      78             :                 DSTPCLK         = 1<<5,
      79             :                 ELINEAR         = 1<<6,
      80             :                 DSMC            = 1<<7,
      81             :                 DTLOCK          = 1<<8,
      82             :                 EDCTLB          = 1<<8,
      83             :                 EMMX            = 1<<9,
      84             :                 DPDC            = 1<<11,
      85             :                 EBRPRED         = 1<<12,
      86             :                 DIC             = 1<<13,
      87             :                 DDC             = 1<<14,
      88             :                 DNA             = 1<<15,
      89             :                 ERETSTK         = 1<<16,
      90             :                 E2MMX           = 1<<19,
      91             :                 EAMD3D          = 1<<20,
      92             : };
      93             : 
      94           0 : static void early_init_centaur(struct cpuinfo_x86 *c)
      95             : {
      96             : #ifdef CONFIG_X86_32
      97             :         /* Emulate MTRRs using Centaur's MCR. */
      98             :         if (c->x86 == 5)
      99             :                 set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
     100             : #endif
     101           0 :         if ((c->x86 == 6 && c->x86_model >= 0xf) ||
     102             :             (c->x86 >= 7))
     103           0 :                 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
     104             : 
     105             : #ifdef CONFIG_X86_64
     106           0 :         set_cpu_cap(c, X86_FEATURE_SYSENTER32);
     107             : #endif
     108           0 :         if (c->x86_power & (1 << 8)) {
     109           0 :                 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
     110           0 :                 set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
     111             :         }
     112           0 : }
     113             : 
     114           0 : static void init_centaur(struct cpuinfo_x86 *c)
     115             : {
     116             : #ifdef CONFIG_X86_32
     117             :         char *name;
     118             :         u32  fcr_set = 0;
     119             :         u32  fcr_clr = 0;
     120             :         u32  lo, hi, newlo;
     121             :         u32  aa, bb, cc, dd;
     122             : 
     123             :         /*
     124             :          * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
     125             :          * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
     126             :          */
     127             :         clear_cpu_cap(c, 0*32+31);
     128             : #endif
     129           0 :         early_init_centaur(c);
     130           0 :         init_intel_cacheinfo(c);
     131           0 :         detect_num_cpu_cores(c);
     132             : #ifdef CONFIG_X86_32
     133             :         detect_ht(c);
     134             : #endif
     135             : 
     136           0 :         if (c->cpuid_level > 9) {
     137           0 :                 unsigned int eax = cpuid_eax(10);
     138             : 
     139             :                 /*
     140             :                  * Check for version and the number of counters
     141             :                  * Version(eax[7:0]) can't be 0;
     142             :                  * Counters(eax[15:8]) should be greater than 1;
     143             :                  */
     144           0 :                 if ((eax & 0xff) && (((eax >> 8) & 0xff) > 1))
     145           0 :                         set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
     146             :         }
     147             : 
     148             : #ifdef CONFIG_X86_32
     149             :         if (c->x86 == 5) {
     150             :                 switch (c->x86_model) {
     151             :                 case 4:
     152             :                         name = "C6";
     153             :                         fcr_set = ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
     154             :                         fcr_clr = DPDC;
     155             :                         pr_notice("Disabling bugged TSC.\n");
     156             :                         clear_cpu_cap(c, X86_FEATURE_TSC);
     157             :                         break;
     158             :                 case 8:
     159             :                         switch (c->x86_stepping) {
     160             :                         default:
     161             :                         name = "2";
     162             :                                 break;
     163             :                         case 7 ... 9:
     164             :                                 name = "2A";
     165             :                                 break;
     166             :                         case 10 ... 15:
     167             :                                 name = "2B";
     168             :                                 break;
     169             :                         }
     170             :                         fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
     171             :                                   E2MMX|EAMD3D;
     172             :                         fcr_clr = DPDC;
     173             :                         break;
     174             :                 case 9:
     175             :                         name = "3";
     176             :                         fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
     177             :                                   E2MMX|EAMD3D;
     178             :                         fcr_clr = DPDC;
     179             :                         break;
     180             :                 default:
     181             :                         name = "??";
     182             :                 }
     183             : 
     184             :                 rdmsr(MSR_IDT_FCR1, lo, hi);
     185             :                 newlo = (lo|fcr_set) & (~fcr_clr);
     186             : 
     187             :                 if (newlo != lo) {
     188             :                         pr_info("Centaur FCR was 0x%X now 0x%X\n",
     189             :                                 lo, newlo);
     190             :                         wrmsr(MSR_IDT_FCR1, newlo, hi);
     191             :                 } else {
     192             :                         pr_info("Centaur FCR is 0x%X\n", lo);
     193             :                 }
     194             :                 /* Emulate MTRRs using Centaur's MCR. */
     195             :                 set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
     196             :                 /* Report CX8 */
     197             :                 set_cpu_cap(c, X86_FEATURE_CX8);
     198             :                 /* Set 3DNow! on Winchip 2 and above. */
     199             :                 if (c->x86_model >= 8)
     200             :                         set_cpu_cap(c, X86_FEATURE_3DNOW);
     201             :                 /* See if we can find out some more. */
     202             :                 if (cpuid_eax(0x80000000) >= 0x80000005) {
     203             :                         /* Yes, we can. */
     204             :                         cpuid(0x80000005, &aa, &bb, &cc, &dd);
     205             :                         /* Add L1 data and code cache sizes. */
     206             :                         c->x86_cache_size = (cc>>24)+(dd>>24);
     207             :                 }
     208             :                 sprintf(c->x86_model_id, "WinChip %s", name);
     209             :         }
     210             : #endif
     211           0 :         if (c->x86 == 6 || c->x86 >= 7)
     212           0 :                 init_c3(c);
     213             : #ifdef CONFIG_X86_64
     214           0 :         set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
     215             : #endif
     216             : 
     217           0 :         init_ia32_feat_ctl(c);
     218           0 : }
     219             : 
     220             : #ifdef CONFIG_X86_32
     221             : static unsigned int
     222             : centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
     223             : {
     224             :         /* VIA C3 CPUs (670-68F) need further shifting. */
     225             :         if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
     226             :                 size >>= 8;
     227             : 
     228             :         /*
     229             :          * There's also an erratum in Nehemiah stepping 1, which
     230             :          * returns '65KB' instead of '64KB'
     231             :          *  - Note, it seems this may only be in engineering samples.
     232             :          */
     233             :         if ((c->x86 == 6) && (c->x86_model == 9) &&
     234             :                                 (c->x86_stepping == 1) && (size == 65))
     235             :                 size -= 1;
     236             :         return size;
     237             : }
     238             : #endif
     239             : 
     240             : static const struct cpu_dev centaur_cpu_dev = {
     241             :         .c_vendor       = "Centaur",
     242             :         .c_ident        = { "CentaurHauls" },
     243             :         .c_early_init   = early_init_centaur,
     244             :         .c_init         = init_centaur,
     245             : #ifdef CONFIG_X86_32
     246             :         .legacy_cache_size = centaur_size_cache,
     247             : #endif
     248             :         .c_x86_vendor   = X86_VENDOR_CENTAUR,
     249             : };
     250             : 
     251             : cpu_dev_register(centaur_cpu_dev);

Generated by: LCOV version 1.14