Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / arch / x86_64 / nacl_syscall_64.S
1 /*
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.
5  */
6
7 /*
8  * The MacOS assembler has a macro facility that is pretty close
9  * to GNU as macros, but not quite the same.
10  */
11 #if NACL_OSX || defined(__clang__)
12 # define MACRO(name)    .macro name
13 # define ENDMACRO       .endmacro
14 # define MACROARG1      $0
15 # define MACROARG2      $1
16 # define MACROARG3      $2
17 # define MACROARG4      $3
18 #else
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
25 #endif
26 /*
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.
30  */
31 #define DOLLAR $
32
33 /*
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.
40  */
41
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"
44
45 /*
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.
49  *
50  * May clobber two registers, %rax and %rcx.
51  *
52  * If %rdx contains 0, then this is an invalid thread.
53  */
54 MACRO(get_tls)
55         /*
56          * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
57          *
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
61          * mysteriously.
62          *
63          * Any changes/fixes for this must be mirrored in nacl_test_capture.S
64          *
65          * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
66          */
67 #if NACL_LINUX
68         /*
69          * Linux uses TLS.
70          * We use "@GOTTPOFF" rather than "@TPOFF" in order to be PIC-friendly.
71          */
72         movq    nacl_current_thread@GOTTPOFF(%rip), %rax
73         movq    %fs:(%rax), %rdx
74 #elif NACL_OSX
75         /*
76          * This assumes a particular implementation of OS X's
77          * pthread_getspecific(), which we check for in NaClTlsInit().
78          */
79         movl    _nacl_current_thread_tls_offset(%rip), %eax
80         movq    %gs:(%rax), %rdx
81 #elif NACL_WINDOWS
82         /*
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.
85          *
86          * The following two lines generate this instruction:
87          *   ba XX XX XX XX    movl $nacl_current_thread@SECREL, %edx
88          *
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.
96          *
97          * For background, see:
98          * http://code.google.com/p/nativeclient/issues/detail?id=2155
99          *
100          * because of the need to do .byte, we cannot simply name the
101          * scratch registers via macro arguments.
102          */
103         .byte 0xba
104         .secrel32 nacl_current_thread
105
106         mov _tls_index(%rip), %ecx
107         movq %gs:0x58, %rax
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
112 #else
113 # error "What OS/compiler is the service runtime being compiled with?"
114 #endif
115 ENDMACRO
116
117 /*
118  * On untrusted stack:
119  *      return-addr-to-caller-of-trampoline
120  *      return-addr-to-trampoline (essentially syscall number)
121  *
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).
126  */
127         .text
128 DEFINE_GLOBAL_HIDDEN_FUNCTION(NaClSyscallSeg):
129         cld
130
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)
138
139         /* rax, rdi, rsi, rdx, rcx, r8, r9 are usable for scratch */
140
141         get_tls
142         /*
143          * Code below will segfault if %rdx is the NULL pointer, since
144          * the zero page is unmapped.
145          */
146
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)
151         /*
152          * Record the value of %rsp that we will restore when
153          * returning to untrusted code from the syscall.
154          */
155         leaq    8(%rsp), %rcx
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 */
161
162         /*
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.
166          */
167         fnstcw  NACL_THREAD_CONTEXT_OFFSET_FCW(%rdx)
168         fldcw   NACL_THREAD_CONTEXT_OFFSET_SYS_FCW(%rdx)
169
170         /*
171          * Save the SSE control word.  Then reload the system default
172          * state to use while running trusted code.
173          */
174         stmxcsr NACL_THREAD_CONTEXT_OFFSET_MXCSR(%rdx)
175         ldmxcsr NACL_THREAD_CONTEXT_OFFSET_SYS_MXCSR(%rdx)
176 DEFINE_GLOBAL_HIDDEN_LOCATION(NaClSyscallSegRegsSaved):
177
178         movq    NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR(%rdx), %rsp
179 #if NACL_LINUX || NACL_OSX
180         movq    %rdx, %rdi
181 #elif NACL_WINDOWS
182         movq    %rdx, %rcx
183 #else
184 # error "What OS/compiler is the service runtime being compiled with?"
185 #endif
186         /*
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.
189          *
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.
194          *
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.
202          *
203          * So, for Windows, the stack has already been set up by
204          * NaClSwitchSavingStackPtr() with a return address with
205          * associated unwind info.
206          */
207 #if NACL_WINDOWS
208         /* NaClSyscallCSegHook returns to NaClSwitchSavingStackPtr. */
209         jmp     IDENTIFIER(NaClSyscallCSegHook)
210 #else
211         call    IDENTIFIER(NaClSyscallCSegHook)
212         /*
213          * NaClSyscallCSegHook returned the struct NaClThreadContext
214          * pointer (in %rax), which will be the argument (in %rdi) to
215          * the NaClSwitch function.
216          */
217         movq    %rax, %rdi
218         call    *IDENTIFIER(NaClSwitch)(%rip)
219         hlt
220         /* noret */
221 #endif
222
223         /*
224          * untrusted stack after call to NaClSyscallCSegHook:
225          *
226          * 0x20   0x8 return-addr-to-caller-of-trampoline
227          * 0x18   0x0 return-addr-to-trampoline (essentially syscall number)
228          * 0x14 -0x04 r9
229          * 0x10 -0x08 r8
230          * 0x0c -0x0c rcx
231          * 0x08 -0x10 rdx
232          * 0x04 -0x14 rsi
233          * 0x00 -0x18 rdi
234          */
235
236 MACRO(tls_syscall)
237 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG1):  /* Entry */
238         get_tls
239         movl    MACROARG4(%rdx), %eax
240         /* sandbox the return, straight off the untrusted stack */
241         pop     %rcx
242 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG2):  /* RspRestored */
243         addl    DOLLAR 31, %ecx
244         andl    DOLLAR 0xffffffe0, %ecx
245         leaq    (%r15, %rcx), %r11
246         /*
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
251          * flags.
252          */
253         xorl    %edx, %edx
254         jmp     *%r11
255 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG3):  /* End */
256 ENDMACRO
257
258         /*
259          * Note that long lines are required here because "\" does not
260          * work in the Windows build.
261          */
262         tls_syscall NaClGetTlsFastPath1, NaClGetTlsFastPath1RspRestored, NaClGetTlsFastPath1End, NACL_THREAD_CONTEXT_OFFSET_TLS_VALUE1
263         tls_syscall NaClGetTlsFastPath2, NaClGetTlsFastPath2RspRestored, NaClGetTlsFastPath2End, NACL_THREAD_CONTEXT_OFFSET_TLS_VALUE2