123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /* SPDX-License-Identifier: GPL-2.0 */
- #include <linux/linkage.h>
- #include <asm/export.h>
- #include <asm/errno.h>
- #include <asm/enclu.h>
- #include "extable.h"
- /* Relative to %rbp. */
- #define SGX_ENCLAVE_OFFSET_OF_RUN 16
- /* The offsets relative to struct sgx_enclave_run. */
- #define SGX_ENCLAVE_RUN_TCS 0
- #define SGX_ENCLAVE_RUN_LEAF 8
- #define SGX_ENCLAVE_RUN_EXCEPTION_VECTOR 12
- #define SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE 14
- #define SGX_ENCLAVE_RUN_EXCEPTION_ADDR 16
- #define SGX_ENCLAVE_RUN_USER_HANDLER 24
- #define SGX_ENCLAVE_RUN_USER_DATA 32 /* not used */
- #define SGX_ENCLAVE_RUN_RESERVED_START 40
- #define SGX_ENCLAVE_RUN_RESERVED_END 256
- .code64
- .section .text, "ax"
- SYM_FUNC_START(__vdso_sgx_enter_enclave)
- /* Prolog */
- .cfi_startproc
- push %rbp
- .cfi_adjust_cfa_offset 8
- .cfi_rel_offset %rbp, 0
- mov %rsp, %rbp
- .cfi_def_cfa_register %rbp
- push %rbx
- .cfi_rel_offset %rbx, -8
- mov %ecx, %eax
- .Lenter_enclave:
- /* EENTER <= function <= ERESUME */
- cmp $EENTER, %eax
- jb .Linvalid_input
- cmp $ERESUME, %eax
- ja .Linvalid_input
- mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rcx
- /* Validate that the reserved area contains only zeros. */
- mov $SGX_ENCLAVE_RUN_RESERVED_START, %rbx
- 1:
- cmpq $0, (%rcx, %rbx)
- jne .Linvalid_input
- add $8, %rbx
- cmpq $SGX_ENCLAVE_RUN_RESERVED_END, %rbx
- jne 1b
- /* Load TCS and AEP */
- mov SGX_ENCLAVE_RUN_TCS(%rcx), %rbx
- lea .Lasync_exit_pointer(%rip), %rcx
- /* Single ENCLU serving as both EENTER and AEP (ERESUME) */
- .Lasync_exit_pointer:
- .Lenclu_eenter_eresume:
- enclu
- /* EEXIT jumps here unless the enclave is doing something fancy. */
- mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx
- /* Set exit_reason. */
- movl $EEXIT, SGX_ENCLAVE_RUN_LEAF(%rbx)
- /* Invoke userspace's exit handler if one was provided. */
- .Lhandle_exit:
- cmpq $0, SGX_ENCLAVE_RUN_USER_HANDLER(%rbx)
- jne .Linvoke_userspace_handler
- /* Success, in the sense that ENCLU was attempted. */
- xor %eax, %eax
- .Lout:
- pop %rbx
- leave
- .cfi_def_cfa %rsp, 8
- RET
- /* The out-of-line code runs with the pre-leave stack frame. */
- .cfi_def_cfa %rbp, 16
- .Linvalid_input:
- mov $(-EINVAL), %eax
- jmp .Lout
- .Lhandle_exception:
- mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx
- /* Set the exception info. */
- mov %eax, (SGX_ENCLAVE_RUN_LEAF)(%rbx)
- mov %di, (SGX_ENCLAVE_RUN_EXCEPTION_VECTOR)(%rbx)
- mov %si, (SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE)(%rbx)
- mov %rdx, (SGX_ENCLAVE_RUN_EXCEPTION_ADDR)(%rbx)
- jmp .Lhandle_exit
- .Linvoke_userspace_handler:
- /* Pass the untrusted RSP (at exit) to the callback via %rcx. */
- mov %rsp, %rcx
- /* Save struct sgx_enclave_exception %rbx is about to be clobbered. */
- mov %rbx, %rax
- /* Save the untrusted RSP offset in %rbx (non-volatile register). */
- mov %rsp, %rbx
- and $0xf, %rbx
- /*
- * Align stack per x86_64 ABI. Note, %rsp needs to be 16-byte aligned
- * _after_ pushing the parameters on the stack, hence the bonus push.
- */
- and $-0x10, %rsp
- push %rax
- /* Push struct sgx_enclave_exception as a param to the callback. */
- push %rax
- /* Clear RFLAGS.DF per x86_64 ABI */
- cld
- /*
- * Load the callback pointer to %rax and lfence for LVI (load value
- * injection) protection before making the call.
- */
- mov SGX_ENCLAVE_RUN_USER_HANDLER(%rax), %rax
- lfence
- call *%rax
- /* Undo the post-exit %rsp adjustment. */
- lea 0x10(%rsp, %rbx), %rsp
- /*
- * If the return from callback is zero or negative, return immediately,
- * else re-execute ENCLU with the positive return value interpreted as
- * the requested ENCLU function.
- */
- cmp $0, %eax
- jle .Lout
- jmp .Lenter_enclave
- .cfi_endproc
- _ASM_VDSO_EXTABLE_HANDLE(.Lenclu_eenter_eresume, .Lhandle_exception)
- SYM_FUNC_END(__vdso_sgx_enter_enclave)
|