| 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ |
| 2 | /* |
| 3 | * Copyright(c) 2016-20 Intel Corporation. |
| 4 | */ |
| 5 | #ifndef _UAPI_ASM_X86_SGX_H |
| 6 | #define _UAPI_ASM_X86_SGX_H |
| 7 | |
| 8 | #include <linux/types.h> |
| 9 | #include <linux/ioctl.h> |
| 10 | |
| 11 | /** |
| 12 | * enum sgx_page_flags - page control flags |
| 13 | * @SGX_PAGE_MEASURE: Measure the page contents with a sequence of |
| 14 | * ENCLS[EEXTEND] operations. |
| 15 | */ |
| 16 | enum sgx_page_flags { |
| 17 | SGX_PAGE_MEASURE = 0x01, |
| 18 | }; |
| 19 | |
| 20 | #define SGX_MAGIC 0xA4 |
| 21 | |
| 22 | #define SGX_IOC_ENCLAVE_CREATE \ |
| 23 | _IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create) |
| 24 | #define SGX_IOC_ENCLAVE_ADD_PAGES \ |
| 25 | _IOWR(SGX_MAGIC, 0x01, struct sgx_enclave_add_pages) |
| 26 | #define SGX_IOC_ENCLAVE_INIT \ |
| 27 | _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init) |
| 28 | #define SGX_IOC_ENCLAVE_PROVISION \ |
| 29 | _IOW(SGX_MAGIC, 0x03, struct sgx_enclave_provision) |
| 30 | #define SGX_IOC_VEPC_REMOVE_ALL \ |
| 31 | _IO(SGX_MAGIC, 0x04) |
| 32 | #define SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS \ |
| 33 | _IOWR(SGX_MAGIC, 0x05, struct sgx_enclave_restrict_permissions) |
| 34 | #define SGX_IOC_ENCLAVE_MODIFY_TYPES \ |
| 35 | _IOWR(SGX_MAGIC, 0x06, struct sgx_enclave_modify_types) |
| 36 | #define SGX_IOC_ENCLAVE_REMOVE_PAGES \ |
| 37 | _IOWR(SGX_MAGIC, 0x07, struct sgx_enclave_remove_pages) |
| 38 | |
| 39 | /** |
| 40 | * struct sgx_enclave_create - parameter structure for the |
| 41 | * %SGX_IOC_ENCLAVE_CREATE ioctl |
| 42 | * @src: address for the SECS page data |
| 43 | */ |
| 44 | struct sgx_enclave_create { |
| 45 | __u64 src; |
| 46 | }; |
| 47 | |
| 48 | /** |
| 49 | * struct sgx_enclave_add_pages - parameter structure for the |
| 50 | * %SGX_IOC_ENCLAVE_ADD_PAGE ioctl |
| 51 | * @src: start address for the page data |
| 52 | * @offset: starting page offset |
| 53 | * @length: length of the data (multiple of the page size) |
| 54 | * @secinfo: address for the SECINFO data |
| 55 | * @flags: page control flags |
| 56 | * @count: number of bytes added (multiple of the page size) |
| 57 | */ |
| 58 | struct sgx_enclave_add_pages { |
| 59 | __u64 src; |
| 60 | __u64 offset; |
| 61 | __u64 length; |
| 62 | __u64 secinfo; |
| 63 | __u64 flags; |
| 64 | __u64 count; |
| 65 | }; |
| 66 | |
| 67 | /** |
| 68 | * struct sgx_enclave_init - parameter structure for the |
| 69 | * %SGX_IOC_ENCLAVE_INIT ioctl |
| 70 | * @sigstruct: address for the SIGSTRUCT data |
| 71 | */ |
| 72 | struct sgx_enclave_init { |
| 73 | __u64 sigstruct; |
| 74 | }; |
| 75 | |
| 76 | /** |
| 77 | * struct sgx_enclave_provision - parameter structure for the |
| 78 | * %SGX_IOC_ENCLAVE_PROVISION ioctl |
| 79 | * @fd: file handle of /dev/sgx_provision |
| 80 | */ |
| 81 | struct sgx_enclave_provision { |
| 82 | __u64 fd; |
| 83 | }; |
| 84 | |
| 85 | /** |
| 86 | * struct sgx_enclave_restrict_permissions - parameters for ioctl |
| 87 | * %SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS |
| 88 | * @offset: starting page offset (page aligned relative to enclave base |
| 89 | * address defined in SECS) |
| 90 | * @length: length of memory (multiple of the page size) |
| 91 | * @permissions:new permission bits for pages in range described by @offset |
| 92 | * and @length |
| 93 | * @result: (output) SGX result code of ENCLS[EMODPR] function |
| 94 | * @count: (output) bytes successfully changed (multiple of page size) |
| 95 | */ |
| 96 | struct sgx_enclave_restrict_permissions { |
| 97 | __u64 offset; |
| 98 | __u64 length; |
| 99 | __u64 permissions; |
| 100 | __u64 result; |
| 101 | __u64 count; |
| 102 | }; |
| 103 | |
| 104 | /** |
| 105 | * struct sgx_enclave_modify_types - parameters for ioctl |
| 106 | * %SGX_IOC_ENCLAVE_MODIFY_TYPES |
| 107 | * @offset: starting page offset (page aligned relative to enclave base |
| 108 | * address defined in SECS) |
| 109 | * @length: length of memory (multiple of the page size) |
| 110 | * @page_type: new type for pages in range described by @offset and @length |
| 111 | * @result: (output) SGX result code of ENCLS[EMODT] function |
| 112 | * @count: (output) bytes successfully changed (multiple of page size) |
| 113 | */ |
| 114 | struct sgx_enclave_modify_types { |
| 115 | __u64 offset; |
| 116 | __u64 length; |
| 117 | __u64 page_type; |
| 118 | __u64 result; |
| 119 | __u64 count; |
| 120 | }; |
| 121 | |
| 122 | /** |
| 123 | * struct sgx_enclave_remove_pages - %SGX_IOC_ENCLAVE_REMOVE_PAGES parameters |
| 124 | * @offset: starting page offset (page aligned relative to enclave base |
| 125 | * address defined in SECS) |
| 126 | * @length: length of memory (multiple of the page size) |
| 127 | * @count: (output) bytes successfully changed (multiple of page size) |
| 128 | * |
| 129 | * Regular (PT_REG) or TCS (PT_TCS) can be removed from an initialized |
| 130 | * enclave if the system supports SGX2. First, the %SGX_IOC_ENCLAVE_MODIFY_TYPES |
| 131 | * ioctl() should be used to change the page type to PT_TRIM. After that |
| 132 | * succeeds ENCLU[EACCEPT] should be run from within the enclave and then |
| 133 | * %SGX_IOC_ENCLAVE_REMOVE_PAGES can be used to complete the page removal. |
| 134 | */ |
| 135 | struct sgx_enclave_remove_pages { |
| 136 | __u64 offset; |
| 137 | __u64 length; |
| 138 | __u64 count; |
| 139 | }; |
| 140 | |
| 141 | struct sgx_enclave_run; |
| 142 | |
| 143 | /** |
| 144 | * typedef sgx_enclave_user_handler_t - Exit handler function accepted by |
| 145 | * __vdso_sgx_enter_enclave() |
| 146 | * @rdi: RDI at the time of EEXIT, undefined on AEX |
| 147 | * @rsi: RSI at the time of EEXIT, undefined on AEX |
| 148 | * @rdx: RDX at the time of EEXIT, undefined on AEX |
| 149 | * @rsp: RSP (untrusted) at the time of EEXIT or AEX |
| 150 | * @r8: R8 at the time of EEXIT, undefined on AEX |
| 151 | * @r9: R9 at the time of EEXIT, undefined on AEX |
| 152 | * @run: The run instance given by the caller |
| 153 | * |
| 154 | * The register parameters contain the snapshot of their values at enclave |
| 155 | * exit. An invalid ENCLU function number will cause -EINVAL to be returned |
| 156 | * to the caller. |
| 157 | * |
| 158 | * Return: |
| 159 | * - <= 0: The given value is returned back to the caller. |
| 160 | * - > 0: ENCLU function to invoke, either EENTER or ERESUME. |
| 161 | */ |
| 162 | typedef int (*sgx_enclave_user_handler_t)(long rdi, long rsi, long rdx, |
| 163 | long rsp, long r8, long r9, |
| 164 | struct sgx_enclave_run *run); |
| 165 | |
| 166 | /** |
| 167 | * struct sgx_enclave_run - the execution context of __vdso_sgx_enter_enclave() |
| 168 | * @tcs: TCS used to enter the enclave |
| 169 | * @function: The last seen ENCLU function (EENTER, ERESUME or EEXIT) |
| 170 | * @exception_vector: The interrupt vector of the exception |
| 171 | * @exception_error_code: The exception error code pulled out of the stack |
| 172 | * @exception_addr: The address that triggered the exception |
| 173 | * @user_handler: User provided callback run on exception |
| 174 | * @user_data: Data passed to the user handler |
| 175 | * @reserved: Reserved for future extensions |
| 176 | * |
| 177 | * If @user_handler is provided, the handler will be invoked on all return paths |
| 178 | * of the normal flow. The user handler may transfer control, e.g. via a |
| 179 | * longjmp() call or a C++ exception, without returning to |
| 180 | * __vdso_sgx_enter_enclave(). |
| 181 | */ |
| 182 | struct sgx_enclave_run { |
| 183 | __u64 tcs; |
| 184 | __u32 function; |
| 185 | __u16 exception_vector; |
| 186 | __u16 exception_error_code; |
| 187 | __u64 exception_addr; |
| 188 | __u64 user_handler; |
| 189 | __u64 user_data; |
| 190 | __u8 reserved[216]; |
| 191 | }; |
| 192 | |
| 193 | /** |
| 194 | * typedef vdso_sgx_enter_enclave_t - Prototype for __vdso_sgx_enter_enclave(), |
| 195 | * a vDSO function to enter an SGX enclave. |
| 196 | * @rdi: Pass-through value for RDI |
| 197 | * @rsi: Pass-through value for RSI |
| 198 | * @rdx: Pass-through value for RDX |
| 199 | * @function: ENCLU function, must be EENTER or ERESUME |
| 200 | * @r8: Pass-through value for R8 |
| 201 | * @r9: Pass-through value for R9 |
| 202 | * @run: struct sgx_enclave_run, must be non-NULL |
| 203 | * |
| 204 | * NOTE: __vdso_sgx_enter_enclave() does not ensure full compliance with the |
| 205 | * x86-64 ABI, e.g. doesn't handle XSAVE state. Except for non-volatile |
| 206 | * general purpose registers, EFLAGS.DF, and RSP alignment, preserving/setting |
| 207 | * state in accordance with the x86-64 ABI is the responsibility of the enclave |
| 208 | * and its runtime, i.e. __vdso_sgx_enter_enclave() cannot be called from C |
| 209 | * code without careful consideration by both the enclave and its runtime. |
| 210 | * |
| 211 | * All general purpose registers except RAX, RBX and RCX are passed as-is to the |
| 212 | * enclave. RAX, RBX and RCX are consumed by EENTER and ERESUME and are loaded |
| 213 | * with @function, asynchronous exit pointer, and @run.tcs respectively. |
| 214 | * |
| 215 | * RBP and the stack are used to anchor __vdso_sgx_enter_enclave() to the |
| 216 | * pre-enclave state, e.g. to retrieve @run.exception and @run.user_handler |
| 217 | * after an enclave exit. All other registers are available for use by the |
| 218 | * enclave and its runtime, e.g. an enclave can push additional data onto the |
| 219 | * stack (and modify RSP) to pass information to the optional user handler (see |
| 220 | * below). |
| 221 | * |
| 222 | * Most exceptions reported on ENCLU, including those that occur within the |
| 223 | * enclave, are fixed up and reported synchronously instead of being delivered |
| 224 | * via a standard signal. Debug Exceptions (#DB) and Breakpoints (#BP) are |
| 225 | * never fixed up and are always delivered via standard signals. On synchronously |
| 226 | * reported exceptions, -EFAULT is returned and details about the exception are |
| 227 | * recorded in @run.exception, the optional sgx_enclave_exception struct. |
| 228 | * |
| 229 | * Return: |
| 230 | * - 0: ENCLU function was successfully executed. |
| 231 | * - -EINVAL: Invalid ENCL number (neither EENTER nor ERESUME). |
| 232 | */ |
| 233 | typedef int (*vdso_sgx_enter_enclave_t)(unsigned long rdi, unsigned long rsi, |
| 234 | unsigned long rdx, unsigned int function, |
| 235 | unsigned long r8, unsigned long r9, |
| 236 | struct sgx_enclave_run *run); |
| 237 | |
| 238 | #endif /* _UAPI_ASM_X86_SGX_H */ |
| 239 | |