1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #define WAKEUP_BASE 0x600
4 #define RELOCATED(x) (x - __wakeup + WAKEUP_BASE)
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.
44 /* disable long mode */
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 */
54 movw %ax, (__wakeup_offset)
56 /* the rest is taken as segment */
58 movw %ax, (__wakeup_segment)
60 /* Activate the right segment descriptor real mode. */
61 ljmp $0x28, $RELOCATED(1f)
64 /* 16 bit code from here on... */
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.
78 /* Turn off protection */
83 /* Now really going into real mode */
84 ljmp $0, $RELOCATED(1f)
93 /* This is a FAR JMP to the OS waking vector. The C code changed
94 * the address to be correct.
98 __wakeup_offset = RELOCATED(.)
101 __wakeup_segment = RELOCATED(.)