@@ -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)
@@ -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];
@@ -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)