2 ; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
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.
15 ;-------------------------------------------------------------------------------
18 ;----------------------------------------------------------------------------
19 ; Procedure: AsmExecute32BitCode
26 ; AsmExecute32BitCode (
30 ; IN IA32_DESCRIPTOR *InternalGdtr
34 ; Description: A thunk function to execute 32-bit code in long mode.
36 ;----------------------------------------------------------------------------
37 global ASM_PFX(AsmExecute32BitCode)
38 ASM_PFX(AsmExecute32BitCode):
40 ; save IFLAG and disable it
46 ; save original GDTR and CS
59 ; Save general purpose register and rflag register
74 ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
76 mov rax, dword 0x10 ; load long mode selector
78 lea r9, [ReloadCS] ;Assume the ReloadCS is under 4G
82 ; Save parameters for 32-bit function call
89 ; save the 32-bit function entry and the return address into stack which will be
90 ; retrieve in compatibility mode.
92 lea rax, [ReturnBack] ;Assume the ReloadCS is under 4G
103 ; Change to Compatible Segment
105 mov rcx, dword 0x8 ; load compatible mode selector
107 lea rdx, [Compatible] ; assume address < 4G
113 ; reload DS/ES/SS to make sure they are correct referred to current GDT
132 ; Now we are in protected mode
134 ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
136 pop rax ; Here is the function entry
138 ; Now the parameter is at the bottom of the stack, then call in to IA32 function.
142 mov ebx, eax ; save return status
143 pop rcx ; drop param1
144 pop rcx ; drop param2
160 ; Set EFER.LME to re-enable ia32-e
172 ; Now we are in compatible mode
180 ; Now we're in Long Mode
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
186 mov eax, ebx ; put return status to EAX
193 ; Switch to original GDT and CS. here rsp is pointer to the original GDT descriptor.
197 ; drop GDT descriptor in stack
201 ; switch to original CS and GDTR
204 shl r9, 32 ; rcx[32..47] <- Cs
211 ; Reload original DS/ES/SS