2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Copyright 2001-2003 Pavel Machek <pavel@suse.cz>
|
|
|
|
* Based on code
|
|
|
|
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
|
|
|
|
*/
|
2008-10-23 13:26:29 +08:00
|
|
|
#ifndef _ASM_X86_SUSPEND_64_H
|
|
|
|
#define _ASM_X86_SUSPEND_64_H
|
2007-10-24 04:37:24 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/desc.h>
|
2015-04-24 08:46:00 +08:00
|
|
|
#include <asm/fpu/api.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-01-30 20:30:04 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
struct saved_context {
|
2007-10-24 04:37:24 +08:00
|
|
|
struct pt_regs regs;
|
2008-03-23 16:03:36 +08:00
|
|
|
u16 ds, es, fs, gs, ss;
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned long gs_base, gs_kernel_base, fs_base;
|
2005-06-26 05:55:14 +08:00
|
|
|
unsigned long cr0, cr2, cr3, cr4, cr8;
|
2010-06-08 06:32:49 +08:00
|
|
|
u64 misc_enable;
|
|
|
|
bool misc_enable_saved;
|
x86/pm: Introduce quirk framework to save/restore extra MSR registers around suspend/resume
A bug was reported that on certain Broadwell platforms, after
resuming from S3, the CPU is running at an anomalously low
speed.
It turns out that the BIOS has modified the value of the
THERM_CONTROL register during S3, and changed it from 0 to 0x10,
thus enabled clock modulation(bit4), but with undefined CPU Duty
Cycle(bit1:3) - which causes the problem.
Here is a simple scenario to reproduce the issue:
1. Boot up the system
2. Get MSR 0x19a, it should be 0
3. Put the system into sleep, then wake it up
4. Get MSR 0x19a, it shows 0x10, while it should be 0
Although some BIOSen want to change the CPU Duty Cycle during
S3, in our case we don't want the BIOS to do any modification.
Fix this issue by introducing a more generic x86 framework to
save/restore specified MSR registers(THERM_CONTROL in this case)
for suspend/resume. This allows us to fix similar bugs in a much
simpler way in the future.
When the kernel wants to protect certain MSRs during suspending,
we simply add a quirk entry in msr_save_dmi_table, and customize
the MSR registers inside the quirk callback, for example:
u32 msr_id_need_to_save[] = {MSR_ID0, MSR_ID1, MSR_ID2...};
and the quirk mechanism ensures that, once resumed from suspend,
the MSRs indicated by these IDs will be restored to their
original, pre-suspend values.
Since both 64-bit and 32-bit kernels are affected, this patch
covers the common 64/32-bit suspend/resume code path. And
because the MSRs specified by the user might not be available or
readable in any situation, we use rdmsrl_safe() to safely save
these MSRs.
Reported-and-tested-by: Marcin Kaszewski <marcin.kaszewski@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: bp@suse.de
Cc: len.brown@intel.com
Cc: linux@horizon.com
Cc: luto@kernel.org
Cc: rjw@rjwysocki.net
Link: http://lkml.kernel.org/r/c9abdcbc173dd2f57e8990e304376f19287e92ba.1448382971.git.yu.c.chen@intel.com
[ More edits to the naming of data structures. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-11-25 01:03:41 +08:00
|
|
|
struct saved_msrs saved_msrs;
|
2007-05-03 01:27:07 +08:00
|
|
|
unsigned long efer;
|
2013-05-02 09:53:30 +08:00
|
|
|
u16 gdt_pad; /* Unused */
|
|
|
|
struct desc_ptr gdt_desc;
|
2005-04-17 06:20:36 +08:00
|
|
|
u16 idt_pad;
|
|
|
|
u16 idt_limit;
|
|
|
|
unsigned long idt_base;
|
|
|
|
u16 ldt;
|
|
|
|
u16 tss;
|
|
|
|
unsigned long tr;
|
|
|
|
unsigned long safety;
|
|
|
|
unsigned long return_address;
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
#define loaddebug(thread,register) \
|
2006-03-25 23:29:22 +08:00
|
|
|
set_debugreg((thread)->debugreg##register, register)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* routines for saving/restoring kernel state */
|
|
|
|
extern int acpi_save_state_mem(void);
|
2007-10-18 18:04:53 +08:00
|
|
|
extern char core_restore_code;
|
|
|
|
extern char restore_registers;
|
2007-10-24 04:37:24 +08:00
|
|
|
|
2008-10-23 13:26:29 +08:00
|
|
|
#endif /* _ASM_X86_SUSPEND_64_H */
|