Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+31 -15
+10 -5
arch/x86/kernel/acpi/sleep.c
··· 43 43 44 44 header->video_mode = saved_video_mode; 45 45 46 + header->pmode_behavior = 0; 47 + 46 48 #ifndef CONFIG_64BIT 47 49 store_gdt((struct desc_ptr *)&header->pmode_gdt); 48 50 49 - if (rdmsr_safe(MSR_EFER, &header->pmode_efer_low, 50 - &header->pmode_efer_high)) 51 - header->pmode_efer_low = header->pmode_efer_high = 0; 51 + if (!rdmsr_safe(MSR_EFER, 52 + &header->pmode_efer_low, 53 + &header->pmode_efer_high)) 54 + header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER); 52 55 #endif /* !CONFIG_64BIT */ 53 56 54 57 header->pmode_cr0 = read_cr0(); 55 - header->pmode_cr4 = read_cr4_safe(); 56 - header->pmode_behavior = 0; 58 + if (__this_cpu_read(cpu_info.cpuid_level) >= 0) { 59 + header->pmode_cr4 = read_cr4(); 60 + header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4); 61 + } 57 62 if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, 58 63 &header->pmode_misc_en_low, 59 64 &header->pmode_misc_en_high))
+2
arch/x86/realmode/rm/wakeup.h
··· 36 36 37 37 /* Wakeup behavior bits */ 38 38 #define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 39 + #define WAKEUP_BEHAVIOR_RESTORE_CR4 1 40 + #define WAKEUP_BEHAVIOR_RESTORE_EFER 2 39 41 40 42 #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
+19 -10
arch/x86/realmode/rm/wakeup_asm.S
··· 74 74 75 75 lidtl wakeup_idt 76 76 77 - /* Clear the EFLAGS */ 78 - pushl $0 77 + /* Clear the EFLAGS but remember if we have EFLAGS.ID */ 78 + movl $X86_EFLAGS_ID, %ecx 79 + pushl %ecx 79 80 popfl 81 + pushfl 82 + popl %edi 83 + pushl $0 84 + popfl 85 + pushfl 86 + popl %edx 87 + xorl %edx, %edi 88 + andl %ecx, %edi /* %edi is zero iff CPUID & %cr4 are missing */ 80 89 81 90 /* Check header signature... */ 82 91 movl signature, %eax ··· 102 93 103 94 /* Restore MISC_ENABLE before entering protected mode, in case 104 95 BIOS decided to clear XD_DISABLE during S3. */ 105 - movl pmode_behavior, %eax 106 - btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax 96 + movl pmode_behavior, %edi 97 + btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi 107 98 jnc 1f 108 99 109 100 movl pmode_misc_en, %eax ··· 119 110 movl pmode_cr3, %eax 120 111 movl %eax, %cr3 121 112 122 - movl pmode_cr4, %ecx 123 - jecxz 1f 124 - movl %ecx, %cr4 113 + btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi 114 + jz 1f 115 + movl pmode_cr4, %eax 116 + movl %eax, %cr4 125 117 1: 118 + btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi 119 + jz 1f 126 120 movl pmode_efer, %eax 127 121 movl pmode_efer + 4, %edx 128 - movl %eax, %ecx 129 - orl %edx, %ecx 130 - jz 1f 131 122 movl $MSR_EFER, %ecx 132 123 wrmsr 133 124 1: