Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i#3544 RV64: Refine fault translation and signal handling #6461

Merged
merged 11 commits into from
Nov 28, 2023
8 changes: 8 additions & 0 deletions core/arch/arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions core/arch/arch_exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions core/arch/riscv64/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
ksco marked this conversation as resolved.
Show resolved Hide resolved
return false;
}

Expand Down Expand Up @@ -674,14 +673,15 @@ instr_is_ldstex_mangling(dcontext_t *dcontext, instr_t *instr)

ptr_int_t val;
if (instr_get_opcode(instr) == OP_fence || instr_get_opcode(instr) == OP_bne ||
instr_get_opcode(instr) == OP_bne ||
/* Check for sc.w/d+bne+jal pattern. */
(instr_get_opcode(instr) == OP_jal && instr_get_prev(instr) != NULL &&
instr_get_opcode(instr_get_prev(instr)) == OP_bne &&
instr_get_prev(instr_get_prev(instr)) != NULL &&
instr_is_exclusive_store(instr_get_prev(instr_get_prev(instr)))) ||
instr_is_exclusive_load(instr) || instr_is_exclusive_store(instr) ||
(instr_is_mov_constant(instr, &val) &&
/* XXX: These are fragile, should we look backward a bit to check for more
specific patterns? */
(val == 1 /* cas fail */ || val == -1 /* reservation invalidation */ ||
ksco marked this conversation as resolved.
Show resolved Hide resolved
val == 4 /* lr.w/sc.w size */ || val == 8 /* lr.d/sc.d size */)))
return true;
Expand Down
1 change: 1 addition & 0 deletions core/unix/os_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
39 changes: 28 additions & 11 deletions core/unix/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand All @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
12 changes: 5 additions & 7 deletions suite/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading