Fix CYG GCC build fail on retf.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / BootScriptSaveOnS3SaveStateThunk / X64 / AsmDispatchExecute.S
CommitLineData
d766b228
JY
1#\r
2# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
3# This program and the accompanying materials\r
4# are licensed and made available under the terms and conditions of the BSD License\r
5# which accompanies this distribution. The full text of the license may be found at\r
6# http://opensource.org/licenses/bsd-license.php\r
7#\r
8# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10#\r
11#\r
12# Module Name:\r
13# \r
14# AsmDispatchExecute.asm\r
15#\r
16# Abstract:\r
17# \r
18# This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then \r
19# transit back to long mode.\r
20#\r
21#------------------------------------------------------------------------------- \r
22\r
23#----------------------------------------------------------------------------\r
24# Procedure: AsmExecute32BitCode\r
25#\r
26# Input: None\r
27#\r
28# Output: None\r
29#\r
30# Prototype: EFI_STATUS\r
31# AsmExecute32BitCode (\r
32# IN UINT64 Function,\r
33# IN UINT64 Param1,\r
34# IN UINT64 Param2,\r
35# IN IA32_DESCRIPTOR *InternalGdtr\r
36# );\r
37#\r
38#\r
39# Description: A thunk function to execute 32-bit code in long mode. \r
40#\r
41#----------------------------------------------------------------------------\r
42\r
43ASM_GLOBAL ASM_PFX(AsmExecute32BitCode)\r
44ASM_PFX(AsmExecute32BitCode):\r
45 #\r
46 # save orignal GDTR and CS\r
47 #\r
48 movq %ds, %rax\r
49 push %rax\r
50 movq %cs, %rax\r
51 push %rax\r
52 subq $0x10, %rsp\r
53 sgdt (%rsp)\r
54 #\r
55 # load internal GDT\r
56 #\r
57 lgdt (%r9)\r
58 #\r
59 # Save general purpose register and rflag register\r
60 #\r
61 pushfq \r
62 push %rdi\r
63 push %rsi\r
64 push %rbp\r
65 push %rbx\r
66 \r
67 #\r
68 # save CR3\r
69 #\r
70 movq %cr3, %rax\r
71 movq %rax, %rbp\r
72\r
73 #\r
74 # Prepare the CS and return address for the transition from 32-bit to 64-bit mode \r
75 # \r
76 movq $0x10, %rax # load long mode selector \r
77 shl $32, %rax\r
78 lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G\r
79 orq %r9, %rax\r
80 push %rax\r
81 #\r
82 # Save parameters for 32-bit function call\r
83 # \r
84 movq %r8, %rax\r
85 shl $32, %rax\r
86 orq %rdx, %rax\r
87 push %rax\r
88 #\r
89 # save the 32-bit function entry and the return address into stack which will be \r
90 # retrieve in compatibility mode.\r
91 #\r
92 lea ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G \r
93 shl $32, %rax\r
94 orq %rcx, %rax\r
95 push %rax\r
96 \r
97 #\r
98 # let rax save DS\r
99 #\r
100 movq $0x18, %rax\r
101\r
102 #\r
103 # Change to Compatible Segment\r
104 #\r
105 movq $8, %rcx # load compatible mode selector \r
106 shl $32, %rcx\r
107 lea Compatible(%rip), %rdx # assume address < 4G\r
108 orq %rdx, %rcx\r
109 push %rcx\r
4eed2dbd 110 .byte 0xcb # retf\r
d766b228
JY
111\r
112Compatible:\r
113 # reload DS/ES/SS to make sure they are correct referred to current GDT\r
6dd67b60
JY
114 movw %ax, %ds\r
115 movw %ax, %es\r
116 movw %ax, %ss\r
d766b228
JY
117\r
118 #\r
119 # Disable paging\r
120 #\r
121 movq %cr0, %rcx\r
122 btc $31, %ecx\r
123 movq %rcx, %cr0\r
124 #\r
125 # Clear EFER.LME\r
126 #\r
127 movl $0xC0000080, %ecx\r
128 rdmsr\r
129 btc $8, %eax\r
130 wrmsr\r
131\r
132# Now we are in protected mode\r
133 #\r
134 # Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
135 # \r
136 pop %rax # Here is the function entry\r
137 # \r
138 # Now the parameter is at the bottom of the stack, then call in to IA32 function.\r
139 #\r
140 jmp *%rax\r
141ReturnBack: \r
142 pop %rcx # drop param1 \r
143 pop %rcx # drop param2 \r
144\r
145 #\r
146 # restore CR4\r
147 #\r
148 movq %cr4, %rax\r
149 bts $5, %eax\r
150 movq %rax, %cr4\r
151\r
152 #\r
153 # restore CR3\r
154 #\r
155 movl %ebp, %eax\r
156 movq %rax, %cr3\r
157\r
158 #\r
159 # Set EFER.LME to re-enable ia32-e\r
160 #\r
161 movl $0xC0000080, %ecx\r
162 rdmsr\r
163 bts $8, %eax\r
164 wrmsr\r
165 #\r
166 # Enable paging\r
167 #\r
168 movq %cr0, %rax\r
169 bts $31, %eax\r
170 mov %rax, %cr0\r
171# Now we are in compatible mode\r
172\r
173 #\r
174 # Reload cs register \r
175 # \r
4eed2dbd 176 .byte 0xcb # retf\r
d766b228
JY
177ReloadCS: \r
178 #\r
179 # Now we're in Long Mode\r
180 #\r
181 #\r
182 # Restore C register and eax hold the return status from 32-bit function.\r
183 # Note: Do not touch rax from now which hold the return value from IA32 function\r
184 #\r
185 pop %rbx\r
186 pop %rbp\r
187 pop %rsi\r
188 pop %rdi\r
189 popfq\r
190 #\r
191 # Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
192 #\r
193 lgdt (%rsp)\r
194 #\r
195 # drop GDT descriptor in stack\r
196 #\r
197 addq $0x10, %rsp\r
198 #\r
199 # switch to orignal CS and GDTR\r
200 #\r
201 pop %r9 # get CS\r
202 shl $32, %r9 # rcx[32..47] <- Cs \r
ef291d07 203 lea ReturnToLongMode(%rip), %rcx\r
d766b228
JY
204 orq %r9, %rcx\r
205 push %rcx\r
4eed2dbd 206 .byte 0xcb # retf\r
ef291d07 207ReturnToLongMode:\r
d766b228
JY
208 #\r
209 # Reload original DS/ES/SS\r
210 #\r
211 pop %rcx\r
212 movq %rcx, %ds\r
213 movq %rcx, %es\r
214 movq %rcx, %ss\r
215 ret\r
216\r