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: H. 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
This commit is contained in:
parent
5a5a51db78
commit
73201dbec6
@ -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;
|
|||||||
|
|
||||||
/* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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:
|
||||||
|
Loading…
Reference in New Issue
Block a user