UefiCpuPkg CpuMpPei: Update INF to refer to NASM source file
[mirror_edk2.git] / IntelFsp2WrapperPkg / Library / BaseFspWrapperApiLib / X64 / Thunk64To32.asm
CommitLineData
cf1d4549
JY
1;\r
2; Copyright (c) 2014, 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; Thunk64To32.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 .code\r
23;----------------------------------------------------------------------------\r
24; Procedure: AsmExecute32BitCode\r
25;\r
26; Input: None\r
27;\r
28; Output: None\r
29;\r
30; Prototype: UINT32\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
42AsmExecute32BitCode PROC\r
43 ;\r
44 ; save IFLAG and disable it\r
45 ;\r
46 pushfq\r
47 cli\r
48\r
49 ;\r
50 ; save orignal GDTR and CS\r
51 ;\r
52 mov rax, ds\r
53 push rax\r
54 mov rax, cs\r
55 push rax\r
56 sub rsp, 10h\r
57 sgdt fword ptr [rsp]\r
58 ;\r
59 ; load internal GDT\r
60 ;\r
61 lgdt fword ptr [r9]\r
62 ;\r
63 ; Save general purpose register and rflag register\r
64 ;\r
65 pushfq\r
66 push rdi\r
67 push rsi\r
68 push rbp\r
69 push rbx\r
70\r
71 ;\r
72 ; save CR3\r
73 ;\r
74 mov rax, cr3\r
75 mov rbp, rax\r
76\r
77 ;\r
78 ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode\r
79 ;\r
80 mov rax, 10h ; load long mode selector\r
81 shl rax, 32\r
82 mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G\r
83 or rax, r9\r
84 push rax\r
85 ;\r
86 ; Save parameters for 32-bit function call\r
87 ;\r
88 mov rax, r8\r
89 shl rax, 32\r
90 or rax, rdx\r
91 push rax\r
92 ;\r
93 ; save the 32-bit function entry and the return address into stack which will be\r
94 ; retrieve in compatibility mode.\r
95 ;\r
96 mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G\r
97 shl rax, 32\r
98 or rax, rcx\r
99 push rax\r
100\r
101 ;\r
102 ; let rax save DS\r
103 ;\r
104 mov rax, 018h\r
105\r
106 ;\r
107 ; Change to Compatible Segment\r
108 ;\r
109 mov rcx, 08h ; load compatible mode selector\r
110 shl rcx, 32\r
111 mov rdx, OFFSET Compatible ; assume address < 4G\r
112 or rcx, rdx\r
113 push rcx\r
114 retf\r
115\r
116Compatible:\r
117 ; reload DS/ES/SS to make sure they are correct referred to current GDT\r
118 mov ds, ax\r
119 mov es, ax\r
120 mov ss, ax\r
121\r
122 ;\r
123 ; Disable paging\r
124 ;\r
125 mov rcx, cr0\r
126 btc ecx, 31\r
127 mov cr0, rcx\r
128 ;\r
129 ; Clear EFER.LME\r
130 ;\r
131 mov ecx, 0C0000080h\r
132 rdmsr\r
133 btc eax, 8\r
134 wrmsr\r
135\r
136; Now we are in protected mode\r
137 ;\r
138 ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
139 ;\r
140 pop rax ; Here is the function entry\r
141 ;\r
142 ; Now the parameter is at the bottom of the stack, then call in to IA32 function.\r
143 ;\r
144 jmp rax\r
145ReturnBack:\r
146 mov ebx, eax ; save return status\r
147 pop rcx ; drop param1\r
148 pop rcx ; drop param2\r
149\r
150 ;\r
151 ; restore CR4\r
152 ;\r
153 mov rax, cr4\r
154 bts eax, 5\r
155 mov cr4, rax\r
156\r
157 ;\r
158 ; restore CR3\r
159 ;\r
160 mov eax, ebp\r
161 mov cr3, rax\r
162\r
163 ;\r
164 ; Set EFER.LME to re-enable ia32-e\r
165 ;\r
166 mov ecx, 0C0000080h\r
167 rdmsr\r
168 bts eax, 8\r
169 wrmsr\r
170 ;\r
171 ; Enable paging\r
172 ;\r
173 mov rax, cr0\r
174 bts eax, 31\r
175 mov cr0, rax\r
176; Now we are in compatible mode\r
177\r
178 ;\r
179 ; Reload cs register\r
180 ;\r
181 retf\r
182ReloadCS:\r
183 ;\r
184 ; Now we're in Long Mode\r
185 ;\r
186 ;\r
187 ; Restore C register and eax hold the return status from 32-bit function.\r
188 ; Note: Do not touch rax from now which hold the return value from IA32 function\r
189 ;\r
190 mov eax, ebx ; put return status to EAX\r
191 pop rbx\r
192 pop rbp\r
193 pop rsi\r
194 pop rdi\r
195 popfq\r
196 ;\r
197 ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
198 ;\r
199 lgdt fword ptr[rsp]\r
200 ;\r
201 ; drop GDT descriptor in stack\r
202 ;\r
203 add rsp, 10h\r
204 ;\r
205 ; switch to orignal CS and GDTR\r
206 ;\r
207 pop r9 ; get CS\r
208 shl r9, 32 ; rcx[32..47] <- Cs\r
209 mov rcx, OFFSET @F\r
210 or rcx, r9\r
211 push rcx\r
212 retf\r
213@@:\r
214 ;\r
215 ; Reload original DS/ES/SS\r
216 ;\r
217 pop rcx\r
218 mov ds, rcx\r
219 mov es, rcx\r
220 mov ss, rcx\r
221\r
222 ;\r
223 ; Restore IFLAG\r
224 ;\r
225 popfq\r
226\r
227 ret\r
228AsmExecute32BitCode ENDP\r
229\r
230 END\r