]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / IntelFsp2WrapperPkg / Library / BaseFspWrapperApiLib / X64 / Thunk64To32.nasm
1 ;
2 ; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
4 ;
5 ;
6 ; Module Name:
7 ;
8 ; Thunk64To32.nasm
9 ;
10 ; Abstract:
11 ;
12 ; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
13 ; transit back to long mode.
14 ;
15 ;-------------------------------------------------------------------------------
16 DEFAULT REL
17 SECTION .text
18 ;----------------------------------------------------------------------------
19 ; Procedure: AsmExecute32BitCode
20 ;
21 ; Input: None
22 ;
23 ; Output: None
24 ;
25 ; Prototype: UINT32
26 ; AsmExecute32BitCode (
27 ; IN UINT64 Function,
28 ; IN UINT64 Param1,
29 ; IN UINT64 Param2,
30 ; IN IA32_DESCRIPTOR *InternalGdtr
31 ; );
32 ;
33 ;
34 ; Description: A thunk function to execute 32-bit code in long mode.
35 ;
36 ;----------------------------------------------------------------------------
37 global ASM_PFX(AsmExecute32BitCode)
38 ASM_PFX(AsmExecute32BitCode):
39 ;
40 ; save IFLAG and disable it
41 ;
42 pushfq
43 cli
44
45 ;
46 ; save original GDTR and CS
47 ;
48 mov rax, ds
49 push rax
50 mov rax, cs
51 push rax
52 sub rsp, 0x10
53 sgdt [rsp]
54 ;
55 ; load internal GDT
56 ;
57 lgdt [r9]
58 ;
59 ; Save general purpose register and rflag register
60 ;
61 pushfq
62 push rdi
63 push rsi
64 push rbp
65 push rbx
66
67 ;
68 ; save CR3
69 ;
70 mov rax, cr3
71 mov rbp, rax
72
73 ;
74 ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
75 ;
76 mov rax, dword 0x10 ; load long mode selector
77 shl rax, 32
78 lea r9, [ReloadCS] ;Assume the ReloadCS is under 4G
79 or rax, r9
80 push rax
81 ;
82 ; Save parameters for 32-bit function call
83 ;
84 mov rax, r8
85 shl rax, 32
86 or rax, rdx
87 push rax
88 ;
89 ; save the 32-bit function entry and the return address into stack which will be
90 ; retrieve in compatibility mode.
91 ;
92 lea rax, [ReturnBack] ;Assume the ReloadCS is under 4G
93 shl rax, 32
94 or rax, rcx
95 push rax
96
97 ;
98 ; let rax save DS
99 ;
100 mov rax, dword 0x18
101
102 ;
103 ; Change to Compatible Segment
104 ;
105 mov rcx, dword 0x8 ; load compatible mode selector
106 shl rcx, 32
107 lea rdx, [Compatible] ; assume address < 4G
108 or rcx, rdx
109 push rcx
110 retf
111
112 Compatible:
113 ; reload DS/ES/SS to make sure they are correct referred to current GDT
114 mov ds, ax
115 mov es, ax
116 mov ss, ax
117
118 ;
119 ; Disable paging
120 ;
121 mov rcx, cr0
122 btc ecx, 31
123 mov cr0, rcx
124 ;
125 ; Clear EFER.LME
126 ;
127 mov ecx, 0xC0000080
128 rdmsr
129 btc eax, 8
130 wrmsr
131
132 ; Now we are in protected mode
133 ;
134 ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
135 ;
136 pop rax ; Here is the function entry
137 ;
138 ; Now the parameter is at the bottom of the stack, then call in to IA32 function.
139 ;
140 jmp rax
141 ReturnBack:
142 mov ebx, eax ; save return status
143 pop rcx ; drop param1
144 pop rcx ; drop param2
145
146 ;
147 ; restore CR4
148 ;
149 mov rax, cr4
150 bts eax, 5
151 mov cr4, rax
152
153 ;
154 ; restore CR3
155 ;
156 mov eax, ebp
157 mov cr3, rax
158
159 ;
160 ; Set EFER.LME to re-enable ia32-e
161 ;
162 mov ecx, 0xC0000080
163 rdmsr
164 bts eax, 8
165 wrmsr
166 ;
167 ; Enable paging
168 ;
169 mov rax, cr0
170 bts eax, 31
171 mov cr0, rax
172 ; Now we are in compatible mode
173
174 ;
175 ; Reload cs register
176 ;
177 retf
178 ReloadCS:
179 ;
180 ; Now we're in Long Mode
181 ;
182 ;
183 ; Restore C register and eax hold the return status from 32-bit function.
184 ; Note: Do not touch rax from now which hold the return value from IA32 function
185 ;
186 mov eax, ebx ; put return status to EAX
187 pop rbx
188 pop rbp
189 pop rsi
190 pop rdi
191 popfq
192 ;
193 ; Switch to original GDT and CS. here rsp is pointer to the original GDT descriptor.
194 ;
195 lgdt [rsp]
196 ;
197 ; drop GDT descriptor in stack
198 ;
199 add rsp, 0x10
200 ;
201 ; switch to original CS and GDTR
202 ;
203 pop r9 ; get CS
204 shl r9, 32 ; rcx[32..47] <- Cs
205 lea rcx, [.0]
206 or rcx, r9
207 push rcx
208 retf
209 .0:
210 ;
211 ; Reload original DS/ES/SS
212 ;
213 pop rcx
214 mov ds, rcx
215 mov es, rcx
216 mov ss, rcx
217
218 ;
219 ; Restore IFLAG
220 ;
221 popfq
222
223 ret
224