1/* 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. 5 */ 6 7#include <asm/msr.h> 8 9#define R(x) x-warm_reboot(%ebx) 10#define R64(x) x-warm_reboot(%rbx) 11 12 /* running in identity mapping and in the first 64k of memory 13 and in compatibility mode. This must be position independent */ 14 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 17 manual, volume 2 */ 18 19 /* ebx: self pointer to warm_reboot */ 20 21 .globl warm_reboot 22warm_reboot: 23 addl %ebx, R64(real_mode_desc) /* relocate tables */ 24 addl %ebx,2+R64(warm_gdt_desc) 25 26 movq %cr0,%rax 27 btr $31,%rax 28 movq %rax,%cr0 /* disable paging */ 29 jmp 1f /* flush prefetch queue */ 30 31 .code32 321: movl $MSR_EFER,%ecx 33 rdmsr 34 andl $~((1<<_EFER_LME)|(1<<_EFER_SCE)|(1<<_EFER_NX)),%eax 35 wrmsr /* disable long mode in EFER */ 36 37 xorl %eax,%eax 38 movl %eax,%cr3 /* flush tlb */ 39 40 /* Running protected mode without paging now */ 41 42 wbinvd /* flush caches. Needed? */ 43 44 lidt R(warm_idt_desc) 45 lgdt R(warm_gdt_desc) 46 47 movl $0x10,%ecx /* load segment registers with real mode settings */ 48 movl %ecx,%ds 49 movl %ecx,%es 50 movl %ecx,%fs 51 movl %ecx,%gs 52 movl %ecx,%ss 53 54 lea R(real_mode_desc),%eax 55 ljmp *(%eax) 56 57 .code16: 58real_mode: 59 xorl %eax,%eax 60 movl %eax,%cr0 61 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 */ 65 66real_mode_desc: 67 .long real_mode - warm_reboot 68 .short 8 69warm_gdt_desc: 70 .short 8*3 71 .long warm_gdt - warm_reboot 72warm_gdt: 73 .quad 0 74 .quad 0x00009a000000ffff /* 16-bit real-mode 64k code at 0x00000000 */ 75 .quad 0x000092000100ffff /* 16-bit real-mode 64k data at 0x00000100 */ 76 77warm_idt_desc: 78 .short 0x3ff 79 .long 0 80 81 .globl warm_reboot_end 82warm_reboot_end: 83 84