+++ /dev/null
-#\r
-# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php.\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#\r
-# Module Name:\r
-#\r
-# Thunk64To32.asm\r
-#\r
-# Abstract:\r
-#\r
-# This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then\r
-# transit back to long mode.\r
-#\r
-#-------------------------------------------------------------------------------\r
-\r
-#----------------------------------------------------------------------------\r
-# Procedure: AsmExecute32BitCode\r
-#\r
-# Input: None\r
-#\r
-# Output: None\r
-#\r
-# Prototype: UINT32\r
-# AsmExecute32BitCode (\r
-# IN UINT64 Function,\r
-# IN UINT64 Param1,\r
-# IN UINT64 Param2,\r
-# IN IA32_DESCRIPTOR *InternalGdtr\r
-# );\r
-#\r
-#\r
-# Description: A thunk function to execute 32-bit code in long mode.\r
-#\r
-#----------------------------------------------------------------------------\r
-\r
-ASM_GLOBAL ASM_PFX(AsmExecute32BitCode)\r
-ASM_PFX(AsmExecute32BitCode):\r
- #\r
- # save IFLAG and disable it\r
- #\r
- pushfq\r
- cli\r
-\r
- #\r
- # save orignal GDTR and CS\r
- #\r
- movl %ds, %eax\r
- push %rax\r
- movl %cs, %eax\r
- push %rax\r
- subq $0x10, %rsp\r
- sgdt (%rsp)\r
- #\r
- # load internal GDT\r
- #\r
- lgdt (%r9)\r
- #\r
- # Save general purpose register and rflag register\r
- #\r
- pushfq\r
- push %rdi\r
- push %rsi\r
- push %rbp\r
- push %rbx\r
-\r
- #\r
- # save CR3\r
- #\r
- movq %cr3, %rax\r
- movq %rax, %rbp\r
-\r
- #\r
- # Prepare the CS and return address for the transition from 32-bit to 64-bit mode\r
- #\r
- movq $0x10, %rax # load long mode selector\r
- shl $32, %rax\r
- lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G\r
- orq %r9, %rax\r
- push %rax\r
- #\r
- # Save parameters for 32-bit function call\r
- #\r
- movq %r8, %rax\r
- shl $32, %rax\r
- orq %rdx, %rax\r
- push %rax\r
- #\r
- # save the 32-bit function entry and the return address into stack which will be\r
- # retrieve in compatibility mode.\r
- #\r
- lea ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G\r
- shl $32, %rax\r
- orq %rcx, %rax\r
- push %rax\r
-\r
- #\r
- # let rax save DS\r
- #\r
- movq $0x18, %rax\r
-\r
- #\r
- # Change to Compatible Segment\r
- #\r
- movq $8, %rcx # load compatible mode selector\r
- shl $32, %rcx\r
- lea Compatible(%rip), %rdx # assume address < 4G\r
- orq %rdx, %rcx\r
- push %rcx\r
- .byte 0xcb # retf\r
-\r
-Compatible:\r
- # reload DS/ES/SS to make sure they are correct referred to current GDT\r
- movw %ax, %ds\r
- movw %ax, %es\r
- movw %ax, %ss\r
-\r
- #\r
- # Disable paging\r
- #\r
- movq %cr0, %rcx\r
- btc $31, %ecx\r
- movq %rcx, %cr0\r
- #\r
- # Clear EFER.LME\r
- #\r
- movl $0xC0000080, %ecx\r
- rdmsr\r
- btc $8, %eax\r
- wrmsr\r
-\r
-# Now we are in protected mode\r
- #\r
- # Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
- #\r
- pop %rax # Here is the function entry\r
- #\r
- # Now the parameter is at the bottom of the stack, then call in to IA32 function.\r
- #\r
- jmp *%rax\r
-ReturnBack:\r
- movl %eax, %ebx # save return status\r
- pop %rcx # drop param1\r
- pop %rcx # drop param2\r
-\r
- #\r
- # restore CR4\r
- #\r
- movq %cr4, %rax\r
- bts $5, %eax\r
- movq %rax, %cr4\r
-\r
- #\r
- # restore CR3\r
- #\r
- movl %ebp, %eax\r
- movq %rax, %cr3\r
-\r
- #\r
- # Set EFER.LME to re-enable ia32-e\r
- #\r
- movl $0xC0000080, %ecx\r
- rdmsr\r
- bts $8, %eax\r
- wrmsr\r
- #\r
- # Enable paging\r
- #\r
- movq %cr0, %rax\r
- bts $31, %eax\r
- mov %rax, %cr0\r
-# Now we are in compatible mode\r
-\r
- #\r
- # Reload cs register\r
- #\r
- .byte 0xcb # retf\r
-ReloadCS:\r
- #\r
- # Now we're in Long Mode\r
- #\r
- #\r
- # Restore C register and eax hold the return status from 32-bit function.\r
- # Note: Do not touch rax from now which hold the return value from IA32 function\r
- #\r
- movl %ebx, %eax # put return status to EAX\r
- pop %rbx\r
- pop %rbp\r
- pop %rsi\r
- pop %rdi\r
- popfq\r
- #\r
- # Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
- #\r
- lgdt (%rsp)\r
- #\r
- # drop GDT descriptor in stack\r
- #\r
- addq $0x10, %rsp\r
- #\r
- # switch to orignal CS and GDTR\r
- #\r
- pop %r9 # get CS\r
- shl $32, %r9 # rcx[32..47] <- Cs\r
- lea ReturnToLongMode(%rip), %rcx\r
- orq %r9, %rcx\r
- push %rcx\r
- .byte 0xcb # retf\r
-ReturnToLongMode:\r
- #\r
- # Reload original DS/ES/SS\r
- #\r
- pop %rcx\r
- movl %ecx, %ds\r
- movl %ecx, %es\r
- movl %ecx, %ss\r
-\r
- #\r
- # Restore IFLAG\r
- #\r
- popfq\r
-\r
- ret\r
-\r
+++ /dev/null
-;\r
-; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
-; This program and the accompanying materials\r
-; are licensed and made available under the terms and conditions of the BSD License\r
-; which accompanies this distribution. The full text of the license may be found at\r
-; http://opensource.org/licenses/bsd-license.php.\r
-;\r
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-;\r
-;\r
-; Module Name:\r
-;\r
-; Thunk64To32.asm\r
-;\r
-; Abstract:\r
-;\r
-; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then\r
-; transit back to long mode.\r
-;\r
-;-------------------------------------------------------------------------------\r
- .code\r
-;----------------------------------------------------------------------------\r
-; Procedure: AsmExecute32BitCode\r
-;\r
-; Input: None\r
-;\r
-; Output: None\r
-;\r
-; Prototype: UINT32\r
-; AsmExecute32BitCode (\r
-; IN UINT64 Function,\r
-; IN UINT64 Param1,\r
-; IN UINT64 Param2,\r
-; IN IA32_DESCRIPTOR *InternalGdtr\r
-; );\r
-;\r
-;\r
-; Description: A thunk function to execute 32-bit code in long mode.\r
-;\r
-;----------------------------------------------------------------------------\r
-AsmExecute32BitCode PROC\r
- ;\r
- ; save IFLAG and disable it\r
- ;\r
- pushfq\r
- cli\r
-\r
- ;\r
- ; save orignal GDTR and CS\r
- ;\r
- mov rax, ds\r
- push rax\r
- mov rax, cs\r
- push rax\r
- sub rsp, 10h\r
- sgdt fword ptr [rsp]\r
- ;\r
- ; load internal GDT\r
- ;\r
- lgdt fword ptr [r9]\r
- ;\r
- ; Save general purpose register and rflag register\r
- ;\r
- pushfq\r
- push rdi\r
- push rsi\r
- push rbp\r
- push rbx\r
-\r
- ;\r
- ; save CR3\r
- ;\r
- mov rax, cr3\r
- mov rbp, rax\r
-\r
- ;\r
- ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode\r
- ;\r
- mov rax, 10h ; load long mode selector\r
- shl rax, 32\r
- mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G\r
- or rax, r9\r
- push rax\r
- ;\r
- ; Save parameters for 32-bit function call\r
- ;\r
- mov rax, r8\r
- shl rax, 32\r
- or rax, rdx\r
- push rax\r
- ;\r
- ; save the 32-bit function entry and the return address into stack which will be\r
- ; retrieve in compatibility mode.\r
- ;\r
- mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G\r
- shl rax, 32\r
- or rax, rcx\r
- push rax\r
-\r
- ;\r
- ; let rax save DS\r
- ;\r
- mov rax, 018h\r
-\r
- ;\r
- ; Change to Compatible Segment\r
- ;\r
- mov rcx, 08h ; load compatible mode selector\r
- shl rcx, 32\r
- mov rdx, OFFSET Compatible ; assume address < 4G\r
- or rcx, rdx\r
- push rcx\r
- retf\r
-\r
-Compatible:\r
- ; reload DS/ES/SS to make sure they are correct referred to current GDT\r
- mov ds, ax\r
- mov es, ax\r
- mov ss, ax\r
-\r
- ;\r
- ; Disable paging\r
- ;\r
- mov rcx, cr0\r
- btc ecx, 31\r
- mov cr0, rcx\r
- ;\r
- ; Clear EFER.LME\r
- ;\r
- mov ecx, 0C0000080h\r
- rdmsr\r
- btc eax, 8\r
- wrmsr\r
-\r
-; Now we are in protected mode\r
- ;\r
- ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
- ;\r
- pop rax ; Here is the function entry\r
- ;\r
- ; Now the parameter is at the bottom of the stack, then call in to IA32 function.\r
- ;\r
- jmp rax\r
-ReturnBack:\r
- mov ebx, eax ; save return status\r
- pop rcx ; drop param1\r
- pop rcx ; drop param2\r
-\r
- ;\r
- ; restore CR4\r
- ;\r
- mov rax, cr4\r
- bts eax, 5\r
- mov cr4, rax\r
-\r
- ;\r
- ; restore CR3\r
- ;\r
- mov eax, ebp\r
- mov cr3, rax\r
-\r
- ;\r
- ; Set EFER.LME to re-enable ia32-e\r
- ;\r
- mov ecx, 0C0000080h\r
- rdmsr\r
- bts eax, 8\r
- wrmsr\r
- ;\r
- ; Enable paging\r
- ;\r
- mov rax, cr0\r
- bts eax, 31\r
- mov cr0, rax\r
-; Now we are in compatible mode\r
-\r
- ;\r
- ; Reload cs register\r
- ;\r
- retf\r
-ReloadCS:\r
- ;\r
- ; Now we're in Long Mode\r
- ;\r
- ;\r
- ; Restore C register and eax hold the return status from 32-bit function.\r
- ; Note: Do not touch rax from now which hold the return value from IA32 function\r
- ;\r
- mov eax, ebx ; put return status to EAX\r
- pop rbx\r
- pop rbp\r
- pop rsi\r
- pop rdi\r
- popfq\r
- ;\r
- ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
- ;\r
- lgdt fword ptr[rsp]\r
- ;\r
- ; drop GDT descriptor in stack\r
- ;\r
- add rsp, 10h\r
- ;\r
- ; switch to orignal CS and GDTR\r
- ;\r
- pop r9 ; get CS\r
- shl r9, 32 ; rcx[32..47] <- Cs\r
- mov rcx, OFFSET @F\r
- or rcx, r9\r
- push rcx\r
- retf\r
-@@:\r
- ;\r
- ; Reload original DS/ES/SS\r
- ;\r
- pop rcx\r
- mov ds, rcx\r
- mov es, rcx\r
- mov ss, rcx\r
-\r
- ;\r
- ; Restore IFLAG\r
- ;\r
- popfq\r
-\r
- ret\r
-AsmExecute32BitCode ENDP\r
-\r
- END\r