1/* SPDX-License-Identifier: GPL-2.0-only */ 2 3#define WAKEUP_BASE 0x600 4#define RELOCATED(x) (x - __wakeup + WAKEUP_BASE) 5 6/* CR0 bits */ 7#define PE (1 << 0) 8 9#if ENV_X86_64 10 .code64 11#else 12 .code32 13#endif 14 15 .globl __wakeup 16__wakeup: 17#if ENV_X86_64 18 /* When called in x86_64 mode, the resume vector is in %rdi 19 * instead of the stack, save it in 4(%rsp) for the 32-bit code. 20 * It's OK to overwrite the return address at (%rsp) because this 21 * function doesn't return. 22 */ 23 mov %edi, 4(%rsp) 24 25 xor %rax,%rax 26 mov %ss, %ax 27 push %rax 28 mov %rsp, %rax 29 add $8, %rax 30 push %rax 31 pushfq 32 push $0x10 33 lea 3(%rip), %rax 34 push %rax 35 iretq 36 37 .code32 38 39 /* disable paging */ 40 mov %cr0, %eax 41 btc $31, %eax 42 mov %eax, %cr0 43 44 /* disable long mode */ 45 mov $0xC0000080, %ecx 46 rdmsr 47 btc $8, %eax 48 wrmsr 49#endif 50 /* First prepare the jmp to the resume vector */ 51 mov 0x4(%esp), %eax /* vector */ 52 /* last 4 bits of linear addr are taken as offset */ 53 andw $0x0f, %ax 54 movw %ax, (__wakeup_offset) 55 mov 0x4(%esp), %eax 56 /* the rest is taken as segment */ 57 shr $4, %eax 58 movw %ax, (__wakeup_segment) 59 60 /* Activate the right segment descriptor real mode. */ 61 ljmp $0x28, $RELOCATED(1f) 621: 63.code16 64 /* 16 bit code from here on... */ 65 66 /* Load the segment registers w/ properly configured 67 * segment descriptors. They will retain these 68 * configurations (limits, writability, etc.) once 69 * protected mode is turned off. 70 */ 71 mov $0x30, %ax 72 mov %ax, %ds 73 mov %ax, %es 74 mov %ax, %fs 75 mov %ax, %gs 76 mov %ax, %ss 77 78 /* Turn off protection */ 79 movl %cr0, %eax 80 andl $~PE, %eax 81 movl %eax, %cr0 82 83 /* Now really going into real mode */ 84 ljmp $0, $RELOCATED(1f) 851: 86 movw $0x0, %ax 87 movw %ax, %ds 88 movw %ax, %es 89 movw %ax, %ss 90 movw %ax, %fs 91 movw %ax, %gs 92 93 /* This is a FAR JMP to the OS waking vector. The C code changed 94 * the address to be correct. 95 */ 96 .byte 0xea 97 98__wakeup_offset = RELOCATED(.) 99 .word 0x0000 100 101__wakeup_segment = RELOCATED(.) 102 .word 0x0000 103 104 .globl __wakeup_size 105__wakeup_size: 106 .long . - __wakeup 107