Skip to content

Commit

Permalink
i#3544 RV64: Fill in the missing pieces to run actual programs (#6437)
Browse files Browse the repository at this point in the history
This patch fills in many missing pieces related to RISC-V porting.

With this patch, plus one more patch to mangle.c yet to be submitted, we
are finally able to run some programs, which means some tests can be
enabled/ported for RISC-V and more RISC-V specific tests can be written.

Issue: #3544
  • Loading branch information
ksco committed Nov 11, 2023
1 parent 86e8581 commit c6f7b74
Show file tree
Hide file tree
Showing 25 changed files with 189 additions and 104 deletions.
26 changes: 12 additions & 14 deletions core/arch/arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,9 @@ shared_gencode_emit(generated_code_t *gencode _IF_X86_64(bool x86_mode))
gencode->do_syscall = pc;
pc = emit_do_syscall(GLOBAL_DCONTEXT, gencode, pc, gencode->fcache_return,
true /*shared*/, 0, &gencode->do_syscall_offs);
# ifdef AARCHXX
/* ARM has no thread-private gencode, so our clone syscall is shared */
# if defined(AARCHXX) || defined(RISCV64)
/* ARM/AArch64/RISC-V has no thread-private gencode, so our clone syscall is shared.
*/
gencode->do_clone_syscall = pc;
pc = emit_do_clone_syscall(GLOBAL_DCONTEXT, gencode, pc, gencode->fcache_return,
true /*shared*/, &gencode->do_clone_syscall_offs);
Expand Down Expand Up @@ -726,7 +727,10 @@ d_r_arch_init(void)

#ifdef AARCHXX
dr_reg_stolen = DR_REG_R0 + DYNAMO_OPTION(steal_reg);
ASSERT(dr_reg_stolen >= DR_REG_STOLEN_MIN && dr_reg_stolen <= DR_REG_STOLEN_MAX)
ASSERT(dr_reg_stolen >= DR_REG_STOLEN_MIN && dr_reg_stolen <= DR_REG_STOLEN_MAX);
#elif defined(RISCV64)
dr_reg_stolen = DR_REG_X0 + DYNAMO_OPTION(steal_reg);
ASSERT(dr_reg_stolen >= DR_REG_STOLEN_MIN && dr_reg_stolen <= DR_REG_STOLEN_MAX);
#endif

/* Ensure we have no unexpected padding inside structs that include
Expand Down Expand Up @@ -1206,7 +1210,7 @@ arch_thread_init(dcontext_t *dcontext)
return;
#endif

#ifdef AARCHXX
#if defined(AARCHXX) || defined(RISCV64)
/* Store addresses we access via TLS from exit stubs and gencode. */
get_local_state_extended()->spill_space.fcache_return =
PC_AS_JMP_TGT(isa_mode, fcache_return_shared_routine());
Expand Down Expand Up @@ -3105,15 +3109,12 @@ hook_vsyscall(dcontext_t *dcontext, bool method_changing)
instr_free(dcontext, &instr);
return res;
# undef CHECK
# elif defined(AARCHXX)
/* No vsyscall support needed for our ARM targets -- still called on
# elif defined(AARCHXX) || defined(RISCV64)
/* No vsyscall support needed for our ARM/AArch64/RISC-V targets -- still called on
* os_process_under_dynamorio().
*/
ASSERT(!method_changing);
return false;
# elif defined(RISCV64)
ASSERT_NOT_IMPLEMENTED(false);
return false;
# endif /* X86/ARM/RISCV64 */
}

Expand Down Expand Up @@ -3152,12 +3153,9 @@ unhook_vsyscall(void)
ASSERT(res);
}
return true;
# elif defined(AARCHXX)
# elif defined(AARCHXX) || defined(RISCV64)
ASSERT_NOT_IMPLEMENTED(get_syscall_method() != SYSCALL_METHOD_SYSENTER);
return false;
# elif defined(RISCV64)
ASSERT_NOT_IMPLEMENTED(false);
return false;
# endif /* X86/ARM/RISCV64 */
}
#endif /* LINUX */
Expand Down Expand Up @@ -3856,7 +3854,7 @@ dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml)
#endif
}

#ifdef AARCHXX
#if defined(AARCHXX) || defined(RISCV64)
reg_t
get_stolen_reg_val(priv_mcontext_t *mc)
{
Expand Down
4 changes: 3 additions & 1 deletion core/arch/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,8 @@ mangle_rel_addr(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
instr_t *
mangle_special_registers(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
instr_t *next_instr);
#endif
#if defined(AARCHXX) || defined(RISCV64)
instr_t *
mangle_exclusive_monitor_op(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
instr_t *next_instr);
Expand Down Expand Up @@ -627,7 +629,7 @@ mangle_insert_clone_code(dcontext_t *dcontext, instrlist_t *ilist,
#elif defined(ARM)
# define ABI_STACK_ALIGNMENT 8
#elif defined(RISCV64)
# define ABI_STACK_ALIGNMENT 8
# define ABI_STACK_ALIGNMENT 16
#endif

/* Returns the number of bytes the stack pointer has to be aligned to. */
Expand Down
2 changes: 1 addition & 1 deletion core/arch/arch_exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ void
dr_mcontext_init(dr_mcontext_t *mc);
void
dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml);
#ifdef AARCHXX
#if defined(AARCHXX) || defined(RISCV64)
reg_t
get_stolen_reg_val(priv_mcontext_t *context);
void
Expand Down
58 changes: 46 additions & 12 deletions core/arch/emit_utils_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -3262,6 +3262,8 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code,
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569: NYI on AArch64 */
#elif defined(ARM)
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1551: NYI on ARM */
#elif defined(RISCV64)
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#3544: NYI on RISCV64 */
#endif
} else {
APP(ilist, SAVE_TO_TLS(dcontext, SCRATCH_REG2, INDIRECT_STUB_SPILL_SLOT));
Expand Down Expand Up @@ -5554,11 +5556,13 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui
instrlist_t ilist;
patch_list_t patch;
instr_t *in;
/* For AArch64 the linkstub has to be in X0 and the app's X0 has to be
* spilled in TLS_REG0_SLOT before calling the ibl routine.
/* For AArch64/RISCV64 the linkstub has to be in SCRATCH_REG0 and the app's
* SCRATCH_REG0 has to be spilled in TLS_REG0_SLOT before calling the ibl routine.
*/
reg_id_t stub_reg = IF_AARCH64_ELSE(SCRATCH_REG0, SCRATCH_REG1);
ushort stub_slot = IF_AARCH64_ELSE(TLS_REG0_SLOT, TLS_REG1_SLOT);
reg_id_t stub_reg =
IF_AARCH64_ELSE(SCRATCH_REG0, IF_RISCV64_ELSE(SCRATCH_REG0, SCRATCH_REG1));
ushort stub_slot =
IF_AARCH64_ELSE(TLS_REG0_SLOT, IF_RISCV64_ELSE(TLS_REG0_SLOT, TLS_REG1_SLOT));
IF_X86(size_t len;)
byte *ibl_linked_tgt = special_ibl_xfer_tgt(dcontext, code, IBL_LINKED, ibl_type);
byte *ibl_unlinked_tgt = special_ibl_xfer_tgt(dcontext, code, IBL_UNLINKED, ibl_type);
Expand Down Expand Up @@ -5628,12 +5632,6 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui
opnd_create_reg(DR_REG_XCX)));
insert_shared_restore_dcontext_reg(dcontext, &ilist, NULL);
APP(&ilist, XINST_CREATE_jump(dcontext, opnd_create_pc(ibl_unlinked_tgt)));
# elif defined(RISCV64)
/* FIXME i#3544: Not implemented */
ASSERT_NOT_IMPLEMENTED(false);
/* Marking as unused to silence -Wunused-variable. */
(void)ibl_unlinked_tgt;
(void)ibl_linked_tgt;
# elif defined(AARCHXX)
/* Reuse SCRATCH_REG5 which contains dcontext currently. */
APP(&ilist,
Expand All @@ -5658,7 +5656,21 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui
dcontext, opnd_create_reg(DR_REG_PC),
OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_unlinked_tgt))));
# endif /* AARCH64/ARM */
# endif /* X86/AARCHXX */
# elif defined(RISCV64)
/* Reuse SCRATCH_REG5 which contains dcontext currently. */
APP(&ilist,
INSTR_CREATE_lb(dcontext, opnd_create_reg(SCRATCH_REG5),
OPND_DC_FIELD(false, dcontext, OPSZ_1, SIGPENDING_OFFSET)));
APP(&ilist,
INSTR_CREATE_beq(dcontext, opnd_create_instr(skip_unlinked_tgt_jump),
opnd_create_reg(SCRATCH_REG5), opnd_create_reg(DR_REG_X0)));
insert_shared_restore_dcontext_reg(dcontext, &ilist, NULL);
APP(&ilist,
INSTR_CREATE_ld(
dcontext, opnd_create_reg(SCRATCH_REG1),
OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_unlinked_tgt))));
APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(SCRATCH_REG1)));
# endif /* X86/AARCHXX/RISCV64 */
APP(&ilist, skip_unlinked_tgt_jump);
# ifdef X86
APP(&ilist,
Expand Down Expand Up @@ -5716,10 +5728,22 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui
INSTR_CREATE_ldr(
dcontext, opnd_create_reg(DR_REG_PC),
OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_linked_tgt))));
#elif defined(RISCV64)
/* Unlike X86 and ARM which use 1 instruction for an indirect jump,
* RISCV64, same as Aarch64, requires 2 instructions: LD+JR. This requires adjusting
* special_ibl_unlink_offs to point to the LD when relinking by
* relink_special_ibl_xfer(). See adjustment below, to offs_instr passed to
* add_patch_marker().
*/
APP(&ilist,
INSTR_CREATE_ld(
dcontext, opnd_create_reg(SCRATCH_REG1),
OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_linked_tgt))));
APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(SCRATCH_REG1)));
#endif

instr_t *offs_instr = instrlist_last(&ilist);
#if defined(AARCH64)
#if defined(AARCH64) || defined(RISCV64)
offs_instr = instr_get_prev(offs_instr);
#endif
add_patch_marker(&patch, offs_instr, PATCH_UINT_SIZED /* pc relative */,
Expand Down Expand Up @@ -5814,6 +5838,10 @@ emit_clean_call_save(dcontext_t *dcontext, byte *pc, generated_code_t *code)
/* save all registers */
insert_push_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE,
OPND_CREATE_INT32(0), REG_NULL, true);
#elif defined(RISCV64)
/* save all registers */
insert_push_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE,
OPND_CREATE_INT32(0), REG_NULL);
#endif

#ifdef WINDOWS
Expand Down Expand Up @@ -5852,6 +5880,8 @@ emit_clean_call_save(dcontext_t *dcontext, byte *pc, generated_code_t *code)
OPND_CREATE_INT16(get_clean_call_temp_stack_size())));
#elif defined(AARCH64)
APP(&ilist, INSTR_CREATE_br(dcontext, opnd_create_reg(DR_REG_X30)));
#elif defined(RISCV64)
APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(DR_REG_RA)));
#else
/* FIXME i#1621: NYI on AArch32 */
ASSERT_NOT_IMPLEMENTED(false);
Expand Down Expand Up @@ -5915,6 +5945,10 @@ emit_clean_call_restore(dcontext_t *dcontext, byte *pc, generated_code_t *code)
insert_pop_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE, true);

APP(&ilist, INSTR_CREATE_br(dcontext, opnd_create_reg(DR_REG_X30)));
#elif defined(RISCV64)
insert_pop_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE);

APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(DR_REG_RA)));
#else
/* FIXME i#1621: NYI on AArch32 */
ASSERT_NOT_IMPLEMENTED(false);
Expand Down
10 changes: 6 additions & 4 deletions core/arch/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5467,6 +5467,7 @@ recreate_fragment_ilist(dcontext_t *dcontext, byte *pc,

/* XXX i#5062 In the future this call should be placed inside mangle_trace() */
IF_AARCH64(fixup_indirect_trace_exit(dcontext, ilist));
IF_RISCV64(ASSERT_NOT_IMPLEMENTED(false));

/* PR 214962: re-apply client changes, this time storing translation
* info for modified instrs
Expand Down Expand Up @@ -6196,6 +6197,7 @@ mangle_indirect_branch_in_trace(dcontext_t *dcontext, instrlist_t *trace,
}
}
# endif
/* end of X86 */
#elif defined(AARCH64)
instr_t *instr;
reg_id_t jump_target_reg;
Expand Down Expand Up @@ -6277,11 +6279,11 @@ mangle_indirect_branch_in_trace(dcontext_t *dcontext, instrlist_t *trace,
instrlist_remove(trace, targeter);
instr_destroy(dcontext, targeter);
added_size -= AARCH64_INSTR_SIZE;

#elif defined(ARM)
/* FIXME i#1551: NYI on ARM */
/* end of AARCH64 */
#else
/* FIXME i#1551 i#3544: NYI on ARM/RISCV64 */
ASSERT_NOT_IMPLEMENTED(false);
#endif /* X86/ARM */
#endif /* X86/ARM/RISCV64 */
return added_size;
}

Expand Down
3 changes: 3 additions & 0 deletions core/arch/mangle_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,10 @@ mangle_rseq_write_exit_reason(dcontext_t *dcontext, instrlist_t *ilist,
insert_mov_immed_ptrsz(dcontext, EXIT_REASON_RSEQ_ABORT, opnd_create_reg(scratch2),
ilist, insert_at, NULL, NULL);
# endif
# ifdef RISCV64
/* FIXME i#3544: Not implemented */
ASSERT_NOT_IMPLEMENTED(false);
# endif
PRE(ilist, insert_at,
XINST_CREATE_store_2bytes(
dcontext,
Expand Down
4 changes: 1 addition & 3 deletions core/arch/x86_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,11 @@ new_thread_setup(priv_mcontext_t *mc)
mc->IF_X86_ELSE(xax, IF_RISCV64_ELSE(a0, r0)) = 0;
/* clear pc */
mc->pc = 0;
# ifdef AARCHXX
# if defined(AARCHXX) || defined(RISCV64)
/* set the stolen register's app value */
set_stolen_reg_val(mc, get_clone_record_stolen_value(crec));
/* set the thread register if necessary */
set_thread_register_from_clone_record(crec);
# elif defined(RISCV64)
ASSERT_NOT_IMPLEMENTED(false);
# endif

DEBUG_DECLARE(int rc =)
Expand Down
2 changes: 1 addition & 1 deletion core/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ dispatch_enter_fcache(dcontext_t *dcontext, fragment_t *targetf)
(fcache_enter_func_t)
/* DEFAULT_ISA_MODE as we want the ISA mode of our gencode */
convert_data_to_function(PC_AS_JMP_TGT(DEFAULT_ISA_MODE, (app_pc)fcache_enter)),
#ifdef AARCH64
#if defined(AARCH64) || defined(RISCV64)
/* Entry to fcache requires indirect branch. */
PC_AS_JMP_TGT(FRAG_ISA_MODE(targetf->flags), FCACHE_PREFIX_ENTRY_PC(targetf))
#else
Expand Down
6 changes: 4 additions & 2 deletions core/fragment.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@
#define FRAG_ISA_MODE(flags) \
IF_X86_ELSE( \
IF_X64_ELSE((FRAG_IS_32(flags)) ? DR_ISA_IA32 : DR_ISA_AMD64, DR_ISA_IA32), \
IF_X64_ELSE(DR_ISA_ARM_A64, \
(TEST(FRAG_THUMB, (flags)) ? DR_ISA_ARM_THUMB : DR_ISA_ARM_A32)))
IF_AARCHXX_ELSE(IF_X64_ELSE(DR_ISA_ARM_A64, \
(TEST(FRAG_THUMB, (flags)) ? DR_ISA_ARM_THUMB \
: DR_ISA_ARM_A32)), \
DR_ISA_RV64IMAFDC))

static inline uint
frag_flags_from_isa_mode(dr_isa_mode_t mode)
Expand Down
5 changes: 3 additions & 2 deletions core/ir/disassemble_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -1508,8 +1508,9 @@ common_disassemble_fragment(dcontext_t *dcontext, fragment_t *f_in, file_t outfi
}
if (LINKSTUB_DIRECT(l->flags) && DIRECT_EXIT_STUB_DATA_SZ > 0) {
ASSERT(DIRECT_EXIT_STUB_DATA_SZ ==
sizeof(cache_pc)
IF_AARCH64(+DIRECT_EXIT_STUB_DATA_SLOT_ALIGNMENT_PADDING));
sizeof(cache_pc) IF_AARCH64_ELSE(
+DIRECT_EXIT_STUB_DATA_SLOT_ALIGNMENT_PADDING,
IF_RISCV64(+DIRECT_EXIT_STUB_DATA_SLOT_ALIGNMENT_PADDING)));
if (stub_is_patched(dcontext, f, EXIT_STUB_PC(dcontext, f, l))) {
print_file(outfile, " <stored target: " PFX ">\n",
*(cache_pc *)IF_AARCH64_ELSE(ALIGN_FORWARD(next_stop_pc, 8),
Expand Down
5 changes: 5 additions & 0 deletions core/ir/opnd.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,11 @@ extern reg_id_t dr_reg_stolen;
# define DR_REG_STOLEN_MAX DR_REG_X31
/* DR's stolen register for TLS access. */
extern reg_id_t dr_reg_stolen;
#elif defined(RISCV64)
/* DR's stolen register for TLS access */
# define DR_REG_STOLEN_MIN DR_REG_X18 /* DR_REG_SYSNUM + 1 */
# define DR_REG_STOLEN_MAX DR_REG_X31
extern reg_id_t dr_reg_stolen;
#endif

#endif /* _OPND_H_ */
5 changes: 1 addition & 4 deletions core/ir/opnd_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,7 @@ bool
opnd_is_memory_reference(opnd_t opnd)
{
return (opnd_is_base_disp(opnd) IF_X86_64(|| opnd_is_abs_addr(opnd)) ||
#if defined(X64) || defined(ARM)
#if (defined(X64) || defined(ARM)) && !defined(RISCV64)
opnd_is_rel_addr(opnd) ||
#endif
opnd_is_mem_instr(opnd));
Expand Down Expand Up @@ -2376,11 +2376,8 @@ opnd_compute_address_priv(opnd_t opnd, priv_mcontext_t *mc)
default: scaled_index = index_val;
}
#elif defined(RISCV64)
/* FIXME i#3544: Not implemented */
/* Marking as unused to silence -Wunused-variable. */
CLIENT_ASSERT(false, "Not implemented");
(void)index;
return NULL;
#endif
}
return opnd_compute_address_helper(opnd, mc, scaled_index);
Expand Down
10 changes: 4 additions & 6 deletions core/ir/riscv64/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ dr_app_pc_as_load_target(dr_isa_mode_t isa_mode, app_pc pc)
byte *
decode_eflags_usage(void *drcontext, byte *pc, uint *usage, dr_opnd_query_flags_t flags)
{
/* FIXME i#3544: Not implemented */
ASSERT_NOT_IMPLEMENTED(false);
return NULL;
*usage = 0; /* No eflags on RISC-V. */
return decode_next_pc(drcontext, pc);
}

byte *
Expand All @@ -92,9 +91,8 @@ decode_from_copy(void *drcontext, byte *copy_pc, byte *orig_pc, instr_t *instr)
byte *
decode_cti(void *drcontext, byte *pc, instr_t *instr)
{
/* FIXME i#3544: Not implemented */
ASSERT_NOT_IMPLEMENTED(false);
return NULL;
dcontext_t *dcontext = (dcontext_t *)drcontext;
return decode(dcontext, pc, instr);
}

byte *
Expand Down
1 change: 1 addition & 0 deletions core/monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,7 @@ end_and_emit_trace(dcontext_t *dcontext, fragment_t *cur_f)

/* XXX i#5062 In the future this call should be placed inside mangle_trace() */
IF_AARCH64(md->emitted_size += fixup_indirect_trace_exit(dcontext, trace));
IF_RISCV64(ASSERT_NOT_IMPLEMENTED(false));

if (DYNAMO_OPTION(speculate_last_exit)
#ifdef HASHTABLE_STATISTICS
Expand Down
13 changes: 8 additions & 5 deletions core/synch.c
Original file line number Diff line number Diff line change
Expand Up @@ -1801,11 +1801,14 @@ translate_from_synchall_to_dispatch(thread_record_t *tr, thread_synch_state_t sy
* But the stolen reg was restored to the application value during
* translate_mcontext.
*/
IF_AARCHXX({
/* Preserve the translated value from mc before we clobber it. */
dcontext->local_state->spill_space.reg_stolen = get_stolen_reg_val(mc);
set_stolen_reg_val(mc, (reg_t)os_get_dr_tls_base(dcontext));
});
#ifdef AARCHXX
/* Preserve the translated value from mc before we clobber it. */
dcontext->local_state->spill_space.reg_stolen = get_stolen_reg_val(mc);
set_stolen_reg_val(mc, (reg_t)os_get_dr_tls_base(dcontext));
#elif defined(RISCV64)
ASSERT_NOT_IMPLEMENTED(false);
#endif

#ifdef WINDOWS
/* i#25: we could have interrupted thread in DR, where has priv fls data
* in TEB, and fcache_return blindly copies into app fls: so swap to app
Expand Down
Loading

0 comments on commit c6f7b74

Please sign in to comment.