corda/psw/urts/linux/enter_enclave.S
zhaohuidu 85947caa12 Upgrade to Linux 1.6 gold release
switch code to linux 1.6 opensource gold release
2016-09-19 14:55:22 +08:00

285 lines
9.1 KiB
ArmAsm

/*
* 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 OCMD_ERET, 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 -> | |
* | <ecall> |
* ------------------
* 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