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

Reply via email to