Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+53 −48
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/msr.h>
#include <asm/asm-offsets.h>

# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
#
@@ -342,23 +343,24 @@ do_suspend_lowlevel:
	xorl	%eax, %eax
	call	save_processor_state

	movq %rsp, saved_context_esp(%rip)
	movq %rax, saved_context_eax(%rip)
	movq %rbx, saved_context_ebx(%rip)
	movq %rcx, saved_context_ecx(%rip)
	movq %rdx, saved_context_edx(%rip)
	movq %rbp, saved_context_ebp(%rip)
	movq %rsi, saved_context_esi(%rip)
	movq %rdi, saved_context_edi(%rip)
	movq %r8,  saved_context_r08(%rip)
	movq %r9,  saved_context_r09(%rip)
	movq %r10, saved_context_r10(%rip)
	movq %r11, saved_context_r11(%rip)
	movq %r12, saved_context_r12(%rip)
	movq %r13, saved_context_r13(%rip)
	movq %r14, saved_context_r14(%rip)
	movq %r15, saved_context_r15(%rip)
	pushfq ; popq saved_context_eflags(%rip)
	movq	$saved_context, %rax
	movq	%rsp, pt_regs_rsp(%rax)
	movq	%rbp, pt_regs_rbp(%rax)
	movq	%rsi, pt_regs_rsi(%rax)
	movq	%rdi, pt_regs_rdi(%rax)
	movq	%rbx, pt_regs_rbx(%rax)
	movq	%rcx, pt_regs_rcx(%rax)
	movq	%rdx, pt_regs_rdx(%rax)
	movq	%r8, pt_regs_r8(%rax)
	movq	%r9, pt_regs_r9(%rax)
	movq	%r10, pt_regs_r10(%rax)
	movq	%r11, pt_regs_r11(%rax)
	movq	%r12, pt_regs_r12(%rax)
	movq	%r13, pt_regs_r13(%rax)
	movq	%r14, pt_regs_r14(%rax)
	movq	%r15, pt_regs_r15(%rax)
	pushfq
	popq	pt_regs_eflags(%rax)

	movq	$.L97, saved_rip(%rip)

@@ -378,31 +380,34 @@ do_suspend_lowlevel:
	.align 4
	movl	$24, %eax
	movw	%ax, %ds
	movq	saved_context+58(%rip), %rax
	movq %rax, %cr4
	movq	saved_context+50(%rip), %rax
	movq %rax, %cr3
	movq	saved_context+42(%rip), %rax
	movq %rax, %cr2
	movq	saved_context+34(%rip), %rax
	movq %rax, %cr0
	pushq saved_context_eflags(%rip) ; popfq
	movq saved_context_esp(%rip), %rsp
	movq saved_context_ebp(%rip), %rbp
	movq saved_context_eax(%rip), %rax
	movq saved_context_ebx(%rip), %rbx
	movq saved_context_ecx(%rip), %rcx
	movq saved_context_edx(%rip), %rdx
	movq saved_context_esi(%rip), %rsi
	movq saved_context_edi(%rip), %rdi
	movq saved_context_r08(%rip), %r8
	movq saved_context_r09(%rip), %r9
	movq saved_context_r10(%rip), %r10
	movq saved_context_r11(%rip), %r11
	movq saved_context_r12(%rip), %r12
	movq saved_context_r13(%rip), %r13
	movq saved_context_r14(%rip), %r14
	movq saved_context_r15(%rip), %r15

	/* We don't restore %rax, it must be 0 anyway */
	movq	$saved_context, %rax
	movq	saved_context_cr4(%rax), %rbx
	movq	%rbx, %cr4
	movq	saved_context_cr3(%rax), %rbx
	movq	%rbx, %cr3
	movq	saved_context_cr2(%rax), %rbx
	movq	%rbx, %cr2
	movq	saved_context_cr0(%rax), %rbx
	movq	%rbx, %cr0
	pushq	pt_regs_eflags(%rax)
	popfq
	movq	pt_regs_rsp(%rax), %rsp
	movq	pt_regs_rbp(%rax), %rbp
	movq	pt_regs_rsi(%rax), %rsi
	movq	pt_regs_rdi(%rax), %rdi
	movq	pt_regs_rbx(%rax), %rbx
	movq	pt_regs_rcx(%rax), %rcx
	movq	pt_regs_rdx(%rax), %rdx
	movq	pt_regs_r8(%rax), %r8
	movq	pt_regs_r9(%rax), %r9
	movq	pt_regs_r10(%rax), %r10
	movq	pt_regs_r11(%rax), %r11
	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
	addq	$8, %rsp
+28 −0
Original line number Diff line number Diff line
@@ -76,6 +76,34 @@ int main(void)
	DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
	DEFINE(pbe_next, offsetof(struct pbe, next));
	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));
	BLANK();
	DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
+0 −6
Original line number Diff line number Diff line
@@ -19,12 +19,6 @@ extern const void __nosave_begin, __nosave_end;

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)
{
	kernel_fpu_begin();
+37 −35
Original line number Diff line number Diff line
@@ -17,24 +17,24 @@
#include <asm/asm-offsets.h>

ENTRY(swsusp_arch_suspend)

	movq %rsp, saved_context_esp(%rip)
	movq %rax, saved_context_eax(%rip)
	movq %rbx, saved_context_ebx(%rip)
	movq %rcx, saved_context_ecx(%rip)
	movq %rdx, saved_context_edx(%rip)
	movq %rbp, saved_context_ebp(%rip)
	movq %rsi, saved_context_esi(%rip)
	movq %rdi, saved_context_edi(%rip)
	movq %r8,  saved_context_r08(%rip)
	movq %r9,  saved_context_r09(%rip)
	movq %r10, saved_context_r10(%rip)
	movq %r11, saved_context_r11(%rip)
	movq %r12, saved_context_r12(%rip)
	movq %r13, saved_context_r13(%rip)
	movq %r14, saved_context_r14(%rip)
	movq %r15, saved_context_r15(%rip)
	pushfq ; popq saved_context_eflags(%rip)
	movq	$saved_context, %rax
	movq	%rsp, pt_regs_rsp(%rax)
	movq	%rbp, pt_regs_rbp(%rax)
	movq	%rsi, pt_regs_rsi(%rax)
	movq	%rdi, pt_regs_rdi(%rax)
	movq	%rbx, pt_regs_rbx(%rax)
	movq	%rcx, pt_regs_rcx(%rax)
	movq	%rdx, pt_regs_rdx(%rax)
	movq	%r8, pt_regs_r8(%rax)
	movq	%r9, pt_regs_r9(%rax)
	movq	%r10, pt_regs_r10(%rax)
	movq	%r11, pt_regs_r11(%rax)
	movq	%r12, pt_regs_r12(%rax)
	movq	%r13, pt_regs_r13(%rax)
	movq	%r14, pt_regs_r14(%rax)
	movq	%r15, pt_regs_r15(%rax)
	pushfq
	popq	pt_regs_eflags(%rax)

	/* save the address of restore_registers */
	movq	$restore_registers, %rax
@@ -113,23 +113,25 @@ ENTRY(restore_registers)
	movq	%rcx, %cr3
	movq	%rax, %cr4;  # turn PGE back on

	movq saved_context_esp(%rip), %rsp
	movq saved_context_ebp(%rip), %rbp
	/* restore GPRs (we don't restore %rax, it must be 0 anyway) */
	movq saved_context_ebx(%rip), %rbx
	movq saved_context_ecx(%rip), %rcx
	movq saved_context_edx(%rip), %rdx
	movq saved_context_esi(%rip), %rsi
	movq saved_context_edi(%rip), %rdi
	movq saved_context_r08(%rip), %r8
	movq saved_context_r09(%rip), %r9
	movq saved_context_r10(%rip), %r10
	movq saved_context_r11(%rip), %r11
	movq saved_context_r12(%rip), %r12
	movq saved_context_r13(%rip), %r13
	movq saved_context_r14(%rip), %r14
	movq saved_context_r15(%rip), %r15
	pushq saved_context_eflags(%rip) ; popfq
	/* We don't restore %rax, it must be 0 anyway */
	movq	$saved_context, %rax
	movq	pt_regs_rsp(%rax), %rsp
	movq	pt_regs_rbp(%rax), %rbp
	movq	pt_regs_rsi(%rax), %rsi
	movq	pt_regs_rdi(%rax), %rdi
	movq	pt_regs_rbx(%rax), %rbx
	movq	pt_regs_rcx(%rax), %rcx
	movq	pt_regs_rdx(%rax), %rdx
	movq	pt_regs_r8(%rax), %r8
	movq	pt_regs_r9(%rax), %r9
	movq	pt_regs_r10(%rax), %r10
	movq	pt_regs_r11(%rax), %r11
	movq	pt_regs_r12(%rax), %r12
	movq	pt_regs_r13(%rax), %r13
	movq	pt_regs_r14(%rax), %r14
	movq	pt_regs_r15(%rax), %r15
	pushq	pt_regs_eflags(%rax)
	popfq

	xorq	%rax, %rax

+7 −16
Original line number Diff line number Diff line
@@ -3,6 +3,9 @@
 * Based on code
 * 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/i387.h>

@@ -12,8 +15,9 @@ arch_prepare_suspend(void)
	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 pt_regs regs;
  	u16 ds, es, fs, gs, ss;
	unsigned long gs_base, gs_kernel_base, fs_base;
	unsigned long cr0, cr2, cr3, cr4, cr8;
@@ -29,29 +33,16 @@ struct saved_context {
	unsigned long tr;
	unsigned long safety;
	unsigned long return_address;
	unsigned long eflags;
} __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) \
	set_debugreg((thread)->debugreg##register, register)

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 */
extern int acpi_save_state_mem(void);
extern char core_restore_code;
extern char restore_registers;

#endif /* __ASM_X86_64_SUSPEND_H */