1# 2# Copyright (c) 2010, 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# AsmDispatchExecute.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 23#---------------------------------------------------------------------------- 24# Procedure: AsmExecute32BitCode 25# 26# Input: None 27# 28# Output: None 29# 30# Prototype: EFI_STATUS 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#---------------------------------------------------------------------------- 42 43ASM_GLOBAL ASM_PFX(AsmExecute32BitCode) 44ASM_PFX(AsmExecute32BitCode): 45 # 46 # save orignal GDTR and CS 47 # 48 movl %ds, %eax 49 push %rax 50 movl %cs, %eax 51 push %rax 52 subq $0x10, %rsp 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 movq %cr3, %rax 71 movq %rax, %rbp 72 73 # 74 # Prepare the CS and return address for the transition from 32-bit to 64-bit mode 75 # 76 movq $0x10, %rax # load long mode selector 77 shl $32, %rax 78 lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G 79 orq %r9, %rax 80 push %rax 81 # 82 # Save parameters for 32-bit function call 83 # 84 movq %r8, %rax 85 shl $32, %rax 86 orq %rdx, %rax 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 ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G 93 shl $32, %rax 94 orq %rcx, %rax 95 push %rax 96 97 # 98 # let rax save DS 99 # 100 movq $0x18, %rax 101 102 # 103 # Change to Compatible Segment 104 # 105 movq $8, %rcx # load compatible mode selector 106 shl $32, %rcx 107 lea Compatible(%rip), %rdx # assume address < 4G 108 orq %rdx, %rcx 109 push %rcx 110 .byte 0xcb # retf 111 112Compatible: 113 # reload DS/ES/SS to make sure they are correct referred to current GDT 114 movw %ax, %ds 115 movw %ax, %es 116 movw %ax, %ss 117 118 # 119 # Disable paging 120 # 121 movq %cr0, %rcx 122 btc $31, %ecx 123 movq %rcx, %cr0 124 # 125 # Clear EFER.LME 126 # 127 movl $0xC0000080, %ecx 128 rdmsr 129 btc $8, %eax 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 141ReturnBack: 142 pop %rcx # drop param1 143 pop %rcx # drop param2 144 145 # 146 # restore CR4 147 # 148 movq %cr4, %rax 149 bts $5, %eax 150 movq %rax, %cr4 151 152 # 153 # restore CR3 154 # 155 movl %ebp, %eax 156 movq %rax, %cr3 157 158 # 159 # Set EFER.LME to re-enable ia32-e 160 # 161 movl $0xC0000080, %ecx 162 rdmsr 163 bts $8, %eax 164 wrmsr 165 # 166 # Enable paging 167 # 168 movq %cr0, %rax 169 bts $31, %eax 170 mov %rax, %cr0 171# Now we are in compatible mode 172 173 # 174 # Reload cs register 175 # 176 .byte 0xcb # retf 177ReloadCS: 178 # 179 # Now we're in Long Mode 180 # 181 # 182 # Restore C register and eax hold the return status from 32-bit function. 183 # Note: Do not touch rax from now which hold the return value from IA32 function 184 # 185 pop %rbx 186 pop %rbp 187 pop %rsi 188 pop %rdi 189 popfq 190 # 191 # Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor. 192 # 193 lgdt (%rsp) 194 # 195 # drop GDT descriptor in stack 196 # 197 addq $0x10, %rsp 198 # 199 # switch to orignal CS and GDTR 200 # 201 pop %r9 # get CS 202 shl $32, %r9 # rcx[32..47] <- Cs 203 lea ReturnToLongMode(%rip), %rcx 204 orq %r9, %rcx 205 push %rcx 206 .byte 0xcb # retf 207ReturnToLongMode: 208 # 209 # Reload original DS/ES/SS 210 # 211 pop %rcx 212 movl %ecx, %ds 213 movl %ecx, %es 214 movl %ecx, %ss 215 ret 216 217