1 /* This symbol is used at runtime to figure out the virtual address that the */
2 /* enclave is loaded at. */
7 .section ".note.x86_64-fortanix-unknown-sgx", "", @note
9 .long 1f - 0f /* name length (not including padding) */
10 .long 3f - 2f /* desc length (not including padding) */
11 .long 1 /* type = NT_VERSION */
12 0: .asciz "toolchain-version" /* name */
14 2: .long 0 /* desc - toolchain version number, 32-bit LE */
18 /* The XSAVE area needs to be a large chunk of readable memory, but since we are */
19 /* going to restore everything to its initial state (XSTATE_BV=0), only certain */
20 /* parts need to have a defined value. In particular: */
22 /* * MXCSR in the legacy area. This register is always restored if RFBM[1] or */
23 /* RFBM[2] is set, regardless of the value of XSTATE_BV */
31 /* We can store a bunch of data in the gap between MXCSR and the XSAVE header */
33 /* MXCSR initialization value for ABI */
37 /* x87 FPU control word initialization value for ABI */
41 /* The following symbols point at read-only data that will be filled in by the */
44 /* When using this macro, don't forget to adjust the linker version script! */
45 .macro globvar name:req size:req
53 /* The base address (relative to enclave start) of the heap area */
55 /* The heap size in bytes */
57 /* Value of the RELA entry in the dynamic table */
59 /* Value of the RELACOUNT entry in the dynamic table */
61 /* The enclave size in bytes */
62 globvar ENCLAVE_SIZE 8
63 /* The base address (relative to enclave start) of the enclave configuration area */
64 globvar CFGDATA_BASE 8
65 /* Non-zero if debugging is enabled, zero otherwise */
67 /* The base address (relative to enclave start) of the enclave text section */
69 /* The size in bytes of enclacve text section */
71 /* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */
72 globvar EH_FRM_HDR_BASE 8
73 /* The size in bytes of enclacve EH_FRM_HDR section */
74 globvar EH_FRM_HDR_SIZE 8
76 .org .Lxsave_clear+512
78 .int 0, 0 /* XSTATE_BV */
79 .int 0, 0 /* XCOMP_BV */
80 .org .+48 /* reserved bits */
86 /* TCS local storage section */
87 .equ tcsls_tos, 0x00 /* initialized by loader to *offset* from image base to TOS */
88 .equ tcsls_flags, 0x08 /* initialized by loader */
89 .equ tcsls_flag_secondary, 0 /* initialized by loader; 0 = standard TCS, 1 = secondary TCS */
90 .equ tcsls_flag_init_once, 1 /* initialized by loader to 0 */
92 .equ tcsls_user_fcw, 0x0a
93 .equ tcsls_user_mxcsr, 0x0c
94 .equ tcsls_last_rsp, 0x10 /* initialized by loader to 0 */
95 .equ tcsls_panic_last_rsp, 0x18 /* initialized by loader to 0 */
96 .equ tcsls_debug_panic_buf_ptr, 0x20 /* initialized by loader to 0 */
97 .equ tcsls_user_rsp, 0x28
98 .equ tcsls_user_retip, 0x30
99 .equ tcsls_user_rbp, 0x38
100 .equ tcsls_user_r12, 0x40
101 .equ tcsls_user_r13, 0x48
102 .equ tcsls_user_r14, 0x50
103 .equ tcsls_user_r15, 0x58
104 .equ tcsls_tls_ptr, 0x60
105 .equ tcsls_tcs_addr, 0x68
107 .macro load_tcsls_flag_secondary_bool reg:req comments:vararg
108 .ifne tcsls_flag_secondary /* to convert to a bool, must be the first bit */
111 mov $(1<<tcsls_flag_secondary),%e\reg
112 and %gs:tcsls_flags,%\reg
115 /* We place the ELF entry point in a separate section so it can be removed by
117 .section .text_no_sgx, "ax"
118 .Lelf_entry_error_msg:
119 .ascii "Error: This file is an SGX enclave which cannot be executed as a standard Linux binary.\nSee the installation guide at https://edp.fortanix.com/docs/installation/guide/ on how to use 'cargo run' or follow the steps at https://edp.fortanix.com/docs/tasks/deployment/ for manual deployment.\n"
120 .Lelf_entry_error_msg_end:
123 .type elf_entry,function
125 /* print error message */
126 movq $2,%rdi /* write to stderr (fd 2) */
127 lea .Lelf_entry_error_msg(%rip),%rsi
128 movq $.Lelf_entry_error_msg_end-.Lelf_entry_error_msg,%rdx
130 movq $1,%rax /* write() syscall */
133 jle .Lelf_exit /* exit on error */
135 sub %rax,%rdx /* all chars written? */
139 movq $60,%rax /* exit() syscall */
140 movq $1,%rdi /* exit code 1 */
142 ud2 /* should not be reached */
145 /* This code needs to be called *after* the enclave stack has been setup. */
146 /* There are 3 places where this needs to happen, so this is put in a macro. */
147 .macro entry_sanitize_final
148 /* Sanitize rflags received from user */
149 /* - DF flag: x86-64 ABI requires DF to be unset at function entry/exit */
150 /* - AC flag: AEX on misaligned memory accesses leaks side channel info */
152 andq $~0x40400, (%rsp)
154 /* check for abort */
155 bt $0,.Laborted(%rip)
161 .type sgx_entry,function
163 /* save user registers */
164 mov %rcx,%gs:tcsls_user_retip
165 mov %rsp,%gs:tcsls_user_rsp
166 mov %rbp,%gs:tcsls_user_rbp
167 mov %r12,%gs:tcsls_user_r12
168 mov %r13,%gs:tcsls_user_r13
169 mov %r14,%gs:tcsls_user_r14
170 mov %r15,%gs:tcsls_user_r15
171 mov %rbx,%gs:tcsls_tcs_addr
172 stmxcsr %gs:tcsls_user_mxcsr
173 fnstcw %gs:tcsls_user_fcw
175 /* check for debug buffer pointer */
176 testb $0xff,DEBUG(%rip)
178 mov %r10,%gs:tcsls_debug_panic_buf_ptr
180 /* check if returning from usercall */
181 mov %gs:tcsls_last_rsp,%r11
184 /* reset user state */
185 ldmxcsr .Lmxcsr_init(%rip)
186 fldcw .Lfpucw_init(%rip)
188 mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
189 /* here. This is fixed below under "adjust stack". */
190 /* check for thread init */
191 bts $tcsls_flag_init_once,%gs:tcsls_flags
194 lea IMAGE_BASE(%rip),%rax
196 mov %rsp,%gs:tcsls_tos
199 /* store caller-saved registers in callee-saved registers */
205 load_tcsls_flag_secondary_bool di /* RDI = tcs_init() argument: secondary: bool */
207 /* reload caller-saved registers */
217 /* call into main entry point */
218 load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */
219 call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */
220 mov %rax,%rsi /* RSI = return value */
221 /* NOP: mov %rdx,%rdx */ /* RDX = return value */
222 xor %rdi,%rdi /* RDI = normal exit */
224 /* clear general purpose register state */
225 /* RAX overwritten by ENCLU */
227 /* RCX overwritten by ENCLU */
228 /* RDX contains return value */
231 /* RDI contains exit mode */
232 /* RSI contains return value */
237 /* R12 ~ R15 set by sgx_exit */
239 /* clear extended register state */
240 mov %rdx, %rcx /* save RDX */
243 xrstor .Lxsave_clear(%rip)
244 mov %rcx, %rdx /* restore RDX */
248 /* restore user registers */
249 mov %gs:tcsls_user_r12,%r12
250 mov %gs:tcsls_user_r13,%r13
251 mov %gs:tcsls_user_r14,%r14
252 mov %gs:tcsls_user_r15,%r15
253 mov %gs:tcsls_user_retip,%rbx
254 mov %gs:tcsls_user_rsp,%rsp
255 mov %gs:tcsls_user_rbp,%rbp
256 fldcw %gs:tcsls_user_fcw
257 ldmxcsr %gs:tcsls_user_mxcsr
259 mov $0x4,%eax /* EEXIT */
267 /* This *MUST* be called with 6 parameters, otherwise register information */
271 test %rcx,%rcx /* check `abort` function argument */
272 jnz .Lusercall_abort /* abort is set, jump to abort code (unlikely forward conditional) */
273 jmp .Lusercall_save_state /* non-aborting usercall */
275 /* set aborted bit */
276 movb $1,.Laborted(%rip)
277 /* save registers in DEBUG mode, so that debugger can reconstruct the stack */
278 testb $0xff,DEBUG(%rip)
279 jz .Lusercall_noreturn
280 .Lusercall_save_state:
281 /* save callee-saved state */
291 movq %rsp,%gs:tcsls_last_rsp
293 /* clear general purpose register state */
294 /* RAX overwritten by ENCLU */
295 /* RBX set by sgx_exit */
296 /* RCX overwritten by ENCLU */
297 /* RDX contains parameter */
298 /* RSP set by sgx_exit */
299 /* RBP set by sgx_exit */
300 /* RDI contains parameter */
301 /* RSI contains parameter */
302 /* R8 contains parameter */
303 /* R9 contains parameter */
306 /* R12 ~ R15 set by sgx_exit */
307 /* extended registers/flags cleared by sgx_exit */
311 movq $0,%gs:tcsls_last_rsp
312 /* restore callee-saved state, cf. "save" above */
325 mov %rsi,%rax /* RAX = return value */
326 /* NOP: mov %rdx,%rdx */ /* RDX = return value */
330 The following functions need to be defined externally:
332 // Called by entry code on re-entry after exit
333 extern "C" fn abort_reentry() -> !;
335 // Called once when a TCS is first entered
336 extern "C" fn tcs_init(secondary: bool);
338 // Standard TCS entrypoint
339 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64);
345 mov %gs:tcsls_tcs_addr,%rax
350 mov %gs:tcsls_tls_ptr,%rax
355 mov %rdi,%gs:tcsls_tls_ptr
358 .global take_debug_panic_buf_ptr
359 take_debug_panic_buf_ptr:
361 xchg %gs:tcsls_debug_panic_buf_ptr,%rax