Commit 0de80bcc authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Thomas Gleixner

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: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent ef685298
...@@ -4,6 +4,7 @@ ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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; ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 { ...@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment