drm/rockchip: vop2: Fix the windows switch between different layers
[drm/drm-misc.git] / arch / x86 / entry / vdso / vsgx.S
blob37a3d4c0236699dd968a96cabc3d46bb78d65ac0
1 /* SPDX-License-Identifier: GPL-2.0 */
3 #include <linux/linkage.h>
4 #include <asm/errno.h>
5 #include <asm/enclu.h>
7 #include "extable.h"
9 /* Relative to %rbp. */
10 #define SGX_ENCLAVE_OFFSET_OF_RUN               16
12 /* The offsets relative to struct sgx_enclave_run. */
13 #define SGX_ENCLAVE_RUN_TCS                     0
14 #define SGX_ENCLAVE_RUN_LEAF                    8
15 #define SGX_ENCLAVE_RUN_EXCEPTION_VECTOR        12
16 #define SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE    14
17 #define SGX_ENCLAVE_RUN_EXCEPTION_ADDR          16
18 #define SGX_ENCLAVE_RUN_USER_HANDLER            24
19 #define SGX_ENCLAVE_RUN_USER_DATA               32      /* not used */
20 #define SGX_ENCLAVE_RUN_RESERVED_START          40
21 #define SGX_ENCLAVE_RUN_RESERVED_END            256
23 .code64
24 .section .text, "ax"
26 SYM_FUNC_START(__vdso_sgx_enter_enclave)
27         /* Prolog */
28         .cfi_startproc
29         push    %rbp
30         .cfi_adjust_cfa_offset  8
31         .cfi_rel_offset         %rbp, 0
32         mov     %rsp, %rbp
33         .cfi_def_cfa_register   %rbp
34         push    %rbx
35         .cfi_rel_offset         %rbx, -8
37         mov     %ecx, %eax
38 .Lenter_enclave:
39         /* EENTER <= function <= ERESUME */
40         cmp     $EENTER, %eax
41         jb      .Linvalid_input
42         cmp     $ERESUME, %eax
43         ja      .Linvalid_input
45         mov     SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rcx
47         /* Validate that the reserved area contains only zeros. */
48         mov     $SGX_ENCLAVE_RUN_RESERVED_START, %rbx
50         cmpq    $0, (%rcx, %rbx)
51         jne     .Linvalid_input
52         add     $8, %rbx
53         cmpq    $SGX_ENCLAVE_RUN_RESERVED_END, %rbx
54         jne     1b
56         /* Load TCS and AEP */
57         mov     SGX_ENCLAVE_RUN_TCS(%rcx), %rbx
58         lea     .Lasync_exit_pointer(%rip), %rcx
60         /* Single ENCLU serving as both EENTER and AEP (ERESUME) */
61 .Lasync_exit_pointer:
62 .Lenclu_eenter_eresume:
63         enclu
65         /* EEXIT jumps here unless the enclave is doing something fancy. */
66         mov     SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx
68         /* Set exit_reason. */
69         movl    $EEXIT, SGX_ENCLAVE_RUN_LEAF(%rbx)
71         /* Invoke userspace's exit handler if one was provided. */
72 .Lhandle_exit:
73         cmpq    $0, SGX_ENCLAVE_RUN_USER_HANDLER(%rbx)
74         jne     .Linvoke_userspace_handler
76         /* Success, in the sense that ENCLU was attempted. */
77         xor     %eax, %eax
79 .Lout:
80         pop     %rbx
81         leave
82         .cfi_def_cfa            %rsp, 8
83         RET
85         /* The out-of-line code runs with the pre-leave stack frame. */
86         .cfi_def_cfa            %rbp, 16
88 .Linvalid_input:
89         mov     $(-EINVAL), %eax
90         jmp     .Lout
92 .Lhandle_exception:
93         mov     SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx
95         /* Set the exception info. */
96         mov     %eax, (SGX_ENCLAVE_RUN_LEAF)(%rbx)
97         mov     %di,  (SGX_ENCLAVE_RUN_EXCEPTION_VECTOR)(%rbx)
98         mov     %si,  (SGX_ENCLAVE_RUN_EXCEPTION_ERROR_CODE)(%rbx)
99         mov     %rdx, (SGX_ENCLAVE_RUN_EXCEPTION_ADDR)(%rbx)
100         jmp     .Lhandle_exit
102 .Linvoke_userspace_handler:
103         /* Pass the untrusted RSP (at exit) to the callback via %rcx. */
104         mov     %rsp, %rcx
106         /* Save struct sgx_enclave_exception %rbx is about to be clobbered. */
107         mov     %rbx, %rax
109         /* Save the untrusted RSP offset in %rbx (non-volatile register). */
110         mov     %rsp, %rbx
111         and     $0xf, %rbx
113         /*
114          * Align stack per x86_64 ABI. Note, %rsp needs to be 16-byte aligned
115          * _after_ pushing the parameters on the stack, hence the bonus push.
116          */
117         and     $-0x10, %rsp
118         push    %rax
120         /* Push struct sgx_enclave_exception as a param to the callback. */
121         push    %rax
123         /* Clear RFLAGS.DF per x86_64 ABI */
124         cld
126         /*
127          * Load the callback pointer to %rax and lfence for LVI (load value
128          * injection) protection before making the call.
129          */
130         mov     SGX_ENCLAVE_RUN_USER_HANDLER(%rax), %rax
131         lfence
132         call    *%rax
134         /* Undo the post-exit %rsp adjustment. */
135         lea     0x10(%rsp, %rbx), %rsp
137         /*
138          * If the return from callback is zero or negative, return immediately,
139          * else re-execute ENCLU with the positive return value interpreted as
140          * the requested ENCLU function.
141          */
142         cmp     $0, %eax
143         jle     .Lout
144         jmp     .Lenter_enclave
146         .cfi_endproc
148 _ASM_VDSO_EXTABLE_HANDLE(.Lenclu_eenter_eresume, .Lhandle_exception)
150 SYM_FUNC_END(__vdso_sgx_enter_enclave)