Commit 32aa2764 authored by Zhimin Gu's avatar Zhimin Gu Committed by Rafael J. Wysocki
Browse files

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: default avatarZhimin Gu <kookoo.gu@intel.com>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarChen Yu <yu.c.chen@intel.com>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 0b0a6b1f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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");
+7 −3
Original line number Diff line number Diff line
@@ -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