[PATCH 01/11] target/hexagon: align exceptions for user/sysemu

Brian Cain <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
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;
 
 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
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.