summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2019-04-03 12:41:36 -0400
committerBorislav Petkov <bp@suse.de>2019-04-10 09:42:40 -0400
commit2722146eb78451b30e4717a267a3a2b44e4ad317 (patch)
tree9e1182428d9bcb6f6034d156c9a068ccd98f7cdb
parent39388e80f9b0c3788bfb6efe3054bdce0c3ead45 (diff)
x86/fpu: Remove fpu->initialized
The struct fpu.initialized member is always set to one for user tasks and zero for kernel tasks. This avoids saving/restoring the FPU registers for kernel threads. The ->initialized = 0 case for user tasks has been removed in previous changes, for instance, by doing an explicit unconditional init at fork() time for FPU-less systems which was otherwise delayed until the emulated opcode. The context switch code (switch_fpu_prepare() + switch_fpu_finish()) can't unconditionally save/restore registers for kernel threads. Not only would it slow down the switch but also load a zeroed xcomp_bv for XSAVES. For kernel_fpu_begin() (+end) the situation is similar: EFI with runtime services uses this before alternatives_patched is true. Which means that this function is used too early and it wasn't the case before. For those two cases, use current->mm to distinguish between user and kernel thread. For kernel_fpu_begin() skip save/restore of the FPU registers. During the context switch into a kernel thread don't do anything. There is no reason to save the FPU state of a kernel thread. The reordering in __switch_to() is important because the current() pointer needs to be valid before switch_fpu_finish() is invoked so ->mm is seen of the new task instead the old one. N.B.: fpu__save() doesn't need to check ->mm because it is called by user tasks only. [ bp: Massage. ] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Dave Hansen <dave.hansen@intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andy Lutomirski <luto@kernel.org> Cc: Aubrey Li <aubrey.li@intel.com> Cc: Babu Moger <Babu.Moger@amd.com> Cc: "Chang S. Bae" <chang.seok.bae@intel.com> Cc: Dmitry Safonov <dima@arista.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jann Horn <jannh@google.com> Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> Cc: Joerg Roedel <jroedel@suse.de> Cc: kvm ML <kvm@vger.kernel.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Nicolai Stange <nstange@suse.de> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Rik van Riel <riel@surriel.com> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Will Deacon <will.deacon@arm.com> Cc: x86-ml <x86@kernel.org> Link: https://lkml.kernel.org/r/20190403164156.19645-8-bigeasy@linutronix.de
-rw-r--r--arch/x86/ia32/ia32_signal.c17
-rw-r--r--arch/x86/include/asm/fpu/internal.h18
-rw-r--r--arch/x86/include/asm/fpu/types.h9
-rw-r--r--arch/x86/include/asm/trace/fpu.h5
-rw-r--r--arch/x86/kernel/fpu/core.c70
-rw-r--r--arch/x86/kernel/fpu/init.c2
-rw-r--r--arch/x86/kernel/fpu/regset.c19
-rw-r--r--arch/x86/kernel/fpu/xstate.c2
-rw-r--r--arch/x86/kernel/process_32.c4
-rw-r--r--arch/x86/kernel/process_64.c4
-rw-r--r--arch/x86/kernel/signal.c17
-rw-r--r--arch/x86/mm/pkeys.c7
12 files changed, 53 insertions, 121 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 321fe5f5d0e9..6eeb3249f22f 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -216,8 +216,7 @@ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
216 size_t frame_size, 216 size_t frame_size,
217 void __user **fpstate) 217 void __user **fpstate)
218{ 218{
219 struct fpu *fpu = &current->thread.fpu; 219 unsigned long sp, fx_aligned, math_size;
220 unsigned long sp;
221 220
222 /* Default to using normal stack */ 221 /* Default to using normal stack */
223 sp = regs->sp; 222 sp = regs->sp;
@@ -231,15 +230,11 @@ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
231 ksig->ka.sa.sa_restorer) 230 ksig->ka.sa.sa_restorer)
232 sp = (unsigned long) ksig->ka.sa.sa_restorer; 231 sp = (unsigned long) ksig->ka.sa.sa_restorer;
233 232
234 if (fpu->initialized) { 233 sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size);
235 unsigned long fx_aligned, math_size; 234 *fpstate = (struct _fpstate_32 __user *) sp;
236 235 if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned,
237 sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size); 236 math_size) < 0)
238 *fpstate = (struct _fpstate_32 __user *) sp; 237 return (void __user *) -1L;
239 if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned,
240 math_size) < 0)
241 return (void __user *) -1L;
242 }
243 238
244 sp -= frame_size; 239 sp -= frame_size;
245 /* Align the stack pointer according to the i386 ABI, 240 /* Align the stack pointer according to the i386 ABI,
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 70ecb7c032cb..04042eacc852 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -494,11 +494,14 @@ static inline void fpregs_activate(struct fpu *fpu)
494 * 494 *
495 * - switch_fpu_finish() restores the new state as 495 * - switch_fpu_finish() restores the new state as
496 * necessary. 496 * necessary.
497 *
498 * The FPU context is only stored/restored for a user task and
499 * ->mm is used to distinguish between kernel and user threads.
497 */ 500 */
498static inline void 501static inline void
499switch_fpu_prepare(struct fpu *old_fpu, int cpu) 502switch_fpu_prepare(struct fpu *old_fpu, int cpu)
500{ 503{
501 if (static_cpu_has(X86_FEATURE_FPU) && old_fpu->initialized) { 504 if (static_cpu_has(X86_FEATURE_FPU) && current->mm) {
502 if (!copy_fpregs_to_fpstate(old_fpu)) 505 if (!copy_fpregs_to_fpstate(old_fpu))
503 old_fpu->last_cpu = -1; 506 old_fpu->last_cpu = -1;
504 else 507 else
@@ -506,8 +509,7 @@ switch_fpu_prepare(struct fpu *old_fpu, int cpu)
506 509
507 /* But leave fpu_fpregs_owner_ctx! */ 510 /* But leave fpu_fpregs_owner_ctx! */
508 trace_x86_fpu_regs_deactivated(old_fpu); 511 trace_x86_fpu_regs_deactivated(old_fpu);
509 } else 512 }
510 old_fpu->last_cpu = -1;
511} 513}
512 514
513/* 515/*
@@ -520,12 +522,12 @@ switch_fpu_prepare(struct fpu *old_fpu, int cpu)
520 */ 522 */
521static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu) 523static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu)
522{ 524{
523 bool preload = static_cpu_has(X86_FEATURE_FPU) && 525 if (static_cpu_has(X86_FEATURE_FPU)) {
524 new_fpu->initialized; 526 if (!fpregs_state_valid(new_fpu, cpu)) {
527 if (current->mm)
528 copy_kernel_to_fpregs(&new_fpu->state);
529 }
525 530
526 if (preload) {
527 if (!fpregs_state_valid(new_fpu, cpu))
528 copy_kernel_to_fpregs(&new_fpu->state);
529 fpregs_activate(new_fpu); 531 fpregs_activate(new_fpu);
530 } 532 }
531} 533}
diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index 2e32e178e064..f098f6cab94b 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -294,15 +294,6 @@ struct fpu {
294 unsigned int last_cpu; 294 unsigned int last_cpu;
295 295
296 /* 296 /*
297 * @initialized:
298 *
299 * This flag indicates whether this context is initialized: if the task
300 * is not running then we can restore from this context, if the task
301 * is running then we should save into this context.
302 */
303 unsigned char initialized;
304
305 /*
306 * @avx512_timestamp: 297 * @avx512_timestamp:
307 * 298 *
308 * Records the timestamp of AVX512 use during last context switch. 299 * Records the timestamp of AVX512 use during last context switch.
diff --git a/arch/x86/include/asm/trace/fpu.h b/arch/x86/include/asm/trace/fpu.h
index 069c04be1507..bd65f6ba950f 100644
--- a/arch/x86/include/asm/trace/fpu.h
+++ b/arch/x86/include/asm/trace/fpu.h
@@ -13,22 +13,19 @@ DECLARE_EVENT_CLASS(x86_fpu,
13 13
14 TP_STRUCT__entry( 14 TP_STRUCT__entry(
15 __field(struct fpu *, fpu) 15 __field(struct fpu *, fpu)
16 __field(bool, initialized)
17 __field(u64, xfeatures) 16 __field(u64, xfeatures)
18 __field(u64, xcomp_bv) 17 __field(u64, xcomp_bv)
19 ), 18 ),
20 19
21 TP_fast_assign( 20 TP_fast_assign(
22 __entry->fpu = fpu; 21 __entry->fpu = fpu;
23 __entry->initialized = fpu->initialized;
24 if (boot_cpu_has(X86_FEATURE_OSXSAVE)) { 22 if (boot_cpu_has(X86_FEATURE_OSXSAVE)) {
25 __entry->xfeatures = fpu->state.xsave.header.xfeatures; 23 __entry->xfeatures = fpu->state.xsave.header.xfeatures;
26 __entry->xcomp_bv = fpu->state.xsave.header.xcomp_bv; 24 __entry->xcomp_bv = fpu->state.xsave.header.xcomp_bv;
27 } 25 }
28 ), 26 ),
29 TP_printk("x86/fpu: %p initialized: %d xfeatures: %llx xcomp_bv: %llx", 27 TP_printk("x86/fpu: %p xfeatures: %llx xcomp_bv: %llx",
30 __entry->fpu, 28 __entry->fpu,
31 __entry->initialized,
32 __entry->xfeatures, 29 __entry->xfeatures,
33 __entry->xcomp_bv 30 __entry->xcomp_bv
34 ) 31 )
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index e43296854e37..97e27de2b7c0 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -101,7 +101,7 @@ static void __kernel_fpu_begin(void)
101 101
102 kernel_fpu_disable(); 102 kernel_fpu_disable();
103 103
104 if (fpu->initialized) { 104 if (current->mm) {
105 /* 105 /*
106 * Ignore return value -- we don't care if reg state 106 * Ignore return value -- we don't care if reg state
107 * is clobbered. 107 * is clobbered.
@@ -116,7 +116,7 @@ static void __kernel_fpu_end(void)
116{ 116{
117 struct fpu *fpu = &current->thread.fpu; 117 struct fpu *fpu = &current->thread.fpu;
118 118
119 if (fpu->initialized) 119 if (current->mm)
120 copy_kernel_to_fpregs(&fpu->state); 120 copy_kernel_to_fpregs(&fpu->state);
121 121
122 kernel_fpu_enable(); 122 kernel_fpu_enable();
@@ -147,11 +147,10 @@ void fpu__save(struct fpu *fpu)
147 147
148 preempt_disable(); 148 preempt_disable();
149 trace_x86_fpu_before_save(fpu); 149 trace_x86_fpu_before_save(fpu);
150 if (fpu->initialized) { 150
151 if (!copy_fpregs_to_fpstate(fpu)) { 151 if (!copy_fpregs_to_fpstate(fpu))
152 copy_kernel_to_fpregs(&fpu->state); 152 copy_kernel_to_fpregs(&fpu->state);
153 } 153
154 }
155 trace_x86_fpu_after_save(fpu); 154 trace_x86_fpu_after_save(fpu);
156 preempt_enable(); 155 preempt_enable();
157} 156}
@@ -190,7 +189,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
190{ 189{
191 dst_fpu->last_cpu = -1; 190 dst_fpu->last_cpu = -1;
192 191
193 if (!src_fpu->initialized || !static_cpu_has(X86_FEATURE_FPU)) 192 if (!static_cpu_has(X86_FEATURE_FPU))
194 return 0; 193 return 0;
195 194
196 WARN_ON_FPU(src_fpu != &current->thread.fpu); 195 WARN_ON_FPU(src_fpu != &current->thread.fpu);
@@ -227,14 +226,10 @@ static void fpu__initialize(struct fpu *fpu)
227{ 226{
228 WARN_ON_FPU(fpu != &current->thread.fpu); 227 WARN_ON_FPU(fpu != &current->thread.fpu);
229 228
230 if (!fpu->initialized) { 229 fpstate_init(&fpu->state);
231 fpstate_init(&fpu->state); 230 trace_x86_fpu_init_state(fpu);
232 trace_x86_fpu_init_state(fpu);
233 231
234 trace_x86_fpu_activate_state(fpu); 232 trace_x86_fpu_activate_state(fpu);
235 /* Safe to do for the current task: */
236 fpu->initialized = 1;
237 }
238} 233}
239 234
240/* 235/*
@@ -247,32 +242,20 @@ static void fpu__initialize(struct fpu *fpu)
247 * 242 *
248 * - or it's called for stopped tasks (ptrace), in which case the 243 * - or it's called for stopped tasks (ptrace), in which case the
249 * registers were already saved by the context-switch code when 244 * registers were already saved by the context-switch code when
250 * the task scheduled out - we only have to initialize the registers 245 * the task scheduled out.
251 * if they've never been initialized.
252 * 246 *
253 * If the task has used the FPU before then save it. 247 * If the task has used the FPU before then save it.
254 */ 248 */
255void fpu__prepare_read(struct fpu *fpu) 249void fpu__prepare_read(struct fpu *fpu)
256{ 250{
257 if (fpu == &current->thread.fpu) { 251 if (fpu == &current->thread.fpu)
258 fpu__save(fpu); 252 fpu__save(fpu);
259 } else {
260 if (!fpu->initialized) {
261 fpstate_init(&fpu->state);
262 trace_x86_fpu_init_state(fpu);
263
264 trace_x86_fpu_activate_state(fpu);
265 /* Safe to do for current and for stopped child tasks: */
266 fpu->initialized = 1;
267 }
268 }
269} 253}
270 254
271/* 255/*
272 * This function must be called before we write a task's fpstate. 256 * This function must be called before we write a task's fpstate.
273 * 257 *
274 * If the task has used the FPU before then invalidate any cached FPU registers. 258 * Invalidate any cached FPU registers.
275 * If the task has not used the FPU before then initialize its fpstate.
276 * 259 *
277 * After this function call, after registers in the fpstate are 260 * After this function call, after registers in the fpstate are
278 * modified and the child task has woken up, the child task will 261 * modified and the child task has woken up, the child task will
@@ -289,17 +272,8 @@ void fpu__prepare_write(struct fpu *fpu)
289 */ 272 */
290 WARN_ON_FPU(fpu == &current->thread.fpu); 273 WARN_ON_FPU(fpu == &current->thread.fpu);
291 274
292 if (fpu->initialized) { 275 /* Invalidate any cached state: */
293 /* Invalidate any cached state: */ 276 __fpu_invalidate_fpregs_state(fpu);
294 __fpu_invalidate_fpregs_state(fpu);
295 } else {
296 fpstate_init(&fpu->state);
297 trace_x86_fpu_init_state(fpu);
298
299 trace_x86_fpu_activate_state(fpu);
300 /* Safe to do for stopped child tasks: */
301 fpu->initialized = 1;
302 }
303} 277}
304 278
305/* 279/*
@@ -316,17 +290,13 @@ void fpu__drop(struct fpu *fpu)
316 preempt_disable(); 290 preempt_disable();
317 291
318 if (fpu == &current->thread.fpu) { 292 if (fpu == &current->thread.fpu) {
319 if (fpu->initialized) { 293 /* Ignore delayed exceptions from user space */
320 /* Ignore delayed exceptions from user space */ 294 asm volatile("1: fwait\n"
321 asm volatile("1: fwait\n" 295 "2:\n"
322 "2:\n" 296 _ASM_EXTABLE(1b, 2b));
323 _ASM_EXTABLE(1b, 2b)); 297 fpregs_deactivate(fpu);
324 fpregs_deactivate(fpu);
325 }
326 } 298 }
327 299
328 fpu->initialized = 0;
329
330 trace_x86_fpu_dropped(fpu); 300 trace_x86_fpu_dropped(fpu);
331 301
332 preempt_enable(); 302 preempt_enable();
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 6abd83572b01..20d8fa7124c7 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -239,8 +239,6 @@ static void __init fpu__init_system_ctx_switch(void)
239 239
240 WARN_ON_FPU(!on_boot_cpu); 240 WARN_ON_FPU(!on_boot_cpu);
241 on_boot_cpu = 0; 241 on_boot_cpu = 0;
242
243 WARN_ON_FPU(current->thread.fpu.initialized);
244} 242}
245 243
246/* 244/*
diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
index 5dbc099178a8..d652b939ccfb 100644
--- a/arch/x86/kernel/fpu/regset.c
+++ b/arch/x86/kernel/fpu/regset.c
@@ -15,16 +15,12 @@
15 */ 15 */
16int regset_fpregs_active(struct task_struct *target, const struct user_regset *regset) 16int regset_fpregs_active(struct task_struct *target, const struct user_regset *regset)
17{ 17{
18 struct fpu *target_fpu = &target->thread.fpu; 18 return regset->n;
19
20 return target_fpu->initialized ? regset->n : 0;
21} 19}
22 20
23int regset_xregset_fpregs_active(struct task_struct *target, const struct user_regset *regset) 21int regset_xregset_fpregs_active(struct task_struct *target, const struct user_regset *regset)
24{ 22{
25 struct fpu *target_fpu = &target->thread.fpu; 23 if (boot_cpu_has(X86_FEATURE_FXSR))
26
27 if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->initialized)
28 return regset->n; 24 return regset->n;
29 else 25 else
30 return 0; 26 return 0;
@@ -370,16 +366,9 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
370int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu) 366int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu)
371{ 367{
372 struct task_struct *tsk = current; 368 struct task_struct *tsk = current;
373 struct fpu *fpu = &tsk->thread.fpu;
374 int fpvalid;
375
376 fpvalid = fpu->initialized;
377 if (fpvalid)
378 fpvalid = !fpregs_get(tsk, NULL,
379 0, sizeof(struct user_i387_ia32_struct),
380 ufpu, NULL);
381 369
382 return fpvalid; 370 return !fpregs_get(tsk, NULL, 0, sizeof(struct user_i387_ia32_struct),
371 ufpu, NULL);
383} 372}
384EXPORT_SYMBOL(dump_fpu); 373EXPORT_SYMBOL(dump_fpu);
385 374
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index d7432c2b1051..8bfcc5b9e04b 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -892,8 +892,6 @@ const void *get_xsave_field_ptr(int xsave_state)
892{ 892{
893 struct fpu *fpu = &current->thread.fpu; 893 struct fpu *fpu = &current->thread.fpu;
894 894
895 if (!fpu->initialized)
896 return NULL;
897 /* 895 /*
898 * fpu__save() takes the CPU's xstate registers 896 * fpu__save() takes the CPU's xstate registers
899 * and saves them off to the 'fpu memory buffer. 897 * and saves them off to the 'fpu memory buffer.
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 7888a41a03cd..77d9eb43ccac 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -288,10 +288,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
288 if (prev->gs | next->gs) 288 if (prev->gs | next->gs)
289 lazy_load_gs(next->gs); 289 lazy_load_gs(next->gs);
290 290
291 switch_fpu_finish(next_fpu, cpu);
292
293 this_cpu_write(current_task, next_p); 291 this_cpu_write(current_task, next_p);
294 292
293 switch_fpu_finish(next_fpu, cpu);
294
295 /* Load the Intel cache allocation PQR MSR. */ 295 /* Load the Intel cache allocation PQR MSR. */
296 resctrl_sched_in(); 296 resctrl_sched_in();
297 297
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e1983b3a16c4..ffea7c557963 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -566,14 +566,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
566 566
567 x86_fsgsbase_load(prev, next); 567 x86_fsgsbase_load(prev, next);
568 568
569 switch_fpu_finish(next_fpu, cpu);
570
571 /* 569 /*
572 * Switch the PDA and FPU contexts. 570 * Switch the PDA and FPU contexts.
573 */ 571 */
574 this_cpu_write(current_task, next_p); 572 this_cpu_write(current_task, next_p);
575 this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p)); 573 this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p));
576 574
575 switch_fpu_finish(next_fpu, cpu);
576
577 /* Reload sp0. */ 577 /* Reload sp0. */
578 update_task_stack(next_p); 578 update_task_stack(next_p);
579 579
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index b419e1a1a0ce..87b327c6cb10 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -246,7 +246,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
246 unsigned long sp = regs->sp; 246 unsigned long sp = regs->sp;
247 unsigned long buf_fx = 0; 247 unsigned long buf_fx = 0;
248 int onsigstack = on_sig_stack(sp); 248 int onsigstack = on_sig_stack(sp);
249 struct fpu *fpu = &current->thread.fpu; 249 int ret;
250 250
251 /* redzone */ 251 /* redzone */
252 if (IS_ENABLED(CONFIG_X86_64)) 252 if (IS_ENABLED(CONFIG_X86_64))
@@ -265,11 +265,9 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
265 sp = (unsigned long) ka->sa.sa_restorer; 265 sp = (unsigned long) ka->sa.sa_restorer;
266 } 266 }
267 267
268 if (fpu->initialized) { 268 sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
269 sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32), 269 &buf_fx, &math_size);
270 &buf_fx, &math_size); 270 *fpstate = (void __user *)sp;
271 *fpstate = (void __user *)sp;
272 }
273 271
274 sp = align_sigframe(sp - frame_size); 272 sp = align_sigframe(sp - frame_size);
275 273
@@ -281,8 +279,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
281 return (void __user *)-1L; 279 return (void __user *)-1L;
282 280
283 /* save i387 and extended state */ 281 /* save i387 and extended state */
284 if (fpu->initialized && 282 ret = copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size);
285 copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size) < 0) 283 if (ret < 0)
286 return (void __user *)-1L; 284 return (void __user *)-1L;
287 285
288 return (void __user *)sp; 286 return (void __user *)sp;
@@ -763,8 +761,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
763 /* 761 /*
764 * Ensure the signal handler starts with the new fpu state. 762 * Ensure the signal handler starts with the new fpu state.
765 */ 763 */
766 if (fpu->initialized) 764 fpu__clear(fpu);
767 fpu__clear(fpu);
768 } 765 }
769 signal_setup_done(failed, ksig, stepping); 766 signal_setup_done(failed, ksig, stepping);
770} 767}
diff --git a/arch/x86/mm/pkeys.c b/arch/x86/mm/pkeys.c
index 047a77f6a10c..05bb9a44eb1c 100644
--- a/arch/x86/mm/pkeys.c
+++ b/arch/x86/mm/pkeys.c
@@ -39,17 +39,12 @@ int __execute_only_pkey(struct mm_struct *mm)
39 * dance to set PKRU if we do not need to. Check it 39 * dance to set PKRU if we do not need to. Check it
40 * first and assume that if the execute-only pkey is 40 * first and assume that if the execute-only pkey is
41 * write-disabled that we do not have to set it 41 * write-disabled that we do not have to set it
42 * ourselves. We need preempt off so that nobody 42 * ourselves.
43 * can make fpregs inactive.
44 */ 43 */
45 preempt_disable();
46 if (!need_to_set_mm_pkey && 44 if (!need_to_set_mm_pkey &&
47 current->thread.fpu.initialized &&
48 !__pkru_allows_read(read_pkru(), execute_only_pkey)) { 45 !__pkru_allows_read(read_pkru(), execute_only_pkey)) {
49 preempt_enable();
50 return execute_only_pkey; 46 return execute_only_pkey;
51 } 47 }
52 preempt_enable();
53 48
54 /* 49 /*
55 * Set up PKRU so that it denies access for everything 50 * Set up PKRU so that it denies access for everything