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
 | 
						|
 |