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