Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * This may not use any stack, nor any variable that is not "NoSave":
0004  *
0005  * Its rewriting one kernel image with another. What is stack in "old"
0006  * image could very well be data page in "new" image, and overwriting
0007  * your own stack under you is bad idea.
0008  */
0009 
0010 #include <linux/linkage.h>
0011 #include <asm/segment.h>
0012 #include <asm/page_types.h>
0013 #include <asm/asm-offsets.h>
0014 #include <asm/processor-flags.h>
0015 #include <asm/frame.h>
0016 
0017 .text
0018 
0019 SYM_FUNC_START(swsusp_arch_suspend)
0020     movl %esp, saved_context_esp
0021     movl %ebx, saved_context_ebx
0022     movl %ebp, saved_context_ebp
0023     movl %esi, saved_context_esi
0024     movl %edi, saved_context_edi
0025     pushfl
0026     popl saved_context_eflags
0027 
0028     /* save cr3 */
0029     movl    %cr3, %eax
0030     movl    %eax, restore_cr3
0031 
0032     FRAME_BEGIN
0033     call swsusp_save
0034     FRAME_END
0035     RET
0036 SYM_FUNC_END(swsusp_arch_suspend)
0037 
0038 SYM_CODE_START(restore_image)
0039     /* prepare to jump to the image kernel */
0040     movl    restore_jump_address, %ebx
0041     movl    restore_cr3, %ebp
0042 
0043     movl    mmu_cr4_features, %ecx
0044 
0045     /* jump to relocated restore code */
0046     movl    relocated_restore_code, %eax
0047     jmpl    *%eax
0048 SYM_CODE_END(restore_image)
0049 
0050 /* code below has been relocated to a safe page */
0051 SYM_CODE_START(core_restore_code)
0052     movl    temp_pgt, %eax
0053     movl    %eax, %cr3
0054 
0055     jecxz   1f  # cr4 Pentium and higher, skip if zero
0056     andl    $~(X86_CR4_PGE), %ecx
0057     movl    %ecx, %cr4;  # turn off PGE
0058     movl    %cr3, %eax;  # flush TLB
0059     movl    %eax, %cr3
0060 1:
0061     movl    restore_pblist, %edx
0062     .p2align 4,,7
0063 
0064 copy_loop:
0065     testl   %edx, %edx
0066     jz  done
0067 
0068     movl    pbe_address(%edx), %esi
0069     movl    pbe_orig_address(%edx), %edi
0070 
0071     movl    $(PAGE_SIZE >> 2), %ecx
0072     rep
0073     movsl
0074 
0075     movl    pbe_next(%edx), %edx
0076     jmp copy_loop
0077     .p2align 4,,7
0078 
0079 done:
0080     jmpl    *%ebx
0081 SYM_CODE_END(core_restore_code)
0082 
0083     /* code below belongs to the image kernel */
0084     .align PAGE_SIZE
0085 SYM_FUNC_START(restore_registers)
0086     /* go back to the original page tables */
0087     movl    %ebp, %cr3
0088     movl    mmu_cr4_features, %ecx
0089     jecxz   1f  # cr4 Pentium and higher, skip if zero
0090     movl    %ecx, %cr4;  # turn PGE back on
0091 1:
0092 
0093     movl saved_context_esp, %esp
0094     movl saved_context_ebp, %ebp
0095     movl saved_context_ebx, %ebx
0096     movl saved_context_esi, %esi
0097     movl saved_context_edi, %edi
0098 
0099     pushl saved_context_eflags
0100     popfl
0101 
0102     /* Saved in save_processor_state. */
0103     movl $saved_context, %eax
0104     lgdt saved_context_gdt_desc(%eax)
0105 
0106     xorl    %eax, %eax
0107 
0108     /* tell the hibernation core that we've just restored the memory */
0109     movl    %eax, in_suspend
0110 
0111     RET
0112 SYM_FUNC_END(restore_registers)