Chromium Code Reviews| Index: src/trusted/service_runtime/arch/mips/nacl_syscall.S |
| diff --git a/src/trusted/service_runtime/arch/mips/nacl_syscall.S b/src/trusted/service_runtime/arch/mips/nacl_syscall.S |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8bb3b9fbf97800b5832bb2e918614cc84465ce0a |
| --- /dev/null |
| +++ b/src/trusted/service_runtime/arch/mips/nacl_syscall.S |
| @@ -0,0 +1,131 @@ |
| +/* |
| + * Copyright 2012 The Native Client Authors. All rights reserved. |
| + * Use of this source code is governed by a BSD-style license that can |
| + * be found in the LICENSE file. |
| + */ |
| + |
| +#include "native_client/src/trusted/service_runtime/arch/mips/sel_rt.h" |
| +#include "native_client/src/trusted/service_runtime/nacl_config.h" |
| + |
| +.text |
| + |
| + |
| +/* |
| + * This trusted code is linked into the service runtime. It is executed when a |
| + * nacl module performs a system call via a service runtime interface. The nacl |
| + * module jumps to the trampoline corresponding to the syscall and then here. |
| + * This code switches the execution contexts (registers and stack) from |
| + * untrusted to trusted. |
| + * |
| + * on stack: |
| + * |
| + * top |
| + * ===== |
| + * a0 - alignment for NaClSyscallCSegHook |
| + * ra - return address |
| + * arg 1 |
| + * arg 2 |
| + * ..... |
| + * arg N |
| + */ |
| + |
| +DEFINE_GLOBAL_HIDDEN_IDENTIFIER(NaClSyscallSeg): |
| + |
| + .set noreorder |
| + |
| +/* |
| + * The following code (next 6 instructions) does what the trampoline code should |
| + * do. It places the first 4 parameters of the system call to the stack, and on |
| + * top of that it places the return address to the user module. On Mips the |
| + * trampoline is too small for all this, so the code is moved here. |
| + * |
| + * Mips passes parameters to a callee in registers a0-a3. If there are more |
| + * than 4 parameters, the first four args are passed in registers and the rest |
| + * are placed on the stack. Regardless of the number of arguments passed, Mips |
| + * o32 ABI requires that the caller should always reserve 16 bytes on stack that |
| + * correspond to registers a0-a3. |
| + * |
| + * This code pushes all parameters from registers into the stack; thus, we keep |
| + * all parameters on the stack as follows: |
| + * top - arg0, arg1, arg2, arg3 .... argN |
| + * |
| + * On top of that we push the return address, so we will know where to return |
| + * after the system call. |
| + * |
| + * After this code the stack layout must look like: |
| + * |
| + * sp+0: retaddr to user module |
| + * sp+4: arg0 (system call argument) |
| + * sp+8: arg1 |
| + * .......... |
| + * sp+X: argN |
| + * |
| + * When service runtime serves a system call, it first creates a structure which |
| + * utilizes these arguments. The structure is created by Decoder functions in |
| + * nacl_syscall_handlers.c. (nacl_syscall_handlers.c is an automatically |
| + * generated file and placed in |
| + * scons-out//gen/native_client/src/trusted/service_runtime). |
| + */ |
| + |
| + /* Place a0-a3 argument registers in the reserved 16-byte region in caller's |
| + stack frame (o32 ABI), and place return address on top of that. */ |
| + |
| + .cpload $t9 |
| + |
| + sw $a3, 12($sp) |
| + sw $a2, 8($sp) |
| + sw $a1, 4($sp) |
| + sw $a0, 0($sp) |
| + addiu $sp, $sp, -8 |
| + sw $ra, 4($sp) |
| + sw $t5, 0($sp) |
| + |
| + /* Load the __thread variable's offset into a3. */ |
| + lui $a3, %tprel_hi(gNaClThreadIdx) |
| + addiu $a3, $a3, %tprel_lo(gNaClThreadIdx) |
| + |
| + /* Fetch the thread-local variable holding the thread index. */ |
| + rdhwr $v1, $29 |
| + addu $a3, $v1, $a3 |
| + lw $a0, 0($a3) |
| + |
| + /* Load the nacl_user entry of this thread. |
| + * a1 = nacl_user[a0*4] */ |
| + lw $a1,%got(nacl_user)($28) |
| + sll $a0, $a0, 2 |
| + addu $a1, $a1, $a0 |
| + lw $a1, 0($a1) |
| + |
| + sw $t6, NACL_THREAD_CONTEXT_OFFSET_T6($a1) |
|
Mark Seaborn
2012/09/18 03:24:34
Optional: if t6/t7/t8 are constants, a micro-optim
petarj
2012/09/19 17:27:51
t6 and 67 are constants. The optimization is actua
|
| + sw $t7, NACL_THREAD_CONTEXT_OFFSET_T7($a1) |
| + sw $s0, NACL_THREAD_CONTEXT_OFFSET_S0($a1) |
| + sw $s1, NACL_THREAD_CONTEXT_OFFSET_S1($a1) |
| + sw $s2, NACL_THREAD_CONTEXT_OFFSET_S2($a1) |
| + sw $s3, NACL_THREAD_CONTEXT_OFFSET_S3($a1) |
| + sw $s4, NACL_THREAD_CONTEXT_OFFSET_S4($a1) |
| + sw $s5, NACL_THREAD_CONTEXT_OFFSET_S5($a1) |
| + sw $s6, NACL_THREAD_CONTEXT_OFFSET_S6($a1) |
| + sw $s7, NACL_THREAD_CONTEXT_OFFSET_S7($a1) |
| + sw $t8, NACL_THREAD_CONTEXT_OFFSET_T8($a1) |
| + sw $gp, NACL_THREAD_CONTEXT_OFFSET_GLOBAL_PTR($a1) |
| + sw $sp, NACL_THREAD_CONTEXT_OFFSET_STACK_PTR($a1) |
| + sw $fp, NACL_THREAD_CONTEXT_OFFSET_FRAME_PTR($a1) |
| + |
| + /* Restore the thread index. */ |
| + srl $a0, $a0, 2 |
| + |
| + /* Reserve 16-byte for arguments (o32 ABI) */ |
| + addiu $sp, $sp, -16 |
| + lw $t9,%call16(NaClSyscallCSegHook)($gp) |
| + jr $t9 |
| + nop |
| + |
| + /* NOTREACHED */ |
| + |
| + /* |
| + * If the thread returns, which must not happen, it will be halted |
| + * by the following instruction |
| + */ |
| + |
| + jr $0 /*NACL_HALT*/ |
| + |