[PATCH] Fix i486 suspend to disk CR4 oops

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: David Fries
Date: Sunday, August 17, 2008 - 9:03 pm

arch/x86/power/cpu_32.c __save_processor_state calls read_cr4()
only a i486 CPU doesn't have the CR4 register.  Trying to read it
produces an invalid opcode oops during suspend to disk.

Added the check (boot_cpu_data.x86 >= 5) before reading the
register.  If the value to be written is zero the write is
skipped.

arch/x86/power/hibernate_asm_32.S
done: swapped the use of %eax and %ecx to use jecxz for
the zero test and jump over store to %cr4.
restore_image: s/%ecx/%eax/ to be consistent with done:

In addition to __save_processor_state, acpi_save_state_mem,
efi_call_phys_prelog, and efi_call_phys_epilog had checks added
(acpi restore was in assembly and already had a check for
non-zero).  There were other reads and writes of CR4, but MCE and
virtualization shouldn't be executed on a i486 anyway.

Signed-off-by: David Fries <david@fries.net>
---
 arch/x86/kernel/acpi/sleep.c      |    4 +++-
 arch/x86/kernel/efi_32.c          |    6 ++++--
 arch/x86/power/cpu_32.c           |    8 ++++++--
 arch/x86/power/hibernate_asm_32.S |   26 +++++++++++++++-----------
 4 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 81e5ab6..bd0f2a3 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -86,7 +86,9 @@ int acpi_save_state_mem(void)
 #endif /* !CONFIG_64BIT */
 
 	header->pmode_cr0 = read_cr0();
-	header->pmode_cr4 = read_cr4();
+	/* cr4 was introduced in the Pentium CPU */
+	if (boot_cpu_data.x86 >= 5)
+		header->pmode_cr4 = read_cr4();
 	header->realmode_flags = acpi_realmode_flags;
 	header->real_magic = 0x12345678;
 
diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c
index 4b63c8e..ad62d31 100644
--- a/arch/x86/kernel/efi_32.c
+++ b/arch/x86/kernel/efi_32.c
@@ -53,7 +53,8 @@ void efi_call_phys_prelog(void)
 	 * directory. If I have PAE, I just need to duplicate one entry in
 	 * page directory.
 	 */
-	cr4 = read_cr4();
+	/* cr4 was introduced in the Pentium CPU */
+	cr4 = boot_cpu_data.x86 >= 5 ? read_cr4() : 0;
 
 	if (cr4 & X86_CR4_PAE) {
 		efi_bak_pg_dir_pointer[0].pgd =
@@ -91,7 +92,8 @@ void efi_call_phys_epilog(void)
 	gdt_descr.size = GDT_SIZE - 1;
 	load_gdt(&gdt_descr);
 
-	cr4 = read_cr4();
+	/* cr4 was introduced in the Pentium CPU */
+	cr4 = boot_cpu_data.x86 >= 5 ? read_cr4() : 0;
 
 	if (cr4 & X86_CR4_PAE) {
 		swapper_pg_dir[pgd_index(0)].pgd =
diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c
index 7dc5d5c..c5647ea 100644
--- a/arch/x86/power/cpu_32.c
+++ b/arch/x86/power/cpu_32.c
@@ -45,7 +45,9 @@ static void __save_processor_state(struct saved_context *ctxt)
 	ctxt->cr0 = read_cr0();
 	ctxt->cr2 = read_cr2();
 	ctxt->cr3 = read_cr3();
-	ctxt->cr4 = read_cr4();
+	/* cr4 was introduced in the Pentium CPU */
+	if (boot_cpu_data.x86 >= 5)
+		ctxt->cr4 = read_cr4();
 }
 
 /* Needed by apm.c */
@@ -98,7 +100,9 @@ static void __restore_processor_state(struct saved_context *ctxt)
 	/*
 	 * control registers
 	 */
-	write_cr4(ctxt->cr4);
+	/* cr4 was introduced in the Pentium CPU */
+	if (ctxt->cr4)
+		write_cr4(ctxt->cr4);
 	write_cr3(ctxt->cr3);
 	write_cr2(ctxt->cr2);
 	write_cr0(ctxt->cr0);
diff --git a/arch/x86/power/hibernate_asm_32.S b/arch/x86/power/hibernate_asm_32.S
index b95aa6c..4fc7e87 100644
--- a/arch/x86/power/hibernate_asm_32.S
+++ b/arch/x86/power/hibernate_asm_32.S
@@ -28,9 +28,9 @@ ENTRY(swsusp_arch_suspend)
 	ret
 
 ENTRY(restore_image)
-	movl	resume_pg_dir, %ecx
-	subl	$__PAGE_OFFSET, %ecx
-	movl	%ecx, %cr3
+	movl	resume_pg_dir, %eax
+	subl	$__PAGE_OFFSET, %eax
+	movl	%eax, %cr3
 
 	movl	restore_pblist, %edx
 	.p2align 4,,7
@@ -52,17 +52,21 @@ copy_loop:
 
 done:
 	/* go back to the original page tables */
-	movl	$swapper_pg_dir, %ecx
-	subl	$__PAGE_OFFSET, %ecx
-	movl	%ecx, %cr3
+	movl	$swapper_pg_dir, %eax
+	subl	$__PAGE_OFFSET, %eax
+	movl	%eax, %cr3
 	/* Flush TLB, including "global" things (vmalloc) */
-	movl	mmu_cr4_features, %eax
-	movl	%eax, %edx
+	movl	mmu_cr4_features, %ecx
+	jecxz	1f	# cr4 Pentium and higher, skip if zero
+	movl	%ecx, %edx
 	andl	$~(1<<7), %edx;  # PGE
 	movl	%edx, %cr4;  # turn off PGE
-	movl	%cr3, %ecx;  # flush TLB
-	movl	%ecx, %cr3
-	movl	%eax, %cr4;  # turn PGE back on
+1:
+	movl	%cr3, %eax;  # flush TLB
+	movl	%eax, %cr3
+	jecxz	1f	# cr4 Pentium and higher, skip if zero
+	movl	%ecx, %cr4;  # turn PGE back on
+1:
 
 	movl saved_context_esp, %esp
 	movl saved_context_ebp, %ebp
-- 
1.4.4.4

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH] Fix i486 suspend to disk CR4 oops, David Fries, (Sun Aug 17, 9:03 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Maciej W. Rozycki, (Sun Aug 17, 9:14 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, H. Peter Anvin, (Sun Aug 17, 9:35 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Andi Kleen, (Sun Aug 17, 11:04 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, H. Peter Anvin, (Sun Aug 17, 11:34 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Ingo Molnar, (Sun Aug 17, 11:41 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Andi Kleen, (Sun Aug 17, 11:42 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, H. Peter Anvin, (Sun Aug 17, 11:45 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Pavel Machek, (Mon Aug 18, 2:15 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Rafael J. Wysocki, (Mon Aug 18, 3:16 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, David Fries, (Mon Aug 18, 5:58 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Ingo Molnar, (Mon Aug 18, 6:25 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Maciej W. Rozycki, (Mon Aug 18, 7:38 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Maciej W. Rozycki, (Mon Aug 18, 7:41 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Dave Jones, (Mon Aug 18, 8:24 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Lennart Sorensen, (Mon Aug 18, 9:04 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Dave Jones, (Mon Aug 18, 10:17 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, H. Peter Anvin, (Mon Aug 18, 10:32 am)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Pavel Machek, (Mon Aug 18, 3:02 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, Pavel Machek, (Mon Aug 18, 3:04 pm)
Re: [PATCH] Fix i486 suspend to disk CR4 oops, H. Peter Anvin, (Mon Aug 18, 3:10 pm)
Re: [PATCH] i486 CR4 oops, no_console_suspend, David Fries, (Mon Aug 18, 8:37 pm)
Re: [PATCH] i486 CR4 oops, no_console_suspend, Ingo Molnar, (Tue Aug 19, 2:34 am)
Re: [PATCH] i486 CR4 oops, no_console_suspend, H. Peter Anvin, (Tue Aug 19, 9:07 am)
Re: [PATCH] i486 CR4 oops, no_console_suspend, David Fries, (Wed Aug 20, 9:17 pm)
Re: [PATCH] i486 CR4 oops, no_console_suspend, H. Peter Anvin, (Wed Aug 20, 10:37 pm)