Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / arch / x86_64 / nacl_switch_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  * This code gets executed when switching from the service
9  * runtime to the NaCl module.  NaClSwitch has one parameter only,
10  * which is a struct passed by reference.
11  *
12  * NB: this is not the only place where context switches from trusted
13  * to untrusted code.  The NaClGetTlsFastPath* code (nacl_syscall_64.S)
14  * also performs a partial switch (to and fro).
15  */
16
17 #include "native_client/src/trusted/service_runtime/arch/x86_64/sel_rt_64.h"
18 #include "native_client/src/trusted/service_runtime/nacl_config.h"
19
20         /*
21          * This function does not return.  Thus, we need to preserve
22          * any callee-saved registers.
23          */
24
25         .text
26
27 .macro switcher arg1, arg2
28 DEFINE_GLOBAL_HIDDEN_FUNCTION(\arg1):
29 #if NACL_WINDOWS
30         /* On Windows, 1st param is in %rcx. */
31         mov     %rcx, %r11
32 #elif NACL_LINUX || NACL_OSX
33         /* On Linux/OSX, 1st param is in %rdi. */
34         mov     %rdi, %r11
35 #else
36 # error "What OS/compiler is the service runtime being compiled with?"
37 #endif
38
39         /*
40          * TODO(mcgrathr): Perhaps drop callee-saved registers (these six)
41          * from this restore and instead just clear them at startup
42          * (i.e. have NaClStartThreadInApp call a NaClStartSwitch that
43          * clears them and calls NaClSwitch).
44          */
45         movq    NACL_THREAD_CONTEXT_OFFSET_RBX(%r11), %rbx
46         movq    NACL_THREAD_CONTEXT_OFFSET_RBP(%r11), %rbp
47         movq    NACL_THREAD_CONTEXT_OFFSET_R12(%r11), %r12
48         movq    NACL_THREAD_CONTEXT_OFFSET_R13(%r11), %r13
49         movq    NACL_THREAD_CONTEXT_OFFSET_R14(%r11), %r14
50         movq    NACL_THREAD_CONTEXT_OFFSET_R15(%r11), %r15
51
52         /* there is no springboard for x86_64 */
53         movq    NACL_THREAD_CONTEXT_OFFSET_RSP(%r11), %rsp
54         movq    NACL_THREAD_CONTEXT_OFFSET_SYSRET(%r11), %rax
55
56         /*
57          * %rdi is the first argument in the user calling convention.
58          * When starting the initial thread, we are passing the address
59          * of the parameter block here.  The initial stack pointer has
60          * been adjusted to one word below there, to insert a dummy
61          * return address for the user entry point function.
62          */
63         leal    8(%rsp), %edi
64
65         /*
66          * Zero all unused registers.  The 32-bit instructions
67          * are a byte shorter than their 64-bit counterparts
68          * when the target register is one of the first eight,
69          * and they implicitly zero the high halves.
70          *
71          * The 'xorl' instruction also resets most flags to known
72          * values.
73          */
74         xorl    %edx, %edx
75         movl    %edx, %ecx
76         movl    %edx, %esi
77         movq    %rdx, %r8
78         movq    %rdx, %r9
79         movq    %rdx, %r10
80
81         /*
82          * Clear the x87, MMX, and SSE state.
83          * Then restore the untrusted code's x87 and SSE control words.
84          * We could roll them together by storing a 512-byte per-thread
85          * buffer and setting the control words in that in NaClSyscallSeg.
86          * But that would bloat struct NaClThreadContext by 504 bytes or so,
87          * and the performance cost of these two instructions after fxrstor
88          * seems to be immeasurably small.
89          */
90         fxrstor fxrstor_default_state(%rip)
91         fldcw   NACL_THREAD_CONTEXT_OFFSET_FCW(%r11)
92         ldmxcsr NACL_THREAD_CONTEXT_OFFSET_MXCSR(%r11)
93
94 .if \arg2
95         /*
96          * Clear the AVX state that the "fxrstor" instruction doesn't cover.
97          * We could roll them together by using the "xrstor" instruction, but
98          * that has a complicated protocol and this seems to perform fine.
99          *
100          * This is "vzeroupper".
101          * Some assembler versions don't know the AVX instructions.
102          */
103         .byte   0xc5, 0xf8, 0x77
104 .endif
105
106         /*
107          * Load the return address into %r11 rather than doing
108          * "jmp *XXX(%r11)" so that we do not leak the address of the
109          * struct NaClThreadContext to untrusted code.  Knowing this
110          * address would make bugs in the sandbox easier to exploit.
111          */
112         movq    NACL_THREAD_CONTEXT_OFFSET_NEW_PROG_CTR(%r11), %r11
113         jmp     *%r11
114 .endm
115
116         switcher NaClSwitchSSE, 0
117         switcher NaClSwitchAVX, 1
118
119
120         NACL_RODATA
121         /*
122          * This is the memory block for "fxrstor" to read.  The only
123          * contents that matter are the fcw and mxcsr words, which we
124          * store separately.  The mxcsr_mask word is ignored by the
125          * hardware, so there is no need to get the hardware-supplied
126          * value for that.  The hardware requires that this address be
127          * aligned to 16 bytes.  Align it further to 64 bytes because
128          * that is the usual size of a cache line; this might help
129          * performance and is very unlikely to hurt it.
130          */
131         .balign 64
132 fxrstor_default_state:
133         .space 512