Files
system76-edk2/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
Ard Biesheuvel 4d1f5a214b MdeModulePkg/EbcDxe AARCH64: use a fixed size thunk structure
The thunk generation is needlessly complex, given that it attempts to
deal with variable length instructions, which don't exist on AArch64.

So replace it with a simple template coded in assembler, with a matching
struct definition in C. That way, we can create and manipulate the thunks
easily without looping over the instructions looking for 'magic' numbers.

Also, use x16 rather than x9, since it is the architectural register to
use for thunks/veneers.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Reviewed-by: Feng Tian <feng.tian@intel.com>
2016-09-02 07:59:21 +01:00

151 lines
4.7 KiB
ArmAsm

///** @file
//
// This code provides low level routines that support the Virtual Machine
// for option ROMs.
//
// Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
// Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>
// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
//
// This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
//**/
ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative)
ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret)
ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint)
ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate)
//****************************************************************************
// EbcLLCALLEX
//
// This function is called to execute an EBC CALLEX instruction.
// This instruction requires that we thunk out to external native
// code. For AArch64, we copy the VM stack into the main stack and then pop
// the first 8 arguments off according to the AArch64 Procedure Call Standard
// On return, we restore the stack pointer to its original location.
//
//****************************************************************************
// UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
ASM_PFX(EbcLLCALLEXNative):
stp x19, x20, [sp, #-16]!
stp x29, x30, [sp, #-16]!
mov x19, x0
mov x20, sp
sub x2, x2, x1 // Length = NewStackPointer-FramePtr
sub sp, sp, x2
sub sp, sp, #64 // Make sure there is room for at least 8 args in the new stack
mov x0, sp
bl CopyMem // Sp, NewStackPointer, Length
ldp x0, x1, [sp], #16
ldp x2, x3, [sp], #16
ldp x4, x5, [sp], #16
ldp x6, x7, [sp], #16
blr x19
mov sp, x20
ldp x29, x30, [sp], #16
ldp x19, x20, [sp], #16
ret
//****************************************************************************
// EbcLLEbcInterpret
//
// This function is called by the thunk code to handle an Native to EBC call
// This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on the stack)
// x16 contains the Entry point that will be the first argument when
// EBCInterpret is called.
//
//****************************************************************************
ASM_PFX(EbcLLEbcInterpret):
stp x29, x30, [sp, #-16]!
// copy the current arguments 9-16 from old location and add arg 7 to stack
// keeping 16 byte stack alignment
sub sp, sp, #80
str x7, [sp]
ldr x11, [sp, #96]
str x11, [sp, #8]
ldr x11, [sp, #104]
str x11, [sp, #16]
ldr x11, [sp, #112]
str x11, [sp, #24]
ldr x11, [sp, #120]
str x11, [sp, #32]
ldr x11, [sp, #128]
str x11, [sp, #40]
ldr x11, [sp, #136]
str x11, [sp, #48]
ldr x11, [sp, #144]
str x11, [sp, #56]
ldr x11, [sp, #152]
str x11, [sp, #64]
// Shift arguments and add entry point and as argument 1
mov x7, x6
mov x6, x5
mov x5, x4
mov x4, x3
mov x3, x2
mov x2, x1
mov x1, x0
mov x0, x16
// call C-code
bl ASM_PFX(EbcInterpret)
add sp, sp, #80
ldp x29, x30, [sp], #16
ret
//****************************************************************************
// EbcLLExecuteEbcImageEntryPoint
//
// This function is called by the thunk code to handle the image entry point
// x16 contains the Entry point that will be the third argument when
// ExecuteEbcImageEntryPoint is called.
//
//****************************************************************************
ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
stp x29, x30, [sp, #-16]!
// build new parameter calling convention
mov x2, x1
mov x1, x0
mov x0, x16
// call C-code
bl ASM_PFX(ExecuteEbcImageEntryPoint)
ldp x29, x30, [sp], #16
ret
//****************************************************************************
// mEbcInstructionBufferTemplate
//****************************************************************************
.section ".rodata", "a"
.align 3
ASM_PFX(mEbcInstructionBufferTemplate):
adr x17, 0f
ldp x16, x17, [x17]
br x17
//
// Add a magic code here to help the VM recognize the thunk.
//
hlt #0xEBC
0: .quad 0 // EBC_ENTRYPOINT_SIGNATURE
.quad 0 // EBC_LL_EBC_ENTRYPOINT_SIGNATURE