x86-32, hibernate: Switch to original page table after resumed
authorZhimin Gu <kookoo.gu@intel.com>
Fri, 21 Sep 2018 06:28:11 +0000 (14:28 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 3 Oct 2018 09:56:34 +0000 (11:56 +0200)
After all the pages are restored to previous address, the page
table switches back to current swapper_pg_dir. However the
swapper_pg_dir currently in used might not be consistent with
previous page table, which might cause issue after resume.

Fix this issue by switching to original page table after resume,
and the address of the original page table is saved in the hibernation
image header.

Move the manipulation of restore_cr3 into common code blocks.

Signed-off-by: Zhimin Gu <kookoo.gu@intel.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
arch/x86/power/hibernate.c
arch/x86/power/hibernate_asm_32.S

index e3409e4..4935b81 100644 (file)
@@ -160,6 +160,7 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
 #ifdef CONFIG_X86_64
        rdr->jump_address = (unsigned long)restore_registers;
        rdr->jump_address_phys = __pa_symbol(restore_registers);
+#endif
 
        /*
         * The restore code fixes up CR3 and CR4 in the following sequence:
@@ -179,7 +180,6 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
         * have any of the PCID bits set.
         */
        rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK;
-#endif
 
        return hibernation_e820_save(rdr->e820_digest);
 }
@@ -201,8 +201,8 @@ int arch_hibernation_header_restore(void *addr)
 #ifdef CONFIG_X86_64
        restore_jump_address = rdr->jump_address;
        jump_address_phys = rdr->jump_address_phys;
-       restore_cr3 = rdr->cr3;
 #endif
+       restore_cr3 = rdr->cr3;
 
        if (hibernation_e820_mismatch(rdr->e820_digest)) {
                pr_crit("Hibernate inconsistent memory map detected!\n");
index f5103ae..6b2b949 100644 (file)
@@ -25,6 +25,10 @@ ENTRY(swsusp_arch_suspend)
        pushfl
        popl saved_context_eflags
 
+       /* save cr3 */
+       movl    %cr3, %eax
+       movl    %eax, restore_cr3
+
        FRAME_BEGIN
        call swsusp_save
        FRAME_END
@@ -32,6 +36,8 @@ ENTRY(swsusp_arch_suspend)
 ENDPROC(swsusp_arch_suspend)
 
 ENTRY(restore_image)
+       movl    restore_cr3, %ebp
+
        movl    mmu_cr4_features, %ecx
        movl    temp_pgt, %eax
        movl    %eax, %cr3
@@ -66,9 +72,7 @@ done:
        .align PAGE_SIZE
 ENTRY(restore_registers)
        /* go back to the original page tables */
-       movl    $swapper_pg_dir, %eax
-       subl    $__PAGE_OFFSET, %eax
-       movl    %eax, %cr3
+       movl    %ebp, %cr3
        movl    mmu_cr4_features, %ecx
        jecxz   1f      # cr4 Pentium and higher, skip if zero
        movl    %ecx, %cr4;  # turn PGE back on