1 /* This symbol is used at runtime to figure out the virtual address that the */
2 /* enclave is loaded at. */
8 /* The XSAVE area needs to be a large chunk of readable memory, but since we are */
9 /* going to restore everything to its initial state (XSTATE_BV=0), only certain */
10 /* parts need to have a defined value. In particular: */
12 /* * MXCSR in the legacy area. This register is always restored if RFBM[1] or */
13 /* RFBM[2] is set, regardless of the value of XSTATE_BV */
21 /* We can store a bunch of data in the gap between MXCSR and the XSAVE header */
23 /* The following symbols point at read-only data that will be filled in by the */
26 /* When using this macro, don't forget to adjust the linker version script! */
27 .macro globvar name:req size:req
35 /* The base address (relative to enclave start) of the heap area */
37 /* The heap size in bytes */
39 /* Value of the RELA entry in the dynamic table */
41 /* Value of the RELACOUNT entry in the dynamic table */
43 /* The enclave size in bytes */
44 globvar ENCLAVE_SIZE 8
45 /* The base address (relative to enclave start) of the enclave configuration area */
46 globvar CFGDATA_BASE 8
47 /* Non-zero if debugging is enabled, zero otherwise */
49 /* The base address (relative to enclave start) of the enclave text section */
51 /* The size in bytes of enclacve text section */
53 /* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */
54 globvar EH_FRM_HDR_BASE 8
55 /* The size in bytes of enclacve EH_FRM_HDR section */
56 globvar EH_FRM_HDR_SIZE 8
59 .asciz "Re-entered panicked enclave!"
60 .Lreentry_panic_msg_end:
63 .asciz "Invalid usercall#!"
64 .Lusercall_panic_msg_end:
66 .org .Lxsave_clear+512
68 .int 0, 0 /* XSTATE_BV */
69 .int 0, 0 /* XCOMP_BV */
70 .org .+48 /* reserved bits */
76 /* TCS local storage section */
77 .equ tcsls_tos, 0x00 /* initialized by loader to *offset* from image base to TOS */
78 .equ tcsls_flags, 0x08 /* initialized by loader */
79 .equ tcsls_flag_secondary, 0 /* initialized by loader; 0 = standard TCS, 1 = secondary TCS */
80 .equ tcsls_flag_init_once, 1 /* initialized by loader to 0 */
82 .equ tcsls_user_fcw, 0x0a
83 .equ tcsls_user_mxcsr, 0x0c
84 .equ tcsls_last_rsp, 0x10 /* initialized by loader to 0 */
85 .equ tcsls_panic_last_rsp, 0x18 /* initialized by loader to 0 */
86 .equ tcsls_debug_panic_buf_ptr, 0x20 /* initialized by loader to 0 */
87 .equ tcsls_user_rsp, 0x28
88 .equ tcsls_user_retip, 0x30
89 .equ tcsls_user_rbp, 0x38
90 .equ tcsls_user_r12, 0x40
91 .equ tcsls_user_r13, 0x48
92 .equ tcsls_user_r14, 0x50
93 .equ tcsls_user_r15, 0x58
94 .equ tcsls_tls_ptr, 0x60
95 .equ tcsls_tcs_addr, 0x68
97 .macro load_tcsls_flag_secondary_bool reg:req comments:vararg
98 .ifne tcsls_flag_secondary /* to convert to a bool, must be the first bit */
101 mov $(1<<tcsls_flag_secondary),%e\reg
102 and %gs:tcsls_flags,%\reg
107 .type sgx_entry,function
109 /* save user registers */
110 mov %rcx,%gs:tcsls_user_retip
111 mov %rsp,%gs:tcsls_user_rsp
112 mov %rbp,%gs:tcsls_user_rbp
113 mov %r12,%gs:tcsls_user_r12
114 mov %r13,%gs:tcsls_user_r13
115 mov %r14,%gs:tcsls_user_r14
116 mov %r15,%gs:tcsls_user_r15
117 mov %rbx,%gs:tcsls_tcs_addr
118 stmxcsr %gs:tcsls_user_mxcsr
119 fnstcw %gs:tcsls_user_fcw
120 /* reset user state */
121 cld /* x86-64 ABI requires DF to be unset at function entry/exit */
122 /* check for debug buffer pointer */
123 testb $0xff,DEBUG(%rip)
125 mov %r10,%gs:tcsls_debug_panic_buf_ptr
127 /* check if returning from usercall */
128 mov %gs:tcsls_last_rsp,%r11
132 mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
133 /* here. This is fixed below under "adjust stack". */
134 /* check for thread init */
135 bts $tcsls_flag_init_once,%gs:tcsls_flags
138 lea IMAGE_BASE(%rip),%rax
140 mov %rsp,%gs:tcsls_tos
142 /* store caller-saved registers in callee-saved registers */
148 load_tcsls_flag_secondary_bool di /* RDI = tcs_init() argument: secondary: bool */
150 /* reload caller-saved registers */
157 /* check for panic */
158 bt $0,.Lpanicked(%rip)
160 /* call into main entry point */
161 load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */
162 call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */
163 mov %rax,%rsi /* RSI = return value */
164 /* NOP: mov %rdx,%rdx */ /* RDX = return value */
165 xor %rdi,%rdi /* RDI = normal exit */
167 /* clear general purpose register state */
168 /* RAX overwritten by ENCLU */
170 /* RCX overwritten by ENCLU */
171 /* RDX contains return value */
174 /* RDI contains exit mode */
175 /* RSI contains return value */
180 /* R12 ~ R15 set by sgx_exit */
182 /* clear extended register state */
183 mov %rdx, %rcx /* save RDX */
186 xrstor .Lxsave_clear(%rip)
187 mov %rcx, %rdx /* restore RDX */
191 /* restore user registers */
192 mov %gs:tcsls_user_r12,%r12
193 mov %gs:tcsls_user_r13,%r13
194 mov %gs:tcsls_user_r14,%r14
195 mov %gs:tcsls_user_r15,%r15
196 mov %gs:tcsls_user_retip,%rbx
197 mov %gs:tcsls_user_rsp,%rsp
198 mov %gs:tcsls_user_rbp,%rbp
199 fldcw %gs:tcsls_user_fcw
200 ldmxcsr %gs:tcsls_user_mxcsr
202 mov $0x4,%eax /* EEXIT */
207 lea .Lreentry_panic_msg(%rip),%rdi
208 mov $.Lreentry_panic_msg_end-.Lreentry_panic_msg,%esi
213 lea .Lusercall_panic_msg(%rip),%rdi
214 mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi
218 .macro push_callee_saved_registers
232 /* save registers in DEBUG mode, so that debugger can reconstruct the stack */
233 testb $0xff,DEBUG(%rip)
234 jz .Lskip_save_registers
235 push_callee_saved_registers
236 movq %rsp,%gs:tcsls_panic_last_rsp
237 .Lskip_save_registers:
238 /* set panicked bit */
239 movb $1,.Lpanicked(%rip)
240 /* call usercall exit(true) */
241 mov $1,%esi /* RSI = usercall() argument: panic = true */
242 xor %rdx,%rdx /* RDX cleared */
243 movq $usercall_nr_exit,%rdi /* RDI = usercall exit */
246 /* This *MUST* be called with 6 parameters, otherwise register information */
252 /* save callee-saved state */
253 push_callee_saved_registers
254 movq %rsp,%gs:tcsls_last_rsp
255 /* clear general purpose register state */
256 /* RAX overwritten by ENCLU */
257 /* RBX set by sgx_exit */
258 /* RCX overwritten by ENCLU */
259 /* RDX contains parameter */
260 /* RSP set by sgx_exit */
261 /* RBP set by sgx_exit */
262 /* RDI contains parameter */
263 /* RSI contains parameter */
264 /* R8 contains parameter */
265 /* R9 contains parameter */
268 /* R12 ~ R15 set by sgx_exit */
269 /* extended registers/flags cleared by sgx_exit */
273 movq $0,%gs:tcsls_last_rsp
274 /* restore callee-saved state, cf. push_callee_saved_registers */
286 mov %rsi,%rax /* RAX = return value */
287 /* NOP: mov %rdx,%rdx */ /* RDX = return value */
291 The following functions need to be defined externally:
293 // Called by entry code when it needs to panic
294 extern "C" fn panic_msg(msg: &'static str) -> ! {
298 // Called once when a TCS is first entered
299 extern "C" fn tcs_init(secondary: bool);
301 // Standard TCS entrypoint
302 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64);
308 mov %gs:tcsls_tcs_addr,%rax
313 mov %gs:tcsls_tls_ptr,%rax
318 mov %rdi,%gs:tcsls_tls_ptr
321 .global take_debug_panic_buf_ptr
322 take_debug_panic_buf_ptr:
324 xchg %gs:tcsls_debug_panic_buf_ptr,%rax