0001
0002
0003 #include <linux/sched.h>
0004 #include <linux/sched/clock.h>
0005
0006 #include <asm/cpu.h>
0007 #include <asm/cpufeature.h>
0008 #include <asm/e820/api.h>
0009 #include <asm/mtrr.h>
0010 #include <asm/msr.h>
0011
0012 #include "cpu.h"
0013
0014 #define ACE_PRESENT (1 << 6)
0015 #define ACE_ENABLED (1 << 7)
0016 #define ACE_FCR (1 << 28)
0017
0018 #define RNG_PRESENT (1 << 2)
0019 #define RNG_ENABLED (1 << 3)
0020 #define RNG_ENABLE (1 << 6)
0021
0022 static void init_c3(struct cpuinfo_x86 *c)
0023 {
0024 u32 lo, hi;
0025
0026
0027 if (cpuid_eax(0xC0000000) >= 0xC0000001) {
0028 u32 tmp = cpuid_edx(0xC0000001);
0029
0030
0031 if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
0032 rdmsr(MSR_VIA_FCR, lo, hi);
0033 lo |= ACE_FCR;
0034 wrmsr(MSR_VIA_FCR, lo, hi);
0035 pr_info("CPU: Enabled ACE h/w crypto\n");
0036 }
0037
0038
0039 if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
0040 rdmsr(MSR_VIA_RNG, lo, hi);
0041 lo |= RNG_ENABLE;
0042 wrmsr(MSR_VIA_RNG, lo, hi);
0043 pr_info("CPU: Enabled h/w RNG\n");
0044 }
0045
0046
0047
0048
0049 c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001);
0050 }
0051 #ifdef CONFIG_X86_32
0052
0053 if (c->x86_model >= 6 && c->x86_model <= 13) {
0054 rdmsr(MSR_VIA_FCR, lo, hi);
0055 lo |= (1<<1 | 1<<7);
0056 wrmsr(MSR_VIA_FCR, lo, hi);
0057 set_cpu_cap(c, X86_FEATURE_CX8);
0058 }
0059
0060
0061 if (c->x86_model >= 6 && c->x86_model < 9)
0062 set_cpu_cap(c, X86_FEATURE_3DNOW);
0063 #endif
0064 if (c->x86 == 0x6 && c->x86_model >= 0xf) {
0065 c->x86_cache_alignment = c->x86_clflush_size * 2;
0066 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
0067 }
0068
0069 if (c->x86 >= 7)
0070 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
0071 }
0072
0073 enum {
0074 ECX8 = 1<<1,
0075 EIERRINT = 1<<2,
0076 DPM = 1<<3,
0077 DMCE = 1<<4,
0078 DSTPCLK = 1<<5,
0079 ELINEAR = 1<<6,
0080 DSMC = 1<<7,
0081 DTLOCK = 1<<8,
0082 EDCTLB = 1<<8,
0083 EMMX = 1<<9,
0084 DPDC = 1<<11,
0085 EBRPRED = 1<<12,
0086 DIC = 1<<13,
0087 DDC = 1<<14,
0088 DNA = 1<<15,
0089 ERETSTK = 1<<16,
0090 E2MMX = 1<<19,
0091 EAMD3D = 1<<20,
0092 };
0093
0094 static void early_init_centaur(struct cpuinfo_x86 *c)
0095 {
0096 #ifdef CONFIG_X86_32
0097
0098 if (c->x86 == 5)
0099 set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
0100 #endif
0101 if ((c->x86 == 6 && c->x86_model >= 0xf) ||
0102 (c->x86 >= 7))
0103 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
0104
0105 #ifdef CONFIG_X86_64
0106 set_cpu_cap(c, X86_FEATURE_SYSENTER32);
0107 #endif
0108 if (c->x86_power & (1 << 8)) {
0109 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
0110 set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
0111 }
0112 }
0113
0114 static void init_centaur(struct cpuinfo_x86 *c)
0115 {
0116 #ifdef CONFIG_X86_32
0117 char *name;
0118 u32 fcr_set = 0;
0119 u32 fcr_clr = 0;
0120 u32 lo, hi, newlo;
0121 u32 aa, bb, cc, dd;
0122
0123
0124
0125
0126
0127 clear_cpu_cap(c, 0*32+31);
0128 #endif
0129 early_init_centaur(c);
0130 init_intel_cacheinfo(c);
0131 detect_num_cpu_cores(c);
0132 #ifdef CONFIG_X86_32
0133 detect_ht(c);
0134 #endif
0135
0136 if (c->cpuid_level > 9) {
0137 unsigned int eax = cpuid_eax(10);
0138
0139
0140
0141
0142
0143
0144 if ((eax & 0xff) && (((eax >> 8) & 0xff) > 1))
0145 set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
0146 }
0147
0148 #ifdef CONFIG_X86_32
0149 if (c->x86 == 5) {
0150 switch (c->x86_model) {
0151 case 4:
0152 name = "C6";
0153 fcr_set = ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
0154 fcr_clr = DPDC;
0155 pr_notice("Disabling bugged TSC.\n");
0156 clear_cpu_cap(c, X86_FEATURE_TSC);
0157 break;
0158 case 8:
0159 switch (c->x86_stepping) {
0160 default:
0161 name = "2";
0162 break;
0163 case 7 ... 9:
0164 name = "2A";
0165 break;
0166 case 10 ... 15:
0167 name = "2B";
0168 break;
0169 }
0170 fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
0171 E2MMX|EAMD3D;
0172 fcr_clr = DPDC;
0173 break;
0174 case 9:
0175 name = "3";
0176 fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
0177 E2MMX|EAMD3D;
0178 fcr_clr = DPDC;
0179 break;
0180 default:
0181 name = "??";
0182 }
0183
0184 rdmsr(MSR_IDT_FCR1, lo, hi);
0185 newlo = (lo|fcr_set) & (~fcr_clr);
0186
0187 if (newlo != lo) {
0188 pr_info("Centaur FCR was 0x%X now 0x%X\n",
0189 lo, newlo);
0190 wrmsr(MSR_IDT_FCR1, newlo, hi);
0191 } else {
0192 pr_info("Centaur FCR is 0x%X\n", lo);
0193 }
0194
0195 set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
0196
0197 set_cpu_cap(c, X86_FEATURE_CX8);
0198
0199 if (c->x86_model >= 8)
0200 set_cpu_cap(c, X86_FEATURE_3DNOW);
0201
0202 if (cpuid_eax(0x80000000) >= 0x80000005) {
0203
0204 cpuid(0x80000005, &aa, &bb, &cc, &dd);
0205
0206 c->x86_cache_size = (cc>>24)+(dd>>24);
0207 }
0208 sprintf(c->x86_model_id, "WinChip %s", name);
0209 }
0210 #endif
0211 if (c->x86 == 6 || c->x86 >= 7)
0212 init_c3(c);
0213 #ifdef CONFIG_X86_64
0214 set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
0215 #endif
0216
0217 init_ia32_feat_ctl(c);
0218 }
0219
0220 #ifdef CONFIG_X86_32
0221 static unsigned int
0222 centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
0223 {
0224
0225 if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
0226 size >>= 8;
0227
0228
0229
0230
0231
0232
0233 if ((c->x86 == 6) && (c->x86_model == 9) &&
0234 (c->x86_stepping == 1) && (size == 65))
0235 size -= 1;
0236 return size;
0237 }
0238 #endif
0239
0240 static const struct cpu_dev centaur_cpu_dev = {
0241 .c_vendor = "Centaur",
0242 .c_ident = { "CentaurHauls" },
0243 .c_early_init = early_init_centaur,
0244 .c_init = init_centaur,
0245 #ifdef CONFIG_X86_32
0246 .legacy_cache_size = centaur_size_cache,
0247 #endif
0248 .c_x86_vendor = X86_VENDOR_CENTAUR,
0249 };
0250
0251 cpu_dev_register(centaur_cpu_dev);