diff --git a/core/arch/arch.c b/core/arch/arch.c index 0273431ff49..40d614202fe 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -3866,6 +3866,14 @@ set_stolen_reg_val(priv_mcontext_t *mc, reg_t newval) { *(reg_t *)(((byte *)mc) + opnd_get_reg_dcontext_offs(dr_reg_stolen)) = newval; } + +# ifdef RISCV64 +void +set_tp_reg_val(priv_mcontext_t *mc, reg_t newval) +{ + *(reg_t *)(((byte *)mc) + opnd_get_reg_dcontext_offs(DR_REG_TP)) = newval; +} +# endif #endif #ifdef PROFILE_RDTSC diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index 3c927cd9907..8eab49dc6ec 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -470,6 +470,10 @@ reg_t get_stolen_reg_val(priv_mcontext_t *context); void set_stolen_reg_val(priv_mcontext_t *mc, reg_t newval); +# ifdef RISCV64 +void +set_tp_reg_val(priv_mcontext_t *mc, reg_t newval); +# endif #endif const char * get_branch_type_name(ibl_branch_type_t branch_type); diff --git a/core/arch/riscv64/mangle.c b/core/arch/riscv64/mangle.c index ae5df4387a5..9c09a6e5281 100644 --- a/core/arch/riscv64/mangle.c +++ b/core/arch/riscv64/mangle.c @@ -272,8 +272,7 @@ patch_mov_immed_arch(dcontext_t *dcontext, ptr_int_t val, byte *pc, instr_t *fir bool instr_check_xsp_mangling(dcontext_t *dcontext, instr_t *inst, int *xsp_adjust) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); + /* Not apply to RISC-V. */ return false; } diff --git a/core/unix/os_public.h b/core/unix/os_public.h index 1647dcbdb4f..79d348e9e74 100644 --- a/core/unix/os_public.h +++ b/core/unix/os_public.h @@ -205,6 +205,7 @@ typedef kernel_sigcontext_t sigcontext_t; # define SC_SYSNUM_REG SC_R7 # define SC_RETURN_REG SC_R0 #elif defined(RISCV64) +# define SC_TP SC_FIELD(sc_regs.tp) # define SC_A0 SC_FIELD(sc_regs.a0) # define SC_A1 SC_FIELD(sc_regs.a1) # define SC_A2 SC_FIELD(sc_regs.a2) diff --git a/core/unix/signal.c b/core/unix/signal.c index d3f00342fa4..90767800081 100644 --- a/core/unix/signal.c +++ b/core/unix/signal.c @@ -2826,6 +2826,7 @@ sigcontext_to_mcontext(priv_mcontext_t *mc, sig_full_cxt_t *sc_full, if (TEST(DR_MC_INTEGER, flags)) { mc->ra = sc->SC_FIELD(sc_regs.ra); mc->gp = sc->SC_FIELD(sc_regs.gp); + mc->tp = sc->SC_FIELD(sc_regs.tp); mc->t0 = sc->SC_FIELD(sc_regs.t0); mc->t1 = sc->SC_FIELD(sc_regs.t1); mc->t2 = sc->SC_FIELD(sc_regs.t2); @@ -2920,13 +2921,6 @@ sigcontext_to_mcontext(priv_mcontext_t *mc, sig_full_cxt_t *sc_full, * thread_get_mcontext() sets the dcontext isa_mode from cpsr, and thread_set_mcontext() * sets it. */ -/* XXX: on RISC-V, the tp register is a general-purpose register, but as its name - * suggests, it is conventionally used as the thread register. - * We save DR's tls by keeping tp's value unchanged, regardless in DR or in application. - * Therefore, when converting between sigcontext and mcontext, we should keep tp - * unchanged, otherwise for example when we sigreturn to app tp will change, causing an - * error. - */ void mcontext_to_sigcontext(sig_full_cxt_t *sc_full, priv_mcontext_t *mc, dr_mcontext_flags_t flags) @@ -2962,6 +2956,7 @@ mcontext_to_sigcontext(sig_full_cxt_t *sc_full, priv_mcontext_t *mc, if (TEST(DR_MC_INTEGER, flags)) { sc->SC_FIELD(sc_regs.ra) = mc->ra; sc->SC_FIELD(sc_regs.gp) = mc->gp; + sc->SC_FIELD(sc_regs.tp) = mc->tp; sc->SC_FIELD(sc_regs.t0) = mc->t0; sc->SC_FIELD(sc_regs.t1) = mc->t1; sc->SC_FIELD(sc_regs.t2) = mc->t2; @@ -3071,6 +3066,20 @@ get_sigcxt_stolen_reg(sigcontext_t *sc) (dr_reg_stolen - IF_AARCHXX_ELSE(DR_REG_R0, DR_REG_A0))); } +# ifdef RISCV64 +static void +set_sigcxt_tp_reg(sigcontext_t *sc, reg_t val) +{ + sc->SC_TP = val; +} + +static reg_t +get_sigcxt_tp_reg(sigcontext_t *sc) +{ + return sc->SC_TP; +} +# endif + # ifdef ARM static dr_isa_mode_t get_pc_mode_from_cpsr(sigcontext_t *sc) @@ -4058,7 +4067,7 @@ transfer_from_sig_handler_to_fcache_return(dcontext_t *dcontext, kernel_ucontext * still go to the private fcache_return for simplicity. */ sc->SC_XIP = (ptr_uint_t)fcache_return_routine(dcontext); -#if defined(AARCHXX) +#if defined(AARCHXX) || defined(RISCV64) /* We do not have to set dr_reg_stolen in dcontext's mcontext here * because dcontext's mcontext is stale and we used the mcontext * created from recreate_app_state_internal with the original sigcontext. @@ -4072,12 +4081,14 @@ transfer_from_sig_handler_to_fcache_return(dcontext_t *dcontext, kernel_ucontext dcontext->local_state->spill_space.reg_stolen = get_sigcxt_stolen_reg(sc); /* Now put DR's base in the sigcontext. */ set_sigcxt_stolen_reg(sc, (reg_t)*get_dr_tls_base_addr()); -# ifndef AARCH64 +# ifdef RISCV64 + set_sigcxt_tp_reg(sc, (reg_t)read_thread_register(TLS_REG_LIB)); +# endif + +# ifdef ARM /* We're going to our fcache_return gencode which uses DEFAULT_ISA_MODE */ set_pc_mode_in_cpsr(sc, DEFAULT_ISA_MODE); # endif -#elif defined(RISCV64) - ASSERT_NOT_IMPLEMENTED(false); #endif #if defined(X64) || defined(ARM) @@ -7391,6 +7402,12 @@ handle_sigreturn(dcontext_t *dcontext, void *ucxt_param, int style) set_stolen_reg_val(get_mcontext(dcontext), get_sigcxt_stolen_reg(sc)); /* The linkstub expects DR's TLS to be in the actual register. */ set_sigcxt_stolen_reg(sc, (reg_t)*get_dr_tls_base_addr()); + +# ifdef RISCV64 + set_tp_reg_val(get_mcontext(dcontext), get_sigcxt_tp_reg(sc)); + set_sigcxt_tp_reg(sc, (reg_t)read_thread_register(TLS_REG_LIB)); +# endif + # if defined(AARCH64) /* On entry to the do_syscall gencode, we save X1 into TLS_REG1_SLOT. * Then the sigreturn would redirect the flow to the fcache_return gencode. diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index f19742abd65..9d63cb47626 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -4996,14 +4996,12 @@ if (UNIX) target_link_libraries(linux.signal_pre_syscall rt) endif () - if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 - tobuild(linux.bad-signal-stack linux/bad-signal-stack.c) + tobuild(linux.bad-signal-stack linux/bad-signal-stack.c) - # i#1145: test re-starting syscalls, both inlined and from dispatch - tobuild(linux.eintr linux/eintr.c) - link_with_pthread(linux.eintr) - torunonly(linux.eintr-noinline linux.eintr linux/eintr.c "-no_ignore_syscalls" "") - endif (NOT RISCV64) + # i#1145: test re-starting syscalls, both inlined and from dispatch + tobuild(linux.eintr linux/eintr.c) + link_with_pthread(linux.eintr) + torunonly(linux.eintr-noinline linux.eintr linux/eintr.c "-no_ignore_syscalls" "") if (NOT ANDROID AND NOT RISCV64) # XXX i#1874: get working on Android # TODO i#3544: Port tests to RISC-V 64