diff mbox series

[07/39] target/hexagon: Implement wait helper

Message ID 20250301052845.1012069-8-brian.cain@oss.qualcomm.com (mailing list archive)
State New
Headers show
Series hexagon system emu, part 2/3 | expand

Commit Message

Brian Cain March 1, 2025, 5:28 a.m. UTC
From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.h |  1 +
 target/hexagon/cpu_helper.c | 40 +++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c  |  6 +++++-
 3 files changed, 46 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 95a0cc0788..e8d89d8526 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -20,6 +20,7 @@  void clear_wait_mode(CPUHexagonState *env);
 void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause);
 void hexagon_start_threads(CPUHexagonState *env, uint32_t mask);
 void hexagon_stop_thread(CPUHexagonState *env);
+void hexagon_wait_thread(CPUHexagonState *env, target_ulong PC);
 
 static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
                                        uint32_t val)
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 3e2364a7b0..e64568b9fc 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -71,6 +71,46 @@  void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
     g_assert_not_reached();
 }
 
+static void set_wait_mode(CPUHexagonState *env)
+{
+    g_assert(bql_locked());
+
+    const uint32_t modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    uint32_t thread_wait_mask = GET_FIELD(MODECTL_W, modectl);
+    thread_wait_mask |= 0x1 << env->threadId;
+    SET_SYSTEM_FIELD(env, HEX_SREG_MODECTL, MODECTL_W, thread_wait_mask);
+}
+
+void hexagon_wait_thread(CPUHexagonState *env, target_ulong PC)
+{
+    g_assert(bql_locked());
+
+    if (qemu_loglevel_mask(LOG_GUEST_ERROR) &&
+        (env->k0_lock_state != HEX_LOCK_UNLOCKED ||
+         env->tlb_lock_state != HEX_LOCK_UNLOCKED)) {
+        qemu_log("WARNING: executing wait() with acquired lock"
+                 "may lead to deadlock\n");
+    }
+    g_assert(get_exe_mode(env) != HEX_EXE_MODE_WAIT);
+
+    CPUState *cs = env_cpu(env);
+    /*
+     * The addtion of cpu_has_work is borrowed from arm's wfi helper
+     * and is critical for our stability
+     */
+    if ((cs->exception_index != HEX_EVENT_NONE) ||
+        (cpu_has_work(cs))) {
+        qemu_log_mask(CPU_LOG_INT,
+            "%s: thread %d skipping WAIT mode, have some work\n",
+            __func__, env->threadId);
+        return;
+    }
+    set_wait_mode(env);
+    env->wait_next_pc = PC + 4;
+
+    cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+}
+
 static MMVector VRegs[VECTOR_UNIT_MAX][NUM_VREGS];
 static MMQReg QRegs[VECTOR_UNIT_MAX][NUM_QREGS];
 
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 83088cfaa3..03bed11f6e 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1458,7 +1458,11 @@  void HELPER(stop)(CPUHexagonState *env)
 
 void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+
+    if (!fIN_DEBUG_MODE(env->threadId)) {
+        hexagon_wait_thread(env, PC);
+    }
 }
 
 void HELPER(resume)(CPUHexagonState *env, uint32_t mask)