[PATCH 2/3] x86/pm: Use fpu_save_state() in __save_processor_state()

Eric Biggers
2025-05-16T23:21:41Z

From: Eric Biggers <ebiggers@google.com>

Make __save_processor_state() use fpu_save_state() instead of a
kernel_fpu_begin() and kernel_fpu_end() pair. This matches more
directly what it needs. This eliminates the need for kernel_fpu_begin()
and kernel_fpu_end() to support the irqs_disabled() case.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
arch/x86/power/cpu.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 916441f5e85ce..dde4ccbc77f4b 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -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();

--
2.49.0