Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0 2 : #include <linux/sched.h> 3 : #include <linux/sched/clock.h> 4 : 5 : #include <asm/cpu.h> 6 : #include <asm/cpufeature.h> 7 : 8 : #include "cpu.h" 9 : 10 : #define MSR_ZHAOXIN_FCR57 0x00001257 11 : 12 : #define ACE_PRESENT (1 << 6) 13 : #define ACE_ENABLED (1 << 7) 14 : #define ACE_FCR (1 << 7) /* MSR_ZHAOXIN_FCR */ 15 : 16 : #define RNG_PRESENT (1 << 2) 17 : #define RNG_ENABLED (1 << 3) 18 : #define RNG_ENABLE (1 << 8) /* MSR_ZHAOXIN_RNG */ 19 : 20 0 : static void init_zhaoxin_cap(struct cpuinfo_x86 *c) 21 : { 22 0 : u32 lo, hi; 23 : 24 : /* Test for Extended Feature Flags presence */ 25 0 : if (cpuid_eax(0xC0000000) >= 0xC0000001) { 26 0 : u32 tmp = cpuid_edx(0xC0000001); 27 : 28 : /* Enable ACE unit, if present and disabled */ 29 0 : if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) { 30 0 : rdmsr(MSR_ZHAOXIN_FCR57, lo, hi); 31 : /* Enable ACE unit */ 32 0 : lo |= ACE_FCR; 33 0 : wrmsr(MSR_ZHAOXIN_FCR57, lo, hi); 34 0 : pr_info("CPU: Enabled ACE h/w crypto\n"); 35 : } 36 : 37 : /* Enable RNG unit, if present and disabled */ 38 0 : if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) { 39 0 : rdmsr(MSR_ZHAOXIN_FCR57, lo, hi); 40 : /* Enable RNG unit */ 41 0 : lo |= RNG_ENABLE; 42 0 : wrmsr(MSR_ZHAOXIN_FCR57, lo, hi); 43 0 : pr_info("CPU: Enabled h/w RNG\n"); 44 : } 45 : 46 : /* 47 : * Store Extended Feature Flags as word 5 of the CPU 48 : * capability bit array 49 : */ 50 0 : c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001); 51 : } 52 : 53 0 : if (c->x86 >= 0x6) 54 0 : set_cpu_cap(c, X86_FEATURE_REP_GOOD); 55 0 : } 56 : 57 0 : static void early_init_zhaoxin(struct cpuinfo_x86 *c) 58 : { 59 0 : if (c->x86 >= 0x6) 60 0 : set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); 61 : #ifdef CONFIG_X86_64 62 0 : set_cpu_cap(c, X86_FEATURE_SYSENTER32); 63 : #endif 64 0 : if (c->x86_power & (1 << 8)) { 65 0 : set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); 66 0 : set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); 67 : } 68 : 69 0 : if (c->cpuid_level >= 0x00000001) { 70 0 : u32 eax, ebx, ecx, edx; 71 : 72 0 : cpuid(0x00000001, &eax, &ebx, &ecx, &edx); 73 : /* 74 : * If HTT (EDX[28]) is set EBX[16:23] contain the number of 75 : * apicids which are reserved per package. Store the resulting 76 : * shift value for the package management code. 77 : */ 78 0 : if (edx & (1U << 28)) 79 0 : c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff); 80 : } 81 : 82 0 : } 83 : 84 0 : static void init_zhaoxin(struct cpuinfo_x86 *c) 85 : { 86 0 : early_init_zhaoxin(c); 87 0 : init_intel_cacheinfo(c); 88 0 : detect_num_cpu_cores(c); 89 : #ifdef CONFIG_X86_32 90 : detect_ht(c); 91 : #endif 92 : 93 0 : if (c->cpuid_level > 9) { 94 0 : unsigned int eax = cpuid_eax(10); 95 : 96 : /* 97 : * Check for version and the number of counters 98 : * Version(eax[7:0]) can't be 0; 99 : * Counters(eax[15:8]) should be greater than 1; 100 : */ 101 0 : if ((eax & 0xff) && (((eax >> 8) & 0xff) > 1)) 102 0 : set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); 103 : } 104 : 105 0 : if (c->x86 >= 0x6) 106 0 : init_zhaoxin_cap(c); 107 : #ifdef CONFIG_X86_64 108 0 : set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); 109 : #endif 110 : 111 0 : init_ia32_feat_ctl(c); 112 0 : } 113 : 114 : #ifdef CONFIG_X86_32 115 : static unsigned int 116 : zhaoxin_size_cache(struct cpuinfo_x86 *c, unsigned int size) 117 : { 118 : return size; 119 : } 120 : #endif 121 : 122 : static const struct cpu_dev zhaoxin_cpu_dev = { 123 : .c_vendor = "zhaoxin", 124 : .c_ident = { " Shanghai " }, 125 : .c_early_init = early_init_zhaoxin, 126 : .c_init = init_zhaoxin, 127 : #ifdef CONFIG_X86_32 128 : .legacy_cache_size = zhaoxin_size_cache, 129 : #endif 130 : .c_x86_vendor = X86_VENDOR_ZHAOXIN, 131 : }; 132 : 133 : cpu_dev_register(zhaoxin_cpu_dev);