|
11 | 11 | #include <asm/alternative.h> |
12 | 12 | #include <asm/cpufeatures.h> |
13 | 13 | #include <asm/page.h> |
| 14 | +#if defined(CONFIG_X86_HYGON_LMC_SSE2_ON) || \ |
| 15 | + defined(CONFIG_X86_HYGON_LMC_AVX2_ON) |
| 16 | +#include <asm/fpu/api.h> |
| 17 | +#endif |
| 18 | + |
| 19 | +extern struct static_key_false hygon_lmc_key; |
14 | 20 |
|
15 | 21 | #ifdef CONFIG_ADDRESS_MASKING |
16 | 22 | /* |
@@ -97,13 +103,91 @@ static inline bool __access_ok(const void __user *ptr, unsigned long size) |
97 | 103 | * Copy To/From Userspace |
98 | 104 | */ |
99 | 105 |
|
| 106 | +#ifdef CONFIG_X86_HYGON_LMC_SSE2_ON |
| 107 | +void fpu_save_xmm0_3(void *to, const void *from, unsigned long len); |
| 108 | +void fpu_restore_xmm0_3(void *to, const void *from, unsigned long len); |
| 109 | + |
| 110 | +#define kernel_fpu_states_save fpu_save_xmm0_3 |
| 111 | +#define kernel_fpu_states_restore fpu_restore_xmm0_3 |
| 112 | + |
| 113 | +__must_check unsigned long copy_user_sse2_opt_string(void *to, const void *from, |
| 114 | + unsigned long len); |
| 115 | + |
| 116 | +#define MAX_FPU_CTX_SIZE 64 |
| 117 | +#define KERNEL_FPU_NONATOMIC_SIZE (2 * (MAX_FPU_CTX_SIZE)) |
| 118 | + |
| 119 | +#define copy_user_large_memory_generic_string copy_user_sse2_opt_string |
| 120 | + |
| 121 | +#endif |
| 122 | + |
| 123 | +#ifdef CONFIG_X86_HYGON_LMC_AVX2_ON |
| 124 | +void fpu_save_ymm0_7(void *to, const void *from, unsigned long len); |
| 125 | +void fpu_restore_ymm0_7(void *to, const void *from, unsigned long len); |
| 126 | + |
| 127 | +#define kernel_fpu_states_save fpu_save_ymm0_7 |
| 128 | +#define kernel_fpu_states_restore fpu_restore_ymm0_7 |
| 129 | + |
| 130 | +__must_check unsigned long |
| 131 | +copy_user_avx2_pf64_nt_string(void *to, const void *from, unsigned long len); |
| 132 | + |
| 133 | +#define MAX_FPU_CTX_SIZE 256 |
| 134 | +#define KERNEL_FPU_NONATOMIC_SIZE (2 * (MAX_FPU_CTX_SIZE)) |
| 135 | + |
| 136 | +#define copy_user_large_memory_generic_string copy_user_avx2_pf64_nt_string |
| 137 | +#endif |
| 138 | + |
| 139 | +#if defined(CONFIG_X86_HYGON_LMC_SSE2_ON) || \ |
| 140 | + defined(CONFIG_X86_HYGON_LMC_AVX2_ON) |
| 141 | +unsigned int get_nt_block_copy_mini_len(void); |
| 142 | +static inline bool Hygon_LMC_check(unsigned long len) |
| 143 | +{ |
| 144 | + unsigned int nt_blk_cpy_mini_len = get_nt_block_copy_mini_len(); |
| 145 | + |
| 146 | + if (((nt_blk_cpy_mini_len) && (nt_blk_cpy_mini_len <= len) && |
| 147 | + (system_state == SYSTEM_RUNNING) && |
| 148 | + (!kernel_fpu_begin_nonatomic()))) |
| 149 | + return true; |
| 150 | + else |
| 151 | + return false; |
| 152 | +} |
| 153 | +static inline unsigned long |
| 154 | +copy_large_memory_generic_string(void *to, const void *from, unsigned long len) |
| 155 | +{ |
| 156 | + unsigned long ret; |
| 157 | + |
| 158 | + ret = copy_user_large_memory_generic_string(to, from, len); |
| 159 | + kernel_fpu_end_nonatomic(); |
| 160 | + return ret; |
| 161 | +} |
| 162 | +#else |
| 163 | +static inline bool Hygon_LMC_check(unsigned long len) |
| 164 | +{ |
| 165 | + return false; |
| 166 | +} |
| 167 | +static inline unsigned long |
| 168 | +copy_large_memory_generic_string(void *to, const void *from, unsigned long len) |
| 169 | +{ |
| 170 | + return 0; |
| 171 | +} |
| 172 | +#endif |
| 173 | + |
100 | 174 | /* Handles exceptions in both to and from, but doesn't do access_ok */ |
101 | 175 | __must_check unsigned long |
102 | 176 | rep_movs_alternative(void *to, const void *from, unsigned len); |
103 | 177 |
|
104 | 178 | static __always_inline __must_check unsigned long |
105 | 179 | copy_user_generic(void *to, const void *from, unsigned long len) |
106 | 180 | { |
| 181 | + /* Check if Hygon large memory copy support enabled. */ |
| 182 | + if (static_branch_unlikely(&hygon_lmc_key)) { |
| 183 | + if (Hygon_LMC_check(len)) { |
| 184 | + unsigned long ret; |
| 185 | + |
| 186 | + ret = copy_large_memory_generic_string(to, from, len); |
| 187 | + return ret; |
| 188 | + } |
| 189 | + } |
| 190 | + |
107 | 191 | stac(); |
108 | 192 | /* |
109 | 193 | * If CPU has FSRM feature, use 'rep movs'. |
|
0 commit comments