Commit 73201dbe authored by H. Peter Anvin's avatar H. Peter Anvin

x86, suspend: On wakeup always initialize cr4 and EFER

We already have a flag word to indicate the existence of MISC_ENABLES,
so use the same flag word to indicate existence of cr4 and EFER, and
always restore them if they exist.  That way if something passes a
nonzero value when the value *should* be zero, we will still
initialize it.
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Link: http://lkml.kernel.org/r/1348529239-17943-1-git-send-email-hpa@linux.intel.com
parent 5a5a51db
...@@ -43,17 +43,22 @@ int acpi_suspend_lowlevel(void) ...@@ -43,17 +43,22 @@ int acpi_suspend_lowlevel(void)
header->video_mode = saved_video_mode; header->video_mode = saved_video_mode;
header->pmode_behavior = 0;
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
store_gdt((struct desc_ptr *)&header->pmode_gdt); store_gdt((struct desc_ptr *)&header->pmode_gdt);
if (rdmsr_safe(MSR_EFER, &header->pmode_efer_low, if (!rdmsr_safe(MSR_EFER,
&header->pmode_efer_high)) &header->pmode_efer_low,
header->pmode_efer_low = header->pmode_efer_high = 0; &header->pmode_efer_high))
header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER);
#endif /* !CONFIG_64BIT */ #endif /* !CONFIG_64BIT */
header->pmode_cr0 = read_cr0(); header->pmode_cr0 = read_cr0();
header->pmode_cr4 = read_cr4_safe(); if (__this_cpu_read(cpu_info.cpuid_level) >= 0) {
header->pmode_behavior = 0; header->pmode_cr4 = read_cr4();
header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4);
}
if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, if (!rdmsr_safe(MSR_IA32_MISC_ENABLE,
&header->pmode_misc_en_low, &header->pmode_misc_en_low,
&header->pmode_misc_en_high)) &header->pmode_misc_en_high))
......
...@@ -36,5 +36,7 @@ extern struct wakeup_header wakeup_header; ...@@ -36,5 +36,7 @@ extern struct wakeup_header wakeup_header;
/* Wakeup behavior bits */ /* Wakeup behavior bits */
#define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 #define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0
#define WAKEUP_BEHAVIOR_RESTORE_CR4 1
#define WAKEUP_BEHAVIOR_RESTORE_EFER 2
#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
...@@ -74,9 +74,18 @@ ENTRY(wakeup_start) ...@@ -74,9 +74,18 @@ ENTRY(wakeup_start)
lidtl wakeup_idt lidtl wakeup_idt
/* Clear the EFLAGS */ /* Clear the EFLAGS but remember if we have EFLAGS.ID */
pushl $0 movl $X86_EFLAGS_ID, %ecx
pushl %ecx
popfl popfl
pushfl
popl %edi
pushl $0
popfl
pushfl
popl %edx
xorl %edx, %edi
andl %ecx, %edi /* %edi is zero iff CPUID & %cr4 are missing */
/* Check header signature... */ /* Check header signature... */
movl signature, %eax movl signature, %eax
...@@ -93,8 +102,8 @@ ENTRY(wakeup_start) ...@@ -93,8 +102,8 @@ ENTRY(wakeup_start)
/* Restore MISC_ENABLE before entering protected mode, in case /* Restore MISC_ENABLE before entering protected mode, in case
BIOS decided to clear XD_DISABLE during S3. */ BIOS decided to clear XD_DISABLE during S3. */
movl pmode_behavior, %eax movl pmode_behavior, %edi
btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi
jnc 1f jnc 1f
movl pmode_misc_en, %eax movl pmode_misc_en, %eax
...@@ -110,15 +119,15 @@ ENTRY(wakeup_start) ...@@ -110,15 +119,15 @@ ENTRY(wakeup_start)
movl pmode_cr3, %eax movl pmode_cr3, %eax
movl %eax, %cr3 movl %eax, %cr3
movl pmode_cr4, %ecx btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
jecxz 1f jz 1f
movl %ecx, %cr4 movl pmode_cr4, %eax
movl %eax, %cr4
1: 1:
btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
jz 1f
movl pmode_efer, %eax movl pmode_efer, %eax
movl pmode_efer + 4, %edx movl pmode_efer + 4, %edx
movl %eax, %ecx
orl %edx, %ecx
jz 1f
movl $MSR_EFER, %ecx movl $MSR_EFER, %ecx
wrmsr wrmsr
1: 1:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment