linux/arch/x86/include/asm/suspend_64.h
Andy Lutomirski 7ee18d6779 x86/power: Make restore_processor_context() sane
My previous attempt to fix a couple of bugs in __restore_processor_context():

  5b06bbcfc2 ("x86/power: Fix some ordering bugs in __restore_processor_context()")

... introduced yet another bug, breaking suspend-resume.

Rather than trying to come up with a minimal fix, let's try to clean it up
for real.  This patch fixes quite a few things:

 - The old code saved a nonsensical subset of segment registers.
   The only registers that need to be saved are those that contain
   userspace state or those that can't be trivially restored without
   percpu access working.  (On x86_32, we can restore percpu access
   by writing __KERNEL_PERCPU to %fs.  On x86_64, it's easier to
   save and restore the kernel's GSBASE.)  With this patch, we
   restore hardcoded values to the kernel state where applicable and
   explicitly restore the user state after fixing all the descriptor
   tables.

 - We used to use an unholy mix of inline asm and C helpers for
   segment register access.  Let's get rid of the inline asm.

This fixes the reported s2ram hangs and make the code all around
more logical.

Analyzed-by: Linus Torvalds <torvalds@linux-foundation.org>
Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Reported-by: Pavel Machek <pavel@ucw.cz>
Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Borislav Petkov <bpetkov@suse.de>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Zhang Rui <rui.zhang@intel.com>
Fixes: 5b06bbcfc2 ("x86/power: Fix some ordering bugs in __restore_processor_context()")
Link: http://lkml.kernel.org/r/398ee68e5c0f766425a7b746becfc810840770ff.1513286253.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-12-15 12:21:38 +01:00

61 lines
1.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2001-2003 Pavel Machek <pavel@suse.cz>
* Based on code
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
*/
#ifndef _ASM_X86_SUSPEND_64_H
#define _ASM_X86_SUSPEND_64_H
#include <asm/desc.h>
#include <asm/fpu/api.h>
/*
* Image of the saved processor state, used by the low level ACPI suspend to
* RAM code and by the low level hibernation code.
*
* If you modify it, fix arch/x86/kernel/acpi/wakeup_64.S and make sure that
* __save/__restore_processor_state(), defined in arch/x86/kernel/suspend_64.c,
* still work as required.
*/
struct saved_context {
struct pt_regs regs;
/*
* User CS and SS are saved in current_pt_regs(). The rest of the
* segment selectors need to be saved and restored here.
*/
u16 ds, es, fs, gs;
/*
* Usermode FSBASE and GSBASE may not match the fs and gs selectors,
* so we save them separately. We save the kernelmode GSBASE to
* restore percpu access after resume.
*/
unsigned long kernelmode_gs_base, usermode_gs_base, fs_base;
unsigned long cr0, cr2, cr3, cr4, cr8;
u64 misc_enable;
bool misc_enable_saved;
struct saved_msrs saved_msrs;
unsigned long efer;
u16 gdt_pad; /* Unused */
struct desc_ptr gdt_desc;
u16 idt_pad;
struct desc_ptr idt;
u16 ldt;
u16 tss;
unsigned long tr;
unsigned long safety;
unsigned long return_address;
} __attribute__((packed));
#define loaddebug(thread,register) \
set_debugreg((thread)->debugreg##register, register)
/* routines for saving/restoring kernel state */
extern char core_restore_code[];
extern char restore_registers[];
#endif /* _ASM_X86_SUSPEND_64_H */