The mtval register can optionally contain the faulting instruction on an illegal instruction exception. This patch adds support for setting the mtval register based on the CPU feature.
Signed-off-by: Alistair Francis <alistair.fran...@wdc.com> --- target/riscv/cpu.h | 4 +++- target/riscv/helper.c | 13 +++++++++++-- target/riscv/translate.c | 12 ++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0243f73129..1bc46aa952 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -85,7 +85,8 @@ is currently no bit in misa to indicate whether an MMU exists or not so a cpu features bitfield is required */ enum { - RISCV_FEATURE_MMU + RISCV_FEATURE_MMU, + RISCV_FEATURE_MTVAL_INST }; #define USER_VERSION_2_02_0 0x00020200 @@ -113,6 +114,7 @@ struct CPURISCVState { target_ulong frm; target_ulong badaddr; + target_ulong bins; target_ulong user_ver; target_ulong priv_ver; diff --git a/target/riscv/helper.c b/target/riscv/helper.c index b4a3f80872..bd78bcff28 100644 --- a/target/riscv/helper.c +++ b/target/riscv/helper.c @@ -491,9 +491,18 @@ void riscv_cpu_do_interrupt(CPUState *cs) ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr); } env->mtval = env->badaddr; + } else if (cs->exception_index & RISCV_EXCP_ILLEGAL_INST) { + if (riscv_feature(env, RISCV_FEATURE_MTVAL_INST)) { + /* The mtval register can optionally also be used to + * return the faulting instruction bits on an illegal + * instruction exception. + */ + env->mtval = env->bins; + } else { + env->mtval = 0; + } } else { - /* otherwise we must clear mbadaddr/mtval - * todo: support populating mtval on illegal instructions */ + /* Otherwise we must clear mbadaddr/mtval */ env->mtval = 0; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 0b6be74f2d..1fe8b9c982 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -102,6 +102,15 @@ static void gen_exception_debug(void) static void gen_exception_illegal(DisasContext *ctx) { +#if defined(TARGET_RISCV64) + TCGv_i64 helper_tmp = tcg_const_i64(ctx->opcode); + tcg_gen_st_tl(helper_tmp, cpu_env, offsetof(CPURISCVState, bins)); + tcg_temp_free_i64(helper_tmp); +#else + TCGv_i32 helper_tmp = tcg_const_i32(ctx->opcode); + tcg_gen_st_tl(helper_tmp, cpu_env, offsetof(CPURISCVState, bins)); + tcg_temp_free_i32(helper_tmp); +#endif generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); } @@ -1287,6 +1296,9 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, tcg_gen_movi_tl(rs1_pass, rs1); tcg_gen_movi_tl(csr_store, csr); /* copy into temp reg to feed to helper */ + /* Store the opcode code incase we need it for mtval/stval. */ + env->bins = ctx->opcode; + #ifndef CONFIG_USER_ONLY /* Extract funct7 value and check whether it matches SFENCE.VMA */ if ((opc == OPC_RISC_ECALL) && ((csr >> 5) == 9)) { -- 2.17.1