Skip to content

Commit

Permalink
x86/fred: Fix system hang during S4 resume with FRED enabled
Browse files Browse the repository at this point in the history
Upon a wakeup from S4, the restore kernel starts and initializes the
FRED MSRs as needed from its perspective.  It then loads a hibernation
image, including the image kernel, and attempts to load image pages
directly into their original page frames used before hibernation unless
those frames are currently in use.  Once all pages are moved to their
original locations, it jumps to a "trampoline" page in the image kernel.

At this point, the image kernel takes control, but the FRED MSRs still
contain values set by the restore kernel, which may differ from those
set by the image kernel before hibernation.  Therefore, the image kernel
must ensure the FRED MSRs have the same values as before hibernation.
Since these values depend only on the location of the kernel text and
data, they can be recomputed from scratch.

Reported-by: Xi Pardee <xi.pardee@intel.com>
Reported-by: Todd Brandt <todd.e.brandt@intel.com>
Tested-by: Todd Brandt <todd.e.brandt@intel.com>
Suggested-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250401075728.3626147-1-xin@zytor.com
  • Loading branch information
Xin Li (Intel) authored and Ingo Molnar committed Apr 1, 2025
1 parent d0ebf4c commit e5f1e8a
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions arch/x86/power/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <asm/mmu_context.h>
#include <asm/cpu_device_id.h>
#include <asm/microcode.h>
#include <asm/fred.h>

#ifdef CONFIG_X86_32
__visible unsigned long saved_context_ebx;
Expand Down Expand Up @@ -231,6 +232,19 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
*/
#ifdef CONFIG_X86_64
wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base);

/*
* Reinitialize FRED to ensure the FRED MSRs contain the same values
* as before hibernation.
*
* Note, the setup of FRED RSPs requires access to percpu data
* structures. Therefore, FRED reinitialization can only occur after
* the percpu access pointer (i.e., MSR_GS_BASE) is restored.
*/
if (ctxt->cr4 & X86_CR4_FRED) {
cpu_init_fred_exceptions();
cpu_init_fred_rsps();
}
#else
loadsegment(fs, __KERNEL_PERCPU);
#endif
Expand Down

0 comments on commit e5f1e8a

Please sign in to comment.