diff mbox series

[21/39] target/hexagon: Implement hexagon_resume_threads()

Message ID 20250301052845.1012069-22-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.h        |  1 +
 target/hexagon/cpu_helper.h |  1 +
 target/hexagon/cpu_helper.c | 37 +++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c  |  3 ++-
 4 files changed, 41 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index d28c1249f3..baa48ec051 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -45,6 +45,7 @@  typedef struct CPUHexagonTLBContext CPUHexagonTLBContext;
 #define REG_WRITES_MAX 32
 #define PRED_WRITES_MAX 5                   /* 4 insns + endloop */
 #define VSTORES_MAX 2
+#define THREADS_MAX 8
 #define VECTOR_UNIT_MAX 8
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 1cdf4f8dd0..0723485e79 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -21,6 +21,7 @@  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);
+void hexagon_resume_threads(CPUHexagonState *env, uint32_t mask);
 
 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 1d9b9f8bef..cc1a896542 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -124,6 +124,43 @@  void hexagon_wait_thread(CPUHexagonState *env, target_ulong PC)
     cpu_interrupt(cs, CPU_INTERRUPT_HALT);
 }
 
+static void hexagon_resume_thread(CPUHexagonState *env)
+{
+    CPUState *cs = env_cpu(env);
+    clear_wait_mode(env);
+    /*
+     * The wait instruction keeps the PC pointing to itself
+     * so that it has an opportunity to check for interrupts.
+     *
+     * When we come out of wait mode, adjust the PC to the
+     * next executable instruction.
+     */
+    env->gpr[HEX_REG_PC] = env->wait_next_pc;
+    cs = env_cpu(env);
+    ASSERT_DIRECT_TO_GUEST_UNSET(env, cs->exception_index);
+    cs->halted = false;
+    cs->exception_index = HEX_EVENT_NONE;
+    qemu_cpu_kick(cs);
+}
+
+void hexagon_resume_threads(CPUHexagonState *current_env, uint32_t mask)
+{
+    CPUState *cs;
+    CPUHexagonState *env;
+
+    g_assert(bql_locked());
+    CPU_FOREACH(cs) {
+        env = cpu_env(cs);
+        g_assert(env->threadId < THREADS_MAX);
+        if ((mask & (0x1 << env->threadId))) {
+            if (get_exe_mode(env) == HEX_EXE_MODE_WAIT) {
+                hexagon_resume_thread(env);
+            }
+        }
+    }
+}
+
+
 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 118f112487..0dce133d3a 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1476,7 +1476,8 @@  void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
 
 void HELPER(resume)(CPUHexagonState *env, uint32_t mask)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+    hexagon_resume_threads(env, mask);
 }
 
 uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)