From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com (foss.arm.com [217.140.101.70]) by ml01.01.org (Postfix) with ESMTP id 171DF1A1DF5 for ; Fri, 5 Aug 2016 12:24:09 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7985828; Fri, 5 Aug 2016 12:25:32 -0700 (PDT) Received: from [192.168.236.128] (unknown [10.118.32.33]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1E0D53F215; Fri, 5 Aug 2016 12:24:08 -0700 (PDT) To: Ard Biesheuvel , leif.lindholm@linaro.org, edk2-devel@lists.01.org References: <1470061349-29611-1-git-send-email-ard.biesheuvel@linaro.org> <1470061349-29611-2-git-send-email-ard.biesheuvel@linaro.org> Cc: feng.tian@intel.com, daniil.egranov@linaro.org, star.zeng@intel.com From: Daniil Egranov Message-ID: Date: Fri, 5 Aug 2016 14:24:07 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: <1470061349-29611-2-git-send-email-ard.biesheuvel@linaro.org> Subject: Re: [PATCH 2/2] MdeModulePkg/EbcDxe: cleanup X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Aug 2016 19:24:09 -0000 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Hi Ard, On 08/01/2016 09:22 AM, Ard Biesheuvel wrote: > - indentation > - premature optimization of the thunking code, i.e., align function prototypes > so we don't have to move arguments around or duplicate them on the stack, > and perform tail calls where possible > - adhere to calling convention (stack frame layout) > - replace instruction buffer with a fixed struct, so that we no longer have > to traverse it to find the entry point slots > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ard Biesheuvel > --- > MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S | 188 ++++++++++--------- > MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c | 193 ++++++-------------- > 2 files changed, 159 insertions(+), 222 deletions(-) > > diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S > index 3c1a461f5e87..d0a5a4c5a37d 100644 > --- a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S > +++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S > @@ -1,10 +1,12 @@ > ///** @file > // > -// This code provides low level routines that support the Virtual Machine > -// for option ROMs. > +// This code provides low level routines that support the Virtual Machine > +// for option ROMs. > // > -// Copyright (c) 2015, The Linux Foundation. All rights reserved. > +// Copyright (c) 2016, Linaro, Ltd. All rights reserved.
> +// Copyright (c) 2015, The Linux Foundation. All rights reserved.
> // Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
> +// > // 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 > @@ -15,9 +17,10 @@ > // > //**/ > > -ASM_GLOBAL ASM_PFX(CopyMem); > -ASM_GLOBAL ASM_PFX(EbcInterpret); > -ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint); > +ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret); > +ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint); > + > +ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate); The ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative); is missing here. The linking fails without it. > > //**************************************************************************** > // EbcLLCALLEX > @@ -30,102 +33,121 @@ ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint); > // > //**************************************************************************** > // UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr) > -ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative); > 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 > + mov x8, x0 // Preserve x0 > + mov x9, x1 // Preserve x1 > + > + // > + // If the EBC stack frame is smaller than or equal to 64 bytes, we know there > + // are no stacked arguments #9 and beyond that we need to copy to the native > + // stack. In this case, we can perform a tail call which is much more > + // efficient, since there is no need to touch the native stack at all. > + // > + sub x3, x2, x1 // Length = NewStackPointer - FramePtr > + cmp x3, #64 > + b.gt 1f > + > + adr x0, 0f > + sub x0, x0, x3, lsr #1 > + br x0 > + > + ldr x7, [x9, #56] > + ldr x6, [x9, #48] > + ldr x5, [x9, #40] > + ldr x4, [x9, #32] > + ldr x3, [x9, #24] > + ldr x2, [x9, #16] > + ldr x1, [x9, #8] > + ldr x0, [x9] > + > +0: br x8 > + > + // > + // More than 64 bytes: we need to build the full native stack frame and copy > + // the part of the VM stack exceeding 64 bytes (which may contain stacked > + // arguments) to the native stack > + // > +1: stp x29, x30, [sp, #-16]! > + mov x29, sp > + > + // > + // Ensure that the stack pointer remains 16 byte aligned, > + // even if the size of the VM stack frame is not a multiple of 16 > + // > + add x1, x1, #64 // Skip over [potential] reg params > + tbz x3, #3, 2f // Multiple of 16? > + ldr x4, [x2, #-8]! // No? Then push one word > + str x4, [sp, #-16]! // ... but use two slots > + b 3f > + > +2: ldp x4, x5, [x2, #-16]! > + stp x4, x5, [sp, #-16]! > +3: cmp x2, x1 > + b.gt 2b > + > + ldp x0, x1, [x9] > + ldp x2, x3, [x9, #16] > + ldp x4, x5, [x9, #32] > + ldp x6, x7, [x9, #48] > + > + blr x8 > + > + mov sp, x29 > + ldp x29, x30, [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) > -// x9 contains the Entry point that will be the first argument when > +// x16 contains the Entry point that will be the first argument when > // EBCInterpret is called. > // > //**************************************************************************** > -ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret); > 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, x9 > - > - # call C-code > - bl ASM_PFX(EbcInterpret) > - add sp, sp, #80 > - > - ldp x29, x30, [sp], #16 > + stp x29, x30, [sp, #-16]! > + mov x29, sp > + > + // push the entry point and the address of args #9 - #16 onto the stack > + add x17, sp, #16 > + stp x16, x17, [sp, #-16]! > > + // call C-code > + bl ASM_PFX(EbcInterpret) > + > + ldp x29, x30, [sp, #16] > + add sp, sp, #32 > ret > > //**************************************************************************** > // EbcLLExecuteEbcImageEntryPoint > // > // This function is called by the thunk code to handle the image entry point > -// x9 contains the Entry point that will be the first argument when > +// x16 contains the Entry point that will be the third argument when > // ExecuteEbcImageEntryPoint is called. > // > //**************************************************************************** > -ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint); > ASM_PFX(EbcLLExecuteEbcImageEntryPoint): > - stp x29, x30, [sp, #-16]! > - # build new paramater calling convention > - mov x2, x1 > - mov x1, x0 > - mov x0, x9 > - > - # call C-code > - bl ASM_PFX(ExecuteEbcImageEntryPoint) > - ldp x29, x30, [sp], #16 > - ret > + mov x2, x16 > + > + // tail call to C code > + b ASM_PFX(ExecuteEbcImageEntryPoint) > + > +//**************************************************************************** > +// 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. > + // > + .long 0xCA112EBC > + > +0: .quad 0 // EBC_ENTRYPOINT_SIGNATURE > + .quad 0 // EBC_LL_EBC_ENTRYPOINT_SIGNATURE > diff --git a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c > index 23261a070143..d15bbc861f33 100644 > --- a/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c > +++ b/MdeModulePkg/Universal/EbcDxe/AArch64/EbcSupport.c > @@ -2,8 +2,10 @@ > This module contains EBC support routines that are customized based on > the target AArch64 processor. > > -Copyright (c) 2015, The Linux Foundation. All rights reserved. > +Copyright (c) 2016, Linaro, Ltd. All rights reserved.
> +Copyright (c) 2015, The Linux Foundation. All rights reserved.
> Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
> + > 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 > @@ -22,47 +24,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > // > #define STACK_REMAIN_SIZE (1024 * 4) > > -// > -// This is instruction buffer used to create EBC thunk > -// > -#define EBC_MAGIC_SIGNATURE 0xCA112EBCCA112EBCull > -#define EBC_ENTRYPOINT_SIGNATURE 0xAFAFAFAFAFAFAFAFull > -#define EBC_LL_EBC_ENTRYPOINT_SIGNATURE 0xFAFAFAFAFAFAFAFAull > -UINT8 mInstructionBufferTemplate[] = { > - 0x03, 0x00, 0x00, 0x14, //b pc+16 > - // > - // Add a magic code here to help the VM recognize the thunk.. > - // > - (UINT8)(EBC_MAGIC_SIGNATURE & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 8) & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 16) & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 24) & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 32) & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 40) & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 48) & 0xFF), > - (UINT8)((EBC_MAGIC_SIGNATURE >> 56) & 0xFF), > - 0x69, 0x00, 0x00, 0x58, //ldr x9, #32 > - 0x8A, 0x00, 0x00, 0x58, //ldr x10, #40 > - 0x05, 0x00, 0x00, 0x14, //b pc+32 > - (UINT8)(EBC_ENTRYPOINT_SIGNATURE & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF), > - (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF), > - (UINT8)(EBC_LL_EBC_ENTRYPOINT_SIGNATURE & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF), > - (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF), > - 0x40, 0x01, 0x1F, 0xD6 //br x10 > - > -}; > +#pragma pack(1) > +typedef struct { > + UINT32 Instr[3]; > + UINT32 Magic; > + UINT64 EbcEntryPoint; > + UINT64 EbcLlEntryPoint; > +} EBC_INSTRUCTION_BUFFER; > +#pragma pack() > + > +extern CONST EBC_INSTRUCTION_BUFFER mEbcInstructionBufferTemplate; > > /** > Begin executing an EBC image. > @@ -109,7 +80,6 @@ PushU64 ( > // > VmPtr->Gpr[0] -= sizeof (UINT64); > *(UINT64 *) VmPtr->Gpr[0] = Arg; > - return; > } > > > @@ -118,7 +88,6 @@ PushU64 ( > > This is a thunk function. > > - @param EntryPoint The entrypoint of EBC code. > @param Arg1 The 1st argument. > @param Arg2 The 2nd argument. > @param Arg3 The 3rd argument. > @@ -127,14 +96,8 @@ PushU64 ( > @param Arg6 The 6th argument. > @param Arg7 The 7th argument. > @param Arg8 The 8th argument. > - @param Arg9 The 9th argument. > - @param Arg10 The 10th argument. > - @param Arg11 The 11th argument. > - @param Arg12 The 12th argument. > - @param Arg13 The 13th argument. > - @param Arg14 The 14th argument. > - @param Arg15 The 15th argument. > - @param Arg16 The 16th argument. > + @param EntryPoint The entrypoint of EBC code. > + @param Args9_16[] Array containing arguments #9 to #16. > > @return The value returned by the EBC application we're going to run. > > @@ -142,7 +105,6 @@ PushU64 ( > UINT64 > EFIAPI > EbcInterpret ( > - IN UINTN EntryPoint, > IN UINTN Arg1, > IN UINTN Arg2, > IN UINTN Arg3, > @@ -151,14 +113,8 @@ EbcInterpret ( > IN UINTN Arg6, > IN UINTN Arg7, > IN UINTN Arg8, > - IN UINTN Arg9, > - IN UINTN Arg10, > - IN UINTN Arg11, > - IN UINTN Arg12, > - IN UINTN Arg13, > - IN UINTN Arg14, > - IN UINTN Arg15, > - IN UINTN Arg16 > + IN UINTN EntryPoint, > + IN UINTN Args9_16[] > ) > { > // > @@ -222,14 +178,14 @@ EbcInterpret ( > // For the worst case, assume there are 4 arguments passed in registers, store > // them to VM's stack. > // > - PushU64 (&VmContext, (UINT64) Arg16); > - PushU64 (&VmContext, (UINT64) Arg15); > - PushU64 (&VmContext, (UINT64) Arg14); > - PushU64 (&VmContext, (UINT64) Arg13); > - PushU64 (&VmContext, (UINT64) Arg12); > - PushU64 (&VmContext, (UINT64) Arg11); > - PushU64 (&VmContext, (UINT64) Arg10); > - PushU64 (&VmContext, (UINT64) Arg9); > + PushU64 (&VmContext, (UINT64) Args9_16[7]); > + PushU64 (&VmContext, (UINT64) Args9_16[6]); > + PushU64 (&VmContext, (UINT64) Args9_16[5]); > + PushU64 (&VmContext, (UINT64) Args9_16[4]); > + PushU64 (&VmContext, (UINT64) Args9_16[3]); > + PushU64 (&VmContext, (UINT64) Args9_16[2]); > + PushU64 (&VmContext, (UINT64) Args9_16[1]); > + PushU64 (&VmContext, (UINT64) Args9_16[0]); > PushU64 (&VmContext, (UINT64) Arg8); > PushU64 (&VmContext, (UINT64) Arg7); > PushU64 (&VmContext, (UINT64) Arg6); > @@ -281,10 +237,10 @@ EbcInterpret ( > /** > Begin executing an EBC image. > > - @param EntryPoint The entrypoint of EBC code. > @param ImageHandle image handle for the EBC application we're executing > @param SystemTable standard system table passed into an driver's entry > point > + @param EntryPoint The entrypoint of EBC code. > > @return The value returned by the EBC application we're going to run. > > @@ -292,9 +248,9 @@ EbcInterpret ( > UINT64 > EFIAPI > ExecuteEbcImageEntryPoint ( > - IN UINTN EntryPoint, > IN EFI_HANDLE ImageHandle, > - IN EFI_SYSTEM_TABLE *SystemTable > + IN EFI_SYSTEM_TABLE *SystemTable, > + IN UINTN EntryPoint > ) > { > // > @@ -335,7 +291,7 @@ ExecuteEbcImageEntryPoint ( > if (EFI_ERROR(Status)) { > return Status; > } > - VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE); > + VmContext.StackTop = (UINT8 *)VmContext.StackPool + (STACK_REMAIN_SIZE); > VmContext.Gpr[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE); > VmContext.HighStackBottom = (UINTN) VmContext.Gpr[0]; > VmContext.Gpr[0] -= sizeof (UINTN); > @@ -372,11 +328,6 @@ ExecuteEbcImageEntryPoint ( > VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0]; > > // > - // Entry function needn't access high stack context, simply > - // put the stack pointer here. > - // > - > - // > // Begin executing the EBC code > // > EbcExecute (&VmContext); > @@ -414,10 +365,7 @@ EbcCreateThunks ( > IN UINT32 Flags > ) > { > - UINT8 *Ptr; > - UINT8 *ThunkBase; > - UINT32 Index; > - INT32 ThunkSize; > + EBC_INSTRUCTION_BUFFER *InstructionBuffer; > > // > // Check alignment of pointer to EBC code > @@ -426,51 +374,38 @@ EbcCreateThunks ( > return EFI_INVALID_PARAMETER; > } > > - ThunkSize = sizeof(mInstructionBufferTemplate); > - > - Ptr = AllocatePool (sizeof(mInstructionBufferTemplate)); > - > - if (Ptr == NULL) { > + InstructionBuffer = AllocatePool (sizeof (EBC_INSTRUCTION_BUFFER)); > + if (InstructionBuffer == NULL) { > return EFI_OUT_OF_RESOURCES; > } > - // > - // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr); > - // > - // Save the start address so we can add a pointer to it to a list later. > - // > - ThunkBase = Ptr; > > // > // Give them the address of our buffer we're going to fix up > // > - *Thunk = (VOID *) Ptr; > + *Thunk = InstructionBuffer; > > // > // Copy whole thunk instruction buffer template > // > - CopyMem (Ptr, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate)); > + CopyMem (InstructionBuffer, &mEbcInstructionBufferTemplate, > + sizeof (EBC_INSTRUCTION_BUFFER)); > > // > // Patch EbcEntryPoint and EbcLLEbcInterpret > // > - for (Index = 0; Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) { > - if (*(UINTN *)&Ptr[Index] == EBC_ENTRYPOINT_SIGNATURE) { > - *(UINTN *)&Ptr[Index] = (UINTN)EbcEntryPoint; > - } > - if (*(UINTN *)&Ptr[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) { > - if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) { > - *(UINTN *)&Ptr[Index] = (UINTN)EbcLLExecuteEbcImageEntryPoint; > - } else { > - *(UINTN *)&Ptr[Index] = (UINTN)EbcLLEbcInterpret; > - } > - } > + InstructionBuffer->EbcEntryPoint = (UINT64)EbcEntryPoint; > + if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) { > + InstructionBuffer->EbcLlEntryPoint = (UINT64)EbcLLExecuteEbcImageEntryPoint; > + } else { > + InstructionBuffer->EbcLlEntryPoint = (UINT64)EbcLLEbcInterpret; > } > > // > // Add the thunk to the list for this image. Do this last since the add > // function flushes the cache for us. > // > - EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize); > + EbcAddImageThunk (ImageHandle, InstructionBuffer, > + sizeof (EBC_INSTRUCTION_BUFFER)); > > return EFI_SUCCESS; > } > @@ -500,40 +435,15 @@ EbcLLCALLEX ( > IN UINT8 Size > ) > { > - UINTN IsThunk; > - UINTN TargetEbcAddr; > - UINT8 InstructionBuffer[sizeof(mInstructionBufferTemplate)]; > - UINTN Index; > - UINTN IndexOfEbcEntrypoint; > - > - IsThunk = 1; > - TargetEbcAddr = 0; > - IndexOfEbcEntrypoint = 0; > + CONST EBC_INSTRUCTION_BUFFER *InstructionBuffer; > > // > // Processor specific code to check whether the callee is a thunk to EBC. > // > - CopyMem (InstructionBuffer, (VOID *)FuncAddr, sizeof(InstructionBuffer)); > - // > - // Fill the signature according to mInstructionBufferTemplate > - // > - for (Index = 0; Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) { > - if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_ENTRYPOINT_SIGNATURE) { > - *(UINTN *)&InstructionBuffer[Index] = EBC_ENTRYPOINT_SIGNATURE; > - IndexOfEbcEntrypoint = Index; > - } > - if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) { > - *(UINTN *)&InstructionBuffer[Index] = EBC_LL_EBC_ENTRYPOINT_SIGNATURE; > - } > - } > - // > - // Check if we need thunk to native > - // > - if (CompareMem (InstructionBuffer, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate)) != 0) { > - IsThunk = 0; > - } > + InstructionBuffer = (EBC_INSTRUCTION_BUFFER *)FuncAddr; > > - if (IsThunk == 1){ > + if (CompareMem (InstructionBuffer, &mEbcInstructionBufferTemplate, > + sizeof(EBC_INSTRUCTION_BUFFER) - 2 * sizeof (UINT64)) == 0) { > // > // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and > // put our return address and frame pointer on the VM stack. > @@ -545,14 +455,19 @@ EbcLLCALLEX ( > VmPtr->Gpr[0] -= 8; > VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN) (VmPtr->Ip + Size)); > > - CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + IndexOfEbcEntrypoint, sizeof(UINTN)); > - VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr; > + VmPtr->Ip = (VMIP) InstructionBuffer->EbcEntryPoint; > } else { > // > // The callee is not a thunk to EBC, call native code, > // and get return value. > // > - VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr); > + // Note that we will not be able to distinguish which part of the interval > + // [NewStackPointer, FramePtr) consists of stacked function arguments for > + // this call, and which part simply consists of locals in the caller's > + // stack frame. All we know is that there is an 8 byte gap at the top that > + // we can ignore. > + // > + VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr - 8); > > // > // Advance the IP.