From: Brian Cain <bc...@quicinc.com> Signed-off-by: Brian Cain <brian.c...@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 --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) -- 2.34.1