Skip to content

Commit e5f1e8a

Browse files
xinli-intelIngo Molnar
authored andcommitted
x86/fred: Fix system hang during S4 resume with FRED enabled
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
1 parent d0ebf4c commit e5f1e8a

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

arch/x86/power/cpu.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <asm/mmu_context.h>
2828
#include <asm/cpu_device_id.h>
2929
#include <asm/microcode.h>
30+
#include <asm/fred.h>
3031

3132
#ifdef CONFIG_X86_32
3233
__visible unsigned long saved_context_ebx;
@@ -231,6 +232,19 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
231232
*/
232233
#ifdef CONFIG_X86_64
233234
wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base);
235+
236+
/*
237+
* Reinitialize FRED to ensure the FRED MSRs contain the same values
238+
* as before hibernation.
239+
*
240+
* Note, the setup of FRED RSPs requires access to percpu data
241+
* structures. Therefore, FRED reinitialization can only occur after
242+
* the percpu access pointer (i.e., MSR_GS_BASE) is restored.
243+
*/
244+
if (ctxt->cr4 & X86_CR4_FRED) {
245+
cpu_init_fred_exceptions();
246+
cpu_init_fred_rsps();
247+
}
234248
#else
235249
loadsegment(fs, __KERNEL_PERCPU);
236250
#endif

0 commit comments

Comments
 (0)