On 8/20/2026 1:40 PM, Pierrick Bouvier wrote:
On 8/18/2026 6:31 PM, Brian Cain wrote:System mode reports an exception as cs->exception_index = HEX_EVENT_* plus env->cause_code = HEX_CAUSE_*, but translated code in user mode put the cause code straight into exception_index, so cpu_loop() was decoding both forms. gen_exception_decode_fail() and the misaligned-PC check used the raw form unconditionally, so in system mode the cause code was misread as an event number. Use the {event, cause} everywhere and drop the duplicated cases from cpu_loop(), which fixes HEX_CAUSE_PRIV_USER_NO_SINSN and HEX_CAUSE_PRIV_USER_NO_GINSN. The misaligned PC is no longer zeroed on its way out either, so it reaches the signal frame as si_addr instead of whatever r31 held. Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/translate.h | 2 +- linux-user/hexagon/cpu_loop.c | 30 +++++++++++------------------- target/hexagon/cpu.c | 3 ++- target/hexagon/translate.c | 27 +++++++++------------------ 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h index 3c5773e2c73..00de2b0d2ec 100644 --- a/target/hexagon/translate.h +++ b/target/hexagon/translate.h @@ -330,7 +330,7 @@ extern TCGv_i32 hex_t_sreg[NUM_SREGS]; #endif-void hex_gen_exception_end_tb(DisasContext *ctx, int excp);+void hex_gen_exception_end_tb(DisasContext *ctx, int cause);void process_store(DisasContext *ctx, int slot_num); diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.cindex d7f73439dbc..e4ef97a1184 100644 --- a/linux-user/hexagon/cpu_loop.c +++ b/linux-user/hexagon/cpu_loop.c @@ -66,21 +66,22 @@ void cpu_loop(CPUHexagonState *env) case HEX_CAUSE_FETCH_NO_UPAGE: case HEX_CAUSE_PRIV_NO_UREAD: case HEX_CAUSE_PRIV_NO_UWRITE: - force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, - env->gpr[HEX_REG_PC]); - - break; + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, + env->gpr[HEX_REG_PC]); + break; case HEX_CAUSE_PRIV_USER_NO_GINSN: case HEX_CAUSE_PRIV_USER_NO_SINSN: case HEX_CAUSE_INVALID_PACKET: - force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, - env->gpr[HEX_REG_PC]); - break; + case HEX_CAUSE_REG_WRITE_CONFLICT: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, + env->gpr[HEX_REG_PC]); + break; case HEX_CAUSE_MISALIGNED_LOAD: case HEX_CAUSE_MISALIGNED_STORE: - force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, - env->gpr[HEX_REG_PC]); - break; + case HEX_CAUSE_PC_NOT_ALIGNED: + force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, + env->gpr[HEX_REG_PC]); + break; default: EXCP_DUMP(env, "\nqemu: unhandled CPU precise exception " "cause code 0x%x - aborting\n", @@ -88,15 +89,6 @@ void cpu_loop(CPUHexagonState *env) exit(EXIT_FAILURE); } break; - case HEX_CAUSE_PC_NOT_ALIGNED: - force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, - env->gpr[HEX_REG_R31]); - break; - case HEX_CAUSE_INVALID_PACKET: - case HEX_CAUSE_REG_WRITE_CONFLICT: - force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, - env->gpr[HEX_REG_PC]); - break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); break; diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index 7067e5b70f7..0bbefc2fb87 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -323,7 +323,8 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs) hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1); } if (pc & PCALIGN_MASK) { - hexagon_raise_exception_err(env, HEX_CAUSE_PC_NOT_ALIGNED, 0); + env->cause_code = HEX_CAUSE_PC_NOT_ALIGNED; + hexagon_raise_exception_err(env, HEX_EVENT_PRECISE, pc); }#ifndef CONFIG_USER_ONLYdiff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 06a8159d283..5cfa60ca302 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -73,8 +73,8 @@ TCGv hex_vstore_pending[VSTORES_MAX]; #ifndef CONFIG_USER_ONLY TCGv_i32 hex_greg[NUM_GREGS]; TCGv_i32 hex_t_sreg[NUM_SREGS]; -TCGv_i32 hex_cause_code; #endif +static TCGv_i32 hex_cause_code;Shouldn't this be part of CPUState? What if multiple cpus trigger an exception at the same time?
The cause_code is part of CPUState. This TCGv is a reference to that state member for use with translation. We take advantage of the single-threaded nature of translation with all of these file-global TCGv values.
static const char * const hexagon_prednames[] = { "p0", "p1", "p2", "p3" @@ -128,19 +128,14 @@ intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum, return offset; }-static void gen_exception(int excp, uint32_t PC)+static void gen_precise_exception(int cause, uint32_t PC) { - gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp), + tcg_gen_movi_i32(hex_cause_code, cause); + gen_helper_raise_exception(tcg_env, tcg_constant_i32(HEX_EVENT_PRECISE), tcg_constant_i32(PC)); }#ifndef CONFIG_USER_ONLY-static inline void gen_precise_exception(int excp, uint32_t PC) -{ - tcg_gen_movi_i32(hex_cause_code, excp); - gen_exception(HEX_EVENT_PRECISE, PC); -} - static void gen_pcycle_counters(DisasContext *ctx) { if (ctx->pcycle_enabled) { @@ -224,14 +219,10 @@ static void gen_end_tb(DisasContext *ctx) ctx->base.is_jmp = DISAS_NORETURN; }-void hex_gen_exception_end_tb(DisasContext *ctx, int excp)+void hex_gen_exception_end_tb(DisasContext *ctx, int cause) { gen_exec_counters(ctx); -#ifdef CONFIG_USER_ONLY - gen_exception(excp, ctx->pkt.pc); -#else - gen_precise_exception(excp, ctx->pkt.pc); -#endif + gen_precise_exception(cause, ctx->pkt.pc); ctx->base.is_jmp = DISAS_NORETURN; }@@ -239,13 +230,13 @@ void hex_gen_exception_end_tb(DisasContext *ctx, int excp)* Generate exception for decode failures. Unlike gen_exception_end_tb, * this is used when decode fails before ctx->next_PC is initialized. */ -static void gen_exception_decode_fail(DisasContext *ctx, int nwords, int excp) +static void gen_exception_decode_fail(DisasContext *ctx, int nwords, int cause) { target_ulong fail_pc = ctx->base.pc_next + nwords * sizeof(uint32_t);gen_exec_counters(ctx);tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], fail_pc); - gen_exception(excp, fail_pc); + gen_precise_exception(cause, fail_pc); ctx->base.is_jmp = DISAS_NORETURN; ctx->base.pc_next = fail_pc; } @@ -1361,9 +1352,9 @@ void hexagon_translate_init(void) offsetof(CPUHexagonState, llsc_val), "llsc_val"); hex_llsc_val_i64 = tcg_global_mem_new_i64(tcg_env, offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64"); -#ifndef CONFIG_USER_ONLY hex_cause_code = tcg_global_mem_new_i32(tcg_env, offsetof(CPUHexagonState, cause_code), "cause_code"); +#ifndef CONFIG_USER_ONLY hex_cycle_count = tcg_global_mem_new_i64(tcg_env, offsetof(CPUHexagonState, t_cycle_count), "t_cycle_count"); #endif
