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?

>  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


Reply via email to