@@ -18,6 +18,7 @@ VDSO32-$(CONFIG_IA32_EMULATION) := y
# files to link into the vdso
vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
+vobjs-$(VDSO64-y) += vsgx_enter_enclave.o
# files to link into kernel
obj-y += vma.o extable.o
@@ -85,6 +86,7 @@ CFLAGS_REMOVE_vdso-note.o = -pg
CFLAGS_REMOVE_vclock_gettime.o = -pg
CFLAGS_REMOVE_vgetcpu.o = -pg
CFLAGS_REMOVE_vvar.o = -pg
+CFLAGS_REMOVE_vsgx_enter_enclave.o = -pg
#
# X32 processes use x32 vDSO to access 64bit kernel data.
@@ -25,6 +25,7 @@ VERSION {
__vdso_getcpu;
time;
__vdso_time;
+ __vdso_sgx_enter_enclave;
local: *;
};
}
new file mode 100644
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/linkage.h>
+#include <asm/export.h>
+#include <asm/errno.h>
+
+#include "extable.h"
+
+#define EX_LEAF 0*8
+#define EX_TRAPNR 0*8+4
+#define EX_ERROR_CODE 0*8+6
+#define EX_ADDRESS 1*8
+
+.code64
+.section .text, "ax"
+
+#ifdef SGX_KERNEL_DOC
+/**
+ * __vdso_sgx_enter_enclave() - Enter an SGX enclave
+ *
+ * @leaf: **IN \%eax** - ENCLU leaf, must be EENTER or ERESUME
+ * @tcs: **IN \%rbx** - TCS, must be non-NULL
+ * @ex_info: **IN \%rcx** - Optional 'struct sgx_enclave_exception' pointer
+ *
+ * Return:
+ * **OUT \%eax** -
+ * %0 on a clean entry/exit to/from the enclave, %-EINVAL if ENCLU leaf is
+ * not allowed or if TCS is NULL, %-EFAULT if ENCLU or the enclave faults
+ *
+ * **Important!** __vdso_sgx_enter_enclave() is **NOT** compliant with the
+ * x86-64 ABI, i.e. cannot be called from standard C code. As noted above,
+ * input parameters must be passed via ``%eax``, ``%rbx`` and ``%rcx``, with
+ * the return value passed via ``%eax``. All registers except ``%rsp`` must
+ * be treated as volatile from the caller's perspective, including but not
+ * limited to GPRs, EFLAGS.DF, MXCSR, FCW, etc... Conversely, the enclave
+ * being run **must** preserve the untrusted ``%rsp`` and stack.
+ */
+__vdso_sgx_enter_enclave(u32 leaf, void *tcs,
+ struct sgx_enclave_exception *ex_info)
+{
+ if (leaf != SGX_EENTER && leaf != SGX_ERESUME)
+ return -EINVAL;
+
+ if (!tcs)
+ return -EINVAL;
+
+ try {
+ ENCLU[leaf];
+ } catch (exception) {
+ if (e)
+ *e = exception;
+ return -EFAULT;
+ }
+
+ return 0;
+}
+#endif
+ENTRY(__vdso_sgx_enter_enclave)
+ /* EENTER <= leaf <= ERESUME */
+ cmp $0x2, %eax
+ jb bad_input
+
+ cmp $0x3, %eax
+ ja bad_input
+
+ /* TCS must be non-NULL */
+ test %rbx, %rbx
+ je bad_input
+
+ /* Save @exception_info */
+ push %rcx
+
+ /* Load AEP for ENCLU */
+ lea 1f(%rip), %rcx
+1: enclu
+
+ add $0x8, %rsp
+ xor %eax, %eax
+ ret
+
+bad_input:
+ mov $(-EINVAL), %rax
+ ret
+
+.pushsection .fixup, "ax"
+ /* Re-load @exception_info and fill it (if it's non-NULL) */
+2: pop %rcx
+ test %rcx, %rcx
+ je 3f
+
+ mov %eax, EX_LEAF(%rcx)
+ mov %di, EX_TRAPNR(%rcx)
+ mov %si, EX_ERROR_CODE(%rcx)
+ mov %rdx, EX_ADDRESS(%rcx)
+3: mov $(-EFAULT), %rax
+ ret
+.popsection
+
+_ASM_VDSO_EXTABLE_HANDLE(1b, 2b)
+
+ENDPROC(__vdso_sgx_enter_enclave)
@@ -65,4 +65,22 @@ struct sgx_enclave_set_attribute {
__u64 attribute_fd;
};
+/**
+ * struct sgx_enclave_exception - structure to report exceptions encountered in
+ * __vdso_sgx_enter_enclave()
+ *
+ * @leaf: ENCLU leaf from \%eax at time of exception
+ * @trapnr: exception trap number, a.k.a. fault vector
+ * @error_code: exception error code
+ * @address: exception address, e.g. CR2 on a #PF
+ * @reserved: reserved for future use
+ */
+struct sgx_enclave_exception {
+ __u32 leaf;
+ __u16 trapnr;
+ __u16 error_code;
+ __u64 address;
+ __u64 reserved[2];
+};
+
#endif /* _UAPI_ASM_X86_SGX_H */