Wake the selected K0 or TLB lock waiter when ownership passes. Update its interrupt state and kick the vCPU.
Reviewed-by: Pierrick Bouvier <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/cpu_helper.c | 2 ++ target/hexagon/hex_interrupts.c | 8 ++++++-- target/hexagon/hex_mmu.c | 3 +++ target/hexagon/op_helper.c | 2 ++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c index 1fdd81ad9b4..6f172270865 100644 --- a/target/hexagon/cpu_helper.c +++ b/target/hexagon/cpu_helper.c @@ -373,6 +373,7 @@ static uint32_t set_enable_mask(CPUHexagonState *env) thread_enabled_mask = GET_FIELD(MODECTL_E, modectl); thread_enabled_mask |= 0x1 << env->threadId; SET_SYSTEM_FIELD(env, HEX_SREG_MODECTL, MODECTL_E, thread_enabled_mask); + hex_interrupt_update(env); return thread_enabled_mask; } @@ -393,6 +394,7 @@ static uint32_t clear_enable_mask(CPUHexagonState *env) thread_enabled_mask = GET_FIELD(MODECTL_E, modectl); thread_enabled_mask &= ~(0x1 << env->threadId); SET_SYSTEM_FIELD(env, HEX_SREG_MODECTL, MODECTL_E, thread_enabled_mask); + hex_interrupt_update(env); return thread_enabled_mask; } static void do_start_thread(CPUState *cs, run_on_cpu_data tbd) diff --git a/target/hexagon/hex_interrupts.c b/target/hexagon/hex_interrupts.c index ab66d548a1e..03e1f28da9b 100644 --- a/target/hexagon/hex_interrupts.c +++ b/target/hexagon/hex_interrupts.c @@ -240,8 +240,10 @@ static bool hex_is_qualified_for_int(CPUHexagonState *env, int int_num) bool ssr_ie = get_ssr_ie(env); bool ssr_ex = get_ssr_ex(env); bool imask = get_imask_bit(env, int_num); + bool lock_pending = env->k0_lock_state != HEX_LOCK_UNLOCKED || + env->tlb_lock_state != HEX_LOCK_UNLOCKED; - return syscfg_gie && !iad && ssr_ie && !ssr_ex && !imask; + return syscfg_gie && !iad && ssr_ie && !ssr_ex && !imask && !lock_pending; } static void clear_pending_locks(CPUHexagonState *env) @@ -257,7 +259,9 @@ static void clear_pending_locks(CPUHexagonState *env) static bool should_not_exec(CPUHexagonState *env) { - return (get_exe_mode(env) == HEX_EXE_MODE_WAIT); + return get_exe_mode(env) == HEX_EXE_MODE_WAIT || + env->k0_lock_state == HEX_LOCK_WAITING || + env->tlb_lock_state == HEX_LOCK_WAITING; } static void restore_state(CPUHexagonState *env, bool int_accepted) diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c index 0ca52ed666d..637873b2668 100644 --- a/target/hexagon/hex_mmu.c +++ b/target/hexagon/hex_mmu.c @@ -19,6 +19,7 @@ #include "sys_macros.h" #include "hw/hexagon/hexagon_tlb.h" #include "hw/hexagon/hexagon_globalreg.h" +#include "hex_interrupts.h" static inline void hex_log_tlbw(uint32_t index, uint64_t entry) { @@ -271,6 +272,8 @@ void hex_tlb_unlock(CPUHexagonState *env) unlock_thread->tlb_lock_state = HEX_LOCK_QUEUED; SET_SYSCFG_FIELD(unlock_thread, SYSCFG_TLBLOCK, 1); cpu_interrupt(cs, CPU_INTERRUPT_TLB_UNLOCK); + hex_interrupt_update(unlock_thread); + qemu_cpu_kick(cs); } if (qemu_loglevel_mask(CPU_LOG_MMU)) { diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 8c292854de3..82d38dc0b08 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -1397,6 +1397,8 @@ static void hex_k0_unlock(CPUHexagonState *env) unlock_thread->k0_lock_state = HEX_LOCK_QUEUED; SET_SYSCFG_FIELD(unlock_thread, SYSCFG_K0LOCK, 1); cpu_interrupt(cs, CPU_INTERRUPT_K0_UNLOCK); + hex_interrupt_update(unlock_thread); + qemu_cpu_kick(cs); } } -- 2.34.1
