x86: Save registers in saved_context during suspend and hibernation
During hibernation and suspend on x86_64 save CPU registers in the saved_context structure rather than in a handful of separate variables. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
committed by
Thomas Gleixner
parent
ef685298b4
commit
0de80bcc2b
@@ -4,6 +4,7 @@
|
|||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
|
|
||||||
# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
|
# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
|
||||||
#
|
#
|
||||||
@@ -342,31 +343,32 @@ do_suspend_lowlevel:
|
|||||||
xorl %eax, %eax
|
xorl %eax, %eax
|
||||||
call save_processor_state
|
call save_processor_state
|
||||||
|
|
||||||
movq %rsp, saved_context_esp(%rip)
|
movq $saved_context, %rax
|
||||||
movq %rax, saved_context_eax(%rip)
|
movq %rsp, pt_regs_rsp(%rax)
|
||||||
movq %rbx, saved_context_ebx(%rip)
|
movq %rbp, pt_regs_rbp(%rax)
|
||||||
movq %rcx, saved_context_ecx(%rip)
|
movq %rsi, pt_regs_rsi(%rax)
|
||||||
movq %rdx, saved_context_edx(%rip)
|
movq %rdi, pt_regs_rdi(%rax)
|
||||||
movq %rbp, saved_context_ebp(%rip)
|
movq %rbx, pt_regs_rbx(%rax)
|
||||||
movq %rsi, saved_context_esi(%rip)
|
movq %rcx, pt_regs_rcx(%rax)
|
||||||
movq %rdi, saved_context_edi(%rip)
|
movq %rdx, pt_regs_rdx(%rax)
|
||||||
movq %r8, saved_context_r08(%rip)
|
movq %r8, pt_regs_r8(%rax)
|
||||||
movq %r9, saved_context_r09(%rip)
|
movq %r9, pt_regs_r9(%rax)
|
||||||
movq %r10, saved_context_r10(%rip)
|
movq %r10, pt_regs_r10(%rax)
|
||||||
movq %r11, saved_context_r11(%rip)
|
movq %r11, pt_regs_r11(%rax)
|
||||||
movq %r12, saved_context_r12(%rip)
|
movq %r12, pt_regs_r12(%rax)
|
||||||
movq %r13, saved_context_r13(%rip)
|
movq %r13, pt_regs_r13(%rax)
|
||||||
movq %r14, saved_context_r14(%rip)
|
movq %r14, pt_regs_r14(%rax)
|
||||||
movq %r15, saved_context_r15(%rip)
|
movq %r15, pt_regs_r15(%rax)
|
||||||
pushfq ; popq saved_context_eflags(%rip)
|
pushfq
|
||||||
|
popq pt_regs_eflags(%rax)
|
||||||
|
|
||||||
movq $.L97, saved_rip(%rip)
|
movq $.L97, saved_rip(%rip)
|
||||||
|
|
||||||
movq %rsp,saved_rsp
|
movq %rsp, saved_rsp
|
||||||
movq %rbp,saved_rbp
|
movq %rbp, saved_rbp
|
||||||
movq %rbx,saved_rbx
|
movq %rbx, saved_rbx
|
||||||
movq %rdi,saved_rdi
|
movq %rdi, saved_rdi
|
||||||
movq %rsi,saved_rsi
|
movq %rsi, saved_rsi
|
||||||
|
|
||||||
addq $8, %rsp
|
addq $8, %rsp
|
||||||
movl $3, %edi
|
movl $3, %edi
|
||||||
@@ -377,32 +379,35 @@ do_suspend_lowlevel:
|
|||||||
.L99:
|
.L99:
|
||||||
.align 4
|
.align 4
|
||||||
movl $24, %eax
|
movl $24, %eax
|
||||||
movw %ax, %ds
|
movw %ax, %ds
|
||||||
movq saved_context+58(%rip), %rax
|
|
||||||
movq %rax, %cr4
|
/* We don't restore %rax, it must be 0 anyway */
|
||||||
movq saved_context+50(%rip), %rax
|
movq $saved_context, %rax
|
||||||
movq %rax, %cr3
|
movq saved_context_cr4(%rax), %rbx
|
||||||
movq saved_context+42(%rip), %rax
|
movq %rbx, %cr4
|
||||||
movq %rax, %cr2
|
movq saved_context_cr3(%rax), %rbx
|
||||||
movq saved_context+34(%rip), %rax
|
movq %rbx, %cr3
|
||||||
movq %rax, %cr0
|
movq saved_context_cr2(%rax), %rbx
|
||||||
pushq saved_context_eflags(%rip) ; popfq
|
movq %rbx, %cr2
|
||||||
movq saved_context_esp(%rip), %rsp
|
movq saved_context_cr0(%rax), %rbx
|
||||||
movq saved_context_ebp(%rip), %rbp
|
movq %rbx, %cr0
|
||||||
movq saved_context_eax(%rip), %rax
|
pushq pt_regs_eflags(%rax)
|
||||||
movq saved_context_ebx(%rip), %rbx
|
popfq
|
||||||
movq saved_context_ecx(%rip), %rcx
|
movq pt_regs_rsp(%rax), %rsp
|
||||||
movq saved_context_edx(%rip), %rdx
|
movq pt_regs_rbp(%rax), %rbp
|
||||||
movq saved_context_esi(%rip), %rsi
|
movq pt_regs_rsi(%rax), %rsi
|
||||||
movq saved_context_edi(%rip), %rdi
|
movq pt_regs_rdi(%rax), %rdi
|
||||||
movq saved_context_r08(%rip), %r8
|
movq pt_regs_rbx(%rax), %rbx
|
||||||
movq saved_context_r09(%rip), %r9
|
movq pt_regs_rcx(%rax), %rcx
|
||||||
movq saved_context_r10(%rip), %r10
|
movq pt_regs_rdx(%rax), %rdx
|
||||||
movq saved_context_r11(%rip), %r11
|
movq pt_regs_r8(%rax), %r8
|
||||||
movq saved_context_r12(%rip), %r12
|
movq pt_regs_r9(%rax), %r9
|
||||||
movq saved_context_r13(%rip), %r13
|
movq pt_regs_r10(%rax), %r10
|
||||||
movq saved_context_r14(%rip), %r14
|
movq pt_regs_r11(%rax), %r11
|
||||||
movq saved_context_r15(%rip), %r15
|
movq pt_regs_r12(%rax), %r12
|
||||||
|
movq pt_regs_r13(%rax), %r13
|
||||||
|
movq pt_regs_r14(%rax), %r14
|
||||||
|
movq pt_regs_r15(%rax), %r15
|
||||||
|
|
||||||
xorl %eax, %eax
|
xorl %eax, %eax
|
||||||
addq $8, %rsp
|
addq $8, %rsp
|
||||||
|
@@ -76,6 +76,34 @@ int main(void)
|
|||||||
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
|
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
|
||||||
DEFINE(pbe_next, offsetof(struct pbe, next));
|
DEFINE(pbe_next, offsetof(struct pbe, next));
|
||||||
BLANK();
|
BLANK();
|
||||||
|
#define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry))
|
||||||
|
ENTRY(rbx);
|
||||||
|
ENTRY(rbx);
|
||||||
|
ENTRY(rcx);
|
||||||
|
ENTRY(rdx);
|
||||||
|
ENTRY(rsp);
|
||||||
|
ENTRY(rbp);
|
||||||
|
ENTRY(rsi);
|
||||||
|
ENTRY(rdi);
|
||||||
|
ENTRY(r8);
|
||||||
|
ENTRY(r9);
|
||||||
|
ENTRY(r10);
|
||||||
|
ENTRY(r11);
|
||||||
|
ENTRY(r12);
|
||||||
|
ENTRY(r13);
|
||||||
|
ENTRY(r14);
|
||||||
|
ENTRY(r15);
|
||||||
|
ENTRY(eflags);
|
||||||
|
BLANK();
|
||||||
|
#undef ENTRY
|
||||||
|
#define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry))
|
||||||
|
ENTRY(cr0);
|
||||||
|
ENTRY(cr2);
|
||||||
|
ENTRY(cr3);
|
||||||
|
ENTRY(cr4);
|
||||||
|
ENTRY(cr8);
|
||||||
|
BLANK();
|
||||||
|
#undef ENTRY
|
||||||
DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
|
DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
|
||||||
BLANK();
|
BLANK();
|
||||||
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
|
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
|
||||||
|
@@ -19,12 +19,6 @@ extern const void __nosave_begin, __nosave_end;
|
|||||||
|
|
||||||
struct saved_context saved_context;
|
struct saved_context saved_context;
|
||||||
|
|
||||||
unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
|
|
||||||
unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
|
|
||||||
unsigned long saved_context_r08, saved_context_r09, saved_context_r10, saved_context_r11;
|
|
||||||
unsigned long saved_context_r12, saved_context_r13, saved_context_r14, saved_context_r15;
|
|
||||||
unsigned long saved_context_eflags;
|
|
||||||
|
|
||||||
void __save_processor_state(struct saved_context *ctxt)
|
void __save_processor_state(struct saved_context *ctxt)
|
||||||
{
|
{
|
||||||
kernel_fpu_begin();
|
kernel_fpu_begin();
|
||||||
|
@@ -17,24 +17,24 @@
|
|||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
|
|
||||||
ENTRY(swsusp_arch_suspend)
|
ENTRY(swsusp_arch_suspend)
|
||||||
|
movq $saved_context, %rax
|
||||||
movq %rsp, saved_context_esp(%rip)
|
movq %rsp, pt_regs_rsp(%rax)
|
||||||
movq %rax, saved_context_eax(%rip)
|
movq %rbp, pt_regs_rbp(%rax)
|
||||||
movq %rbx, saved_context_ebx(%rip)
|
movq %rsi, pt_regs_rsi(%rax)
|
||||||
movq %rcx, saved_context_ecx(%rip)
|
movq %rdi, pt_regs_rdi(%rax)
|
||||||
movq %rdx, saved_context_edx(%rip)
|
movq %rbx, pt_regs_rbx(%rax)
|
||||||
movq %rbp, saved_context_ebp(%rip)
|
movq %rcx, pt_regs_rcx(%rax)
|
||||||
movq %rsi, saved_context_esi(%rip)
|
movq %rdx, pt_regs_rdx(%rax)
|
||||||
movq %rdi, saved_context_edi(%rip)
|
movq %r8, pt_regs_r8(%rax)
|
||||||
movq %r8, saved_context_r08(%rip)
|
movq %r9, pt_regs_r9(%rax)
|
||||||
movq %r9, saved_context_r09(%rip)
|
movq %r10, pt_regs_r10(%rax)
|
||||||
movq %r10, saved_context_r10(%rip)
|
movq %r11, pt_regs_r11(%rax)
|
||||||
movq %r11, saved_context_r11(%rip)
|
movq %r12, pt_regs_r12(%rax)
|
||||||
movq %r12, saved_context_r12(%rip)
|
movq %r13, pt_regs_r13(%rax)
|
||||||
movq %r13, saved_context_r13(%rip)
|
movq %r14, pt_regs_r14(%rax)
|
||||||
movq %r14, saved_context_r14(%rip)
|
movq %r15, pt_regs_r15(%rax)
|
||||||
movq %r15, saved_context_r15(%rip)
|
pushfq
|
||||||
pushfq ; popq saved_context_eflags(%rip)
|
popq pt_regs_eflags(%rax)
|
||||||
|
|
||||||
/* save the address of restore_registers */
|
/* save the address of restore_registers */
|
||||||
movq $restore_registers, %rax
|
movq $restore_registers, %rax
|
||||||
@@ -113,23 +113,25 @@ ENTRY(restore_registers)
|
|||||||
movq %rcx, %cr3
|
movq %rcx, %cr3
|
||||||
movq %rax, %cr4; # turn PGE back on
|
movq %rax, %cr4; # turn PGE back on
|
||||||
|
|
||||||
movq saved_context_esp(%rip), %rsp
|
/* We don't restore %rax, it must be 0 anyway */
|
||||||
movq saved_context_ebp(%rip), %rbp
|
movq $saved_context, %rax
|
||||||
/* restore GPRs (we don't restore %rax, it must be 0 anyway) */
|
movq pt_regs_rsp(%rax), %rsp
|
||||||
movq saved_context_ebx(%rip), %rbx
|
movq pt_regs_rbp(%rax), %rbp
|
||||||
movq saved_context_ecx(%rip), %rcx
|
movq pt_regs_rsi(%rax), %rsi
|
||||||
movq saved_context_edx(%rip), %rdx
|
movq pt_regs_rdi(%rax), %rdi
|
||||||
movq saved_context_esi(%rip), %rsi
|
movq pt_regs_rbx(%rax), %rbx
|
||||||
movq saved_context_edi(%rip), %rdi
|
movq pt_regs_rcx(%rax), %rcx
|
||||||
movq saved_context_r08(%rip), %r8
|
movq pt_regs_rdx(%rax), %rdx
|
||||||
movq saved_context_r09(%rip), %r9
|
movq pt_regs_r8(%rax), %r8
|
||||||
movq saved_context_r10(%rip), %r10
|
movq pt_regs_r9(%rax), %r9
|
||||||
movq saved_context_r11(%rip), %r11
|
movq pt_regs_r10(%rax), %r10
|
||||||
movq saved_context_r12(%rip), %r12
|
movq pt_regs_r11(%rax), %r11
|
||||||
movq saved_context_r13(%rip), %r13
|
movq pt_regs_r12(%rax), %r12
|
||||||
movq saved_context_r14(%rip), %r14
|
movq pt_regs_r13(%rax), %r13
|
||||||
movq saved_context_r15(%rip), %r15
|
movq pt_regs_r14(%rax), %r14
|
||||||
pushq saved_context_eflags(%rip) ; popfq
|
movq pt_regs_r15(%rax), %r15
|
||||||
|
pushq pt_regs_eflags(%rax)
|
||||||
|
popfq
|
||||||
|
|
||||||
xorq %rax, %rax
|
xorq %rax, %rax
|
||||||
|
|
||||||
|
@@ -3,6 +3,9 @@
|
|||||||
* Based on code
|
* Based on code
|
||||||
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
|
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
|
||||||
*/
|
*/
|
||||||
|
#ifndef __ASM_X86_64_SUSPEND_H
|
||||||
|
#define __ASM_X86_64_SUSPEND_H
|
||||||
|
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/i387.h>
|
#include <asm/i387.h>
|
||||||
|
|
||||||
@@ -12,8 +15,9 @@ arch_prepare_suspend(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Image of the saved processor state. If you touch this, fix acpi_wakeup.S. */
|
/* Image of the saved processor state. If you touch this, fix acpi/wakeup.S. */
|
||||||
struct saved_context {
|
struct saved_context {
|
||||||
|
struct pt_regs regs;
|
||||||
u16 ds, es, fs, gs, ss;
|
u16 ds, es, fs, gs, ss;
|
||||||
unsigned long gs_base, gs_kernel_base, fs_base;
|
unsigned long gs_base, gs_kernel_base, fs_base;
|
||||||
unsigned long cr0, cr2, cr3, cr4, cr8;
|
unsigned long cr0, cr2, cr3, cr4, cr8;
|
||||||
@@ -29,29 +33,16 @@ struct saved_context {
|
|||||||
unsigned long tr;
|
unsigned long tr;
|
||||||
unsigned long safety;
|
unsigned long safety;
|
||||||
unsigned long return_address;
|
unsigned long return_address;
|
||||||
unsigned long eflags;
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* We'll access these from assembly, so we'd better have them outside struct */
|
|
||||||
extern unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
|
|
||||||
extern unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
|
|
||||||
extern unsigned long saved_context_r08, saved_context_r09, saved_context_r10, saved_context_r11;
|
|
||||||
extern unsigned long saved_context_r12, saved_context_r13, saved_context_r14, saved_context_r15;
|
|
||||||
extern unsigned long saved_context_eflags;
|
|
||||||
|
|
||||||
#define loaddebug(thread,register) \
|
#define loaddebug(thread,register) \
|
||||||
set_debugreg((thread)->debugreg##register, register)
|
set_debugreg((thread)->debugreg##register, register)
|
||||||
|
|
||||||
extern void fix_processor_context(void);
|
extern void fix_processor_context(void);
|
||||||
|
|
||||||
extern unsigned long saved_rip;
|
|
||||||
extern unsigned long saved_rsp;
|
|
||||||
extern unsigned long saved_rbp;
|
|
||||||
extern unsigned long saved_rbx;
|
|
||||||
extern unsigned long saved_rsi;
|
|
||||||
extern unsigned long saved_rdi;
|
|
||||||
|
|
||||||
/* routines for saving/restoring kernel state */
|
/* routines for saving/restoring kernel state */
|
||||||
extern int acpi_save_state_mem(void);
|
extern int acpi_save_state_mem(void);
|
||||||
extern char core_restore_code;
|
extern char core_restore_code;
|
||||||
extern char restore_registers;
|
extern char restore_registers;
|
||||||
|
|
||||||
|
#endif /* __ASM_X86_64_SUSPEND_H */
|
||||||
|
Reference in New Issue
Block a user