diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-10-23 16:37:24 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2007-10-23 16:37:24 -0400 |
| commit | 0de80bcc2baed116a569c38cbc38c5dcb945d14d (patch) | |
| tree | 5eef7beda7307be2e8949f1bf0e7f84799d8ae31 | |
| parent | ef685298b4b3dead1efa1d47cd27ced0f2673254 (diff) | |
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>
| -rw-r--r-- | arch/x86/kernel/acpi/wakeup_64.S | 101 | ||||
| -rw-r--r-- | arch/x86/kernel/asm-offsets_64.c | 28 | ||||
| -rw-r--r-- | arch/x86/kernel/suspend_64.c | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/suspend_asm_64.S | 72 | ||||
| -rw-r--r-- | include/asm-x86/suspend_64.h | 23 |
5 files changed, 125 insertions, 105 deletions
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 55608ec2ed72..5ed3bc5c61d7 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <asm/pgtable.h> | 4 | #include <asm/pgtable.h> |
| 5 | #include <asm/page.h> | 5 | #include <asm/page.h> |
| 6 | #include <asm/msr.h> | 6 | #include <asm/msr.h> |
| 7 | #include <asm/asm-offsets.h> | ||
| 7 | 8 | ||
| 8 | # Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2 | 9 | # Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2 |
| 9 | # | 10 | # |
| @@ -342,31 +343,32 @@ do_suspend_lowlevel: | |||
| 342 | xorl %eax, %eax | 343 | xorl %eax, %eax |
| 343 | call save_processor_state | 344 | call save_processor_state |
| 344 | 345 | ||
| 345 | movq %rsp, saved_context_esp(%rip) | 346 | movq $saved_context, %rax |
| 346 | movq %rax, saved_context_eax(%rip) | 347 | movq %rsp, pt_regs_rsp(%rax) |
| 347 | movq %rbx, saved_context_ebx(%rip) | 348 | movq %rbp, pt_regs_rbp(%rax) |
| 348 | movq %rcx, saved_context_ecx(%rip) | 349 | movq %rsi, pt_regs_rsi(%rax) |
| 349 | movq %rdx, saved_context_edx(%rip) | 350 | movq %rdi, pt_regs_rdi(%rax) |
| 350 | movq %rbp, saved_context_ebp(%rip) | 351 | movq %rbx, pt_regs_rbx(%rax) |
| 351 | movq %rsi, saved_context_esi(%rip) | 352 | movq %rcx, pt_regs_rcx(%rax) |
| 352 | movq %rdi, saved_context_edi(%rip) | 353 | movq %rdx, pt_regs_rdx(%rax) |
| 353 | movq %r8, saved_context_r08(%rip) | 354 | movq %r8, pt_regs_r8(%rax) |
| 354 | movq %r9, saved_context_r09(%rip) | 355 | movq %r9, pt_regs_r9(%rax) |
| 355 | movq %r10, saved_context_r10(%rip) | 356 | movq %r10, pt_regs_r10(%rax) |
| 356 | movq %r11, saved_context_r11(%rip) | 357 | movq %r11, pt_regs_r11(%rax) |
| 357 | movq %r12, saved_context_r12(%rip) | 358 | movq %r12, pt_regs_r12(%rax) |
| 358 | movq %r13, saved_context_r13(%rip) | 359 | movq %r13, pt_regs_r13(%rax) |
| 359 | movq %r14, saved_context_r14(%rip) | 360 | movq %r14, pt_regs_r14(%rax) |
| 360 | movq %r15, saved_context_r15(%rip) | 361 | movq %r15, pt_regs_r15(%rax) |
| 361 | pushfq ; popq saved_context_eflags(%rip) | 362 | pushfq |
| 363 | popq pt_regs_eflags(%rax) | ||
| 362 | 364 | ||
| 363 | movq $.L97, saved_rip(%rip) | 365 | movq $.L97, saved_rip(%rip) |
| 364 | 366 | ||
| 365 | movq %rsp,saved_rsp | 367 | movq %rsp, saved_rsp |
| 366 | movq %rbp,saved_rbp | 368 | movq %rbp, saved_rbp |
| 367 | movq %rbx,saved_rbx | 369 | movq %rbx, saved_rbx |
| 368 | movq %rdi,saved_rdi | 370 | movq %rdi, saved_rdi |
| 369 | movq %rsi,saved_rsi | 371 | movq %rsi, saved_rsi |
| 370 | 372 | ||
| 371 | addq $8, %rsp | 373 | addq $8, %rsp |
| 372 | movl $3, %edi | 374 | movl $3, %edi |
| @@ -377,32 +379,35 @@ do_suspend_lowlevel: | |||
| 377 | .L99: | 379 | .L99: |
| 378 | .align 4 | 380 | .align 4 |
| 379 | movl $24, %eax | 381 | movl $24, %eax |
| 380 | movw %ax, %ds | 382 | movw %ax, %ds |
| 381 | movq saved_context+58(%rip), %rax | 383 | |
| 382 | movq %rax, %cr4 | 384 | /* We don't restore %rax, it must be 0 anyway */ |
| 383 | movq saved_context+50(%rip), %rax | 385 | movq $saved_context, %rax |
| 384 | movq %rax, %cr3 | 386 | movq saved_context_cr4(%rax), %rbx |
| 385 | movq saved_context+42(%rip), %rax | 387 | movq %rbx, %cr4 |
| 386 | movq %rax, %cr2 | 388 | movq saved_context_cr3(%rax), %rbx |
| 387 | movq saved_context+34(%rip), %rax | 389 | movq %rbx, %cr3 |
| 388 | movq %rax, %cr0 | 390 | movq saved_context_cr2(%rax), %rbx |
| 389 | pushq saved_context_eflags(%rip) ; popfq | 391 | movq %rbx, %cr2 |
| 390 | movq saved_context_esp(%rip), %rsp | 392 | movq saved_context_cr0(%rax), %rbx |
| 391 | movq saved_context_ebp(%rip), %rbp | 393 | movq %rbx, %cr0 |
| 392 | movq saved_context_eax(%rip), %rax | 394 | pushq pt_regs_eflags(%rax) |
| 393 | movq saved_context_ebx(%rip), %rbx | 395 | popfq |
| 394 | movq saved_context_ecx(%rip), %rcx | 396 | movq pt_regs_rsp(%rax), %rsp |
| 395 | movq saved_context_edx(%rip), %rdx | 397 | movq pt_regs_rbp(%rax), %rbp |
| 396 | movq saved_context_esi(%rip), %rsi | 398 | movq pt_regs_rsi(%rax), %rsi |
| 397 | movq saved_context_edi(%rip), %rdi | 399 | movq pt_regs_rdi(%rax), %rdi |
| 398 | movq saved_context_r08(%rip), %r8 | 400 | movq pt_regs_rbx(%rax), %rbx |
| 399 | movq saved_context_r09(%rip), %r9 | 401 | movq pt_regs_rcx(%rax), %rcx |
| 400 | movq saved_context_r10(%rip), %r10 | 402 | movq pt_regs_rdx(%rax), %rdx |
| 401 | movq saved_context_r11(%rip), %r11 | 403 | movq pt_regs_r8(%rax), %r8 |
| 402 | movq saved_context_r12(%rip), %r12 | 404 | movq pt_regs_r9(%rax), %r9 |
| 403 | movq saved_context_r13(%rip), %r13 | 405 | movq pt_regs_r10(%rax), %r10 |
| 404 | movq saved_context_r14(%rip), %r14 | 406 | movq pt_regs_r11(%rax), %r11 |
| 405 | movq saved_context_r15(%rip), %r15 | 407 | movq pt_regs_r12(%rax), %r12 |
| 408 | movq pt_regs_r13(%rax), %r13 | ||
| 409 | movq pt_regs_r14(%rax), %r14 | ||
| 410 | movq pt_regs_r15(%rax), %r15 | ||
| 406 | 411 | ||
| 407 | xorl %eax, %eax | 412 | xorl %eax, %eax |
| 408 | addq $8, %rsp | 413 | addq $8, %rsp |
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 778953bc636c..7e50bda565b4 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
| @@ -76,6 +76,34 @@ int main(void) | |||
| 76 | DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); | 76 | DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); |
| 77 | DEFINE(pbe_next, offsetof(struct pbe, next)); | 77 | DEFINE(pbe_next, offsetof(struct pbe, next)); |
| 78 | BLANK(); | 78 | BLANK(); |
| 79 | #define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry)) | ||
| 80 | ENTRY(rbx); | ||
| 81 | ENTRY(rbx); | ||
| 82 | ENTRY(rcx); | ||
| 83 | ENTRY(rdx); | ||
| 84 | ENTRY(rsp); | ||
| 85 | ENTRY(rbp); | ||
| 86 | ENTRY(rsi); | ||
| 87 | ENTRY(rdi); | ||
| 88 | ENTRY(r8); | ||
| 89 | ENTRY(r9); | ||
| 90 | ENTRY(r10); | ||
| 91 | ENTRY(r11); | ||
| 92 | ENTRY(r12); | ||
| 93 | ENTRY(r13); | ||
| 94 | ENTRY(r14); | ||
| 95 | ENTRY(r15); | ||
| 96 | ENTRY(eflags); | ||
| 97 | BLANK(); | ||
| 98 | #undef ENTRY | ||
| 99 | #define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry)) | ||
| 100 | ENTRY(cr0); | ||
| 101 | ENTRY(cr2); | ||
| 102 | ENTRY(cr3); | ||
| 103 | ENTRY(cr4); | ||
| 104 | ENTRY(cr8); | ||
| 105 | BLANK(); | ||
| 106 | #undef ENTRY | ||
| 79 | DEFINE(TSS_ist, offsetof(struct tss_struct, ist)); | 107 | DEFINE(TSS_ist, offsetof(struct tss_struct, ist)); |
| 80 | BLANK(); | 108 | BLANK(); |
| 81 | DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); | 109 | DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); |
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c index bc9f59c246fd..db284ef44d53 100644 --- a/arch/x86/kernel/suspend_64.c +++ b/arch/x86/kernel/suspend_64.c | |||
| @@ -19,12 +19,6 @@ extern const void __nosave_begin, __nosave_end; | |||
| 19 | 19 | ||
| 20 | struct saved_context saved_context; | 20 | struct saved_context saved_context; |
| 21 | 21 | ||
| 22 | unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx; | ||
| 23 | unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi; | ||
| 24 | unsigned long saved_context_r08, saved_context_r09, saved_context_r10, saved_context_r11; | ||
| 25 | unsigned long saved_context_r12, saved_context_r13, saved_context_r14, saved_context_r15; | ||
| 26 | unsigned long saved_context_eflags; | ||
| 27 | |||
| 28 | void __save_processor_state(struct saved_context *ctxt) | 22 | void __save_processor_state(struct saved_context *ctxt) |
| 29 | { | 23 | { |
| 30 | kernel_fpu_begin(); | 24 | kernel_fpu_begin(); |
diff --git a/arch/x86/kernel/suspend_asm_64.S b/arch/x86/kernel/suspend_asm_64.S index 48344b666d2c..72f952103e50 100644 --- a/arch/x86/kernel/suspend_asm_64.S +++ b/arch/x86/kernel/suspend_asm_64.S | |||
| @@ -17,24 +17,24 @@ | |||
| 17 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
| 18 | 18 | ||
| 19 | ENTRY(swsusp_arch_suspend) | 19 | ENTRY(swsusp_arch_suspend) |
| 20 | 20 | movq $saved_context, %rax | |
| 21 | movq %rsp, saved_context_esp(%rip) | 21 | movq %rsp, pt_regs_rsp(%rax) |
| 22 | movq %rax, saved_context_eax(%rip) | 22 | movq %rbp, pt_regs_rbp(%rax) |
| 23 | movq %rbx, saved_context_ebx(%rip) | 23 | movq %rsi, pt_regs_rsi(%rax) |
| 24 | movq %rcx, saved_context_ecx(%rip) | 24 | movq %rdi, pt_regs_rdi(%rax) |
| 25 | movq %rdx, saved_context_edx(%rip) | 25 | movq %rbx, pt_regs_rbx(%rax) |
| 26 | movq %rbp, saved_context_ebp(%rip) | 26 | movq %rcx, pt_regs_rcx(%rax) |
| 27 | movq %rsi, saved_context_esi(%rip) | 27 | movq %rdx, pt_regs_rdx(%rax) |
| 28 | movq %rdi, saved_context_edi(%rip) | 28 | movq %r8, pt_regs_r8(%rax) |
| 29 | movq %r8, saved_context_r08(%rip) | 29 | movq %r9, pt_regs_r9(%rax) |
| 30 | movq %r9, saved_context_r09(%rip) | 30 | movq %r10, pt_regs_r10(%rax) |
| 31 | movq %r10, saved_context_r10(%rip) | 31 | movq %r11, pt_regs_r11(%rax) |
| 32 | movq %r11, saved_context_r11(%rip) | 32 | movq %r12, pt_regs_r12(%rax) |
| 33 | movq %r12, saved_context_r12(%rip) | 33 | movq %r13, pt_regs_r13(%rax) |
| 34 | movq %r13, saved_context_r13(%rip) | 34 | movq %r14, pt_regs_r14(%rax) |
| 35 | movq %r14, saved_context_r14(%rip) | 35 | movq %r15, pt_regs_r15(%rax) |
| 36 | movq %r15, saved_context_r15(%rip) | 36 | pushfq |
| 37 | pushfq ; popq saved_context_eflags(%rip) | 37 | popq pt_regs_eflags(%rax) |
| 38 | 38 | ||
| 39 | /* save the address of restore_registers */ | 39 | /* save the address of restore_registers */ |
| 40 | movq $restore_registers, %rax | 40 | movq $restore_registers, %rax |
| @@ -113,23 +113,25 @@ ENTRY(restore_registers) | |||
| 113 | movq %rcx, %cr3 | 113 | movq %rcx, %cr3 |
| 114 | movq %rax, %cr4; # turn PGE back on | 114 | movq %rax, %cr4; # turn PGE back on |
| 115 | 115 | ||
| 116 | movq saved_context_esp(%rip), %rsp | 116 | /* We don't restore %rax, it must be 0 anyway */ |
| 117 | movq saved_context_ebp(%rip), %rbp | 117 | movq $saved_context, %rax |
| 118 | /* restore GPRs (we don't restore %rax, it must be 0 anyway) */ | 118 | movq pt_regs_rsp(%rax), %rsp |
| 119 | movq saved_context_ebx(%rip), %rbx | 119 | movq pt_regs_rbp(%rax), %rbp |
| 120 | movq saved_context_ecx(%rip), %rcx | 120 | movq pt_regs_rsi(%rax), %rsi |
| 121 | movq saved_context_edx(%rip), %rdx | 121 | movq pt_regs_rdi(%rax), %rdi |
| 122 | movq saved_context_esi(%rip), %rsi | 122 | movq pt_regs_rbx(%rax), %rbx |
| 123 | movq saved_context_edi(%rip), %rdi | 123 | movq pt_regs_rcx(%rax), %rcx |
| 124 | movq saved_context_r08(%rip), %r8 | 124 | movq pt_regs_rdx(%rax), %rdx |
| 125 | movq saved_context_r09(%rip), %r9 | 125 | movq pt_regs_r8(%rax), %r8 |
| 126 | movq saved_context_r10(%rip), %r10 | 126 | movq pt_regs_r9(%rax), %r9 |
| 127 | movq saved_context_r11(%rip), %r11 | 127 | movq pt_regs_r10(%rax), %r10 |
| 128 | movq saved_context_r12(%rip), %r12 | 128 | movq pt_regs_r11(%rax), %r11 |
| 129 | movq saved_context_r13(%rip), %r13 | 129 | movq pt_regs_r12(%rax), %r12 |
| 130 | movq saved_context_r14(%rip), %r14 | 130 | movq pt_regs_r13(%rax), %r13 |
| 131 | movq saved_context_r15(%rip), %r15 | 131 | movq pt_regs_r14(%rax), %r14 |
| 132 | pushq saved_context_eflags(%rip) ; popfq | 132 | movq pt_regs_r15(%rax), %r15 |
| 133 | pushq pt_regs_eflags(%rax) | ||
| 134 | popfq | ||
| 133 | 135 | ||
| 134 | xorq %rax, %rax | 136 | xorq %rax, %rax |
| 135 | 137 | ||
diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h index 9440a7a1b99a..c505a76bcf6e 100644 --- a/include/asm-x86/suspend_64.h +++ b/include/asm-x86/suspend_64.h | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | * Based on code | 3 | * Based on code |
| 4 | * Copyright 2001 Patrick Mochel <mochel@osdl.org> | 4 | * Copyright 2001 Patrick Mochel <mochel@osdl.org> |
| 5 | */ | 5 | */ |
| 6 | #ifndef __ASM_X86_64_SUSPEND_H | ||
| 7 | #define __ASM_X86_64_SUSPEND_H | ||
| 8 | |||
| 6 | #include <asm/desc.h> | 9 | #include <asm/desc.h> |
| 7 | #include <asm/i387.h> | 10 | #include <asm/i387.h> |
| 8 | 11 | ||
| @@ -12,8 +15,9 @@ arch_prepare_suspend(void) | |||
| 12 | return 0; | 15 | return 0; |
| 13 | } | 16 | } |
| 14 | 17 | ||
| 15 | /* Image of the saved processor state. If you touch this, fix acpi_wakeup.S. */ | 18 | /* Image of the saved processor state. If you touch this, fix acpi/wakeup.S. */ |
| 16 | struct saved_context { | 19 | struct saved_context { |
| 20 | struct pt_regs regs; | ||
| 17 | u16 ds, es, fs, gs, ss; | 21 | u16 ds, es, fs, gs, ss; |
| 18 | unsigned long gs_base, gs_kernel_base, fs_base; | 22 | unsigned long gs_base, gs_kernel_base, fs_base; |
| 19 | unsigned long cr0, cr2, cr3, cr4, cr8; | 23 | unsigned long cr0, cr2, cr3, cr4, cr8; |
| @@ -29,29 +33,16 @@ struct saved_context { | |||
| 29 | unsigned long tr; | 33 | unsigned long tr; |
| 30 | unsigned long safety; | 34 | unsigned long safety; |
| 31 | unsigned long return_address; | 35 | unsigned long return_address; |
| 32 | unsigned long eflags; | ||
| 33 | } __attribute__((packed)); | 36 | } __attribute__((packed)); |
| 34 | 37 | ||
| 35 | /* We'll access these from assembly, so we'd better have them outside struct */ | ||
| 36 | extern unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx; | ||
| 37 | extern unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi; | ||
| 38 | extern unsigned long saved_context_r08, saved_context_r09, saved_context_r10, saved_context_r11; | ||
| 39 | extern unsigned long saved_context_r12, saved_context_r13, saved_context_r14, saved_context_r15; | ||
| 40 | extern unsigned long saved_context_eflags; | ||
| 41 | |||
| 42 | #define loaddebug(thread,register) \ | 38 | #define loaddebug(thread,register) \ |
| 43 | set_debugreg((thread)->debugreg##register, register) | 39 | set_debugreg((thread)->debugreg##register, register) |
| 44 | 40 | ||
| 45 | extern void fix_processor_context(void); | 41 | extern void fix_processor_context(void); |
| 46 | 42 | ||
| 47 | extern unsigned long saved_rip; | ||
| 48 | extern unsigned long saved_rsp; | ||
| 49 | extern unsigned long saved_rbp; | ||
| 50 | extern unsigned long saved_rbx; | ||
| 51 | extern unsigned long saved_rsi; | ||
| 52 | extern unsigned long saved_rdi; | ||
| 53 | |||
| 54 | /* routines for saving/restoring kernel state */ | 43 | /* routines for saving/restoring kernel state */ |
| 55 | extern int acpi_save_state_mem(void); | 44 | extern int acpi_save_state_mem(void); |
| 56 | extern char core_restore_code; | 45 | extern char core_restore_code; |
| 57 | extern char restore_registers; | 46 | extern char restore_registers; |
| 47 | |||
| 48 | #endif /* __ASM_X86_64_SUSPEND_H */ | ||
