Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / arch / mips / nacl_syscall.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 #include "native_client/src/trusted/service_runtime/arch/mips/sel_ldr_mips.h"
8 #include "native_client/src/trusted/service_runtime/arch/mips/sel_rt.h"
9 #include "native_client/src/trusted/service_runtime/nacl_config.h"
10
11 .text
12
13
14 /*
15  * This trusted code is linked into the service runtime. It is executed when a
16  * nacl module performs a system call via a service runtime interface. The nacl
17  * module jumps to the trampoline corresponding to the syscall and then here.
18  * This code switches the execution contexts (registers and stack) from
19  * untrusted to trusted.
20  *
21  * on stack:
22  *
23  * top
24  * =====
25  * a0 - alignment for NaClSyscallCSegHook
26  * ra - return address
27  * arg 1
28  * arg 2
29  * .....
30  * arg N
31  */
32
33 DEFINE_GLOBAL_HIDDEN_IDENTIFIER(NaClSyscallSeg):
34
35   .set noreorder
36
37 /*
38  * The following code (next 6 instructions) does what the trampoline code should
39  * do. It places the first 4 parameters of the system call to the stack, and on
40  * top of that it places the return address to the user module. On Mips the
41  * trampoline is too small for all this, so the code is moved here.
42  *
43  * Mips passes parameters to a callee in registers a0-a3. If there are more
44  * than 4 parameters, the first four args are passed in registers and the rest
45  * are placed on the stack. Regardless of the number of arguments passed, Mips
46  * o32 ABI requires that the caller should always reserve 16 bytes on stack that
47  * correspond to registers a0-a3.
48  *
49  * This code pushes all parameters from registers into the stack; thus, we keep
50  * all parameters on the stack as follows:
51  * top - arg0, arg1, arg2, arg3 .... argN
52  *
53  * On top of that we push the return address, so we will know where to return
54  * after the system call.
55  *
56  * After this code the stack layout must look like:
57  *
58  * sp+0: retaddr to user module
59  * sp+4: arg0 (system call argument)
60  * sp+8: arg1
61  * ..........
62  * sp+X: argN
63  *
64  * When service runtime serves a system call, it first creates a structure which
65  * utilizes these arguments. The structure is created by Decoder functions in
66  * nacl_syscall_handlers.c. (nacl_syscall_handlers.c is an automatically
67  * generated file and placed in
68  * scons-out//gen/native_client/src/trusted/service_runtime).
69  */
70
71   /*
72    * .cpload will expand into the three instructions function prologue that sets
73    * up the $gp register to the trusted value.
74    */
75   .cpload $t9
76
77   /*
78    * Place a0-a3 argument registers in the reserved 16-byte region in caller's
79    * stack frame (o32 ABI), and place return address on top of that.
80    */
81   sw    $a3, 12($sp)
82   sw    $a2,  8($sp)
83   sw    $a1,  4($sp)
84   sw    $a0,  0($sp)
85   /* Save return address for returning to untrusted code. */
86   sw    $ra, -4($sp)
87   /* Save return address that indicates which trampoline was called. */
88   sw    $t5, -8($sp)
89
90   /* Load the __thread variable's offset into a3. */
91   lui   $a3, %tprel_hi(nacl_current_thread)
92   addiu $a3, $a3, %tprel_lo(nacl_current_thread)
93
94   /* Fetch the thread-local variable: set a0 = nacl_current_thread */
95   rdhwr $v1, $29
96   addu  $a3, $v1, $a3
97   lw    $a0, 0($a3)
98
99 DEFINE_GLOBAL_HIDDEN_IDENTIFIER(NaClSyscallThreadCaptureFault):
100   sw $s0, NACL_THREAD_CONTEXT_OFFSET_S0($a0)
101   sw $s1, NACL_THREAD_CONTEXT_OFFSET_S1($a0)
102   sw $s2, NACL_THREAD_CONTEXT_OFFSET_S2($a0)
103   sw $s3, NACL_THREAD_CONTEXT_OFFSET_S3($a0)
104   sw $s4, NACL_THREAD_CONTEXT_OFFSET_S4($a0)
105   sw $s5, NACL_THREAD_CONTEXT_OFFSET_S5($a0)
106   sw $s6, NACL_THREAD_CONTEXT_OFFSET_S6($a0)
107   sw $s7, NACL_THREAD_CONTEXT_OFFSET_S7($a0)
108   sw $t8, NACL_THREAD_CONTEXT_OFFSET_T8($a0)
109   sw $sp, NACL_THREAD_CONTEXT_OFFSET_STACK_PTR($a0)
110   sw $fp, NACL_THREAD_CONTEXT_OFFSET_FRAME_PTR($a0)
111 DEFINE_GLOBAL_HIDDEN_IDENTIFIER(NaClSyscallSegRegsSaved):
112
113   /* Restore the trusted stack */
114   lw $sp, NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR($a0)
115
116   lw    $t9,%call16(NaClSyscallCSegHook)($gp)
117   jalr  $t9
118   nop
119
120   /*
121    * NaClSyscallCSegHook returned the NaClThreadContext pointer in $v0.
122    * Make that the argument (in $a0) to NaClSwitch.
123    */
124   lw    $t9,%call16(NaClSwitch)($gp)
125   jr    $t9
126   move  $a0, $v0 /* delay slot */
127
128   /* NOTREACHED */
129
130   /*
131    * If the thread returns, which must not happen, it will be halted
132    * by the following instruction.
133    */
134
135   .word NACL_HALT_WORD