/* * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "enter_enclave.h" /* int __morestack(const tcs_t *tcs, const int fn, const void *ocall_table, const void *ms, CTrustThread *trust_thread); */ .file "enter_enclave.S" .text DECLARE_GLOBAL_FUNC __morestack __morestack: EENTER_PROLOG movl frame_arg1, %edi /* fn */ #if defined(__x86_64__) /* we defined fn as int, so we do sign extend.*/ movslq %edi, %rdi #endif mov frame_arg3, %xsi /* ms */ .Ldo_eenter: mov frame_arg0, %xbx /* tcs addr */ lea_pic .Lasync_exit_pointer, %xcx /* aep addr */ mov $SE_EENTER, %xax /* EENTER leaf */ .Leenter_inst: ENCLU /* * at this point, we may have returned due to a normal EEXIT, * or we may have returned due to an OCALL. We differentiate * by popping the top of the stack. If it is not -1, we have * an untrusted bridge to call at that address. */ /* We have an ocall. Call our bridge function. */ cmp $OCMD_ERET, %xdi je .Leret .Ldo_ocall: /* call ocall * int ocall(const unsigned int proc, void *ocall_table, const void *ms, CEnclave *enclave); * * When EEXIT'ed from tRTS due to an OCALL, * - `rdi' holds OCALL index *- `rsi' holds the pointer to marshalling structure */ .type sgx_ocall,@function .hidden sgx_ocall #if defined(__i386__) sub $(3*SE_WORDSIZE), %xsp /* make stack 16 bytes aligned */ push frame_arg0 push frame_arg4 push %esi push frame_arg2 push %edi #endif #if defined(__x86_64__) mov %rsi, %rdx /* param2 */ /*mov %rdi, %rdi */ /* param0 */ mov frame_arg2, %rsi /* param1 */ mov frame_arg4, %rcx /* param3 */ mov frame_arg0, %r8 /* param4 */ #endif call stack_sticker cmp $SE_ERROR_READ_LOCK_FAIL, %eax je .Loret mov $ECMD_ORET, %xdi /* oret */ mov %xax, %xsi /* the result of ocall */ jmp .Ldo_eenter /* never return here */ ud2 .Leret: mov %xsi, %xax .Loret: EENTER_EPILOG .Lasync_exit_pointer: ENCLU .size __morestack, .-__morestack DECLARE_GLOBAL_FUNC get_aep lea_pic .Lasync_exit_pointer, %xax ret DECLARE_GLOBAL_FUNC get_eenterp lea_pic .Leenter_inst, %xax ret DECLARE_GLOBAL_FUNC get_eretp lea_pic .Leret, %xax ret /* * function stack_sticker is the wrapper of ocall, * before call ocall, update the ret address and frame pointer (BP) on the stack * * Stack before: * |__morestack stack |<--| * ------------- | * |return adress | | * xbp -> | caller xbp | --| * | | * xsp -> | | * ------------- * * Stack after: * |__morestack stack | * ------------------ * | __morestack(inside)| * xbp -> | xbp_t | ---->the frame point of __morestack * | | * xsp -> | | * | | * ------------------ * int stack_sticker(unsigned int proc, sgx_ocall_table_t *ocall_table, void *ms, CTrustThread *trust_thread, tcs_t *tcs) */ DECLARE_GLOBAL_FUNC stack_sticker .hidden stack_sticker .type push_ocall_frame,@function .hidden push_ocall_frame .type pop_ocall_frame,@function .hidden pop_ocall_frame .cfi_startproc push %xbp .cfi_def_cfa_offset 2*SE_WORDSIZE .cfi_offset xbp,-2*SE_WORDSIZE mov %xsp, %xbp .cfi_def_cfa_register xbp #if defined(__i386__) sub $(10*SE_WORDSIZE), %xsp /* We should have the stack 16 bytes aligned */ #elif defined(__x86_64__) sub $(10*SE_WORDSIZE), %xsp #endif /* save the return address and the frame point */ mov (0*SE_WORDSIZE)(%xbp), %xax mov %xax, (4*SE_WORDSIZE)(%xsp) mov (1*SE_WORDSIZE)(%xbp), %xax mov %xax, (5*SE_WORDSIZE)(%xsp) #if defined(__i386__) /* save the first 4 parameters */ mov frame_arg0, %xax mov %xax, (0*SE_WORDSIZE)(%xsp) mov frame_arg1, %xax mov %xax, (1*SE_WORDSIZE)(%xsp) mov frame_arg2, %xax mov %xax, (2*SE_WORDSIZE)(%xsp) mov frame_arg3, %xax mov %xax, (3*SE_WORDSIZE)(%xsp) /* update the frame infomation */ mov frame_arg3, %xax /* the pointer of trustthread instance */ push %xax mov frame_arg4, %xax /* tcs */ push %xax push %xbp /*just for call push_ocall_frame and return, no stack 16 bytes alignment needed */ call push_ocall_frame /* recover parameters */ add $(3*SE_WORDSIZE), %xsp #elif defined(__x86_64__) /* save the first 4 parameters */ mov %xdi, (0*SE_WORDSIZE)(%xsp) mov %xsi, (1*SE_WORDSIZE)(%xsp) mov %xdx, (2*SE_WORDSIZE)(%xsp) mov %xcx, (3*SE_WORDSIZE)(%xsp) /* update the frame infomation */ mov %xcx, %xdx /* the pointer of trustthread instance */ mov %r8, %xsi /* tcs */ mov %xbp, %xdi call push_ocall_frame /* recover parameters */ mov (0*SE_WORDSIZE)(%xsp), %xdi mov (1*SE_WORDSIZE)(%xsp), %xsi mov (2*SE_WORDSIZE)(%xsp), %xdx mov (3*SE_WORDSIZE)(%xsp), %xcx #endif /* start the ocall */ call sgx_ocall /* save the return value */ mov %xax, (0*SE_WORDSIZE)(%xsp) #if defined(__i386__) /* pop the frame infomation */ mov frame_arg3, %xax /* the pointer of trustthread instance */ push %xax mov frame_arg4, %xax /* tcs is not used for now */ push %xax call pop_ocall_frame /* recover parameters */ add $(2*SE_WORDSIZE), %xsp #elif defined(__x86_64__) /* pop the frame infomation */ mov (3*SE_WORDSIZE)(%xsp), %xsi /* the pointer of trustthread instance */ call pop_ocall_frame #endif /* recover the return address and frame point */ mov (4*SE_WORDSIZE)(%xsp), %xax mov %xax, (0*SE_WORDSIZE)(%xbp) mov (5*SE_WORDSIZE)(%xsp), %xax mov %xax, (1*SE_WORDSIZE)(%xbp) /* recover the return value */ mov (0*SE_WORDSIZE)(%xsp), %xax leave ret .cfi_endproc /* * void sgx_debug_load_state_add_element(debug_enclave_info_t* new_enclave_info, debug_enclave_info_t** g_debug_enclave_info_list) * On x86, calling convention is "void sgx_debug_load_state_add_element(eax, edx)" * On x64, calling convention is "void sgx_debug_load_state_add_element(rdi, rsi)" * Add an new enclave info to list head and raise enclave load event */ DECLARE_GLOBAL_FUNC sgx_debug_load_state_add_element #if defined(__i386__) movl %eax, (%edx) #else movq %rdi, (%rsi) #endif ret /* * void sgx_debug_unload_state_remove_element(debug_enclave_info_t* enclave_info, debug_enclave_info_t** pre_enclave_info, debug_enclave_info_t* next_enclave_info) * On x86, calling convention is "void se_debug_load_state_remove_element(eax, edx, ecx)" * On x64, calling convention is "void se_debug_load_state_remove_element(rdi, rsi, rdx)" * eax is to pass the removed enclave info to debugger. * Remove an enclave info from list and raise enclave unload event */ DECLARE_GLOBAL_FUNC sgx_debug_unload_state_remove_element #if defined(__i386__) movl %ecx, (%edx) #else movq %rdx, (%rsi) #endif ret /* We do not need executable stack.*/ .section .note.GNU-stack,"",@progbits