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