aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/acpi/sleep.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/acpi/sleep.c')
-rw-r--r--arch/x86/kernel/acpi/sleep.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index afc25ee9964b..fa2161d5003b 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -9,6 +9,7 @@
9#include <linux/bootmem.h> 9#include <linux/bootmem.h>
10#include <linux/dmi.h> 10#include <linux/dmi.h>
11#include <linux/cpumask.h> 11#include <linux/cpumask.h>
12#include <asm/segment.h>
12 13
13#include "realmode/wakeup.h" 14#include "realmode/wakeup.h"
14#include "sleep.h" 15#include "sleep.h"
@@ -50,6 +51,29 @@ int acpi_save_state_mem(void)
50 51
51 header->video_mode = saved_video_mode; 52 header->video_mode = saved_video_mode;
52 53
54 header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
55
56 /*
57 * Set up the wakeup GDT. We set these up as Big Real Mode,
58 * that is, with limits set to 4 GB. At least the Lenovo
59 * Thinkpad X61 is known to need this for the video BIOS
60 * initialization quirk to work; this is likely to also
61 * be the case for other laptops or integrated video devices.
62 */
63
64 /* GDT[0]: GDT self-pointer */
65 header->wakeup_gdt[0] =
66 (u64)(sizeof(header->wakeup_gdt) - 1) +
67 ((u64)(acpi_wakeup_address +
68 ((char *)&header->wakeup_gdt - (char *)acpi_realmode))
69 << 16);
70 /* GDT[1]: big real mode-like code segment */
71 header->wakeup_gdt[1] =
72 GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
73 /* GDT[2]: big real mode-like data segment */
74 header->wakeup_gdt[2] =
75 GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
76
53#ifndef CONFIG_64BIT 77#ifndef CONFIG_64BIT
54 store_gdt((struct desc_ptr *)&header->pmode_gdt); 78 store_gdt((struct desc_ptr *)&header->pmode_gdt);
55 79
@@ -72,7 +96,9 @@ int acpi_save_state_mem(void)
72 saved_magic = 0x12345678; 96 saved_magic = 0x12345678;
73#else /* CONFIG_64BIT */ 97#else /* CONFIG_64BIT */
74 header->trampoline_segment = setup_trampoline() >> 4; 98 header->trampoline_segment = setup_trampoline() >> 4;
75 init_rsp = (unsigned long)temp_stack + 4096; 99#ifdef CONFIG_SMP
100 stack_start.sp = temp_stack + 4096;
101#endif
76 initial_code = (unsigned long)wakeup_long64; 102 initial_code = (unsigned long)wakeup_long64;
77 saved_magic = 0x123456789abcdef0; 103 saved_magic = 0x123456789abcdef0;
78#endif /* CONFIG_64BIT */ 104#endif /* CONFIG_64BIT */
@@ -111,7 +137,7 @@ void __init acpi_reserve_bootmem(void)
111 return; 137 return;
112 } 138 }
113 139
114 acpi_wakeup_address = acpi_realmode; 140 acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
115} 141}
116 142
117 143
@@ -124,6 +150,12 @@ static int __init acpi_sleep_setup(char *str)
124 acpi_realmode_flags |= 2; 150 acpi_realmode_flags |= 2;
125 if (strncmp(str, "s3_beep", 7) == 0) 151 if (strncmp(str, "s3_beep", 7) == 0)
126 acpi_realmode_flags |= 4; 152 acpi_realmode_flags |= 4;
153#ifdef CONFIG_HIBERNATION
154 if (strncmp(str, "s4_nohwsig", 10) == 0)
155 acpi_no_s4_hw_signature();
156#endif
157 if (strncmp(str, "old_ordering", 12) == 0)
158 acpi_old_suspend_ordering();
127 str = strchr(str, ','); 159 str = strchr(str, ',');
128 if (str != NULL) 160 if (str != NULL)
129 str += strspn(str, ", \t"); 161 str += strspn(str, ", \t");