hexagon-softmmu had no enforcement of alignment for scalar loads and
stores: the MO_ALIGN flag added by the previous two commits triggers
TLB_INVALID_MASK/alignment faults in cputlb.c, but Hexagon's
TCGCPUOps did not implement do_unaligned_access, so the fault was
never delivered to the guest.

Add hexagon_cpu_do_unaligned_access(), which raises
HEX_CAUSE_MISALIGNED_LOAD/_STORE via the existing HEX_EVENT_PRECISE
path, mirroring raise_tlbmiss_exception()/raise_perm_exception().

Also add a linux-user cpu_loop handler for these two cause codes for
consistency with hexswi.c's sysemu handling, even though linux-user's
own alignment check in accel/tcg/user-exec.c currently raises SIGBUS
before Hexagon's cause-code machinery is reached.

Signed-off-by: Brian Cain <[email protected]>
---
 linux-user/hexagon/cpu_loop.c |  5 +++++
 target/hexagon/cpu.c          | 25 +++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 0958c51fbb3..d7f73439dbc 100644
--- a/linux-user/hexagon/cpu_loop.c
+++ b/linux-user/hexagon/cpu_loop.c
@@ -76,6 +76,11 @@ void cpu_loop(CPUHexagonState *env)
             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;
             default:
                 EXCP_DUMP(env, "\nqemu: unhandled CPU precise exception "
                     "cause code 0x%x - aborting\n",
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 42d93e5da47..e2af736a99d 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -637,6 +637,18 @@ static void raise_perm_exception(CPUState *cs, uint32_t 
VA, int slot,
     cs->exception_index = excp;
 }
 
+static void raise_misaligned_exception(CPUState *cs, uint32_t VA, int slot,
+                                       MMUAccessType access_type)
+{
+    CPUHexagonState *env = cpu_env(cs);
+    int32_t excp = (access_type == MMU_DATA_STORE) ?
+                   HEX_CAUSE_MISALIGNED_STORE : HEX_CAUSE_MISALIGNED_LOAD;
+
+    set_badva_regs(env, VA, slot, access_type);
+    cs->exception_index = HEX_EVENT_PRECISE;
+    env->cause_code = excp;
+}
+
 static const char *access_type_names[] = { "MMU_DATA_LOAD ", "MMU_DATA_STORE",
                                            "MMU_INST_FETCH" };
 
@@ -715,6 +727,18 @@ static vaddr hexagon_pointer_wrap(CPUState *cs, int 
mmu_idx,
     return result;
 }
 
+static G_NORETURN
+void hexagon_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+                                     MMUAccessType access_type, int mmu_idx,
+                                     uintptr_t retaddr)
+{
+    CPUHexagonState *env = cpu_env(cs);
+
+    raise_misaligned_exception(cs, addr, 0, access_type);
+    do_raise_exception(env, cs->exception_index, env->gpr[HEX_REG_PC],
+                       retaddr);
+}
+
 #endif
 
 static const TCGCPUOps hexagon_tcg_ops = {
@@ -732,6 +756,7 @@ static const TCGCPUOps hexagon_tcg_ops = {
     .pointer_wrap = hexagon_pointer_wrap,
     .cpu_exec_reset = cpu_reset,
     .tlb_fill = hexagon_tlb_fill,
+    .do_unaligned_access = hexagon_cpu_do_unaligned_access,
     .cpu_exec_halt = hexagon_cpu_has_work,
     .do_interrupt = hexagon_cpu_do_interrupt,
 #endif /* !CONFIG_USER_ONLY */
-- 
2.34.1


Reply via email to