|
@@ -2,8 +2,8 @@
|
|
*
|
|
*
|
|
* Distribute under GPLv2.
|
|
* Distribute under GPLv2.
|
|
*
|
|
*
|
|
- * swsusp_arch_resume may not use any stack, nor any variable that is
|
|
|
|
- * not "NoSave" during copying pages:
|
|
|
|
|
|
+ * swsusp_arch_resume must not use any stack or any nonlocal variables while
|
|
|
|
+ * copying pages:
|
|
*
|
|
*
|
|
* Its rewriting one kernel image with another. What is stack in "old"
|
|
* Its rewriting one kernel image with another. What is stack in "old"
|
|
* image could very well be data page in "new" image, and overwriting
|
|
* image could very well be data page in "new" image, and overwriting
|
|
@@ -36,6 +36,10 @@ ENTRY(swsusp_arch_suspend)
|
|
movq %r15, saved_context_r15(%rip)
|
|
movq %r15, saved_context_r15(%rip)
|
|
pushfq ; popq saved_context_eflags(%rip)
|
|
pushfq ; popq saved_context_eflags(%rip)
|
|
|
|
|
|
|
|
+ /* save the address of restore_registers */
|
|
|
|
+ movq $restore_registers, %rax
|
|
|
|
+ movq %rax, restore_jump_address(%rip)
|
|
|
|
+
|
|
call swsusp_save
|
|
call swsusp_save
|
|
ret
|
|
ret
|
|
|
|
|
|
@@ -54,7 +58,16 @@ ENTRY(restore_image)
|
|
movq %rcx, %cr3;
|
|
movq %rcx, %cr3;
|
|
movq %rax, %cr4; # turn PGE back on
|
|
movq %rax, %cr4; # turn PGE back on
|
|
|
|
|
|
|
|
+ /* prepare to jump to the image kernel */
|
|
|
|
+ movq restore_jump_address(%rip), %rax
|
|
|
|
+
|
|
|
|
+ /* prepare to copy image data to their original locations */
|
|
movq restore_pblist(%rip), %rdx
|
|
movq restore_pblist(%rip), %rdx
|
|
|
|
+ movq relocated_restore_code(%rip), %rcx
|
|
|
|
+ jmpq *%rcx
|
|
|
|
+
|
|
|
|
+ /* code below has been relocated to a safe page */
|
|
|
|
+ENTRY(core_restore_code)
|
|
loop:
|
|
loop:
|
|
testq %rdx, %rdx
|
|
testq %rdx, %rdx
|
|
jz done
|
|
jz done
|
|
@@ -62,7 +75,7 @@ loop:
|
|
/* get addresses from the pbe and copy the page */
|
|
/* get addresses from the pbe and copy the page */
|
|
movq pbe_address(%rdx), %rsi
|
|
movq pbe_address(%rdx), %rsi
|
|
movq pbe_orig_address(%rdx), %rdi
|
|
movq pbe_orig_address(%rdx), %rdi
|
|
- movq $512, %rcx
|
|
|
|
|
|
+ movq $(PAGE_SIZE >> 3), %rcx
|
|
rep
|
|
rep
|
|
movsq
|
|
movsq
|
|
|
|
|
|
@@ -70,6 +83,20 @@ loop:
|
|
movq pbe_next(%rdx), %rdx
|
|
movq pbe_next(%rdx), %rdx
|
|
jmp loop
|
|
jmp loop
|
|
done:
|
|
done:
|
|
|
|
+ /* jump to the restore_registers address from the image header */
|
|
|
|
+ jmpq *%rax
|
|
|
|
+ /*
|
|
|
|
+ * NOTE: This assumes that the boot kernel's text mapping covers the
|
|
|
|
+ * image kernel's page containing restore_registers and the address of
|
|
|
|
+ * this page is the same as in the image kernel's text mapping (it
|
|
|
|
+ * should always be true, because the text mapping is linear, starting
|
|
|
|
+ * from 0, and is supposed to cover the entire kernel text for every
|
|
|
|
+ * kernel).
|
|
|
|
+ *
|
|
|
|
+ * code below belongs to the image kernel
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ENTRY(restore_registers)
|
|
/* go back to the original page tables */
|
|
/* go back to the original page tables */
|
|
movq $(init_level4_pgt - __START_KERNEL_map), %rax
|
|
movq $(init_level4_pgt - __START_KERNEL_map), %rax
|
|
addq phys_base(%rip), %rax
|
|
addq phys_base(%rip), %rax
|
|
@@ -84,12 +111,9 @@ done:
|
|
movq %rcx, %cr3
|
|
movq %rcx, %cr3
|
|
movq %rax, %cr4; # turn PGE back on
|
|
movq %rax, %cr4; # turn PGE back on
|
|
|
|
|
|
- movl $24, %eax
|
|
|
|
- movl %eax, %ds
|
|
|
|
-
|
|
|
|
movq saved_context_esp(%rip), %rsp
|
|
movq saved_context_esp(%rip), %rsp
|
|
movq saved_context_ebp(%rip), %rbp
|
|
movq saved_context_ebp(%rip), %rbp
|
|
- /* Don't restore %rax, it must be 0 anyway */
|
|
|
|
|
|
+ /* restore GPRs (we don't restore %rax, it must be 0 anyway) */
|
|
movq saved_context_ebx(%rip), %rbx
|
|
movq saved_context_ebx(%rip), %rbx
|
|
movq saved_context_ecx(%rip), %rcx
|
|
movq saved_context_ecx(%rip), %rcx
|
|
movq saved_context_edx(%rip), %rdx
|
|
movq saved_context_edx(%rip), %rdx
|
|
@@ -107,4 +131,7 @@ done:
|
|
|
|
|
|
xorq %rax, %rax
|
|
xorq %rax, %rax
|
|
|
|
|
|
|
|
+ /* tell the hibernation core that we've just restored the memory */
|
|
|
|
+ movq %rax, in_suspend(%rip)
|
|
|
|
+
|
|
ret
|
|
ret
|