]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/entry.S
Rollup merge of #56425 - scottmcm:redo-vec-set_len-docs, r=Centril
[rust.git] / src / libstd / sys / sgx / abi / entry.S
1 /*  This symbol is used at runtime to figure out the virtual address that the */
2 /*  enclave is loaded at. */
3 .section absolute
4 .global IMAGE_BASE
5 IMAGE_BASE:
6
7 .section .rodata
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: */
11 /*  */
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 */
14 /*    * XSAVE header */
15 .align 64
16 .Lxsave_clear:
17 .org .+24
18 .Lxsave_mxcsr:
19     .int 0
20
21 /*  We can store a bunch of data in the gap between MXCSR and the XSAVE header */
22
23 /*  The following symbols point at read-only data that will be filled in by the */
24 /*  post-linker. */
25
26 /*  When using this macro, don't forget to adjust the linker version script! */
27 .macro globvar name:req size:req
28     .global \name
29     .protected \name
30     .align \size
31     .size \name , \size
32     \name :
33         .org .+\size
34 .endm
35     /*  The base address (relative to enclave start) of the heap area */
36     globvar HEAP_BASE 8
37     /*  The heap size in bytes */
38     globvar HEAP_SIZE 8
39     /*  Value of the RELA entry in the dynamic table */
40     globvar RELA 8
41     /*  Value of the RELACOUNT entry in the dynamic table */
42     globvar RELACOUNT 8
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 */
48     globvar DEBUG 1
49     /*  The base address (relative to enclave start) of the enclave text section */
50     globvar TEXT_BASE 8
51     /*  The size in bytes of enclacve text section */
52     globvar TEXT_SIZE 8
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
57
58 .Lreentry_panic_msg:
59     .asciz "Re-entered panicked enclave!"
60 .Lreentry_panic_msg_end:
61
62 .Lusercall_panic_msg:
63     .asciz "Invalid usercall#!"
64 .Lusercall_panic_msg_end:
65
66 .org .Lxsave_clear+512
67 .Lxsave_header:
68     .int 0, 0 /*  XSTATE_BV */
69     .int 0, 0 /*  XCOMP_BV */
70     .org .+48 /*  reserved bits */
71
72 .data
73 .Lpanicked:
74     .byte 0
75
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 */
81 /*  14 unused bits */
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
96
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 */
99     .abort
100     .endif
101         mov $(1<<tcsls_flag_secondary),%e\reg
102         and %gs:tcsls_flags,%\reg
103 .endm
104
105 .text
106 .global sgx_entry
107 .type sgx_entry,function
108 sgx_entry:
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)
124     jz .Lskip_debug_init
125     mov %r10,%gs:tcsls_debug_panic_buf_ptr
126 .Lskip_debug_init:
127 /*  check if returning from usercall */
128     mov %gs:tcsls_last_rsp,%r11
129     test %r11,%r11
130     jnz .Lusercall_ret
131 /*  setup stack */
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
136     jc .Lskip_init
137 /*  adjust stack */
138     lea IMAGE_BASE(%rip),%rax
139     add %rax,%rsp
140     mov %rsp,%gs:tcsls_tos
141 /*  call tcs_init */
142 /*  store caller-saved registers in callee-saved registers */
143     mov %rdi,%rbx
144     mov %rsi,%r12
145     mov %rdx,%r13
146     mov %r8,%r14
147     mov %r9,%r15
148     load_tcsls_flag_secondary_bool di /* RDI = tcs_init() argument: secondary: bool */
149     call tcs_init
150 /*  reload caller-saved registers */
151     mov %rbx,%rdi
152     mov %r12,%rsi
153     mov %r13,%rdx
154     mov %r14,%r8
155     mov %r15,%r9
156 .Lskip_init:
157 /*  check for panic */
158     bt $0,.Lpanicked(%rip)
159     jc .Lreentry_panic
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 */
166 .Lexit:
167 /*  clear general purpose register state */
168     /*  RAX overwritten by ENCLU */
169     /*  RBX set later */
170     /*  RCX overwritten by ENCLU */
171     /*  RDX contains return value */
172     /*  RSP set later */
173     /*  RBP set later */
174     /*  RDI contains exit mode */
175     /*  RSI contains return value */
176     xor %r8,%r8
177     xor %r9,%r9
178     xor %r10,%r10
179     xor %r11,%r11
180     /*  R12 ~ R15 set by sgx_exit */
181 .Lsgx_exit:
182 /*  clear extended register state */
183     mov %rdx, %rcx /*  save RDX */
184     mov $-1, %rax
185     mov %rax, %rdx
186     xrstor .Lxsave_clear(%rip)
187     mov %rcx, %rdx /*  restore RDX */
188 /*  clear flags */
189     pushq $0
190     popfq
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
201 /*  exit enclave */
202     mov $0x4,%eax /*  EEXIT */
203     enclu
204 /*  end sgx_entry */
205
206 .Lreentry_panic:
207     lea .Lreentry_panic_msg(%rip),%rdi
208     mov $.Lreentry_panic_msg_end-.Lreentry_panic_msg,%esi
209     orq $8,%rsp
210     jmp panic_msg
211
212 .Lusercall_panic:
213     lea .Lusercall_panic_msg(%rip),%rdi
214     mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi
215     orq $8,%rsp
216     jmp panic_msg
217
218 .macro push_callee_saved_registers
219     push %r15
220     push %r14
221     push %r13
222     push %r12
223     push %rbp
224     push %rbx
225     sub $8, %rsp
226     fstcw 4(%rsp)
227     stmxcsr (%rsp)
228 .endm
229
230 .global panic_exit
231 panic_exit:
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 */
244     jmp .Lexit
245
246 /*  This *MUST* be called with 6 parameters, otherwise register information */
247 /*  might leak! */
248 .global usercall
249 usercall:
250     test %rdi,%rdi
251     jle .Lusercall_panic
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 */
266     xor %r10,%r10
267     xor %r11,%r11
268     /*  R12 ~ R15 set by sgx_exit */
269 /*  extended registers/flags cleared by sgx_exit */
270 /*  exit */
271     jmp .Lsgx_exit
272 .Lusercall_ret:
273     movq $0,%gs:tcsls_last_rsp
274 /*  restore callee-saved state, cf. push_callee_saved_registers */
275     mov %r11,%rsp
276     ldmxcsr (%rsp)
277     fldcw 4(%rsp)
278     add $8, %rsp
279     pop %rbx
280     pop %rbp
281     pop %r12
282     pop %r13
283     pop %r14
284     pop %r15
285 /*  return */
286     mov %rsi,%rax /*  RAX = return value */
287     /* NOP: mov %rdx,%rdx */ /*  RDX = return value */
288     ret
289
290 /*
291 The following functions need to be defined externally:
292 ```
293 // Called by entry code when it needs to panic
294 extern "C" fn panic_msg(msg: &'static str) -> ! {
295     panic!(msg)
296 }
297
298 // Called once when a TCS is first entered
299 extern "C" fn tcs_init(secondary: bool);
300
301 // Standard TCS entrypoint
302 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64);
303 ```
304 */
305
306 .global get_tcs_addr
307 get_tcs_addr:
308     mov %gs:tcsls_tcs_addr,%rax
309     ret
310
311 .global get_tls_ptr
312 get_tls_ptr:
313     mov %gs:tcsls_tls_ptr,%rax
314     ret
315
316 .global set_tls_ptr
317 set_tls_ptr:
318     mov %rdi,%gs:tcsls_tls_ptr
319     ret
320
321 .global take_debug_panic_buf_ptr
322 take_debug_panic_buf_ptr:
323     xor %rax,%rax
324     xchg %gs:tcsls_debug_panic_buf_ptr,%rax
325     ret