blob: 7462dadbe8d5188238b3a04f3ce9fec2f851bf26 [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Rudolf Marek33cafe52009-04-13 18:07:02 +00002
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +00003#define WAKEUP_BASE 0x600
4#define RELOCATED(x) (x - __wakeup + WAKEUP_BASE)
5
6/* CR0 bits */
7#define PE (1 << 0)
8
Patrick Rudolphadcf7822020-08-27 20:50:18 +02009#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -070010 .code64
11#else
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000012 .code32
Stefan Reinauer96938852015-06-18 01:23:48 -070013#endif
14
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000015 .globl __wakeup
16__wakeup:
Patrick Rudolphadcf7822020-08-27 20:50:18 +020017#if ENV_X86_64
Iru Cai88eb1672021-06-29 21:16:26 +080018 /* 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
Elyes HAOUAS2397baf2018-12-22 09:47:46 +010025 xor %rax,%rax
26 mov %ss, %ax
27 push %rax
28 mov %rsp, %rax
29 add $8, %rax
30 push %rax
Stefan Reinauerac901e62015-07-31 16:46:28 -070031 pushfq
Elyes HAOUAS2397baf2018-12-22 09:47:46 +010032 push $0x10
33 lea 3(%rip), %rax
34 push %rax
Stefan Reinauerac901e62015-07-31 16:46:28 -070035 iretq
36
37 .code32
38
39 /* disable paging */
Elyes HAOUAS2397baf2018-12-22 09:47:46 +010040 mov %cr0, %eax
41 btc $31, %eax
42 mov %eax, %cr0
Stefan Reinauerac901e62015-07-31 16:46:28 -070043
44 /* disable long mode */
Elyes HAOUAS2397baf2018-12-22 09:47:46 +010045 mov $0xC0000080, %ecx
Stefan Reinauerac901e62015-07-31 16:46:28 -070046 rdmsr
Elyes HAOUAS2397baf2018-12-22 09:47:46 +010047 btc $8, %eax
Stefan Reinauerac901e62015-07-31 16:46:28 -070048 wrmsr
Stefan Reinauerac901e62015-07-31 16:46:28 -070049#endif
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000050 /* First prepare the jmp to the resume vector */
51 mov 0x4(%esp), %eax /* vector */
Rudolf Marek33cafe52009-04-13 18:07:02 +000052 /* last 4 bits of linear addr are taken as offset */
53 andw $0x0f, %ax
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000054 movw %ax, (__wakeup_offset)
Rudolf Marek33cafe52009-04-13 18:07:02 +000055 mov 0x4(%esp), %eax
56 /* the rest is taken as segment */
57 shr $4, %eax
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000058 movw %ax, (__wakeup_segment)
59
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000060 /* 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
Stefan Reinauer14e22772010-04-27 06:56:47 +000072 mov %ax, %ds
73 mov %ax, %es
74 mov %ax, %fs
75 mov %ax, %gs
76 mov %ax, %ss
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000077
78 /* Turn off protection */
Rudolf Marek33cafe52009-04-13 18:07:02 +000079 movl %cr0, %eax
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000080 andl $~PE, %eax
Rudolf Marek33cafe52009-04-13 18:07:02 +000081 movl %eax, %cr0
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000082
83 /* Now really going into real mode */
84 ljmp $0, $RELOCATED(1f)
851:
Rudolf Marek33cafe52009-04-13 18:07:02 +000086 movw $0x0, %ax
87 movw %ax, %ds
88 movw %ax, %es
89 movw %ax, %ss
90 movw %ax, %fs
91 movw %ax, %gs
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000092
93 /* This is a FAR JMP to the OS waking vector. The C code changed
94 * the address to be correct.
95 */
Rudolf Marek33cafe52009-04-13 18:07:02 +000096 .byte 0xea
Rudolf Marek33cafe52009-04-13 18:07:02 +000097
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000098__wakeup_offset = RELOCATED(.)
99 .word 0x0000
Rudolf Marek33cafe52009-04-13 18:07:02 +0000100
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000101__wakeup_segment = RELOCATED(.)
102 .word 0x0000
Rudolf Marek33cafe52009-04-13 18:07:02 +0000103
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000104 .globl __wakeup_size
Aaron Durbina146d582013-02-08 16:56:51 -0600105__wakeup_size:
106 .long . - __wakeup