On 8/20/2026 12:02 PM, Brian Cain wrote:
> 
> 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.c
>>> index 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_ONLY
>>> diff --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

Reviewed-by: Pierrick Bouvier <[email protected]>


Reply via email to