2008-02-09 15:24:09 -07:00
|
|
|
/*
|
2005-04-16 16:20:36 -06:00
|
|
|
* This may not use any stack, nor any variable that is not "NoSave":
|
|
|
|
*
|
|
|
|
* Its rewriting one kernel image with another. What is stack in "old"
|
|
|
|
* image could very well be data page in "new" image, and overwriting
|
|
|
|
* your own stack under you is bad idea.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <asm/segment.h>
|
2009-02-13 12:14:01 -07:00
|
|
|
#include <asm/page_types.h>
|
2005-09-09 11:28:28 -06:00
|
|
|
#include <asm/asm-offsets.h>
|
2008-08-20 02:44:47 -06:00
|
|
|
#include <asm/processor-flags.h>
|
2005-04-16 16:20:36 -06:00
|
|
|
|
2008-08-20 02:44:47 -06:00
|
|
|
.text
|
2005-04-16 16:20:36 -06:00
|
|
|
|
|
|
|
ENTRY(swsusp_arch_suspend)
|
|
|
|
movl %esp, saved_context_esp
|
|
|
|
movl %ebx, saved_context_ebx
|
|
|
|
movl %ebp, saved_context_ebp
|
|
|
|
movl %esi, saved_context_esi
|
|
|
|
movl %edi, saved_context_edi
|
2008-08-20 02:44:47 -06:00
|
|
|
pushfl
|
|
|
|
popl saved_context_eflags
|
2005-04-16 16:20:36 -06:00
|
|
|
|
|
|
|
call swsusp_save
|
|
|
|
ret
|
|
|
|
|
2006-12-06 21:34:29 -07:00
|
|
|
ENTRY(restore_image)
|
2008-08-17 22:03:40 -06:00
|
|
|
movl resume_pg_dir, %eax
|
|
|
|
subl $__PAGE_OFFSET, %eax
|
|
|
|
movl %eax, %cr3
|
2005-04-16 16:20:36 -06:00
|
|
|
|
2006-09-26 00:32:52 -06:00
|
|
|
movl restore_pblist, %edx
|
2005-04-16 16:20:36 -06:00
|
|
|
.p2align 4,,7
|
|
|
|
|
|
|
|
copy_loop:
|
|
|
|
testl %edx, %edx
|
|
|
|
jz done
|
|
|
|
|
|
|
|
movl pbe_address(%edx), %esi
|
|
|
|
movl pbe_orig_address(%edx), %edi
|
|
|
|
|
|
|
|
movl $1024, %ecx
|
|
|
|
rep
|
|
|
|
movsl
|
|
|
|
|
|
|
|
movl pbe_next(%edx), %edx
|
|
|
|
jmp copy_loop
|
|
|
|
.p2align 4,,7
|
|
|
|
|
|
|
|
done:
|
2006-12-06 21:34:29 -07:00
|
|
|
/* go back to the original page tables */
|
2008-08-17 22:03:40 -06:00
|
|
|
movl $swapper_pg_dir, %eax
|
|
|
|
subl $__PAGE_OFFSET, %eax
|
|
|
|
movl %eax, %cr3
|
2005-04-16 16:20:36 -06:00
|
|
|
/* Flush TLB, including "global" things (vmalloc) */
|
2008-08-17 22:03:40 -06:00
|
|
|
movl mmu_cr4_features, %ecx
|
|
|
|
jecxz 1f # cr4 Pentium and higher, skip if zero
|
|
|
|
movl %ecx, %edx
|
2008-08-20 02:44:47 -06:00
|
|
|
andl $~(X86_CR4_PGE), %edx
|
2005-04-16 16:20:36 -06:00
|
|
|
movl %edx, %cr4; # turn off PGE
|
2008-08-17 22:03:40 -06:00
|
|
|
1:
|
|
|
|
movl %cr3, %eax; # flush TLB
|
|
|
|
movl %eax, %cr3
|
|
|
|
jecxz 1f # cr4 Pentium and higher, skip if zero
|
|
|
|
movl %ecx, %cr4; # turn PGE back on
|
|
|
|
1:
|
2005-04-16 16:20:36 -06:00
|
|
|
|
|
|
|
movl saved_context_esp, %esp
|
|
|
|
movl saved_context_ebp, %ebp
|
|
|
|
movl saved_context_ebx, %ebx
|
|
|
|
movl saved_context_esi, %esi
|
|
|
|
movl saved_context_edi, %edi
|
|
|
|
|
2008-08-20 02:44:47 -06:00
|
|
|
pushl saved_context_eflags
|
|
|
|
popfl
|
2005-04-16 16:20:36 -06:00
|
|
|
|
|
|
|
xorl %eax, %eax
|
|
|
|
|
|
|
|
ret
|