diff options
-rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 15 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup.h | 2 | ||||
-rw-r--r-- | arch/x86/realmode/rm/wakeup_asm.S | 29 |
3 files changed, 31 insertions, 15 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 1b8e5a03d942..11676cf65aee 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -43,17 +43,22 @@ int acpi_suspend_lowlevel(void) | |||
43 | 43 | ||
44 | header->video_mode = saved_video_mode; | 44 | header->video_mode = saved_video_mode; |
45 | 45 | ||
46 | header->pmode_behavior = 0; | ||
47 | |||
46 | #ifndef CONFIG_64BIT | 48 | #ifndef CONFIG_64BIT |
47 | store_gdt((struct desc_ptr *)&header->pmode_gdt); | 49 | store_gdt((struct desc_ptr *)&header->pmode_gdt); |
48 | 50 | ||
49 | if (rdmsr_safe(MSR_EFER, &header->pmode_efer_low, | 51 | if (!rdmsr_safe(MSR_EFER, |
50 | &header->pmode_efer_high)) | 52 | &header->pmode_efer_low, |
51 | header->pmode_efer_low = header->pmode_efer_high = 0; | 53 | &header->pmode_efer_high)) |
54 | header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER); | ||
52 | #endif /* !CONFIG_64BIT */ | 55 | #endif /* !CONFIG_64BIT */ |
53 | 56 | ||
54 | header->pmode_cr0 = read_cr0(); | 57 | header->pmode_cr0 = read_cr0(); |
55 | header->pmode_cr4 = read_cr4_safe(); | 58 | if (__this_cpu_read(cpu_info.cpuid_level) >= 0) { |
56 | header->pmode_behavior = 0; | 59 | header->pmode_cr4 = read_cr4(); |
60 | header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4); | ||
61 | } | ||
57 | if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, | 62 | if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, |
58 | &header->pmode_misc_en_low, | 63 | &header->pmode_misc_en_low, |
59 | &header->pmode_misc_en_high)) | 64 | &header->pmode_misc_en_high)) |
diff --git a/arch/x86/realmode/rm/wakeup.h b/arch/x86/realmode/rm/wakeup.h index 9317e0042f24..7dd86a419f5d 100644 --- a/arch/x86/realmode/rm/wakeup.h +++ b/arch/x86/realmode/rm/wakeup.h | |||
@@ -36,5 +36,7 @@ extern struct wakeup_header wakeup_header; | |||
36 | 36 | ||
37 | /* Wakeup behavior bits */ | 37 | /* Wakeup behavior bits */ |
38 | #define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 | 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 | #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ | 42 | #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ |
diff --git a/arch/x86/realmode/rm/wakeup_asm.S b/arch/x86/realmode/rm/wakeup_asm.S index 8905166b0bbb..e56479e58053 100644 --- a/arch/x86/realmode/rm/wakeup_asm.S +++ b/arch/x86/realmode/rm/wakeup_asm.S | |||
@@ -74,9 +74,18 @@ ENTRY(wakeup_start) | |||
74 | 74 | ||
75 | lidtl wakeup_idt | 75 | lidtl wakeup_idt |
76 | 76 | ||
77 | /* Clear the EFLAGS */ | 77 | /* Clear the EFLAGS but remember if we have EFLAGS.ID */ |
78 | pushl $0 | 78 | movl $X86_EFLAGS_ID, %ecx |
79 | pushl %ecx | ||
79 | popfl | 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 | /* Check header signature... */ | 90 | /* Check header signature... */ |
82 | movl signature, %eax | 91 | movl signature, %eax |
@@ -93,8 +102,8 @@ ENTRY(wakeup_start) | |||
93 | 102 | ||
94 | /* Restore MISC_ENABLE before entering protected mode, in case | 103 | /* Restore MISC_ENABLE before entering protected mode, in case |
95 | BIOS decided to clear XD_DISABLE during S3. */ | 104 | BIOS decided to clear XD_DISABLE during S3. */ |
96 | movl pmode_behavior, %eax | 105 | movl pmode_behavior, %edi |
97 | btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax | 106 | btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi |
98 | jnc 1f | 107 | jnc 1f |
99 | 108 | ||
100 | movl pmode_misc_en, %eax | 109 | movl pmode_misc_en, %eax |
@@ -110,15 +119,15 @@ ENTRY(wakeup_start) | |||
110 | movl pmode_cr3, %eax | 119 | movl pmode_cr3, %eax |
111 | movl %eax, %cr3 | 120 | movl %eax, %cr3 |
112 | 121 | ||
113 | movl pmode_cr4, %ecx | 122 | btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi |
114 | jecxz 1f | 123 | jz 1f |
115 | movl %ecx, %cr4 | 124 | movl pmode_cr4, %eax |
125 | movl %eax, %cr4 | ||
116 | 1: | 126 | 1: |
127 | btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi | ||
128 | jz 1f | ||
117 | movl pmode_efer, %eax | 129 | movl pmode_efer, %eax |
118 | movl pmode_efer + 4, %edx | 130 | movl pmode_efer + 4, %edx |
119 | movl %eax, %ecx | ||
120 | orl %edx, %ecx | ||
121 | jz 1f | ||
122 | movl $MSR_EFER, %ecx | 131 | movl $MSR_EFER, %ecx |
123 | wrmsr | 132 | wrmsr |
124 | 1: | 133 | 1: |