184664369SSean Christopherson/* SPDX-License-Identifier: GPL-2.0 */ 284664369SSean Christopherson 384664369SSean Christopherson#include <linux/linkage.h> 484664369SSean Christopherson#include <asm/export.h> 584664369SSean Christopherson#include <asm/errno.h> 684664369SSean Christopherson#include <asm/enclu.h> 784664369SSean Christopherson 884664369SSean Christopherson#include "extable.h" 984664369SSean Christopherson 1084664369SSean Christopherson/* Relative to %rbp. */ 1184664369SSean Christopherson#define SGX_ENCLAVE_OFFSET_OF_RUN 16 1284664369SSean Christopherson 1384664369SSean Christopherson/* The offsets relative to struct sgx_enclave_run. */ 1484664369SSean Christopherson#define SGX_ENCLAVE_RUN_TCS 0 1584664369SSean Christopherson#define SGX_ENCLAVE_RUN_LEAF 8 1684664369SSean Christopherson#define SGX_ENCLAVE_RUN_EXCEPTION_VECTOR 12 1784664369SSean Christopherson#define SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE 14 1884664369SSean Christopherson#define SGX_ENCLAVE_RUN_EXCEPTION_ADDR 16 1984664369SSean Christopherson#define SGX_ENCLAVE_RUN_USER_HANDLER 24 2084664369SSean Christopherson#define SGX_ENCLAVE_RUN_USER_DATA 32 /* not used */ 2184664369SSean Christopherson#define SGX_ENCLAVE_RUN_RESERVED_START 40 2284664369SSean Christopherson#define SGX_ENCLAVE_RUN_RESERVED_END 256 2384664369SSean Christopherson 2484664369SSean Christopherson.code64 2584664369SSean Christopherson.section .text, "ax" 2684664369SSean Christopherson 2784664369SSean ChristophersonSYM_FUNC_START(__vdso_sgx_enter_enclave) 2884664369SSean Christopherson /* Prolog */ 2984664369SSean Christopherson .cfi_startproc 3084664369SSean Christopherson push %rbp 3184664369SSean Christopherson .cfi_adjust_cfa_offset 8 3284664369SSean Christopherson .cfi_rel_offset %rbp, 0 3384664369SSean Christopherson mov %rsp, %rbp 3484664369SSean Christopherson .cfi_def_cfa_register %rbp 3584664369SSean Christopherson push %rbx 3684664369SSean Christopherson .cfi_rel_offset %rbx, -8 3784664369SSean Christopherson 3884664369SSean Christopherson mov %ecx, %eax 3984664369SSean Christopherson.Lenter_enclave: 4084664369SSean Christopherson /* EENTER <= function <= ERESUME */ 4184664369SSean Christopherson cmp $EENTER, %eax 4284664369SSean Christopherson jb .Linvalid_input 4384664369SSean Christopherson cmp $ERESUME, %eax 4484664369SSean Christopherson ja .Linvalid_input 4584664369SSean Christopherson 4684664369SSean Christopherson mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rcx 4784664369SSean Christopherson 4884664369SSean Christopherson /* Validate that the reserved area contains only zeros. */ 4984664369SSean Christopherson mov $SGX_ENCLAVE_RUN_RESERVED_START, %rbx 5084664369SSean Christopherson1: 5184664369SSean Christopherson cmpq $0, (%rcx, %rbx) 5284664369SSean Christopherson jne .Linvalid_input 5384664369SSean Christopherson add $8, %rbx 5484664369SSean Christopherson cmpq $SGX_ENCLAVE_RUN_RESERVED_END, %rbx 5584664369SSean Christopherson jne 1b 5684664369SSean Christopherson 5784664369SSean Christopherson /* Load TCS and AEP */ 5884664369SSean Christopherson mov SGX_ENCLAVE_RUN_TCS(%rcx), %rbx 5984664369SSean Christopherson lea .Lasync_exit_pointer(%rip), %rcx 6084664369SSean Christopherson 6184664369SSean Christopherson /* Single ENCLU serving as both EENTER and AEP (ERESUME) */ 6284664369SSean Christopherson.Lasync_exit_pointer: 6384664369SSean Christopherson.Lenclu_eenter_eresume: 6484664369SSean Christopherson enclu 6584664369SSean Christopherson 6684664369SSean Christopherson /* EEXIT jumps here unless the enclave is doing something fancy. */ 6784664369SSean Christopherson mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx 6884664369SSean Christopherson 6984664369SSean Christopherson /* Set exit_reason. */ 7084664369SSean Christopherson movl $EEXIT, SGX_ENCLAVE_RUN_LEAF(%rbx) 7184664369SSean Christopherson 7284664369SSean Christopherson /* Invoke userspace's exit handler if one was provided. */ 7384664369SSean Christopherson.Lhandle_exit: 7484664369SSean Christopherson cmpq $0, SGX_ENCLAVE_RUN_USER_HANDLER(%rbx) 7584664369SSean Christopherson jne .Linvoke_userspace_handler 7684664369SSean Christopherson 7784664369SSean Christopherson /* Success, in the sense that ENCLU was attempted. */ 7884664369SSean Christopherson xor %eax, %eax 7984664369SSean Christopherson 8084664369SSean Christopherson.Lout: 8184664369SSean Christopherson pop %rbx 8284664369SSean Christopherson leave 8384664369SSean Christopherson .cfi_def_cfa %rsp, 8 84*f94909ceSPeter Zijlstra RET 8584664369SSean Christopherson 8684664369SSean Christopherson /* The out-of-line code runs with the pre-leave stack frame. */ 8784664369SSean Christopherson .cfi_def_cfa %rbp, 16 8884664369SSean Christopherson 8984664369SSean Christopherson.Linvalid_input: 9084664369SSean Christopherson mov $(-EINVAL), %eax 9184664369SSean Christopherson jmp .Lout 9284664369SSean Christopherson 9384664369SSean Christopherson.Lhandle_exception: 9484664369SSean Christopherson mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx 9584664369SSean Christopherson 9684664369SSean Christopherson /* Set the exception info. */ 9784664369SSean Christopherson mov %eax, (SGX_ENCLAVE_RUN_LEAF)(%rbx) 9884664369SSean Christopherson mov %di, (SGX_ENCLAVE_RUN_EXCEPTION_VECTOR)(%rbx) 9984664369SSean Christopherson mov %si, (SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE)(%rbx) 10084664369SSean Christopherson mov %rdx, (SGX_ENCLAVE_RUN_EXCEPTION_ADDR)(%rbx) 10184664369SSean Christopherson jmp .Lhandle_exit 10284664369SSean Christopherson 10384664369SSean Christopherson.Linvoke_userspace_handler: 10484664369SSean Christopherson /* Pass the untrusted RSP (at exit) to the callback via %rcx. */ 10584664369SSean Christopherson mov %rsp, %rcx 10684664369SSean Christopherson 10784664369SSean Christopherson /* Save struct sgx_enclave_exception %rbx is about to be clobbered. */ 10884664369SSean Christopherson mov %rbx, %rax 10984664369SSean Christopherson 11084664369SSean Christopherson /* Save the untrusted RSP offset in %rbx (non-volatile register). */ 11184664369SSean Christopherson mov %rsp, %rbx 11284664369SSean Christopherson and $0xf, %rbx 11384664369SSean Christopherson 11484664369SSean Christopherson /* 11584664369SSean Christopherson * Align stack per x86_64 ABI. Note, %rsp needs to be 16-byte aligned 11684664369SSean Christopherson * _after_ pushing the parameters on the stack, hence the bonus push. 11784664369SSean Christopherson */ 11884664369SSean Christopherson and $-0x10, %rsp 11984664369SSean Christopherson push %rax 12084664369SSean Christopherson 12184664369SSean Christopherson /* Push struct sgx_enclave_exception as a param to the callback. */ 12284664369SSean Christopherson push %rax 12384664369SSean Christopherson 12484664369SSean Christopherson /* Clear RFLAGS.DF per x86_64 ABI */ 12584664369SSean Christopherson cld 12684664369SSean Christopherson 12784664369SSean Christopherson /* 12884664369SSean Christopherson * Load the callback pointer to %rax and lfence for LVI (load value 12984664369SSean Christopherson * injection) protection before making the call. 13084664369SSean Christopherson */ 13184664369SSean Christopherson mov SGX_ENCLAVE_RUN_USER_HANDLER(%rax), %rax 13284664369SSean Christopherson lfence 13384664369SSean Christopherson call *%rax 13484664369SSean Christopherson 13584664369SSean Christopherson /* Undo the post-exit %rsp adjustment. */ 13684664369SSean Christopherson lea 0x10(%rsp, %rbx), %rsp 13784664369SSean Christopherson 13884664369SSean Christopherson /* 13984664369SSean Christopherson * If the return from callback is zero or negative, return immediately, 140163b0991SIngo Molnar * else re-execute ENCLU with the positive return value interpreted as 14184664369SSean Christopherson * the requested ENCLU function. 14284664369SSean Christopherson */ 14384664369SSean Christopherson cmp $0, %eax 14484664369SSean Christopherson jle .Lout 14584664369SSean Christopherson jmp .Lenter_enclave 14684664369SSean Christopherson 14784664369SSean Christopherson .cfi_endproc 14884664369SSean Christopherson 14984664369SSean Christopherson_ASM_VDSO_EXTABLE_HANDLE(.Lenclu_eenter_eresume, .Lhandle_exception) 15084664369SSean Christopherson 15184664369SSean ChristophersonSYM_FUNC_END(__vdso_sgx_enter_enclave) 152