aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Henrique Barboza <dbarboza@ventanamicro.com>2025-07-14 10:37:39 -0300
committerAlistair Francis <alistair.francis@wdc.com>2025-07-30 10:59:26 +1000
commit16aa7771afeac422dcf7be2833d5426da6b814fa (patch)
treedecb1fd98e9d3c061ccf6150b5066e61c3985d8c
parente111ffe48b29ca8abd450af9ee5dd71af3f93536 (diff)
downloadqemu-16aa7771afeac422dcf7be2833d5426da6b814fa.zip
qemu-16aa7771afeac422dcf7be2833d5426da6b814fa.tar.gz
qemu-16aa7771afeac422dcf7be2833d5426da6b814fa.tar.bz2
target/riscv: do not call GETPC() in check_ret_from_m_mode()
GETPC() should always be called from the top level helper, e.g. the first helper that is called by the translation code. We stopped doing that in commit 3157a553ec, and then we introduced problems when unwinding the exceptions being thrown by helper_mret(), as reported by [1]. Call GETPC() at the top level helper and pass the value along. [1] https://gitlab.com/qemu-project/qemu/-/issues/3020 Suggested-by: Richard Henderson <richard.henderson@linaro.org> Fixes: 3157a553ec ("target/riscv: Add Smrnmi mnret instruction") Closes: https://gitlab.com/qemu-project/qemu/-/issues/3020 Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Nutty Liu <liujingqi@lanxincomputing.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20250714133739.1248296-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
-rw-r--r--target/riscv/op_helper.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 15460bf..110292e 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -355,21 +355,22 @@ target_ulong helper_sret(CPURISCVState *env)
}
static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc,
- target_ulong prev_priv)
+ target_ulong prev_priv,
+ uintptr_t ra)
{
if (!(env->priv >= PRV_M)) {
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
}
if (!riscv_cpu_allow_16bit_insn(&env_archcpu(env)->cfg,
env->priv_ver,
env->misa_ext) && (retpc & 0x3)) {
- riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, ra);
}
if (riscv_cpu_cfg(env)->pmp &&
!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
- riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, ra);
}
}
static target_ulong ssdbltrp_mxret(CPURISCVState *env, target_ulong mstatus,
@@ -394,8 +395,9 @@ target_ulong helper_mret(CPURISCVState *env)
target_ulong retpc = env->mepc & get_xepc_mask(env);
uint64_t mstatus = env->mstatus;
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
+ uintptr_t ra = GETPC();
- check_ret_from_m_mode(env, retpc, prev_priv);
+ check_ret_from_m_mode(env, retpc, prev_priv, ra);
target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV) &&
(prev_priv != PRV_M);
@@ -443,8 +445,9 @@ target_ulong helper_mnret(CPURISCVState *env)
target_ulong retpc = env->mnepc;
target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
target_ulong prev_virt;
+ uintptr_t ra = GETPC();
- check_ret_from_m_mode(env, retpc, prev_priv);
+ check_ret_from_m_mode(env, retpc, prev_priv, ra);
prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV) &&
(prev_priv != PRV_M);