/* SPDX-License-Identifier: GPL-2.0 */12#include <linux/linkage.h>3#include <asm/errno.h>4#include <asm/enclu.h>56#include "extable.h"78/* Relative to %rbp. */9#define SGX_ENCLAVE_OFFSET_OF_RUN 161011/* The offsets relative to struct sgx_enclave_run. */12#define SGX_ENCLAVE_RUN_TCS 013#define SGX_ENCLAVE_RUN_LEAF 814#define SGX_ENCLAVE_RUN_EXCEPTION_VECTOR 1215#define SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE 1416#define SGX_ENCLAVE_RUN_EXCEPTION_ADDR 1617#define SGX_ENCLAVE_RUN_USER_HANDLER 2418#define SGX_ENCLAVE_RUN_USER_DATA 32 /* not used */19#define SGX_ENCLAVE_RUN_RESERVED_START 4020#define SGX_ENCLAVE_RUN_RESERVED_END 2562122.code6423.section .text, "ax"2425SYM_FUNC_START(__vdso_sgx_enter_enclave)26/* Prolog */27.cfi_startproc28push %rbp29.cfi_adjust_cfa_offset 830.cfi_rel_offset %rbp, 031mov %rsp, %rbp32.cfi_def_cfa_register %rbp33push %rbx34.cfi_rel_offset %rbx, -83536mov %ecx, %eax37.Lenter_enclave:38/* EENTER <= function <= ERESUME */39cmp $EENTER, %eax40jb .Linvalid_input41cmp $ERESUME, %eax42ja .Linvalid_input4344mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rcx4546/* Validate that the reserved area contains only zeros. */47mov $SGX_ENCLAVE_RUN_RESERVED_START, %rbx481:49cmpq $0, (%rcx, %rbx)50jne .Linvalid_input51add $8, %rbx52cmpq $SGX_ENCLAVE_RUN_RESERVED_END, %rbx53jne 1b5455/* Load TCS and AEP */56mov SGX_ENCLAVE_RUN_TCS(%rcx), %rbx57lea .Lasync_exit_pointer(%rip), %rcx5859/* Single ENCLU serving as both EENTER and AEP (ERESUME) */60.Lasync_exit_pointer:61.Lenclu_eenter_eresume:62enclu6364/* EEXIT jumps here unless the enclave is doing something fancy. */65mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx6667/* Set exit_reason. */68movl $EEXIT, SGX_ENCLAVE_RUN_LEAF(%rbx)6970/* Invoke userspace's exit handler if one was provided. */71.Lhandle_exit:72cmpq $0, SGX_ENCLAVE_RUN_USER_HANDLER(%rbx)73jne .Linvoke_userspace_handler7475/* Success, in the sense that ENCLU was attempted. */76xor %eax, %eax7778.Lout:79pop %rbx80leave81.cfi_def_cfa %rsp, 882RET8384/* The out-of-line code runs with the pre-leave stack frame. */85.cfi_def_cfa %rbp, 168687.Linvalid_input:88mov $(-EINVAL), %eax89jmp .Lout9091.Lhandle_exception:92mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx9394/* Set the exception info. */95mov %eax, (SGX_ENCLAVE_RUN_LEAF)(%rbx)96mov %di, (SGX_ENCLAVE_RUN_EXCEPTION_VECTOR)(%rbx)97mov %si, (SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE)(%rbx)98mov %rdx, (SGX_ENCLAVE_RUN_EXCEPTION_ADDR)(%rbx)99jmp .Lhandle_exit100101.Linvoke_userspace_handler:102/* Pass the untrusted RSP (at exit) to the callback via %rcx. */103mov %rsp, %rcx104105/* Save struct sgx_enclave_exception %rbx is about to be clobbered. */106mov %rbx, %rax107108/* Save the untrusted RSP offset in %rbx (non-volatile register). */109mov %rsp, %rbx110and $0xf, %rbx111112/*113* Align stack per x86_64 ABI. Note, %rsp needs to be 16-byte aligned114* _after_ pushing the parameters on the stack, hence the bonus push.115*/116and $-0x10, %rsp117push %rax118119/* Push struct sgx_enclave_exception as a param to the callback. */120push %rax121122/* Clear RFLAGS.DF per x86_64 ABI */123cld124125/*126* Load the callback pointer to %rax and lfence for LVI (load value127* injection) protection before making the call.128*/129mov SGX_ENCLAVE_RUN_USER_HANDLER(%rax), %rax130lfence131call *%rax132133/* Undo the post-exit %rsp adjustment. */134lea 0x10(%rsp, %rbx), %rsp135136/*137* If the return from callback is zero or negative, return immediately,138* else re-execute ENCLU with the positive return value interpreted as139* the requested ENCLU function.140*/141cmp $0, %eax142jle .Lout143jmp .Lenter_enclave144145.cfi_endproc146147_ASM_VDSO_EXTABLE_HANDLE(.Lenclu_eenter_eresume, .Lhandle_exception)148149SYM_FUNC_END(__vdso_sgx_enter_enclave)150151152