@@ -81,11 +81,17 @@ static void msr_restore_context(struct saved_context *ctxt)
static void __save_processor_state(struct saved_context *ctxt)
{
#ifdef CONFIG_X86_32
mtrr_save_fixed_ranges(NULL);
#endif
- kernel_fpu_begin();
+
+ /*
+ * The FPU registers may be live for the current task, so save them to
+ * current's memory register state. The corresponding restore happens
+ * lazily when returning to userspace, not in restore_processor_state().
+ */
+ fpu_save_state();
/*
* descriptor tables
*/
store_idt(&ctxt->idt);
@@ -99,11 +105,10 @@ static void __save_processor_state(struct saved_context *ctxt)
ctxt->gdt_desc.size = GDT_SIZE - 1;
ctxt->gdt_desc.address = (unsigned long)get_cpu_gdt_rw(smp_processor_id());
store_tr(ctxt->tr);
- /* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
/*
* segment registers
*/
savesegment(gs, ctxt->gs);
#ifdef CONFIG_X86_64
@@ -139,18 +144,10 @@ void save_processor_state(void)
}
#ifdef CONFIG_X86_32
EXPORT_SYMBOL(save_processor_state);
#endif
-static void do_fpu_end(void)
-{
- /*
- * Restore FPU regs if necessary.
- */
- kernel_fpu_end();
-}
-
static void fix_processor_context(void)
{
int cpu = smp_processor_id();
#ifdef CONFIG_X86_64
struct desc_struct *desc = get_cpu_gdt_rw(cpu);
@@ -272,11 +269,10 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
wrmsrq(MSR_KERNEL_GS_BASE, ctxt->usermode_gs_base);
#else
loadsegment(gs, ctxt->gs);
#endif
- do_fpu_end();
tsc_verify_tsc_adjust(true);
x86_platform.restore_sched_clock_state();
cache_bp_restore();
perf_restore_debug_store();