2 * Switch back to real mode and call the BIOS reboot vector.
3 * This is a trampoline copied around in process.c
4 * Written 2003 by Andi Kleen, SuSE Labs.
9 #define R(x) x-warm_reboot(%ebx)
10 #define R64(x) x-warm_reboot(%rbx)
12 /* running in identity mapping and in the first 64k of memory
13 and in compatibility mode. This must be position independent */
15 /* Follows 14.7 "Leaving Long Mode" in the AMD x86-64 manual, volume 2
16 and 8.9.2 "Switching Back to Real-Address Mode" in the Intel IA32
19 /* ebx: self pointer to warm_reboot */
23 addl %ebx, R64(real_mode_desc) /* relocate tables */
24 addl %ebx,2+R64(warm_gdt_desc)
28 movq %rax,%cr0 /* disable paging */
29 jmp 1f /* flush prefetch queue */
32 1: movl $MSR_EFER,%ecx
34 andl $~((1<<_EFER_LME)|(1<<_EFER_SCE)|(1<<_EFER_NX)),%eax
35 wrmsr /* disable long mode in EFER */
38 movl %eax,%cr3 /* flush tlb */
40 /* Running protected mode without paging now */
42 wbinvd /* flush caches. Needed? */
47 movl $0x10,%ecx /* load segment registers with real mode settings */
54 lea R(real_mode_desc),%eax
62 /* some people claim $0xf000,0xfff0 is better. Use what 32bit linux uses. */
63 /* code as bytes because gas has problems with it */
64 .byte 0xea,0xf0,0xff,0x00,0xf0 /* ljmp 0xf000:0xfff0 */
67 .long real_mode - warm_reboot
71 .long warm_gdt - warm_reboot
74 .quad 0x00009a000000ffff /* 16-bit real-mode 64k code at 0x00000000 */
75 .quad 0x000092000100ffff /* 16-bit real-mode 64k data at 0x00000100 */
81 .globl warm_reboot_end