summaryrefslogtreecommitdiffstats
path: root/arch/x86/power
diff options
context:
space:
mode:
authorZhimin Gu <kookoo.gu@intel.com>2018-09-21 02:28:11 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-10-03 05:56:34 -0400
commit32aa276437f6128df63111af13e57fe8f0272af3 (patch)
tree58a65d9e86baba9db8ba38c66eea8bd0a7d8e3fd /arch/x86/power
parent0b0a6b1f76835cbaf746e7c72edd374ec0fe818b (diff)
x86-32, hibernate: Switch to original page table after resumed
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>
Diffstat (limited to 'arch/x86/power')
-rw-r--r--arch/x86/power/hibernate.c4
-rw-r--r--arch/x86/power/hibernate_asm_32.S10
2 files changed, 9 insertions, 5 deletions
diff --git a/arch/x86/power/hibernate.c b/arch/x86/power/hibernate.c
index e3409e4a9b6a..4935b8139229 100644
--- a/arch/x86/power/hibernate.c
+++ b/arch/x86/power/hibernate.c
@@ -160,6 +160,7 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
160#ifdef CONFIG_X86_64 160#ifdef CONFIG_X86_64
161 rdr->jump_address = (unsigned long)restore_registers; 161 rdr->jump_address = (unsigned long)restore_registers;
162 rdr->jump_address_phys = __pa_symbol(restore_registers); 162 rdr->jump_address_phys = __pa_symbol(restore_registers);
163#endif
163 164
164 /* 165 /*
165 * The restore code fixes up CR3 and CR4 in the following sequence: 166 * 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)
179 * have any of the PCID bits set. 180 * have any of the PCID bits set.
180 */ 181 */
181 rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK; 182 rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK;
182#endif
183 183
184 return hibernation_e820_save(rdr->e820_digest); 184 return hibernation_e820_save(rdr->e820_digest);
185} 185}
@@ -201,8 +201,8 @@ int arch_hibernation_header_restore(void *addr)
201#ifdef CONFIG_X86_64 201#ifdef CONFIG_X86_64
202 restore_jump_address = rdr->jump_address; 202 restore_jump_address = rdr->jump_address;
203 jump_address_phys = rdr->jump_address_phys; 203 jump_address_phys = rdr->jump_address_phys;
204 restore_cr3 = rdr->cr3;
205#endif 204#endif
205 restore_cr3 = rdr->cr3;
206 206
207 if (hibernation_e820_mismatch(rdr->e820_digest)) { 207 if (hibernation_e820_mismatch(rdr->e820_digest)) {
208 pr_crit("Hibernate inconsistent memory map detected!\n"); 208 pr_crit("Hibernate inconsistent memory map detected!\n");
diff --git a/arch/x86/power/hibernate_asm_32.S b/arch/x86/power/hibernate_asm_32.S
index f5103ae96582..6b2b94937113 100644
--- a/arch/x86/power/hibernate_asm_32.S
+++ b/arch/x86/power/hibernate_asm_32.S
@@ -25,6 +25,10 @@ ENTRY(swsusp_arch_suspend)
25 pushfl 25 pushfl
26 popl saved_context_eflags 26 popl saved_context_eflags
27 27
28 /* save cr3 */
29 movl %cr3, %eax
30 movl %eax, restore_cr3
31
28 FRAME_BEGIN 32 FRAME_BEGIN
29 call swsusp_save 33 call swsusp_save
30 FRAME_END 34 FRAME_END
@@ -32,6 +36,8 @@ ENTRY(swsusp_arch_suspend)
32ENDPROC(swsusp_arch_suspend) 36ENDPROC(swsusp_arch_suspend)
33 37
34ENTRY(restore_image) 38ENTRY(restore_image)
39 movl restore_cr3, %ebp
40
35 movl mmu_cr4_features, %ecx 41 movl mmu_cr4_features, %ecx
36 movl temp_pgt, %eax 42 movl temp_pgt, %eax
37 movl %eax, %cr3 43 movl %eax, %cr3
@@ -66,9 +72,7 @@ done:
66 .align PAGE_SIZE 72 .align PAGE_SIZE
67ENTRY(restore_registers) 73ENTRY(restore_registers)
68 /* go back to the original page tables */ 74 /* go back to the original page tables */
69 movl $swapper_pg_dir, %eax 75 movl %ebp, %cr3
70 subl $__PAGE_OFFSET, %eax
71 movl %eax, %cr3
72 movl mmu_cr4_features, %ecx 76 movl mmu_cr4_features, %ecx
73 jecxz 1f # cr4 Pentium and higher, skip if zero 77 jecxz 1f # cr4 Pentium and higher, skip if zero
74 movl %ecx, %cr4; # turn PGE back on 78 movl %ecx, %cr4; # turn PGE back on