2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 * The MacOS assembler has a macro facility that is pretty close
9 * to GNU as macros, but not quite the same.
11 #if NACL_OSX || defined(__clang__)
12 # define MACRO(name) .macro name
13 # define ENDMACRO .endmacro
19 # define MACRO(name) .macro name arg1=0, arg2=0, arg3=0, arg4=0
20 # define ENDMACRO .endm
21 # define MACROARG1 \arg1
22 # define MACROARG2 \arg2
23 # define MACROARG3 \arg3
24 # define MACROARG4 \arg4
27 * We must write x86 assembly immediates as "$ 0" rather than "$0" to
28 * avoid this being treated as a macro argument by the Mac/Clang
29 * assemblers. We use DOLLAR below to make this more explicit.
34 * This code gets executed when switching from a 64-bit nacl module to
35 * the 64-bit service. NaClSyscallSeg is the lcall target from the
36 * syscall trampoline code, and this code is responsible for figuring
37 * out the identity of the thread, saving the user registers, finish
38 * restoring the segment registers (and getting out of the sandbox),
39 * and actually invoking the C system call handler code.
42 #include "native_client/src/trusted/service_runtime/arch/x86_64/sel_rt_64.h"
43 #include "native_client/src/trusted/service_runtime/nacl_config.h"
46 * This macro gets the NaClThreadContext from the nacl_current_thread
47 * TLS variable in Windows or Linux, or the corresponding
48 * pthread_getspecific(...) TSD data in OSX and puts it in %rdx.
50 * May clobber two registers, %rax and %rcx.
52 * If %rdx contains 0, then this is an invalid thread.
56 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
58 * Open coded TLS (or TSD) access, for all of our target host
59 * OS/toolchains. If the compiler / runtime conventions for
60 * how to access TLS or TSD changes, this code will break
63 * Any changes/fixes for this must be mirrored in nacl_test_capture.S
65 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
70 * We use "@GOTTPOFF" rather than "@TPOFF" in order to be PIC-friendly.
72 movq nacl_current_thread@GOTTPOFF(%rip), %rax
76 * This assumes a particular implementation of OS X's
77 * pthread_getspecific(), which we check for in NaClTlsInit().
79 movl _nacl_current_thread_tls_offset(%rip), %eax
83 * NOTE: This code should match the code in platform/win/test_tls.S!
84 * If you change this code, please update that file as well.
86 * The following two lines generate this instruction:
87 * ba XX XX XX XX movl $nacl_current_thread@SECREL, %edx
89 * SECREL is a relocation type which gives the offset of
90 * nacl_current_thread within the TLS template section. GNU
91 * binutils' assembler does not have a syntax for generating
92 * this relocation as part of an instruction. It only has the
93 * .secrel32 syntax for generating the relocated value as a
94 * 32-bit literal. We use this here for generating the
95 * instruction by hand.
97 * For background, see:
98 * http://code.google.com/p/nativeclient/issues/detail?id=2155
100 * because of the need to do .byte, we cannot simply name the
101 * scratch registers via macro arguments.
104 .secrel32 nacl_current_thread
106 mov _tls_index(%rip), %ecx
108 /* Get the address of this module (executable/DLL)'s TLS area. */
109 movq (%rax,%rcx,8), %rax
110 /* Get the value of nacl_current_thread from the TLS area. */
111 movq (%rdx,%rax), %rdx
113 # error "What OS/compiler is the service runtime being compiled with?"
118 * On untrusted stack:
119 * return-addr-to-caller-of-trampoline
120 * return-addr-to-trampoline (essentially syscall number)
122 * This code must save the syscall arguments so that they can be
123 * accessed in an uniformed way, regardless of whether the service
124 * runtime was compiled using gcc (NACL_LINUX and NACL_OSX) or
125 * using MS Studio (NACL_WINDOWS).
128 DEFINE_GLOBAL_HIDDEN_FUNCTION(NaClSyscallSeg):
131 /* Save system call arguments on the untrusted stack. */
132 movl %r9d, -0x0c(%rsp)
133 movl %r8d, -0x10(%rsp)
134 movl %ecx, -0x14(%rsp)
135 movl %edx, -0x18(%rsp)
136 movl %esi, -0x1c(%rsp)
137 movl %edi, -0x20(%rsp)
139 /* rax, rdi, rsi, rdx, rcx, r8, r9 are usable for scratch */
143 * Code below will segfault if %rdx is the NULL pointer, since
144 * the zero page is unmapped.
147 /* only save the callee saved registers */
148 DEFINE_GLOBAL_HIDDEN_LOCATION(NaClSyscallThreadCaptureFault):
149 movq %rbx, NACL_THREAD_CONTEXT_OFFSET_RBX(%rdx)
150 movq %rbp, NACL_THREAD_CONTEXT_OFFSET_RBP(%rdx)
152 * Record the value of %rsp that we will restore when
153 * returning to untrusted code from the syscall.
156 movq %rcx, NACL_THREAD_CONTEXT_OFFSET_RSP(%rdx)
157 movq %r12, NACL_THREAD_CONTEXT_OFFSET_R12(%rdx)
158 movq %r13, NACL_THREAD_CONTEXT_OFFSET_R13(%rdx)
159 movq %r14, NACL_THREAD_CONTEXT_OFFSET_R14(%rdx)
160 /* r15 need not be saved, since it is immutable from user code */
163 * Save the x87 FPU control word. This is callee-saved,
164 * while all other x87 state is caller-saved. Then reload
165 * the system default state to use while running trusted code.
167 fnstcw NACL_THREAD_CONTEXT_OFFSET_FCW(%rdx)
168 fldcw NACL_THREAD_CONTEXT_OFFSET_SYS_FCW(%rdx)
171 * Save the SSE control word. Then reload the system default
172 * state to use while running trusted code.
174 stmxcsr NACL_THREAD_CONTEXT_OFFSET_MXCSR(%rdx)
175 ldmxcsr NACL_THREAD_CONTEXT_OFFSET_SYS_MXCSR(%rdx)
176 DEFINE_GLOBAL_HIDDEN_LOCATION(NaClSyscallSegRegsSaved):
178 movq NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR(%rdx), %rsp
179 #if NACL_LINUX || NACL_OSX
184 # error "What OS/compiler is the service runtime being compiled with?"
187 * We want to make sure that the return address on the stack will
188 * be handled properly by the host system's stack unwinder.
190 * For Linux, it is fine that the return address does not have
191 * associated unwind info, because libgcc's stack unwinder
192 * will stop unwinding when it reaches such an address. Note
193 * that pthread_exit() causes stack unwinding.
195 * We cannot do the same thing on Windows because its stack
196 * unwinder does not have a similar safe default. If it
197 * encounters a return address without unwind info, it applies
198 * the rule for leaf functions (even though this rule does not
199 * make sense for return addresses in the Windows x86-64 ABI),
200 * and it does so even for zero return addresses. This can
201 * cause it to read uninitialised memory.
203 * So, for Windows, the stack has already been set up by
204 * NaClSwitchSavingStackPtr() with a return address with
205 * associated unwind info.
208 /* NaClSyscallCSegHook returns to NaClSwitchSavingStackPtr. */
209 jmp IDENTIFIER(NaClSyscallCSegHook)
211 call IDENTIFIER(NaClSyscallCSegHook)
213 * NaClSyscallCSegHook returned the struct NaClThreadContext
214 * pointer (in %rax), which will be the argument (in %rdi) to
215 * the NaClSwitch function.
218 call *IDENTIFIER(NaClSwitch)(%rip)
224 * untrusted stack after call to NaClSyscallCSegHook:
226 * 0x20 0x8 return-addr-to-caller-of-trampoline
227 * 0x18 0x0 return-addr-to-trampoline (essentially syscall number)
237 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG1): /* Entry */
239 movl MACROARG4(%rdx), %eax
240 /* sandbox the return, straight off the untrusted stack */
242 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG2): /* RspRestored */
244 andl DOLLAR 0xffffffe0, %ecx
245 leaq (%r15, %rcx), %r11
247 * Set %rdx to zero so that we do not leak the address of the
248 * NaClThreadContext struct. This also resets flags.
249 * Resetting flags to fixed values by doing this last
250 * simplifies testing that we do not leak any information via
255 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG3): /* End */
259 * Note that long lines are required here because "\" does not
260 * work in the Windows build.
262 tls_syscall NaClGetTlsFastPath1, NaClGetTlsFastPath1RspRestored, NaClGetTlsFastPath1End, NACL_THREAD_CONTEXT_OFFSET_TLS_VALUE1
263 tls_syscall NaClGetTlsFastPath2, NaClGetTlsFastPath2RspRestored, NaClGetTlsFastPath2End, NACL_THREAD_CONTEXT_OFFSET_TLS_VALUE2