aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/kernel/acpi/sleep.c24
-rw-r--r--arch/x86_64/kernel/acpi/wakeup.S59
-rw-r--r--arch/x86_64/kernel/head.S9
3 files changed, 41 insertions, 51 deletions
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index e1548fbe95ae..195b7034a148 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -60,19 +60,6 @@ extern char wakeup_start, wakeup_end;
60 60
61extern unsigned long acpi_copy_wakeup_routine(unsigned long); 61extern unsigned long acpi_copy_wakeup_routine(unsigned long);
62 62
63static pgd_t low_ptr;
64
65static void init_low_mapping(void)
66{
67 pgd_t *slot0 = pgd_offset(current->mm, 0UL);
68 low_ptr = *slot0;
69 /* FIXME: We're playing with the current task's page tables here, which
70 * is potentially dangerous on SMP systems.
71 */
72 set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
73 local_flush_tlb();
74}
75
76/** 63/**
77 * acpi_save_state_mem - save kernel state 64 * acpi_save_state_mem - save kernel state
78 * 65 *
@@ -81,8 +68,6 @@ static void init_low_mapping(void)
81 */ 68 */
82int acpi_save_state_mem(void) 69int acpi_save_state_mem(void)
83{ 70{
84 init_low_mapping();
85
86 memcpy((void *)acpi_wakeup_address, &wakeup_start, 71 memcpy((void *)acpi_wakeup_address, &wakeup_start,
87 &wakeup_end - &wakeup_start); 72 &wakeup_end - &wakeup_start);
88 acpi_copy_wakeup_routine(acpi_wakeup_address); 73 acpi_copy_wakeup_routine(acpi_wakeup_address);
@@ -95,8 +80,6 @@ int acpi_save_state_mem(void)
95 */ 80 */
96void acpi_restore_state_mem(void) 81void acpi_restore_state_mem(void)
97{ 82{
98 set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
99 local_flush_tlb();
100} 83}
101 84
102/** 85/**
@@ -109,10 +92,11 @@ void acpi_restore_state_mem(void)
109 */ 92 */
110void __init acpi_reserve_bootmem(void) 93void __init acpi_reserve_bootmem(void)
111{ 94{
112 acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); 95 acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
113 if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) 96 if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE*2))
114 printk(KERN_CRIT 97 printk(KERN_CRIT
115 "ACPI: Wakeup code way too big, will crash on attempt to suspend\n"); 98 "ACPI: Wakeup code way too big, will crash on attempt"
99 " to suspend\n");
116} 100}
117 101
118static int __init acpi_sleep_setup(char *str) 102static int __init acpi_sleep_setup(char *str)
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S
index bd4c6f1a6f32..766cfbcac1db 100644
--- a/arch/x86_64/kernel/acpi/wakeup.S
+++ b/arch/x86_64/kernel/acpi/wakeup.S
@@ -1,6 +1,7 @@
1.text 1.text
2#include <linux/linkage.h> 2#include <linux/linkage.h>
3#include <asm/segment.h> 3#include <asm/segment.h>
4#include <asm/pgtable.h>
4#include <asm/page.h> 5#include <asm/page.h>
5#include <asm/msr.h> 6#include <asm/msr.h>
6 7
@@ -62,12 +63,15 @@ wakeup_code:
62 63
63 movb $0xa2, %al ; outb %al, $0x80 64 movb $0xa2, %al ; outb %al, $0x80
64 65
65 lidt %ds:idt_48a - wakeup_code 66 mov %ds, %ax # Find 32bit wakeup_code addr
66 xorl %eax, %eax 67 movzx %ax, %esi # (Convert %ds:gdt to a liner ptr)
67 movw %ds, %ax # (Convert %ds:gdt to a linear ptr) 68 shll $4, %esi
68 shll $4, %eax 69 # Fix up the vectors
69 addl $(gdta - wakeup_code), %eax 70 addl %esi, wakeup_32_vector - wakeup_code
70 movl %eax, gdt_48a +2 - wakeup_code 71 addl %esi, wakeup_long64_vector - wakeup_code
72 addl %esi, gdt_48a + 2 - wakeup_code # Fixup the gdt pointer
73
74 lidtl %ds:idt_48a - wakeup_code
71 lgdtl %ds:gdt_48a - wakeup_code # load gdt with whatever is 75 lgdtl %ds:gdt_48a - wakeup_code # load gdt with whatever is
72 # appropriate 76 # appropriate
73 77
@@ -80,7 +84,7 @@ wakeup_code:
80 84
81 .balign 4 85 .balign 4
82wakeup_32_vector: 86wakeup_32_vector:
83 .long wakeup_32 - __START_KERNEL_map 87 .long wakeup_32 - wakeup_code
84 .word __KERNEL32_CS, 0 88 .word __KERNEL32_CS, 0
85 89
86 .code32 90 .code32
@@ -103,10 +107,6 @@ wakeup_32:
103 movl $__KERNEL_DS, %eax 107 movl $__KERNEL_DS, %eax
104 movl %eax, %ds 108 movl %eax, %ds
105 109
106 movl saved_magic - __START_KERNEL_map, %eax
107 cmpl $0x9abcdef0, %eax
108 jne bogus_32_magic
109
110 movw $0x0e00 + 'i', %ds:(0xb8012) 110 movw $0x0e00 + 'i', %ds:(0xb8012)
111 movb $0xa8, %al ; outb %al, $0x80; 111 movb $0xa8, %al ; outb %al, $0x80;
112 112
@@ -120,7 +120,7 @@ wakeup_32:
120 movl %eax, %cr4 120 movl %eax, %cr4
121 121
122 /* Setup early boot stage 4 level pagetables */ 122 /* Setup early boot stage 4 level pagetables */
123 movl $(wakeup_level4_pgt - __START_KERNEL_map), %eax 123 leal (wakeup_level4_pgt - wakeup_code)(%esi), %eax
124 movl %eax, %cr3 124 movl %eax, %cr3
125 125
126 /* Enable Long Mode */ 126 /* Enable Long Mode */
@@ -159,11 +159,11 @@ wakeup_32:
159 */ 159 */
160 160
161 /* Finally jump in 64bit mode */ 161 /* Finally jump in 64bit mode */
162 ljmp *(wakeup_long64_vector - __START_KERNEL_map) 162 ljmp *(wakeup_long64_vector - wakeup_code)(%esi)
163 163
164 .balign 4 164 .balign 4
165wakeup_long64_vector: 165wakeup_long64_vector:
166 .long wakeup_long64 - __START_KERNEL_map 166 .long wakeup_long64 - wakeup_code
167 .word __KERNEL_CS, 0 167 .word __KERNEL_CS, 0
168 168
169.code64 169.code64
@@ -178,11 +178,16 @@ wakeup_long64:
178 * addresses where we're currently running on. We have to do that here 178 * addresses where we're currently running on. We have to do that here
179 * because in 32bit we couldn't load a 64bit linear address. 179 * because in 32bit we couldn't load a 64bit linear address.
180 */ 180 */
181 lgdt cpu_gdt_descr - __START_KERNEL_map 181 lgdt cpu_gdt_descr
182 182
183 movw $0x0e00 + 'n', %ds:(0xb8014) 183 movw $0x0e00 + 'n', %ds:(0xb8014)
184 movb $0xa9, %al ; outb %al, $0x80 184 movb $0xa9, %al ; outb %al, $0x80
185 185
186 movq saved_magic, %rax
187 movq $0x123456789abcdef0, %rdx
188 cmpq %rdx, %rax
189 jne bogus_64_magic
190
186 movw $0x0e00 + 'u', %ds:(0xb8016) 191 movw $0x0e00 + 'u', %ds:(0xb8016)
187 192
188 nop 193 nop
@@ -223,20 +228,21 @@ idt_48a:
223gdt_48a: 228gdt_48a:
224 .word 0x800 # gdt limit=2048, 229 .word 0x800 # gdt limit=2048,
225 # 256 GDT entries 230 # 256 GDT entries
226 .word 0, 0 # gdt base (filled in later) 231 .long gdta - wakeup_code # gdt base (relocated in later)
227
228 232
229real_magic: .quad 0 233real_magic: .quad 0
230video_mode: .quad 0 234video_mode: .quad 0
231video_flags: .quad 0 235video_flags: .quad 0
232 236
237.code16
233bogus_real_magic: 238bogus_real_magic:
234 movb $0xba,%al ; outb %al,$0x80 239 movb $0xba,%al ; outb %al,$0x80
235 jmp bogus_real_magic 240 jmp bogus_real_magic
236 241
237bogus_32_magic: 242.code64
243bogus_64_magic:
238 movb $0xb3,%al ; outb %al,$0x80 244 movb $0xb3,%al ; outb %al,$0x80
239 jmp bogus_32_magic 245 jmp bogus_64_magic
240 246
241bogus_cpu: 247bogus_cpu:
242 movb $0xbc,%al ; outb %al,$0x80 248 movb $0xbc,%al ; outb %al,$0x80
@@ -263,6 +269,7 @@ bogus_cpu:
263#define VIDEO_FIRST_V7 0x0900 269#define VIDEO_FIRST_V7 0x0900
264 270
265# Setting of user mode (AX=mode ID) => CF=success 271# Setting of user mode (AX=mode ID) => CF=success
272.code16
266mode_seta: 273mode_seta:
267 movw %ax, %bx 274 movw %ax, %bx
268#if 0 275#if 0
@@ -313,6 +320,13 @@ wakeup_stack_begin: # Stack grows down
313.org 0xff0 320.org 0xff0
314wakeup_stack: # Just below end of page 321wakeup_stack: # Just below end of page
315 322
323.org 0x1000
324ENTRY(wakeup_level4_pgt)
325 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
326 .fill 510,8,0
327 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
328 .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
329
316ENTRY(wakeup_end) 330ENTRY(wakeup_end)
317 331
318## 332##
@@ -338,9 +352,10 @@ ENTRY(acpi_copy_wakeup_routine)
338 movq $0x123456789abcdef0, %rdx 352 movq $0x123456789abcdef0, %rdx
339 movq %rdx, saved_magic 353 movq %rdx, saved_magic
340 354
341 movl saved_magic - __START_KERNEL_map, %eax 355 movq saved_magic, %rax
342 cmpl $0x9abcdef0, %eax 356 movq $0x123456789abcdef0, %rdx
343 jne bogus_32_magic 357 cmpq %rdx, %rax
358 jne bogus_64_magic
344 359
345 # restore the regs we used 360 # restore the regs we used
346 popq %rdx 361 popq %rdx
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 562d62fbd69f..926aa2197aaa 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -308,15 +308,6 @@ NEXT_PAGE(level2_kernel_pgt)
308 308
309 .data 309 .data
310 310
311#ifdef CONFIG_ACPI_SLEEP
312 .align PAGE_SIZE
313ENTRY(wakeup_level4_pgt)
314 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
315 .fill 510,8,0
316 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
317 .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
318#endif
319
320#ifndef CONFIG_HOTPLUG_CPU 311#ifndef CONFIG_HOTPLUG_CPU
321 __INITDATA 312 __INITDATA
322#endif 313#endif