diff options
author | Vivek Goyal <vgoyal@in.ibm.com> | 2007-05-02 13:27:07 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-05-02 13:27:07 -0400 |
commit | d8e1baf10d62c06fc52e89137357e54da3d92672 (patch) | |
tree | 57bc6d9858e2136ab8492f46badad9bcd9c4beb3 /arch/x86_64/kernel/acpi/wakeup.S | |
parent | 275f55170ec2b5d777b070cb8ab9e5d58e65a2a8 (diff) |
[PATCH] x86-64: 64bit ACPI wakeup trampoline
o Moved wakeup_level4_pgt into the wakeup routine so we can
run the kernel above 4G.
o Now we first go to 64bit mode and continue to run from trampoline and
then then start accessing kernel symbols and restore processor context.
This enables us to resume even in relocatable kernel context when
kernel might not be loaded at physical addr it has been compiled for.
o Removed the need for modifying any existing kernel page table.
o Increased the size of the wakeup routine to 8K. This is required as
wake page tables are on trampoline itself and they got to be at 4K
boundary, hence one page is not sufficient.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64/kernel/acpi/wakeup.S')
-rw-r--r-- | arch/x86_64/kernel/acpi/wakeup.S | 59 |
1 files changed, 37 insertions, 22 deletions
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 |
82 | wakeup_32_vector: | 86 | wakeup_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 |
165 | wakeup_long64_vector: | 165 | wakeup_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: | |||
223 | gdt_48a: | 228 | gdt_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 | ||
229 | real_magic: .quad 0 | 233 | real_magic: .quad 0 |
230 | video_mode: .quad 0 | 234 | video_mode: .quad 0 |
231 | video_flags: .quad 0 | 235 | video_flags: .quad 0 |
232 | 236 | ||
237 | .code16 | ||
233 | bogus_real_magic: | 238 | bogus_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 | ||
237 | bogus_32_magic: | 242 | .code64 |
243 | bogus_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 | ||
241 | bogus_cpu: | 247 | bogus_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 | ||
266 | mode_seta: | 273 | mode_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 |
314 | wakeup_stack: # Just below end of page | 321 | wakeup_stack: # Just below end of page |
315 | 322 | ||
323 | .org 0x1000 | ||
324 | ENTRY(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 | |||
316 | ENTRY(wakeup_end) | 330 | ENTRY(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 |