[MIPS] Add support for thread_suspension test This change: - implements NaClSignalContextUnsetClobberedRegisters() for MIPS, - modifies Unwind for thread suspension to match what is needed for MIPS, - adds MIPS-arch specific parts in suspend_test_guest.c and suspend_test_host.c. BUG= run_thread_suspension_test fails for MIPS TEST= run run_thread_suspension_test on MIPS-board Review URL: https://codereview.chromium.org/121833002 git-svn-id: svn://svn.chromium.org/native_client/trunk/src/native_client@12571 fcba33aa-ac0c-11dd-b9e7-8d5594d729c2
diff --git a/src/trusted/service_runtime/arch/mips/nacl_syscall.S b/src/trusted/service_runtime/arch/mips/nacl_syscall.S index 24e4b5f..8347d8d 100644 --- a/src/trusted/service_runtime/arch/mips/nacl_syscall.S +++ b/src/trusted/service_runtime/arch/mips/nacl_syscall.S
@@ -108,6 +108,7 @@ sw $t8, NACL_THREAD_CONTEXT_OFFSET_T8($a0) sw $sp, NACL_THREAD_CONTEXT_OFFSET_STACK_PTR($a0) sw $fp, NACL_THREAD_CONTEXT_OFFSET_FRAME_PTR($a0) +DEFINE_GLOBAL_HIDDEN_IDENTIFIER(NaClSyscallSegRegsSaved): /* Restore the trusted stack */ lw $sp, NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR($a0)
diff --git a/src/trusted/service_runtime/arch/mips/sel_rt.c b/src/trusted/service_runtime/arch/mips/sel_rt.c index b549662..adadca9 100644 --- a/src/trusted/service_runtime/arch/mips/sel_rt.c +++ b/src/trusted/service_runtime/arch/mips/sel_rt.c
@@ -83,3 +83,27 @@ sig_ctx->prog_ctr = th_ctx->new_prog_ctr; sig_ctx->return_addr = 0; } + + +void NaClSignalContextUnsetClobberedRegisters( + struct NaClSignalContext *sig_ctx) { + sig_ctx->zero = 0; + sig_ctx->at = 0; + sig_ctx->v0 = 0; + sig_ctx->v1 = 0; + sig_ctx->a0 = 0; + sig_ctx->a1 = 0; + sig_ctx->a2 = 0; + sig_ctx->a3 = 0; + sig_ctx->t0 = 0; + sig_ctx->t1 = 0; + sig_ctx->t2 = 0; + sig_ctx->t3 = 0; + sig_ctx->t4 = 0; + sig_ctx->t5 = 0; + sig_ctx->t9 = 0; + sig_ctx->k0 = 0; + sig_ctx->k1 = 0; + sig_ctx->global_ptr = 0; + sig_ctx->return_addr = 0; +}
diff --git a/src/trusted/service_runtime/thread_suspension_unwind.c b/src/trusted/service_runtime/thread_suspension_unwind.c index 22f82f2..0bb274d 100644 --- a/src/trusted/service_runtime/thread_suspension_unwind.c +++ b/src/trusted/service_runtime/thread_suspension_unwind.c
@@ -15,9 +15,6 @@ #include "native_client/src/trusted/service_runtime/sel_ldr.h" -#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 || \ - NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm - static void GetNaClSyscallSeg(struct NaClApp *nap, uintptr_t *nacl_syscall_seg, uintptr_t *nacl_syscall_seg_regs_saved) { @@ -78,6 +75,13 @@ regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->lr); return 1; } +#elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips + if (regs->prog_ctr >= NACL_TRAMPOLINE_START && + regs->prog_ctr < NACL_TRAMPOLINE_END) { + *unwind_case = NACL_UNWIND_in_trampoline; + regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->return_addr); + return 1; + } #endif #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 @@ -113,15 +117,19 @@ if (regs->prog_ctr >= nacl_syscall_seg && regs->prog_ctr < nacl_syscall_seg_regs_saved) { *unwind_case = NACL_UNWIND_in_syscallseg; - if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86) { - if (NACL_BUILD_SUBARCH == 32) { - /* Pop user + trampoline return addresses */ - regs->stack_ptr += 4 + 8; - } else { - /* Pop user return address. */ - regs->stack_ptr += 8; - } - } +#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 + /* Pop user + trampoline return addresses */ + regs->stack_ptr += 4 + 8; +#elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64 + /* Pop user return address. */ + regs->stack_ptr += 8; +#elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips + /* + * On MIPS, $ra is not modified from the start of the trampoline to the + * point where registers are saved. + */ + regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->return_addr); +#endif return 1; } @@ -146,7 +154,10 @@ if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 || (NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm && - *unwind_case != NACL_UNWIND_in_trampoline)) { + *unwind_case != NACL_UNWIND_in_trampoline) || + (NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips && + *unwind_case != NACL_UNWIND_in_trampoline && + *unwind_case != NACL_UNWIND_in_syscallseg)) { /* * Read the return address from the untrusted stack. * NaClCopyInFromUser() can fault or return an error here, but only @@ -164,16 +175,3 @@ regs->prog_ctr = NaClSandboxCodeAddr(natp->nap, user_ret); } } - -#else - -/* TODO(mseaborn): Extend this to handle MIPS. */ -void NaClGetRegistersForContextSwitch(struct NaClAppThread *natp, - struct NaClSignalContext *regs, - enum NaClUnwindCase *unwind_case) { - UNREFERENCED_PARAMETER(natp); - UNREFERENCED_PARAMETER(regs); - *unwind_case = 0; -} - -#endif
diff --git a/tests/thread_suspension/suspend_test_guest.c b/tests/thread_suspension/suspend_test_guest.c index 2d2f847..1773ed5 100644 --- a/tests/thread_suspension/suspend_test_guest.c +++ b/tests/thread_suspension/suspend_test_guest.c
@@ -105,6 +105,19 @@ "str r0, [r0]\n" "spin_instruction:\n" "b spin_instruction\n"); +#elif defined(__mips__) + regs->a0 = (uintptr_t) test_shm; + ASM_WITH_REGS( + regs, + /* Align to ensure no NOPs are inserted in the code that follows. */ + ".p2align 4\n" + /* Set "test_shm->var = test_shm" to indicate that we are ready. */ + "and $a0, $a0, $t7\n" + "sw $a0, 0($a0)\n" + ".global spin_instruction\n" + "spin_instruction:\n" + "b spin_instruction\n" + "nop\n"); #else # error Unsupported architecture #endif @@ -161,6 +174,15 @@ &call_regs, "bic r1, r1, #0xf000000f\n" "bx r1\n"); +#elif defined(__mips__) + call_regs.a0 = (uintptr_t) test_shm; /* Set syscall argument */ + call_regs.t9 = syscall_addr; /* Scratch register */ + call_regs.return_addr = (uintptr_t) ContinueAfterSyscall; + ASM_WITH_REGS( + &call_regs, + "and $t9, $t9, $t6\n" + "jr $t9\n" + "nop\n"); #else # error Unsupported architecture #endif @@ -193,6 +215,17 @@ "bic r4, r4, #0xc000000f\n" "bx r4\n" ".popsection\n"); +#elif defined(__mips__) +__asm__(".pushsection .text, \"ax\", %progbits\n" + ".p2align 4\n" + ".global SyscallReturnAddress\n" + "SyscallReturnAddress:\n" + "lui $ra, %hi(SyscallReturnAddress)\n" + "addiu $ra, $ra, %lo(SyscallReturnAddress)\n" + "and $s0, $s0, $t6\n" + "jr $s0\n" + "nop\n" + ".popsection\n"); #else # error Unsupported architecture #endif @@ -220,6 +253,8 @@ regs->r12 = syscall_addr; #elif defined(__arm__) regs->r4 = syscall_addr; +#elif defined(__mips__) + regs->s0 = syscall_addr; #else # error Unsupported architecture #endif
diff --git a/tests/thread_suspension/suspend_test_host.c b/tests/thread_suspension/suspend_test_host.c index 445ce8b..aacd272 100644 --- a/tests/thread_suspension/suspend_test_host.c +++ b/tests/thread_suspension/suspend_test_host.c
@@ -339,6 +339,38 @@ regs.r12 = 0x1234000c; /* Leave sp (r13) and lr (r14) alone for now. */ regs.prog_ctr = test_shm->continue_after_suspension_func; +#elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips + /* Skip setting zero register because it's read-only. */ + regs.at = 0x12340001; + regs.v0 = 0x12340002; + regs.v1 = 0x12340003; + regs.a0 = 0x12340004; + regs.a1 = 0x12340005; + regs.a2 = 0x12340006; + regs.a3 = 0x12340007; + regs.t0 = 0x12340008; + regs.t1 = 0x12340009; + regs.t2 = 0x12340010; + regs.t3 = 0x12340011; + regs.t4 = 0x12340012; + regs.t5 = 0x12340013; + /* Skip setting t6 and t7 because those are mask registers. */ + regs.s0 = 0x12340014; + regs.s1 = 0x12340015; + regs.s2 = 0x12340016; + regs.s3 = 0x12340017; + regs.s4 = 0x12340018; + regs.s5 = 0x12340019; + regs.s6 = 0x12340020; + regs.s7 = 0x12340021; + /* Skip setting t8 because it holds thread pointer. */ + regs.t9 = 0x12340022; + /* Skip setting k0 and k1 registers, they are used by kernel. */ + regs.global_ptr = 0x12340023; + /* Skip setting sp also. */ + regs.frame_ptr = 0x12340025; + regs.return_addr = 0x12340026; + regs.prog_ctr = test_shm->continue_after_suspension_func; #else # error Unsupported architecture #endif @@ -431,15 +463,7 @@ regs.prog_ctr = test_shm->expected_regs.prog_ctr; RegsUnsetNonCalleeSavedRegisters(®s); } - /* - * TODO(mseaborn): Enable the RegsAssertEqual() check for MIPS - * once NaClGetRegistersForContextSwitch() is implemented for - * MIPS. - */ - if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 || - NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm) { - RegsAssertEqual(®s, &test_shm->expected_regs); - } + RegsAssertEqual(®s, &test_shm->expected_regs); NaClUntrustedThreadsResumeAll(nap); }