After excpetion return, we should give a xlen view of context in new priveledge, including the general registers, pc, and CSRs.
Signed-off-by: LIU Zhiwei <zhiwei_...@c-sky.com> --- target/riscv/helper.h | 1 + .../riscv/insn_trans/trans_privileged.c.inc | 2 ++ target/riscv/op_helper.c | 26 +++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index e198d43981..9b379d7232 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -71,6 +71,7 @@ DEF_HELPER_2(sret, tl, env, tl) DEF_HELPER_2(mret, tl, env, tl) DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(tlb_flush, void, env) +DEF_HELPER_1(switch_context_xl, void, env) #endif /* Hypervisor functions */ diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index 75c6ef80a6..6e39632f83 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -78,6 +78,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) if (has_ext(ctx, RVS)) { gen_helper_sret(cpu_pc, cpu_env, cpu_pc); + gen_helper_switch_context_xl(cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; } else { @@ -94,6 +95,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a) #ifndef CONFIG_USER_ONLY tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); gen_helper_mret(cpu_pc, cpu_env, cpu_pc); + gen_helper_switch_context_xl(cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; return true; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index ee7c24efe7..20cf8ad883 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -70,6 +70,32 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr, } #ifndef CONFIG_USER_ONLY +void helper_switch_context_xl(CPURISCVState *env) +{ + RISCVMXL xl = cpu_get_xl(env); + if (xl == env->misa_mxl_max) { + return; + } + assert(xl < env->misa_mxl_max); + switch (xl) { + case MXL_RV32: + for (int i = 1; i < 32; i++) { + env->gpr[i] = (int32_t)env->gpr[i]; + } + env->pc = (int32_t)env->pc; + /* + * For the read-only bits of the previous-width CSR, the bits at the + * same positions in the temporary register are set to zeros. + */ + if ((env->priv == PRV_U) && (env->misa_ext & RVV)) { + env->vl = 0; + env->vtype = 0; + } + break; + default: + break; + } +} target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) { -- 2.25.1