]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / AArch64 / EbcLowLevel.S
CommitLineData
72b0eaa0
AB
1///** @file\r
2//\r
3// This code provides low level routines that support the Virtual Machine\r
4// for option ROMs.\r
5//\r
4d1f5a21
AB
6// Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>\r
7// Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>\r
72b0eaa0 8// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
4d1f5a21 9//\r
9d510e61 10// SPDX-License-Identifier: BSD-2-Clause-Patent\r
72b0eaa0
AB
11//\r
12//**/\r
13\r
14ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative)\r
15ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret)\r
16ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint)\r
17\r
4d1f5a21
AB
18ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate)\r
19\r
72b0eaa0
AB
20//****************************************************************************\r
21// EbcLLCALLEX\r
22//\r
23// This function is called to execute an EBC CALLEX instruction.\r
24// This instruction requires that we thunk out to external native\r
25// code. For AArch64, we copy the VM stack into the main stack and then pop\r
26// the first 8 arguments off according to the AArch64 Procedure Call Standard\r
27// On return, we restore the stack pointer to its original location.\r
28//\r
29//****************************************************************************\r
30// UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)\r
a15e5bc2 31ASM_PFX(EbcLLCALLEXNative):\r
3226e315
AB
32 mov x8, x0 // Preserve x0\r
33 mov x9, x1 // Preserve x1\r
a15e5bc2 34\r
3226e315
AB
35 //\r
36 // If the EBC stack frame is smaller than or equal to 64 bytes, we know there\r
37 // are no stacked arguments #9 and beyond that we need to copy to the native\r
38 // stack. In this case, we can perform a tail call which is much more\r
39 // efficient, since there is no need to touch the native stack at all.\r
40 //\r
41 sub x3, x2, x1 // Length = NewStackPointer - FramePtr\r
42 cmp x3, #64\r
43 b.gt 1f\r
a15e5bc2 44\r
3226e315
AB
45 //\r
46 // While probably harmless in practice, we should not access the VM stack\r
47 // outside of the interval [NewStackPointer, FramePtr), which means we\r
48 // should not blindly fill all 8 argument registers with VM stack data.\r
49 // So instead, calculate how many argument registers we can fill based on\r
50 // the size of the VM stack frame, and skip the remaining ones.\r
51 //\r
52 adr x0, 0f // Take address of 'br' instruction below\r
53 bic x3, x3, #7 // Ensure correct alignment\r
54 sub x0, x0, x3, lsr #1 // Subtract 4 bytes for each arg to unstack\r
55 br x0 // Skip remaining argument registers\r
a15e5bc2 56\r
3226e315
AB
57 ldr x7, [x9, #56] // Call with 8 arguments\r
58 ldr x6, [x9, #48] // |\r
59 ldr x5, [x9, #40] // |\r
60 ldr x4, [x9, #32] // |\r
61 ldr x3, [x9, #24] // |\r
62 ldr x2, [x9, #16] // |\r
63 ldr x1, [x9, #8] // V\r
64 ldr x0, [x9] // Call with 1 argument\r
a15e5bc2 65\r
3226e315 660: br x8 // Call with no arguments\r
a15e5bc2 67\r
3226e315
AB
68 //\r
69 // More than 64 bytes: we need to build the full native stack frame and copy\r
70 // the part of the VM stack exceeding 64 bytes (which may contain stacked\r
71 // arguments) to the native stack\r
72 //\r
731: stp x29, x30, [sp, #-16]!\r
74 mov x29, sp\r
a15e5bc2 75\r
3226e315
AB
76 //\r
77 // Ensure that the stack pointer remains 16 byte aligned,\r
78 // even if the size of the VM stack frame is not a multiple of 16\r
79 //\r
80 add x1, x1, #64 // Skip over [potential] reg params\r
81 tbz x3, #3, 2f // Multiple of 16?\r
82 ldr x4, [x2, #-8]! // No? Then push one word\r
83 str x4, [sp, #-16]! // ... but use two slots\r
84 b 3f\r
85\r
862: ldp x4, x5, [x2, #-16]!\r
87 stp x4, x5, [sp, #-16]!\r
883: cmp x2, x1\r
89 b.gt 2b\r
90\r
91 ldp x0, x1, [x9]\r
92 ldp x2, x3, [x9, #16]\r
93 ldp x4, x5, [x9, #32]\r
94 ldp x6, x7, [x9, #48]\r
95\r
96 blr x8\r
97\r
98 mov sp, x29\r
99 ldp x29, x30, [sp], #16\r
100 ret\r
a15e5bc2 101\r
72b0eaa0
AB
102//****************************************************************************\r
103// EbcLLEbcInterpret\r
104//\r
105// This function is called by the thunk code to handle an Native to EBC call\r
106// This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on the stack)\r
4a2aaff2 107// x16 contains the Entry point that will be the first stacked argument when\r
72b0eaa0
AB
108// EBCInterpret is called.\r
109//\r
110//****************************************************************************\r
a15e5bc2 111ASM_PFX(EbcLLEbcInterpret):\r
4a2aaff2
AB
112 stp x29, x30, [sp, #-16]!\r
113 mov x29, sp\r
a15e5bc2 114\r
4a2aaff2
AB
115 // push the entry point and the address of args #9 - #16 onto the stack\r
116 add x17, sp, #16\r
117 stp x16, x17, [sp, #-16]!\r
a15e5bc2 118\r
4a2aaff2
AB
119 // call C-code\r
120 bl ASM_PFX(EbcInterpret)\r
a15e5bc2 121\r
4a2aaff2
AB
122 add sp, sp, #16\r
123 ldp x29, x30, [sp], #16\r
a15e5bc2
JB
124 ret\r
125\r
72b0eaa0
AB
126//****************************************************************************\r
127// EbcLLExecuteEbcImageEntryPoint\r
128//\r
129// This function is called by the thunk code to handle the image entry point\r
4d1f5a21 130// x16 contains the Entry point that will be the third argument when\r
72b0eaa0
AB
131// ExecuteEbcImageEntryPoint is called.\r
132//\r
133//****************************************************************************\r
a15e5bc2 134ASM_PFX(EbcLLExecuteEbcImageEntryPoint):\r
4a2aaff2 135 mov x2, x16\r
a15e5bc2 136\r
4a2aaff2
AB
137 // tail call to C code\r
138 b ASM_PFX(ExecuteEbcImageEntryPoint)\r
4d1f5a21
AB
139\r
140//****************************************************************************\r
141// mEbcInstructionBufferTemplate\r
142//****************************************************************************\r
143 .section ".rodata", "a"\r
144 .align 3\r
145ASM_PFX(mEbcInstructionBufferTemplate):\r
146 adr x17, 0f\r
147 ldp x16, x17, [x17]\r
148 br x17\r
149\r
150 //\r
151 // Add a magic code here to help the VM recognize the thunk.\r
152 //\r
153 hlt #0xEBC\r
154\r
1550: .quad 0 // EBC_ENTRYPOINT_SIGNATURE\r
156 .quad 0 // EBC_LL_EBC_ENTRYPOINT_SIGNATURE\r