• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1///** @file
2//
3//  This code provides low level routines that support the Virtual Machine
4//  for option ROMs.
5//
6//  Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
7//  Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>
8//  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
9//
10//  This program and the accompanying materials
11//  are licensed and made available under the terms and conditions of the BSD License
12//  which accompanies this distribution.  The full text of the license may be found at
13//  http://opensource.org/licenses/bsd-license.php
14//
15//  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16//  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17//
18//**/
19
20ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative)
21ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret)
22ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint)
23
24ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate)
25
26//****************************************************************************
27// EbcLLCALLEX
28//
29// This function is called to execute an EBC CALLEX instruction.
30// This instruction requires that we thunk out to external native
31// code. For AArch64, we copy the VM stack into the main stack and then pop
32// the first 8 arguments off according to the AArch64 Procedure Call Standard
33// On return, we restore the stack pointer to its original location.
34//
35//****************************************************************************
36// UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
37ASM_PFX(EbcLLCALLEXNative):
38    mov     x8, x0                 // Preserve x0
39    mov     x9, x1                 // Preserve x1
40
41    //
42    // If the EBC stack frame is smaller than or equal to 64 bytes, we know there
43    // are no stacked arguments #9 and beyond that we need to copy to the native
44    // stack. In this case, we can perform a tail call which is much more
45    // efficient, since there is no need to touch the native stack at all.
46    //
47    sub     x3, x2, x1              // Length = NewStackPointer - FramePtr
48    cmp     x3, #64
49    b.gt    1f
50
51    //
52    // While probably harmless in practice, we should not access the VM stack
53    // outside of the interval [NewStackPointer, FramePtr), which means we
54    // should not blindly fill all 8 argument registers with VM stack data.
55    // So instead, calculate how many argument registers we can fill based on
56    // the size of the VM stack frame, and skip the remaining ones.
57    //
58    adr     x0, 0f                  // Take address of 'br' instruction below
59    bic     x3, x3, #7              // Ensure correct alignment
60    sub     x0, x0, x3, lsr #1      // Subtract 4 bytes for each arg to unstack
61    br      x0                      // Skip remaining argument registers
62
63    ldr     x7, [x9, #56]           // Call with 8 arguments
64    ldr     x6, [x9, #48]           //  |
65    ldr     x5, [x9, #40]           //  |
66    ldr     x4, [x9, #32]           //  |
67    ldr     x3, [x9, #24]           //  |
68    ldr     x2, [x9, #16]           //  |
69    ldr     x1, [x9, #8]            //  V
70    ldr     x0, [x9]                // Call with 1 argument
71
720:  br      x8                      // Call with no arguments
73
74    //
75    // More than 64 bytes: we need to build the full native stack frame and copy
76    // the part of the VM stack exceeding 64 bytes (which may contain stacked
77    // arguments) to the native stack
78    //
791:  stp     x29, x30, [sp, #-16]!
80    mov     x29, sp
81
82    //
83    // Ensure that the stack pointer remains 16 byte aligned,
84    // even if the size of the VM stack frame is not a multiple of 16
85    //
86    add     x1, x1, #64             // Skip over [potential] reg params
87    tbz     x3, #3, 2f              // Multiple of 16?
88    ldr     x4, [x2, #-8]!          // No? Then push one word
89    str     x4, [sp, #-16]!         // ... but use two slots
90    b       3f
91
922:  ldp     x4, x5, [x2, #-16]!
93    stp     x4, x5, [sp, #-16]!
943:  cmp     x2, x1
95    b.gt    2b
96
97    ldp     x0, x1, [x9]
98    ldp     x2, x3, [x9, #16]
99    ldp     x4, x5, [x9, #32]
100    ldp     x6, x7, [x9, #48]
101
102    blr     x8
103
104    mov     sp, x29
105    ldp     x29, x30, [sp], #16
106    ret
107
108//****************************************************************************
109// EbcLLEbcInterpret
110//
111// This function is called by the thunk code to handle an Native to EBC call
112// This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on the stack)
113// x16 contains the Entry point that will be the first stacked argument when
114// EBCInterpret is called.
115//
116//****************************************************************************
117ASM_PFX(EbcLLEbcInterpret):
118    stp     x29, x30, [sp, #-16]!
119    mov     x29, sp
120
121    // push the entry point and the address of args #9 - #16 onto the stack
122    add     x17, sp, #16
123    stp     x16, x17, [sp, #-16]!
124
125    // call C-code
126    bl      ASM_PFX(EbcInterpret)
127
128    add     sp, sp, #16
129    ldp     x29, x30, [sp], #16
130    ret
131
132//****************************************************************************
133// EbcLLExecuteEbcImageEntryPoint
134//
135// This function is called by the thunk code to handle the image entry point
136// x16 contains the Entry point that will be the third argument when
137// ExecuteEbcImageEntryPoint is called.
138//
139//****************************************************************************
140ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
141    mov     x2, x16
142
143    // tail call to C code
144    b       ASM_PFX(ExecuteEbcImageEntryPoint)
145
146//****************************************************************************
147// mEbcInstructionBufferTemplate
148//****************************************************************************
149    .section    ".rodata", "a"
150    .align      3
151ASM_PFX(mEbcInstructionBufferTemplate):
152    adr     x17, 0f
153    ldp     x16, x17, [x17]
154    br      x17
155
156    //
157    // Add a magic code here to help the VM recognize the thunk.
158    //
159    hlt     #0xEBC
160
1610:  .quad   0   // EBC_ENTRYPOINT_SIGNATURE
162    .quad   0   // EBC_LL_EBC_ENTRYPOINT_SIGNATURE
163