]> Git Repo - J-linux.git/blob - arch/x86/kernel/cpu/sgx/encls.h
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / arch / x86 / kernel / cpu / sgx / encls.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _X86_ENCLS_H
3 #define _X86_ENCLS_H
4
5 #include <linux/bitops.h>
6 #include <linux/err.h>
7 #include <linux/io.h>
8 #include <linux/rwsem.h>
9 #include <linux/types.h>
10 #include <asm/asm.h>
11 #include <asm/traps.h>
12 #include "sgx.h"
13
14 /* Retrieve the encoded trapnr from the specified return code. */
15 #define ENCLS_TRAPNR(r) ((r) & ~SGX_ENCLS_FAULT_FLAG)
16
17 /* Issue a WARN() about an ENCLS function. */
18 #define ENCLS_WARN(r, name) {                                             \
19         do {                                                              \
20                 int _r = (r);                                             \
21                 WARN_ONCE(_r, "%s returned %d (0x%x)\n", (name), _r, _r); \
22         } while (0);                                                      \
23 }
24
25 /*
26  * encls_faulted() - Check if an ENCLS leaf faulted given an error code
27  * @ret:        the return value of an ENCLS leaf function call
28  *
29  * Return:
30  * - true:      ENCLS leaf faulted.
31  * - false:     Otherwise.
32  */
33 static inline bool encls_faulted(int ret)
34 {
35         return ret & SGX_ENCLS_FAULT_FLAG;
36 }
37
38 /**
39  * encls_failed() - Check if an ENCLS function failed
40  * @ret:        the return value of an ENCLS function call
41  *
42  * Check if an ENCLS function failed. This happens when the function causes a
43  * fault that is not caused by an EPCM conflict or when the function returns a
44  * non-zero value.
45  */
46 static inline bool encls_failed(int ret)
47 {
48         if (encls_faulted(ret))
49                 return ENCLS_TRAPNR(ret) != X86_TRAP_PF;
50
51         return !!ret;
52 }
53
54 /**
55  * __encls_ret_N - encode an ENCLS function that returns an error code in EAX
56  * @rax:        function number
57  * @inputs:     asm inputs for the function
58  *
59  * Emit assembly for an ENCLS function that returns an error code, e.g. EREMOVE.
60  * And because SGX isn't complex enough as it is, function that return an error
61  * code also modify flags.
62  *
63  * Return:
64  *      0 on success,
65  *      SGX error code on failure
66  */
67 #define __encls_ret_N(rax, inputs...)                           \
68         ({                                                      \
69         int ret;                                                \
70         asm volatile(                                           \
71         "1: .byte 0x0f, 0x01, 0xcf;\n\t"                        \
72         "2:\n"                                                  \
73         _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_SGX)            \
74         : "=a"(ret)                                             \
75         : "a"(rax), inputs                                      \
76         : "memory", "cc");                                      \
77         ret;                                                    \
78         })
79
80 #define __encls_ret_1(rax, rcx)         \
81         ({                              \
82         __encls_ret_N(rax, "c"(rcx));   \
83         })
84
85 #define __encls_ret_2(rax, rbx, rcx)            \
86         ({                                      \
87         __encls_ret_N(rax, "b"(rbx), "c"(rcx)); \
88         })
89
90 #define __encls_ret_3(rax, rbx, rcx, rdx)                       \
91         ({                                                      \
92         __encls_ret_N(rax, "b"(rbx), "c"(rcx), "d"(rdx));       \
93         })
94
95 /**
96  * __encls_N - encode an ENCLS function that doesn't return an error code
97  * @rax:        function number
98  * @rbx_out:    optional output variable
99  * @inputs:     asm inputs for the function
100  *
101  * Emit assembly for an ENCLS function that does not return an error code, e.g.
102  * ECREATE.  Leaves without error codes either succeed or fault.  @rbx_out is an
103  * optional parameter for use by EDGBRD, which returns the requested value in
104  * RBX.
105  *
106  * Return:
107  *   0 on success,
108  *   trapnr with SGX_ENCLS_FAULT_FLAG set on fault
109  */
110 #define __encls_N(rax, rbx_out, inputs...)                      \
111         ({                                                      \
112         int ret;                                                \
113         asm volatile(                                           \
114         "1: .byte 0x0f, 0x01, 0xcf;\n\t"                        \
115         "   xor %%eax,%%eax;\n"                                 \
116         "2:\n"                                                  \
117         _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_SGX)            \
118         : "=a"(ret), "=b"(rbx_out)                              \
119         : "a"(rax), inputs                                      \
120         : "memory");                                            \
121         ret;                                                    \
122         })
123
124 #define __encls_2(rax, rbx, rcx)                                \
125         ({                                                      \
126         unsigned long ign_rbx_out;                              \
127         __encls_N(rax, ign_rbx_out, "b"(rbx), "c"(rcx));        \
128         })
129
130 #define __encls_1_1(rax, data, rcx)                     \
131         ({                                              \
132         unsigned long rbx_out;                          \
133         int ret = __encls_N(rax, rbx_out, "c"(rcx));    \
134         if (!ret)                                       \
135                 data = rbx_out;                         \
136         ret;                                            \
137         })
138
139 /* Initialize an EPC page into an SGX Enclave Control Structure (SECS) page. */
140 static inline int __ecreate(struct sgx_pageinfo *pginfo, void *secs)
141 {
142         return __encls_2(ECREATE, pginfo, secs);
143 }
144
145 /* Hash a 256 byte region of an enclave page to SECS:MRENCLAVE. */
146 static inline int __eextend(void *secs, void *addr)
147 {
148         return __encls_2(EEXTEND, secs, addr);
149 }
150
151 /*
152  * Associate an EPC page to an enclave either as a REG or TCS page
153  * populated with the provided data.
154  */
155 static inline int __eadd(struct sgx_pageinfo *pginfo, void *addr)
156 {
157         return __encls_2(EADD, pginfo, addr);
158 }
159
160 /* Finalize enclave build, initialize enclave for user code execution. */
161 static inline int __einit(void *sigstruct, void *token, void *secs)
162 {
163         return __encls_ret_3(EINIT, sigstruct, secs, token);
164 }
165
166 /* Disassociate EPC page from its enclave and mark it as unused. */
167 static inline int __eremove(void *addr)
168 {
169         return __encls_ret_1(EREMOVE, addr);
170 }
171
172 /* Copy data to an EPC page belonging to a debug enclave. */
173 static inline int __edbgwr(void *addr, unsigned long *data)
174 {
175         return __encls_2(EDGBWR, *data, addr);
176 }
177
178 /* Copy data from an EPC page belonging to a debug enclave. */
179 static inline int __edbgrd(void *addr, unsigned long *data)
180 {
181         return __encls_1_1(EDGBRD, *data, addr);
182 }
183
184 /* Track that software has completed the required TLB address clears. */
185 static inline int __etrack(void *addr)
186 {
187         return __encls_ret_1(ETRACK, addr);
188 }
189
190 /* Load, verify, and unblock an EPC page. */
191 static inline int __eldu(struct sgx_pageinfo *pginfo, void *addr,
192                          void *va)
193 {
194         return __encls_ret_3(ELDU, pginfo, addr, va);
195 }
196
197 /* Make EPC page inaccessible to enclave, ready to be written to memory. */
198 static inline int __eblock(void *addr)
199 {
200         return __encls_ret_1(EBLOCK, addr);
201 }
202
203 /* Initialize an EPC page into a Version Array (VA) page. */
204 static inline int __epa(void *addr)
205 {
206         unsigned long rbx = SGX_PAGE_TYPE_VA;
207
208         return __encls_2(EPA, rbx, addr);
209 }
210
211 /* Invalidate an EPC page and write it out to main memory. */
212 static inline int __ewb(struct sgx_pageinfo *pginfo, void *addr,
213                         void *va)
214 {
215         return __encls_ret_3(EWB, pginfo, addr, va);
216 }
217
218 /* Restrict the EPCM permissions of an EPC page. */
219 static inline int __emodpr(struct sgx_secinfo *secinfo, void *addr)
220 {
221         return __encls_ret_2(EMODPR, secinfo, addr);
222 }
223
224 /* Change the type of an EPC page. */
225 static inline int __emodt(struct sgx_secinfo *secinfo, void *addr)
226 {
227         return __encls_ret_2(EMODT, secinfo, addr);
228 }
229
230 /* Zero a page of EPC memory and add it to an initialized enclave. */
231 static inline int __eaug(struct sgx_pageinfo *pginfo, void *addr)
232 {
233         return __encls_2(EAUG, pginfo, addr);
234 }
235
236 #endif /* _X86_ENCLS_H */
This page took 0.040952 seconds and 4 git commands to generate.