Fix various typos in comments and documentation. Cc: Chasel Chiu <chasel.chiu@intel.com> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Star Zeng <star.zeng@intel.com> Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daude <philmd@redhat.com> Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com> Reviewed-by: Chasel Chiu <chasel.chiu@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			225 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;
 | |
| ; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| ; SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| ;
 | |
| ;
 | |
| ; Module Name:
 | |
| ;
 | |
| ;    Thunk64To32.nasm
 | |
| ;
 | |
| ; Abstract:
 | |
| ;
 | |
| ;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
 | |
| ;   transit back to long mode.
 | |
| ;
 | |
| ;-------------------------------------------------------------------------------
 | |
|     DEFAULT REL
 | |
|     SECTION .text
 | |
| ;----------------------------------------------------------------------------
 | |
| ; Procedure:    AsmExecute32BitCode
 | |
| ;
 | |
| ; Input:        None
 | |
| ;
 | |
| ; Output:       None
 | |
| ;
 | |
| ; Prototype:    UINT32
 | |
| ;               AsmExecute32BitCode (
 | |
| ;                 IN UINT64           Function,
 | |
| ;                 IN UINT64           Param1,
 | |
| ;                 IN UINT64           Param2,
 | |
| ;                 IN IA32_DESCRIPTOR  *InternalGdtr
 | |
| ;                 );
 | |
| ;
 | |
| ;
 | |
| ; Description:  A thunk function to execute 32-bit code in long mode.
 | |
| ;
 | |
| ;----------------------------------------------------------------------------
 | |
| global ASM_PFX(AsmExecute32BitCode)
 | |
| ASM_PFX(AsmExecute32BitCode):
 | |
|     ;
 | |
|     ; save IFLAG and disable it
 | |
|     ;
 | |
|     pushfq
 | |
|     cli
 | |
| 
 | |
|     ;
 | |
|     ; save original GDTR and CS
 | |
|     ;
 | |
|     mov     rax, ds
 | |
|     push    rax
 | |
|     mov     rax, cs
 | |
|     push    rax
 | |
|     sub     rsp, 0x10
 | |
|     sgdt    [rsp]
 | |
|     ;
 | |
|     ; load internal GDT
 | |
|     ;
 | |
|     lgdt    [r9]
 | |
|     ;
 | |
|     ; Save general purpose register and rflag register
 | |
|     ;
 | |
|     pushfq
 | |
|     push    rdi
 | |
|     push    rsi
 | |
|     push    rbp
 | |
|     push    rbx
 | |
| 
 | |
|     ;
 | |
|     ; save CR3
 | |
|     ;
 | |
|     mov     rax, cr3
 | |
|     mov     rbp, rax
 | |
| 
 | |
|     ;
 | |
|     ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
 | |
|     ;
 | |
|     mov     rax, dword 0x10              ; load long mode selector
 | |
|     shl     rax, 32
 | |
|     lea     r9,  [ReloadCS]          ;Assume the ReloadCS is under 4G
 | |
|     or      rax, r9
 | |
|     push    rax
 | |
|     ;
 | |
|     ; Save parameters for 32-bit function call
 | |
|     ;
 | |
|     mov     rax, r8
 | |
|     shl     rax, 32
 | |
|     or      rax, rdx
 | |
|     push    rax
 | |
|     ;
 | |
|     ; save the 32-bit function entry and the return address into stack which will be
 | |
|     ; retrieve in compatibility mode.
 | |
|     ;
 | |
|     lea     rax, [ReturnBack]   ;Assume the ReloadCS is under 4G
 | |
|     shl     rax, 32
 | |
|     or      rax, rcx
 | |
|     push    rax
 | |
| 
 | |
|     ;
 | |
|     ; let rax save DS
 | |
|     ;
 | |
|     mov     rax, dword 0x18
 | |
| 
 | |
|     ;
 | |
|     ; Change to Compatible Segment
 | |
|     ;
 | |
|     mov     rcx, dword 0x8               ; load compatible mode selector
 | |
|     shl     rcx, 32
 | |
|     lea     rdx, [Compatible] ; assume address < 4G
 | |
|     or      rcx, rdx
 | |
|     push    rcx
 | |
|     retf
 | |
| 
 | |
| Compatible:
 | |
|     ; reload DS/ES/SS to make sure they are correct referred to current GDT
 | |
|     mov     ds, ax
 | |
|     mov     es, ax
 | |
|     mov     ss, ax
 | |
| 
 | |
|     ;
 | |
|     ; Disable paging
 | |
|     ;
 | |
|     mov     rcx, cr0
 | |
|     btc     ecx, 31
 | |
|     mov     cr0, rcx
 | |
|     ;
 | |
|     ; Clear EFER.LME
 | |
|     ;
 | |
|     mov     ecx, 0xC0000080
 | |
|     rdmsr
 | |
|     btc     eax, 8
 | |
|     wrmsr
 | |
| 
 | |
| ; Now we are in protected mode
 | |
|     ;
 | |
|     ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
 | |
|     ;
 | |
|     pop    rax                 ; Here is the function entry
 | |
|     ;
 | |
|     ; Now the parameter is at the bottom of the stack,  then call in to IA32 function.
 | |
|     ;
 | |
|     jmp   rax
 | |
| ReturnBack:
 | |
|     mov   ebx, eax             ; save return status
 | |
|     pop   rcx                  ; drop param1
 | |
|     pop   rcx                  ; drop param2
 | |
| 
 | |
|     ;
 | |
|     ; restore CR4
 | |
|     ;
 | |
|     mov     rax, cr4
 | |
|     bts     eax, 5
 | |
|     mov     cr4, rax
 | |
| 
 | |
|     ;
 | |
|     ; restore CR3
 | |
|     ;
 | |
|     mov     eax, ebp
 | |
|     mov     cr3, rax
 | |
| 
 | |
|     ;
 | |
|     ; Set EFER.LME to re-enable ia32-e
 | |
|     ;
 | |
|     mov     ecx, 0xC0000080
 | |
|     rdmsr
 | |
|     bts     eax, 8
 | |
|     wrmsr
 | |
|     ;
 | |
|     ; Enable paging
 | |
|     ;
 | |
|     mov     rax, cr0
 | |
|     bts     eax, 31
 | |
|     mov     cr0, rax
 | |
| ; Now we are in compatible mode
 | |
| 
 | |
|     ;
 | |
|     ; Reload cs register
 | |
|     ;
 | |
|     retf
 | |
| ReloadCS:
 | |
|     ;
 | |
|     ; Now we're in Long Mode
 | |
|     ;
 | |
|     ;
 | |
|     ; Restore C register and eax hold the return status from 32-bit function.
 | |
|     ; Note: Do not touch rax from now which hold the return value from IA32 function
 | |
|     ;
 | |
|     mov     eax, ebx ; put return status to EAX
 | |
|     pop     rbx
 | |
|     pop     rbp
 | |
|     pop     rsi
 | |
|     pop     rdi
 | |
|     popfq
 | |
|     ;
 | |
|     ; Switch to original GDT and CS. here rsp is pointer to the original GDT descriptor.
 | |
|     ;
 | |
|     lgdt    [rsp]
 | |
|     ;
 | |
|     ; drop GDT descriptor in stack
 | |
|     ;
 | |
|     add     rsp, 0x10
 | |
|     ;
 | |
|     ; switch to original CS and GDTR
 | |
|     ;
 | |
|     pop     r9                 ; get  CS
 | |
|     shl     r9,  32            ; rcx[32..47] <- Cs
 | |
|     lea     rcx, [.0]
 | |
|     or      rcx, r9
 | |
|     push    rcx
 | |
|     retf
 | |
| .0:
 | |
|     ;
 | |
|     ; Reload original DS/ES/SS
 | |
|     ;
 | |
|     pop     rcx
 | |
|     mov     ds, rcx
 | |
|     mov     es, rcx
 | |
|     mov     ss, rcx
 | |
| 
 | |
|     ;
 | |
|     ; Restore IFLAG
 | |
|     ;
 | |
|     popfq
 | |
| 
 | |
|     ret
 | |
| 
 |