Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * x86 FPU boot time init code: 4 : : */ 5 : : #include <asm/fpu/internal.h> 6 : : #include <asm/tlbflush.h> 7 : : #include <asm/setup.h> 8 : : #include <asm/cmdline.h> 9 : : 10 : : #include <linux/sched.h> 11 : : #include <linux/sched/task.h> 12 : : #include <linux/init.h> 13 : : 14 : : /* 15 : : * Initialize the registers found in all CPUs, CR0 and CR4: 16 : : */ 17 : 22 : static void fpu__init_cpu_generic(void) 18 : : { 19 : 22 : unsigned long cr0; 20 : 22 : unsigned long cr4_mask = 0; 21 : : 22 : 22 : if (boot_cpu_has(X86_FEATURE_FXSR)) 23 : 22 : cr4_mask |= X86_CR4_OSFXSR; 24 : 22 : if (boot_cpu_has(X86_FEATURE_XMM)) 25 : 22 : cr4_mask |= X86_CR4_OSXMMEXCPT; 26 : 22 : if (cr4_mask) 27 : 22 : cr4_set_bits(cr4_mask); 28 : : 29 : 22 : cr0 = read_cr0(); 30 : 22 : cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ 31 : 22 : if (!boot_cpu_has(X86_FEATURE_FPU)) 32 : : cr0 |= X86_CR0_EM; 33 : 22 : write_cr0(cr0); 34 : : 35 : : /* Flush out any pending x87 state: */ 36 : : #ifdef CONFIG_MATH_EMULATION 37 : : if (!boot_cpu_has(X86_FEATURE_FPU)) 38 : : fpstate_init_soft(¤t->thread.fpu.state.soft); 39 : : else 40 : : #endif 41 : 22 : asm volatile ("fninit"); 42 : 22 : } 43 : : 44 : : /* 45 : : * Enable all supported FPU features. Called when a CPU is brought online: 46 : : */ 47 : 22 : void fpu__init_cpu(void) 48 : : { 49 : 11 : fpu__init_cpu_generic(); 50 : 22 : fpu__init_cpu_xstate(); 51 : 11 : } 52 : : 53 : 0 : static bool fpu__probe_without_cpuid(void) 54 : : { 55 : 0 : unsigned long cr0; 56 : 0 : u16 fsw, fcw; 57 : : 58 : 0 : fsw = fcw = 0xffff; 59 : : 60 : 0 : cr0 = read_cr0(); 61 : 0 : cr0 &= ~(X86_CR0_TS | X86_CR0_EM); 62 : 0 : write_cr0(cr0); 63 : : 64 : 0 : asm volatile("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw)); 65 : : 66 : 0 : pr_info("x86/fpu: Probing for FPU: FSW=0x%04hx FCW=0x%04hx\n", fsw, fcw); 67 : : 68 [ # # # # ]: 0 : return fsw == 0 && (fcw & 0x103f) == 0x003f; 69 : : } 70 : : 71 : : static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) 72 : : { 73 : : if (!boot_cpu_has(X86_FEATURE_CPUID) && 74 : : !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) { 75 : : if (fpu__probe_without_cpuid()) 76 : : setup_force_cpu_cap(X86_FEATURE_FPU); 77 : : else 78 : : setup_clear_cpu_cap(X86_FEATURE_FPU); 79 : : } 80 : : 81 : : #ifndef CONFIG_MATH_EMULATION 82 : : if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_FPU)) { 83 : : pr_emerg("x86/fpu: Giving up, no FPU found and no math emulation present\n"); 84 : : for (;;) 85 : : asm volatile("hlt"); 86 : : } 87 : : #endif 88 : : } 89 : : 90 : : /* 91 : : * Boot time FPU feature detection code: 92 : : */ 93 : : unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; 94 : : EXPORT_SYMBOL_GPL(mxcsr_feature_mask); 95 : : 96 : 11 : static void __init fpu__init_system_mxcsr(void) 97 : : { 98 : 11 : unsigned int mask = 0; 99 : : 100 : 11 : if (boot_cpu_has(X86_FEATURE_FXSR)) { 101 : : /* Static because GCC does not get 16-byte stack alignment right: */ 102 : 11 : static struct fxregs_state fxregs __initdata; 103 : : 104 : 11 : asm volatile("fxsave %0" : "+m" (fxregs)); 105 : : 106 : 11 : mask = fxregs.mxcsr_mask; 107 : : 108 : : /* 109 : : * If zero then use the default features mask, 110 : : * which has all features set, except the 111 : : * denormals-are-zero feature bit: 112 : : */ 113 [ - + ]: 11 : if (mask == 0) 114 : 0 : mask = 0x0000ffbf; 115 : : } 116 : 11 : mxcsr_feature_mask &= mask; 117 : 11 : } 118 : : 119 : : /* 120 : : * Once per bootup FPU initialization sequences that will run on most x86 CPUs: 121 : : */ 122 : 11 : static void __init fpu__init_system_generic(void) 123 : : { 124 : : /* 125 : : * Set up the legacy init FPU context. (xstate init might overwrite this 126 : : * with a more modern format, if the CPU supports it.) 127 : : */ 128 : 11 : fpstate_init(&init_fpstate); 129 : : 130 : 11 : fpu__init_system_mxcsr(); 131 : 11 : } 132 : : 133 : : /* 134 : : * Size of the FPU context state. All tasks in the system use the 135 : : * same context size, regardless of what portion they use. 136 : : * This is inherent to the XSAVE architecture which puts all state 137 : : * components into a single, continuous memory block: 138 : : */ 139 : : unsigned int fpu_kernel_xstate_size; 140 : : EXPORT_SYMBOL_GPL(fpu_kernel_xstate_size); 141 : : 142 : : /* Get alignment of the TYPE. */ 143 : : #define TYPE_ALIGN(TYPE) offsetof(struct { char x; TYPE test; }, test) 144 : : 145 : : /* 146 : : * Enforce that 'MEMBER' is the last field of 'TYPE'. 147 : : * 148 : : * Align the computed size with alignment of the TYPE, 149 : : * because that's how C aligns structs. 150 : : */ 151 : : #define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ 152 : : BUILD_BUG_ON(sizeof(TYPE) != ALIGN(offsetofend(TYPE, MEMBER), \ 153 : : TYPE_ALIGN(TYPE))) 154 : : 155 : : /* 156 : : * We append the 'struct fpu' to the task_struct: 157 : : */ 158 : 11 : static void __init fpu__init_task_struct_size(void) 159 : : { 160 : 11 : int task_size = sizeof(struct task_struct); 161 : : 162 : : /* 163 : : * Subtract off the static size of the register state. 164 : : * It potentially has a bunch of padding. 165 : : */ 166 : 11 : task_size -= sizeof(((struct task_struct *)0)->thread.fpu.state); 167 : : 168 : : /* 169 : : * Add back the dynamically-calculated register state 170 : : * size. 171 : : */ 172 : 11 : task_size += fpu_kernel_xstate_size; 173 : : 174 : : /* 175 : : * We dynamically size 'struct fpu', so we require that 176 : : * it be at the end of 'thread_struct' and that 177 : : * 'thread_struct' be at the end of 'task_struct'. If 178 : : * you hit a compile error here, check the structure to 179 : : * see if something got added to the end. 180 : : */ 181 : 11 : CHECK_MEMBER_AT_END_OF(struct fpu, state); 182 : 11 : CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); 183 : 11 : CHECK_MEMBER_AT_END_OF(struct task_struct, thread); 184 : : 185 : 11 : arch_task_struct_size = task_size; 186 : 11 : } 187 : : 188 : : /* 189 : : * Set up the user and kernel xstate sizes based on the legacy FPU context size. 190 : : * 191 : : * We set this up first, and later it will be overwritten by 192 : : * fpu__init_system_xstate() if the CPU knows about xstates. 193 : : */ 194 : 11 : static void __init fpu__init_system_xstate_size_legacy(void) 195 : : { 196 : 11 : static int on_boot_cpu __initdata = 1; 197 : : 198 [ - + ]: 11 : WARN_ON_FPU(!on_boot_cpu); 199 : 11 : on_boot_cpu = 0; 200 : : 201 : : /* 202 : : * Note that xstate sizes might be overwritten later during 203 : : * fpu__init_system_xstate(). 204 : : */ 205 : : 206 : 11 : if (!boot_cpu_has(X86_FEATURE_FPU)) { 207 : : fpu_kernel_xstate_size = sizeof(struct swregs_state); 208 : : } else { 209 : 11 : if (boot_cpu_has(X86_FEATURE_FXSR)) 210 : 11 : fpu_kernel_xstate_size = 211 : : sizeof(struct fxregs_state); 212 : : else 213 : : fpu_kernel_xstate_size = 214 : : sizeof(struct fregs_state); 215 : : } 216 : : 217 : 11 : fpu_user_xstate_size = fpu_kernel_xstate_size; 218 : 11 : } 219 : : 220 : : /* 221 : : * Find supported xfeatures based on cpu features and command-line input. 222 : : * This must be called after fpu__init_parse_early_param() is called and 223 : : * xfeatures_mask is enumerated. 224 : : */ 225 : 0 : u64 __init fpu__get_supported_xfeatures_mask(void) 226 : : { 227 : 0 : return XCNTXT_MASK; 228 : : } 229 : : 230 : : /* Legacy code to initialize eager fpu mode. */ 231 : 11 : static void __init fpu__init_system_ctx_switch(void) 232 : : { 233 : 11 : static bool on_boot_cpu __initdata = 1; 234 : : 235 [ - + ]: 11 : WARN_ON_FPU(!on_boot_cpu); 236 : 11 : on_boot_cpu = 0; 237 : 11 : } 238 : : 239 : : /* 240 : : * We parse fpu parameters early because fpu__init_system() is executed 241 : : * before parse_early_param(). 242 : : */ 243 : 11 : static void __init fpu__init_parse_early_param(void) 244 : : { 245 : 11 : char arg[32]; 246 : 11 : char *argptr = arg; 247 : 11 : int bit; 248 : : 249 : : #ifdef CONFIG_X86_32 250 : : if (cmdline_find_option_bool(boot_command_line, "no387")) 251 : : #ifdef CONFIG_MATH_EMULATION 252 : : setup_clear_cpu_cap(X86_FEATURE_FPU); 253 : : #else 254 : : pr_err("Option 'no387' required CONFIG_MATH_EMULATION enabled.\n"); 255 : : #endif 256 : : 257 : : if (cmdline_find_option_bool(boot_command_line, "nofxsr")) 258 : : setup_clear_cpu_cap(X86_FEATURE_FXSR); 259 : : #endif 260 : : 261 [ - + ]: 11 : if (cmdline_find_option_bool(boot_command_line, "noxsave")) 262 : 0 : setup_clear_cpu_cap(X86_FEATURE_XSAVE); 263 : : 264 [ - + ]: 11 : if (cmdline_find_option_bool(boot_command_line, "noxsaveopt")) 265 : 0 : setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); 266 : : 267 [ - + ]: 11 : if (cmdline_find_option_bool(boot_command_line, "noxsaves")) 268 : 0 : setup_clear_cpu_cap(X86_FEATURE_XSAVES); 269 : : 270 [ + - ]: 11 : if (cmdline_find_option(boot_command_line, "clearcpuid", arg, 271 [ - + ]: 11 : sizeof(arg)) && 272 : 11 : get_option(&argptr, &bit) && 273 [ # # # # ]: 0 : bit >= 0 && 274 : : bit < NCAPINTS * 32) 275 : 0 : setup_clear_cpu_cap(bit); 276 : 11 : } 277 : : 278 : : /* 279 : : * Called on the boot CPU once per system bootup, to set up the initial 280 : : * FPU state that is later cloned into all processes: 281 : : */ 282 : 11 : void __init fpu__init_system(struct cpuinfo_x86 *c) 283 : : { 284 : 11 : fpu__init_parse_early_param(); 285 : 11 : fpu__init_system_early_generic(c); 286 : : 287 : : /* 288 : : * The FPU has to be operational for some of the 289 : : * later FPU init activities: 290 : : */ 291 : 11 : fpu__init_cpu(); 292 : : 293 : 11 : fpu__init_system_generic(); 294 : 11 : fpu__init_system_xstate_size_legacy(); 295 : 11 : fpu__init_system_xstate(); 296 : 11 : fpu__init_task_struct_size(); 297 : : 298 : 11 : fpu__init_system_ctx_switch(); 299 : 11 : }