qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/39] hexagon system emulation v2, part 2/3
@ 2025-09-02  3:48 Brian Cain
  2025-09-02  3:48 ` [PATCH v2 01/39] target/hexagon: Implement ciad helper Brian Cain
                   ` (38 more replies)
  0 siblings, 39 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning

As with part 1, several issues have been addressed with v2 but some remain.
* From "Implement modify SSR": HVX context management is moved out of this
series (it is no longer present in any of part 1, 2, 3).  It can be
revisited after these land.

Issues remaining, to be considered for v3:
* "Implement wait helper" - move hexagon_wait_thread() to op_helper.c?
* "Implement arch_{s, g}et_{thread, system}_reg()" - remove
    arch_[sg]et_system_reg() entirely?
* "Implement setprio, resched" - use ~0 for BESTWAIT_PRIO
* "Add exec-start-addr prop" - don't use ULL for UINT32
* "Define system, guest reg names" - fix last five reg names
* "Add TLB, k0 {un,}lock" - revisit design with suggestion from Richard
* "Define gen_precise_exception" - reword commit subject

Brian Cain (37):
  target/hexagon: Implement ciad helper
  target/hexagon: Implement {c,}swi helpers
  target/hexagon: Implement iassign{r,w} helpers
  target/hexagon: Implement start/stop helpers, soft reset
  target/hexagon: Implement modify SSR
  target/hexagon: Implement {g,s}etimask helpers
  target/hexagon: Implement wait helper
  target/hexagon: Implement get_exe_mode()
  target/hexagon: Implement arch_get_system_reg()
  target/hexagon: Implement arch_{s,g}et_{thread,system}_reg()
  target/hexagon: Add representation to count cycles
  target/hexagon: Add implementation of cycle counters
  target/hexagon: Implement modify_syscfg()
  target/hexagon: Implement hex_tlb_entry_get_perm()
  target/hexagon: Implement hex_tlb_lookup_by_asid()
  target/hexagon: Implement software interrupt
  target/hexagon: Implement exec_interrupt, set_irq
  target/hexagon: Implement hexagon_tlb_fill()
  target/hexagon: Implement siad inst
  target/hexagon: Implement hexagon_resume_threads()
  target/hexagon: Implement setprio, resched
  target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug()
  target/hexagon: Add exec-start-addr prop
  target/hexagon: extend hexagon_cpu_mmu_index() for sysemu
  target/hexagon: Decode trap1, rte as COF
  target/hexagon: Implement hexagon_find_last_irq()
  target/hexagon: Implement modify_ssr, resched, pending_interrupt
  target/hexagon: Add pkt_ends_tb to translation
  target/hexagon: Add next_PC, {s,g}reg writes
  target/hexagon: Add implicit sysreg writes
  target/hexagon: Define system, guest reg names
  target/hexagon: initialize sys/guest reg TCGvs
  target/hexagon: Add TLB, k0 {un,}lock
  target/hexagon: Define gen_precise_exception()
  target/hexagon: Add TCG overrides for transfer insts
  target/hexagon: Add support for loadw_phys
  target/hexagon: Add pcycle setting functionality

Matheus Tavares Bernardino (2):
  target/hexagon: add simple cpu_exec_reset and pointer_wrap
  target/hexagon: Add guest reg reading functionality

 target/hexagon/cpu.h                  |  13 +-
 target/hexagon/cpu_helper.h           |  21 +-
 target/hexagon/gen_tcg.h              |   7 -
 target/hexagon/gen_tcg_sys.h          |  25 ++
 target/hexagon/helper.h               |   7 +-
 target/hexagon/hexswi.h               |  17 +
 target/hexagon/internal.h             |   2 +
 target/hexagon/sys_macros.h           |   8 +-
 target/hexagon/translate.h            |   5 +
 target/hexagon/reg_fields_def.h.inc   |  11 +
 linux-user/hexagon/cpu_loop.c         |   7 +
 target/hexagon/cpu.c                  | 349 ++++++++++++++++++++-
 target/hexagon/cpu_helper.c           | 358 ++++++++++++++++++++-
 target/hexagon/decode.c               |  14 +
 target/hexagon/genptr.c               |   7 +-
 target/hexagon/hex_mmu.c              |  84 ++++-
 target/hexagon/hexswi.c               | 256 +++++++++++++++
 target/hexagon/machine.c              |   2 +-
 target/hexagon/op_helper.c            | 430 ++++++++++++++++++++++++--
 target/hexagon/translate.c            | 304 ++++++++++++++++--
 target/hexagon/hex_common.py          |   3 +
 target/hexagon/imported/encode_pp.def |   1 +
 target/hexagon/imported/ldst.idef     |   3 +
 23 files changed, 1848 insertions(+), 86 deletions(-)
 create mode 100644 target/hexagon/hexswi.h
 create mode 100644 target/hexagon/hexswi.c

-- 
2.34.1



^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 01/39] target/hexagon: Implement ciad helper
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 02/39] target/hexagon: Implement {c,}swi helpers Brian Cain
                   ` (37 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

ciad is the clear interrupt auto disable instruction.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 45 +++++++++++++++++++++++++++++++++-----
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index a03fd078be..c38107d5a8 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -34,6 +34,12 @@
 #include "op_helper.h"
 #include "cpu_helper.h"
 #include "translate.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/hexagon/hexagon_globalreg.h"
+#include "hex_mmu.h"
+#include "hw/intc/l2vic.h"
+#include "hex_interrupts.h"
+#endif
 
 #define SF_BIAS        127
 #define SF_MANTBITS    23
@@ -1338,9 +1344,41 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
 }
 
 #ifndef CONFIG_USER_ONLY
+static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, uint32_t val)
+{
+    g_assert((offset == L2VIC_VID_0) || (offset == L2VIC_VID_1));
+    CPUState *cs = env_cpu(env);
+    HexagonCPU *cpu = HEXAGON_CPU(cs);
+    const hwaddr pend_mem = cpu->l2vic_base_addr + offset;
+    cpu_physical_memory_write(pend_mem, &val, sizeof(val));
+}
+
+static void hexagon_clear_last_irq(CPUHexagonState *env, uint32_t offset)
+{
+    hexagon_set_vid(env, offset, L2VIC_CIAD_INSTRUCTION);
+}
+
+/*
+ * ciad - clear interrupt auto disable
+ *  - When taking an interrupt the hardware will set ipend.iad to
+ *    prevent another thread from servicing the interrupt.  At the completion
+ *    of service software uses ciad to clear the bit indicating the
+ *    interrupt can be accepted again.
+ *  - ciad also handshakes with the l2vic allowing a new vid on the vector
+ *    port.
+ */
 void HELPER(ciad)(CPUHexagonState *env, uint32_t mask)
 {
-    g_assert_not_reached();
+    uint32_t ipendad;
+    uint32_t iad;
+
+    BQL_LOCK_GUARD();
+    ipendad = READ_SREG(HEX_SREG_IPENDAD);
+    iad = fGET_FIELD(ipendad, IPENDAD_IAD);
+    fSET_FIELD(ipendad, IPENDAD_IAD, iad & ~(mask));
+    arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+    hexagon_clear_last_irq(env, L2VIC_VID_0);
+    hex_interrupt_update(env);
 }
 
 void HELPER(siad)(CPUHexagonState *env, uint32_t mask)
@@ -1416,11 +1454,6 @@ static void modify_syscfg(CPUHexagonState *env, uint32_t val)
     g_assert_not_reached();
 }
 
-static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, int val)
-{
-    g_assert_not_reached();
-}
-
 static uint32_t hexagon_find_last_irq(CPUHexagonState *env, uint32_t vid)
 {
     g_assert_not_reached();
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 02/39] target/hexagon: Implement {c,}swi helpers
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
  2025-09-02  3:48 ` [PATCH v2 01/39] target/hexagon: Implement ciad helper Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 03/39] target/hexagon: Implement iassign{r,w} helpers Brian Cain
                   ` (36 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

{c,}swi are the "software interrupt"/"Cancel pending interrupts" instructions.


Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index c38107d5a8..875935b903 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -23,6 +23,7 @@
 #include "exec/helper-proto.h"
 #include "fpu/softfloat.h"
 #include "cpu.h"
+#include "exec/cpu-interrupt.h"
 #include "internal.h"
 #include "macros.h"
 #include "sys_macros.h"
@@ -1388,12 +1389,14 @@ void HELPER(siad)(CPUHexagonState *env, uint32_t mask)
 
 void HELPER(swi)(CPUHexagonState *env, uint32_t mask)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+    hex_raise_interrupts(env, mask, CPU_INTERRUPT_SWI);
 }
 
 void HELPER(cswi)(CPUHexagonState *env, uint32_t mask)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+    hex_clear_interrupts(env, mask, CPU_INTERRUPT_SWI);
 }
 
 void HELPER(iassignw)(CPUHexagonState *env, uint32_t src)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 03/39] target/hexagon: Implement iassign{r,w} helpers
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
  2025-09-02  3:48 ` [PATCH v2 01/39] target/hexagon: Implement ciad helper Brian Cain
  2025-09-02  3:48 ` [PATCH v2 02/39] target/hexagon: Implement {c,}swi helpers Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 04/39] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
                   ` (35 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

iassign{r,w} are the "Interrupt to thread assignment {read,write}"
instructions.


Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 48 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 875935b903..74f8c1bf4f 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1401,12 +1401,56 @@ void HELPER(cswi)(CPUHexagonState *env, uint32_t mask)
 
 void HELPER(iassignw)(CPUHexagonState *env, uint32_t src)
 {
-    g_assert_not_reached();
+    uint32_t modectl;
+    uint32_t thread_enabled_mask;
+    CPUState *cpu;
+
+    BQL_LOCK_GUARD();
+    modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
+
+    CPU_FOREACH(cpu) {
+        CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env);
+        uint32_t thread_id_mask = 0x1 << thread_env->threadId;
+        if (thread_enabled_mask & thread_id_mask) {
+            uint32_t imask = arch_get_system_reg(thread_env, HEX_SREG_IMASK);
+            uint32_t intbitpos = (src >> 16) & 0xF;
+            uint32_t val = (src >> thread_env->threadId) & 0x1;
+            imask = deposit32(imask, intbitpos, 1, val);
+            arch_set_system_reg(thread_env, HEX_SREG_IMASK, imask);
+
+            qemu_log_mask(CPU_LOG_INT, "%s: thread " TARGET_FMT_ld
+               ", new imask 0x%" PRIx32 "\n", __func__,
+               thread_env->threadId, imask);
+        }
+    }
+    hex_interrupt_update(env);
 }
 
 uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src)
 {
-    g_assert_not_reached();
+    uint32_t modectl;
+    uint32_t thread_enabled_mask;
+    uint32_t intbitpos;
+    uint32_t dest_reg;
+    CPUState *cpu;
+
+    BQL_LOCK_GUARD();
+    modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
+    /* src fields are in same position as modectl, but mean different things */
+    intbitpos = GET_FIELD(MODECTL_W, src);
+    dest_reg = 0;
+    CPU_FOREACH(cpu) {
+        CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env);
+        uint32_t thread_id_mask = 0x1 << thread_env->threadId;
+        if (thread_enabled_mask & thread_id_mask) {
+            uint32_t imask = arch_get_system_reg(thread_env, HEX_SREG_IMASK);
+            dest_reg |= ((imask >> intbitpos) & 0x1) << thread_env->threadId;
+        }
+    }
+
+    return dest_reg;
 }
 
 void HELPER(start)(CPUHexagonState *env, uint32_t imask)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 04/39] target/hexagon: Implement start/stop helpers, soft reset
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (2 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 03/39] target/hexagon: Implement iassign{r,w} helpers Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 05/39] target/hexagon: Implement modify SSR Brian Cain
                   ` (34 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

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 |  3 ++
 target/hexagon/cpu.c        | 18 ++++++-
 target/hexagon/cpu_helper.c | 94 +++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c  |  4 +-
 5 files changed, 117 insertions(+), 3 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index d369e104ae..a0448eba44 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -209,6 +209,7 @@ G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
 uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg);
 uint32_t hexagon_sreg_read(CPUHexagonState *env, uint32_t reg);
 void hexagon_gdb_sreg_write(CPUHexagonState *env, uint32_t reg, uint32_t val);
+void hexagon_cpu_soft_reset(CPUHexagonState *env);
 #endif
 
 typedef HexagonCPU ArchCPU;
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 6f0c6697ad..95a0cc0788 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -17,6 +17,9 @@ void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env, uint32_t);
 void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old);
 int get_exe_mode(CPUHexagonState *env);
 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);
 
 static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
                                        uint32_t val)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index c128f47ad3..e35ac92402 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -32,6 +32,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "sys_macros.h"
 #include "accel/tcg/cpu-ldst.h"
+#include "qemu/main-loop.h"
 #endif
 
 static void hexagon_v66_cpu_init(Object *obj) { }
@@ -312,9 +313,23 @@ static void mmu_reset(CPUHexagonState *env)
         memset(env->hex_tlb, 0, sizeof(*env->hex_tlb));
     }
 }
+
+void hexagon_cpu_soft_reset(CPUHexagonState *env)
+{
+    BQL_LOCK_GUARD();
+    arch_set_system_reg(env, HEX_SREG_SSR, 0);
+    hexagon_ssr_set_cause(env, HEX_CAUSE_RESET);
+
+    HexagonCPU *cpu = env_archcpu(env);
+    if (cpu->globalregs) {
+        target_ulong evb = arch_get_system_reg(env, HEX_SREG_EVB);
+        arch_set_thread_reg(env, HEX_REG_PC, evb);
+    } else {
+        arch_set_thread_reg(env, HEX_REG_PC, cpu->boot_addr);
+    }
+}
 #endif
 
-
 static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
 {
     CPUState *cs = CPU(obj);
@@ -337,6 +352,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
 
     mmu_reset(env);
     arch_set_system_reg(env, HEX_SREG_HTID, cs->cpu_index);
+    hexagon_cpu_soft_reset(env);
     memset(env->t_sreg, 0, sizeof(target_ulong) * NUM_SREGS);
     memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS);
     env->threadId = cs->cpu_index;
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 00f47e5a07..74ce59adf4 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -89,8 +89,102 @@ void clear_wait_mode(CPUHexagonState *env)
     }
 }
 
+void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause)
+{
+    g_assert(bql_locked());
+
+    const uint32_t old = arch_get_system_reg(env, HEX_SREG_SSR);
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_EX, 1);
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_CAUSE, cause);
+    const uint32_t new = arch_get_system_reg(env, HEX_SREG_SSR);
+
+    hexagon_modify_ssr(env, new, old);
+}
+
+
 int get_exe_mode(CPUHexagonState *env)
 {
     g_assert_not_reached();
 }
+
+static void set_enable_mask(CPUHexagonState *env)
+{
+    g_assert(bql_locked());
+
+    const uint32_t modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    uint32_t 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);
+}
+
+static uint32_t clear_enable_mask(CPUHexagonState *env)
+{
+    g_assert(bql_locked());
+
+    const uint32_t modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    uint32_t 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);
+    return thread_enabled_mask;
+}
+static void do_start_thread(CPUState *cs, run_on_cpu_data tbd)
+{
+    BQL_LOCK_GUARD();
+
+    CPUHexagonState *env = cpu_env(cs);
+
+    hexagon_cpu_soft_reset(env);
+
+    set_enable_mask(env);
+
+    cs->halted = 0;
+    cs->exception_index = HEX_EVENT_NONE;
+    cpu_resume(cs);
+}
+
+void hexagon_start_threads(CPUHexagonState *current_env, uint32_t mask)
+{
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        CPUHexagonState *env = cpu_env(cs);
+        if (!(mask & (0x1 << env->threadId))) {
+            continue;
+        }
+
+        if (current_env->threadId != env->threadId) {
+            async_safe_run_on_cpu(cs, do_start_thread, RUN_ON_CPU_NULL);
+        }
+    }
+}
+
+/*
+ * When we have all threads stopped, the return
+ * value to the shell is register 2 from thread 0.
+ */
+static target_ulong get_thread0_r2(void)
+{
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        CPUHexagonState *thread = cpu_env(cs);
+        if (thread->threadId == 0) {
+            return thread->gpr[2];
+        }
+    }
+    g_assert_not_reached();
+}
+
+void hexagon_stop_thread(CPUHexagonState *env)
+
+{
+    BQL_LOCK_GUARD();
+
+    uint32_t thread_enabled_mask = clear_enable_mask(env);
+    CPUState *cs = env_cpu(env);
+    cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+    if (!thread_enabled_mask) {
+        /* All threads are stopped, exit */
+        exit(get_thread0_r2());
+    }
+}
+
 #endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 74f8c1bf4f..4b1fc23a15 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1455,12 +1455,12 @@ uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src)
 
 void HELPER(start)(CPUHexagonState *env, uint32_t imask)
 {
-    g_assert_not_reached();
+    hexagon_start_threads(env, imask);
 }
 
 void HELPER(stop)(CPUHexagonState *env)
 {
-    g_assert_not_reached();
+    hexagon_stop_thread(env);
 }
 
 void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 05/39] target/hexagon: Implement modify SSR
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (3 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 04/39] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 06/39] target/hexagon: Implement {g,s}etimask helpers Brian Cain
                   ` (33 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

The per-vCPU System Status Register controls many modal behaviors of the
system architecture.  When the SSR is updated, we trigger the necessary
effects for interrupts, privilege/MMU, and HVX context mapping.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 74ce59adf4..11a9dff522 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -14,6 +14,9 @@
 #else
 #include "hw/boards.h"
 #include "hw/hexagon/hexagon.h"
+#include "hw/hexagon/hexagon_globalreg.h"
+#include "hex_interrupts.h"
+#include "hex_mmu.h"
 #endif
 #include "exec/cpu-interrupt.h"
 #include "exec/target_page.h"
@@ -73,7 +76,35 @@ void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
 
 void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
 {
-    g_assert_not_reached();
+    g_assert(bql_locked());
+
+    bool old_EX = GET_SSR_FIELD(SSR_EX, old);
+    bool old_UM = GET_SSR_FIELD(SSR_UM, old);
+    bool old_GM = GET_SSR_FIELD(SSR_GM, old);
+    bool old_IE = GET_SSR_FIELD(SSR_IE, old);
+    bool new_EX = GET_SSR_FIELD(SSR_EX, new);
+    bool new_UM = GET_SSR_FIELD(SSR_UM, new);
+    bool new_GM = GET_SSR_FIELD(SSR_GM, new);
+    bool new_IE = GET_SSR_FIELD(SSR_IE, new);
+
+    if ((old_EX != new_EX) ||
+        (old_UM != new_UM) ||
+        (old_GM != new_GM)) {
+        hex_mmu_mode_change(env);
+    }
+
+    uint8_t old_asid = GET_SSR_FIELD(SSR_ASID, old);
+    uint8_t new_asid = GET_SSR_FIELD(SSR_ASID, new);
+    if (new_asid != old_asid) {
+        CPUState *cs = env_cpu(env);
+        tlb_flush(cs);
+    }
+
+    /* See if the interrupts have been enabled or we have exited EX mode */
+    if ((new_IE && !old_IE) ||
+        (!new_EX && old_EX)) {
+        hex_interrupt_update(env);
+    }
 }
 
 void clear_wait_mode(CPUHexagonState *env)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 06/39] target/hexagon: Implement {g,s}etimask helpers
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (4 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 05/39] target/hexagon: Implement modify SSR Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 07/39] target/hexagon: Implement wait helper Brian Cain
                   ` (32 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 4b1fc23a15..03e69421c7 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1475,12 +1475,41 @@ void HELPER(resume)(CPUHexagonState *env, uint32_t mask)
 
 uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
 {
-    g_assert_not_reached();
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        HexagonCPU *found_cpu = HEXAGON_CPU(cs);
+        CPUHexagonState *found_env = &found_cpu->env;
+        if (found_env->threadId == tid) {
+            target_ulong imask = arch_get_system_reg(found_env, HEX_SREG_IMASK);
+            qemu_log_mask(CPU_LOG_INT, "%s: tid %d imask = 0x%x\n",
+                          __func__, env->threadId,
+                          (unsigned)GET_FIELD(IMASK_MASK, imask));
+            return GET_FIELD(IMASK_MASK, imask);
+        }
+    }
+    return 0;
 }
 
 void HELPER(setimask)(CPUHexagonState *env, uint32_t pred, uint32_t imask)
 {
-    g_assert_not_reached();
+    CPUState *cs;
+
+    BQL_LOCK_GUARD();
+    CPU_FOREACH(cs) {
+        HexagonCPU *found_cpu = HEXAGON_CPU(cs);
+        CPUHexagonState *found_env = &found_cpu->env;
+
+        if (pred == found_env->threadId) {
+            SET_SYSTEM_FIELD(found_env, HEX_SREG_IMASK, IMASK_MASK, imask);
+            qemu_log_mask(CPU_LOG_INT, "%s: tid %d imask 0x%x\n",
+                          __func__, found_env->threadId, imask);
+            hex_interrupt_update(env);
+            return;
+        }
+    }
+    qemu_log_mask(LOG_GUEST_ERROR,
+                  "setimask used with an invalid predicate near PC: 0x%x\n",
+                  env->next_PC);
 }
 
 static bool handle_pmu_sreg_write(CPUHexagonState *env, uint32_t reg,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 07/39] target/hexagon: Implement wait helper
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (5 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 06/39] target/hexagon: Implement {g,s}etimask helpers Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 08/39] target/hexagon: Implement get_exe_mode() Brian Cain
                   ` (31 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.h | 1 +
 target/hexagon/op_helper.c  | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 95a0cc0788..e8d89d8526 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -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)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 03e69421c7..a8b44a73bd 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1465,7 +1465,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)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 08/39] target/hexagon: Implement get_exe_mode()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (6 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 07/39] target/hexagon: Implement wait helper Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 09/39] target/hexagon: Implement arch_get_system_reg() Brian Cain
                   ` (30 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/reg_fields_def.h.inc | 11 +++++++++++
 target/hexagon/cpu_helper.c         | 23 +++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/target/hexagon/reg_fields_def.h.inc b/target/hexagon/reg_fields_def.h.inc
index 9b112ccec6..d2c706d56b 100644
--- a/target/hexagon/reg_fields_def.h.inc
+++ b/target/hexagon/reg_fields_def.h.inc
@@ -135,3 +135,14 @@ DEF_REG_FIELD(CCR_GRE, 27, 1)
 DEF_REG_FIELD(CCR_VV1, 29, 1)
 DEF_REG_FIELD(CCR_VV2, 30, 1)
 DEF_REG_FIELD(CCR_VV3, 31, 1)
+
+/* ISDB ST fields */
+DEF_REG_FIELD(ISDBST_WAITRUN, 24, 8)
+DEF_REG_FIELD(ISDBST_ONOFF, 16, 8)
+DEF_REG_FIELD(ISDBST_DEBUGMODE, 8, 8)
+DEF_REG_FIELD(ISDBST_STUFFSTATUS, 5, 1)
+DEF_REG_FIELD(ISDBST_CMDSTATUS, 4, 1)
+DEF_REG_FIELD(ISDBST_PROCMODE, 3, 1)
+DEF_REG_FIELD(ISDBST_MBXINSTATUS, 2, 1)
+DEF_REG_FIELD(ISDBST_MBXOUTSTATUS, 1, 1)
+DEF_REG_FIELD(ISDBST_READY, 0, 1)
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 11a9dff522..1a1520214e 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -135,6 +135,29 @@ void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause)
 
 int get_exe_mode(CPUHexagonState *env)
 {
+    g_assert(bql_locked());
+
+    target_ulong modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    uint32_t thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
+    bool E_bit = thread_enabled_mask & (0x1 << env->threadId);
+    uint32_t thread_wait_mask = GET_FIELD(MODECTL_W, modectl);
+    bool W_bit = thread_wait_mask & (0x1 << env->threadId);
+    target_ulong isdbst = arch_get_system_reg(env, HEX_SREG_ISDBST);
+    uint32_t debugmode = GET_FIELD(ISDBST_DEBUGMODE, isdbst);
+    bool D_bit = debugmode & (0x1 << env->threadId);
+
+    if (!D_bit && !W_bit && !E_bit) {
+        return HEX_EXE_MODE_OFF;
+    }
+    if (!D_bit && !W_bit && E_bit) {
+        return HEX_EXE_MODE_RUN;
+    }
+    if (!D_bit && W_bit && E_bit) {
+        return HEX_EXE_MODE_WAIT;
+    }
+    if (D_bit && !W_bit && E_bit) {
+        return HEX_EXE_MODE_DEBUG;
+    }
     g_assert_not_reached();
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 09/39] target/hexagon: Implement arch_get_system_reg()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (7 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 08/39] target/hexagon: Implement get_exe_mode() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 10/39] target/hexagon: Implement arch_{s, g}et_{thread, system}_reg() Brian Cain via
                   ` (29 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 1a1520214e..4732a698b4 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -39,7 +39,38 @@ uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index)
 
 uint32_t arch_get_system_reg(CPUHexagonState *env, uint32_t reg)
 {
-    g_assert_not_reached();
+    if (reg == HEX_SREG_PCYCLELO) {
+        return hexagon_get_sys_pcycle_count_low(env);
+    } else if (reg == HEX_SREG_PCYCLEHI) {
+        return hexagon_get_sys_pcycle_count_high(env);
+    }
+
+    g_assert(reg < NUM_SREGS);
+    if (reg < HEX_SREG_GLB_START) {
+        return env->t_sreg[reg];
+    } else {
+#ifndef CONFIG_USER_ONLY
+        HexagonCPU *cpu = env_archcpu(env);
+        return cpu->globalregs ? hexagon_globalreg_read(cpu, reg) : 0;
+#else
+        return 0;
+#endif
+    }
+}
+
+void arch_set_system_reg(CPUHexagonState *env, uint32_t reg, uint32_t val)
+{
+    g_assert(reg < NUM_SREGS);
+    if (reg < HEX_SREG_GLB_START) {
+        env->t_sreg[reg] = val;
+    } else {
+#ifndef CONFIG_USER_ONLY
+        HexagonCPU *cpu = env_archcpu(env);
+        if (cpu->globalregs) {
+            hexagon_globalreg_write(cpu, reg, val);
+        }
+#endif
+    }
 }
 
 uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 10/39] target/hexagon: Implement arch_{s, g}et_{thread, system}_reg()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (8 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 09/39] target/hexagon: Implement arch_get_system_reg() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain via
  2025-09-02  3:48 ` [PATCH v2 11/39] target/hexagon: Add representation to count cycles Brian Cain
                   ` (28 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain via @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.h | 15 ++++++++-------
 target/hexagon/cpu_helper.c | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index e8d89d8526..f7400031ef 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -26,20 +26,21 @@ static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
                                        uint32_t val)
 {
     g_assert(reg < TOTAL_PER_THREAD_REGS);
-    g_assert_not_reached();
+    env->gpr[reg] = val;
 }
 
 static inline uint32_t arch_get_thread_reg(CPUHexagonState *env, uint32_t reg)
 {
     g_assert(reg < TOTAL_PER_THREAD_REGS);
-    g_assert_not_reached();
+    return env->gpr[reg];
 }
 
-static inline void arch_set_system_reg(CPUHexagonState *env, uint32_t reg,
-                                       uint32_t val)
-{
-    g_assert_not_reached();
-}
+#ifndef CONFIG_USER_ONLY
+void arch_set_system_reg(CPUHexagonState *env, uint32_t reg,
+                        uint32_t val);
+void arch_set_system_reg_masked(CPUHexagonState *env, uint32_t reg,
+                                uint32_t val);
+#endif
 
 uint32_t arch_get_system_reg(CPUHexagonState *env, uint32_t reg);
 
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 4732a698b4..fc49fe7883 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -73,6 +73,22 @@ void arch_set_system_reg(CPUHexagonState *env, uint32_t reg, uint32_t val)
     }
 }
 
+void arch_set_system_reg_masked(CPUHexagonState *env, uint32_t reg,
+                                 uint32_t val)
+{
+    g_assert(reg < NUM_SREGS);
+    if (reg < HEX_SREG_GLB_START) {
+        env->t_sreg[reg] = val;
+    } else {
+#ifndef CONFIG_USER_ONLY
+        HexagonCPU *cpu = env_archcpu(env);
+        if (cpu->globalregs) {
+            hexagon_globalreg_write_masked(cpu, reg, val);
+        }
+#endif
+    }
+}
+
 uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env)
 {
     g_assert_not_reached();
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 11/39] target/hexagon: Add representation to count cycles
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (9 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 10/39] target/hexagon: Implement arch_{s, g}et_{thread, system}_reg() Brian Cain via
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 12/39] target/hexagon: Add implementation of cycle counters Brian Cain
                   ` (27 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

The PCYCLE register can be enabled to indicate accumulated clock cycles.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h     | 2 +-
 target/hexagon/machine.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index a0448eba44..8046f7bff0 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -128,7 +128,7 @@ typedef struct CPUArchState {
     target_ulong stack_start;
 
     uint8_t slot_cancelled;
-
+    uint64_t t_cycle_count;
 #ifndef CONFIG_USER_ONLY
     /* Some system registers are per thread and some are global. */
     target_ulong t_sreg[NUM_SREGS];
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index f3d2bdf41d..7c471d1f3b 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -35,7 +35,6 @@ const VMStateInfo vmstate_info_hex_tlb_ptr = {
     .put  = put_hex_tlb_ptr,
 };
 
-
 const VMStateDescription vmstate_hexagon_cpu = {
     .name = "cpu",
     .version_id = 0,
@@ -56,6 +55,7 @@ const VMStateDescription vmstate_hexagon_cpu = {
         VMSTATE_UINTTL(env.wait_next_pc, HexagonCPU),
         VMSTATE_POINTER(env.hex_tlb, HexagonCPU, 0,
                         vmstate_info_hex_tlb_ptr, CPUHexagonTLBContext *),
+        VMSTATE_UINT64(env.t_cycle_count, HexagonCPU),
 
         VMSTATE_END_OF_LIST()
     },
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 12/39] target/hexagon: Add implementation of cycle counters
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (10 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 11/39] target/hexagon: Add representation to count cycles Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 13/39] target/hexagon: Implement modify_syscfg() Brian Cain
                   ` (26 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain, Sid Manning

From: Brian Cain <bcain@quicinc.com>

The PCYCLE register is available in system mode, but only increments
when the SYSCFG.PCYCLEEN field is set.

The UPCYCLE register is available in user mode and we model it
unconditionally in linux-user emulation, as if the system had enabled
PCYCCLEEN.

For now, the model is very crudely counting the sum of instructions
executed among vCPUs, regardless of how the instructions were actually
scheduled.  This is sufficient for demonstrating a rough level of
activity but will be particularly misleading for benchmarks and performance
tuning.  We may decide to revisit this model in order to give more
a bit more fidelity, though without a cache model it would still be very far
from accurate.

Co-authored-by: Sid Manning <sidneym@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h        |  3 +++
 target/hexagon/translate.h  |  2 ++
 target/hexagon/cpu.c        | 11 +++++++++++
 target/hexagon/cpu_helper.c | 33 +++++++++++++++++++++++++++++----
 target/hexagon/translate.c  | 27 +++++++++++++++++++++++++++
 5 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 8046f7bff0..354e9e9cbf 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -28,6 +28,7 @@
 #include "cpu-qom.h"
 #include "exec/cpu-common.h"
 #include "exec/cpu-defs.h"
+#include "exec/cpu-common.h"
 #include "hex_regs.h"
 #include "mmvec/mmvec.h"
 #include "hw/registerfields.h"
@@ -37,6 +38,7 @@
 #endif
 
 #ifndef CONFIG_USER_ONLY
+#include "reg_fields.h"
 typedef struct CPUHexagonTLBContext CPUHexagonTLBContext;
 #endif
 
@@ -200,6 +202,7 @@ struct ArchCPU {
 
 FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
 FIELD(TB_FLAGS, MMU_INDEX, 1, 3)
+FIELD(TB_FLAGS, PCYCLE_ENABLED, 4, 1)
 
 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
                                             uint32_t exception,
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index c3806fe068..0bdf526a9e 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -83,6 +83,8 @@ typedef struct DisasContext {
     TCGv new_pred_value[NUM_PREGS];
     TCGv branch_taken;
     TCGv dczero_addr;
+    bool pcycle_enabled;
+    uint32_t num_cycles;
 } DisasContext;
 
 bool is_gather_store_insn(DisasContext *ctx);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index e35ac92402..b7e21c913f 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -281,9 +281,20 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
     }
 
 #ifndef CONFIG_USER_ONLY
+    target_ulong syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+
+    bool pcycle_enabled = extract32(syscfg,
+                                    reg_field_info[SYSCFG_PCYCLEEN].offset,
+                                    reg_field_info[SYSCFG_PCYCLEEN].width);
+
     hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX,
                            cpu_mmu_index(env_cpu(env), false));
+
+    if (pcycle_enabled) {
+        hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, PCYCLE_ENABLED, 1);
+    }
 #else
+    hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, PCYCLE_ENABLED, true);
     hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX, MMU_USER_IDX);
 #endif
 
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index fc49fe7883..f540eadef4 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -91,17 +91,30 @@ void arch_set_system_reg_masked(CPUHexagonState *env, uint32_t reg,
 
 uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+    uint64_t cycles = 0;
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        CPUHexagonState *thread_env = cpu_env(cs);
+        cycles += thread_env->t_cycle_count;
+    }
+#ifndef CONFIG_USER_ONLY
+    HexagonCPU *cpu = env_archcpu(env);
+    return (cpu->globalregs ? hexagon_globalreg_get_pcycle_base(cpu) : 0) +
+           cycles;
+#else
+    return cycles;
+#endif
 }
 
 uint32_t hexagon_get_sys_pcycle_count_high(CPUHexagonState *env)
 {
-    g_assert_not_reached();
+    return hexagon_get_sys_pcycle_count(env) >> 32;
 }
 
 uint32_t hexagon_get_sys_pcycle_count_low(CPUHexagonState *env)
 {
-    g_assert_not_reached();
+    return extract64(hexagon_get_sys_pcycle_count(env), 0, 32);
 }
 
 void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env,
@@ -118,7 +131,19 @@ void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env,
 
 void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+#ifndef CONFIG_USER_ONLY
+    HexagonCPU *cpu = env_archcpu(env);
+    if (cpu->globalregs) {
+        hexagon_globalreg_set_pcycle_base(cpu, cycles);
+    }
+#endif
+
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        CPUHexagonState *thread_env = cpu_env(cs);
+        thread_env->t_cycle_count = 0;
+    }
 }
 
 void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index b74ddc2acb..a71fa33ccf 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -57,6 +57,7 @@ TCGv_i64 hex_store_val64[STORES_MAX];
 TCGv hex_llsc_addr;
 TCGv hex_llsc_val;
 TCGv_i64 hex_llsc_val_i64;
+TCGv_i64 hex_cycle_count;
 TCGv hex_vstore_addr[VSTORES_MAX];
 TCGv hex_vstore_size[VSTORES_MAX];
 TCGv hex_vstore_pending[VSTORES_MAX];
@@ -124,6 +125,22 @@ static void gen_exception_raw(int excp)
     gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
 }
 
+#ifndef CONFIG_USER_ONLY
+static inline void gen_precise_exception(int excp, target_ulong PC)
+{
+    tcg_gen_movi_tl(hex_cause_code, excp);
+    gen_exception(HEX_EVENT_PRECISE, PC);
+}
+
+static inline void gen_pcycle_counters(DisasContext *ctx)
+{
+    if (ctx->pcycle_enabled) {
+        tcg_gen_addi_i64(hex_cycle_count, hex_cycle_count, ctx->num_cycles);
+        ctx->num_cycles = 0;
+    }
+}
+#endif
+
 static void gen_exec_counters(DisasContext *ctx)
 {
     tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
@@ -132,6 +149,10 @@ static void gen_exec_counters(DisasContext *ctx)
                     hex_gpr[HEX_REG_QEMU_INSN_CNT], ctx->num_insns);
     tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_HVX_CNT],
                     hex_gpr[HEX_REG_QEMU_HVX_CNT], ctx->num_hvx_insns);
+
+#ifndef CONFIG_USER_ONLY
+   gen_pcycle_counters(ctx);
+#endif
 }
 
 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
@@ -784,6 +805,7 @@ static void gen_commit_hvx(DisasContext *ctx)
     }
 }
 
+static const int PCYCLES_PER_PACKET = 3;
 static void update_exec_counters(DisasContext *ctx)
 {
     Packet *pkt = ctx->pkt;
@@ -803,6 +825,7 @@ static void update_exec_counters(DisasContext *ctx)
     }
 
     ctx->num_packets++;
+    ctx->num_cycles += PCYCLES_PER_PACKET;
     ctx->num_insns += num_real_insns;
     ctx->num_hvx_insns += num_hvx_insns;
 }
@@ -945,11 +968,13 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
 
     ctx->mem_idx = FIELD_EX32(hex_flags, TB_FLAGS, MMU_INDEX);
     ctx->num_packets = 0;
+    ctx->num_cycles = 0;
     ctx->num_insns = 0;
     ctx->num_hvx_insns = 0;
     ctx->branch_cond = TCG_COND_NEVER;
     ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
     ctx->short_circuit = hex_cpu->short_circuit;
+    ctx->pcycle_enabled = FIELD_EX32(hex_flags, TB_FLAGS, PCYCLE_ENABLED);
 }
 
 static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
@@ -1076,6 +1101,8 @@ void hexagon_translate_init(void)
         offsetof(CPUHexagonState, llsc_val), "llsc_val");
     hex_llsc_val_i64 = tcg_global_mem_new_i64(tcg_env,
         offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
+    hex_cycle_count = tcg_global_mem_new_i64(tcg_env,
+            offsetof(CPUHexagonState, t_cycle_count), "t_cycle_count");
     for (i = 0; i < STORES_MAX; i++) {
         snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
         hex_store_addr[i] = tcg_global_mem_new(tcg_env,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 13/39] target/hexagon: Implement modify_syscfg()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (11 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 12/39] target/hexagon: Add implementation of cycle counters Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 14/39] target/hexagon: Implement hex_tlb_entry_get_perm() Brian Cain
                   ` (25 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 47 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index a8b44a73bd..53bf0591ec 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1531,7 +1531,52 @@ static bool handle_pmu_sreg_write(CPUHexagonState *env, uint32_t reg,
 
 static void modify_syscfg(CPUHexagonState *env, uint32_t val)
 {
-    g_assert_not_reached();
+    g_assert(bql_locked());
+
+    uint32_t syscfg_read_only_mask = 0x80001c00;
+    uint32_t old = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+    uint8_t old_en = GET_SYSCFG_FIELD(SYSCFG_PCYCLEEN, old);
+    uint8_t old_gie = GET_SYSCFG_FIELD(SYSCFG_GIE, old);
+    uint8_t new_en = GET_SYSCFG_FIELD(SYSCFG_PCYCLEEN, val);
+    uint8_t new_gie = GET_SYSCFG_FIELD(SYSCFG_GIE, val);
+    CPUState *cs;
+    target_ulong old_mmu_enable = GET_SYSCFG_FIELD(SYSCFG_MMUEN, old);
+    target_ulong new_mmu_enable =
+        GET_SYSCFG_FIELD(SYSCFG_MMUEN, val);
+
+    /* clear read-only bits if they are set in the new value. */
+    val &= ~syscfg_read_only_mask;
+    /* if read-only are currently set in syscfg keep them set. */
+    val |= (old & syscfg_read_only_mask);
+
+    arch_set_system_reg(env, HEX_SREG_SYSCFG, val);
+
+    /* Check for change in MMU enable */
+    if (new_mmu_enable && !old_mmu_enable) {
+        hex_mmu_on(env);
+    } else if (!new_mmu_enable && old_mmu_enable) {
+        hex_mmu_off(env);
+    }
+
+    /* Changing pcycle enable from 0 to 1 resets the counters */
+    if (old_en == 0 && new_en == 1) {
+        CPU_FOREACH(cs) {
+            cpu_env(cs)->t_cycle_count = 0;
+        }
+    }
+
+    /* See if global interrupts are turned on */
+    if (!old_gie && new_gie) {
+        qemu_log_mask(CPU_LOG_INT, "%s: global interrupts enabled\n", __func__);
+        hex_interrupt_update(env);
+    }
+
+    if (qemu_loglevel_mask(LOG_UNIMP)) {
+        int new_v2x = GET_SYSCFG_FIELD(SYSCFG_V2X, val);
+        if (!new_v2x) {
+            qemu_log("HVX: 64 byte vector length is unsupported\n");
+        }
+    }
 }
 
 static uint32_t hexagon_find_last_irq(CPUHexagonState *env, uint32_t vid)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 14/39] target/hexagon: Implement hex_tlb_entry_get_perm()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (12 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 13/39] target/hexagon: Implement modify_syscfg() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 15/39] target/hexagon: Implement hex_tlb_lookup_by_asid() Brian Cain
                   ` (24 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 linux-user/hexagon/cpu_loop.c |  7 +++++
 target/hexagon/hex_mmu.c      | 54 ++++++++++++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 28ad8073f6..7853819f77 100644
--- a/linux-user/hexagon/cpu_loop.c
+++ b/linux-user/hexagon/cpu_loop.c
@@ -63,6 +63,13 @@ void cpu_loop(CPUHexagonState *env)
             break;
         case HEX_EVENT_PRECISE:
             switch (env->cause_code) {
+            case HEX_CAUSE_FETCH_NO_UPAGE:
+            case HEX_CAUSE_PRIV_NO_UREAD:
+            case HEX_CAUSE_PRIV_NO_UWRITE:
+            force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
+                    env->gpr[HEX_REG_PC]);
+
+            break;
             case HEX_CAUSE_PRIV_USER_NO_GINSN:
             case HEX_CAUSE_PRIV_USER_NO_SINSN:
             case HEX_CAUSE_INVALID_PACKET:
diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
index 332e7f4029..8f9f16158f 100644
--- a/target/hexagon/hex_mmu.c
+++ b/target/hexagon/hex_mmu.c
@@ -264,7 +264,59 @@ static inline void hex_tlb_entry_get_perm(CPUHexagonState *env, uint64_t entry,
                                           int mmu_idx, int *prot,
                                           int32_t *excp)
 {
-    g_assert_not_reached();
+    bool perm_x = GET_TLB_FIELD(entry, PTE_X);
+    bool perm_w = GET_TLB_FIELD(entry, PTE_W);
+    bool perm_r = GET_TLB_FIELD(entry, PTE_R);
+    bool perm_u = GET_TLB_FIELD(entry, PTE_U);
+    bool user_idx = mmu_idx == MMU_USER_IDX;
+
+    if (mmu_idx == MMU_KERNEL_IDX) {
+        *prot = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return;
+    }
+
+    *prot = PAGE_VALID;
+    switch (access_type) {
+    case MMU_INST_FETCH:
+        if (user_idx && !perm_u) {
+            *excp = HEX_EVENT_PRECISE;
+            env->cause_code = HEX_CAUSE_FETCH_NO_UPAGE;
+        } else if (!perm_x) {
+            *excp = HEX_EVENT_PRECISE;
+            env->cause_code = HEX_CAUSE_FETCH_NO_XPAGE;
+        }
+        break;
+    case MMU_DATA_LOAD:
+        if (user_idx && !perm_u) {
+            *excp = HEX_EVENT_PRECISE;
+            env->cause_code = HEX_CAUSE_PRIV_NO_UREAD;
+        } else if (!perm_r) {
+            *excp = HEX_EVENT_PRECISE;
+            env->cause_code = HEX_CAUSE_PRIV_NO_READ;
+        }
+        break;
+    case MMU_DATA_STORE:
+        if (user_idx && !perm_u) {
+            *excp = HEX_EVENT_PRECISE;
+            env->cause_code = HEX_CAUSE_PRIV_NO_UWRITE;
+        } else if (!perm_w) {
+            *excp = HEX_EVENT_PRECISE;
+            env->cause_code = HEX_CAUSE_PRIV_NO_WRITE;
+        }
+        break;
+    }
+
+    if (!user_idx || perm_u) {
+        if (perm_x) {
+            *prot |= PAGE_EXEC;
+        }
+        if (perm_r) {
+            *prot |= PAGE_READ;
+        }
+        if (perm_w) {
+            *prot |= PAGE_WRITE;
+        }
+    }
 }
 
 static inline bool hex_tlb_entry_match(CPUHexagonState *env, uint64_t entry,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 15/39] target/hexagon: Implement hex_tlb_lookup_by_asid()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (13 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 14/39] target/hexagon: Implement hex_tlb_entry_get_perm() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 16/39] target/hexagon: Implement software interrupt Brian Cain
                   ` (23 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/hex_mmu.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
index 8f9f16158f..476796265b 100644
--- a/target/hexagon/hex_mmu.c
+++ b/target/hexagon/hex_mmu.c
@@ -359,7 +359,32 @@ bool hex_tlb_find_match(CPUHexagonState *env, target_ulong VA,
 static uint32_t hex_tlb_lookup_by_asid(CPUHexagonState *env, uint32_t asid,
                                        uint32_t VA)
 {
-    g_assert_not_reached();
+    uint32_t not_found = 0x80000000;
+    uint32_t idx = not_found;
+    int i;
+
+    HexagonCPU *cpu = env_archcpu(env);
+    for (i = 0; i < cpu->num_tlbs; i++) {
+        uint64_t entry = env->hex_tlb->entries[i];
+        if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
+            if (idx != not_found) {
+                env->cause_code = HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH;
+                break;
+            }
+            idx = i;
+        }
+    }
+
+    if (idx == not_found) {
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s: 0x%" PRIx32 ", 0x%08" PRIx32 " => NOT FOUND\n",
+                      __func__, asid, VA);
+    } else {
+        qemu_log_mask(CPU_LOG_MMU, "%s: 0x%" PRIx32 ", 0x%08" PRIx32 " => %d\n",
+                      __func__, asid, VA, idx);
+    }
+
+    return idx;
 }
 
 /* Called from tlbp instruction */
@@ -461,7 +486,8 @@ static inline void print_thread_states(const char *str)
 
 void hex_tlb_lock(CPUHexagonState *env)
 {
-    qemu_log_mask(CPU_LOG_MMU, "hex_tlb_lock: %d\n", env->threadId);
+    qemu_log_mask(CPU_LOG_MMU, "hex_tlb_lock: " TARGET_FMT_ld "\n",
+                  env->threadId);
     BQL_LOCK_GUARD();
     g_assert((env->tlb_lock_count == 0) || (env->tlb_lock_count == 1));
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 16/39] target/hexagon: Implement software interrupt
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (14 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 15/39] target/hexagon: Implement hex_tlb_lookup_by_asid() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 17/39] target/hexagon: Implement exec_interrupt, set_irq Brian Cain
                   ` (22 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain, Mike Lambert

From: Brian Cain <bcain@quicinc.com>

Co-authored-by: Mike Lambert <mlambert@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/hexswi.h    |  17 +++
 target/hexagon/cpu.c       |   2 +
 target/hexagon/hexswi.c    | 256 +++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c |   1 +
 4 files changed, 276 insertions(+)
 create mode 100644 target/hexagon/hexswi.h
 create mode 100644 target/hexagon/hexswi.c

diff --git a/target/hexagon/hexswi.h b/target/hexagon/hexswi.h
new file mode 100644
index 0000000000..5d232cb06c
--- /dev/null
+++ b/target/hexagon/hexswi.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright(c) 2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXSWI_H
+#define HEXSWI_H
+
+
+#include "cpu.h"
+
+void hexagon_cpu_do_interrupt(CPUState *cpu);
+void register_trap_exception(CPUHexagonState *env, int type, int imm,
+                             target_ulong PC);
+
+#endif /* HEXSWI_H */
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index b7e21c913f..22e21d401b 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -33,6 +33,8 @@
 #include "sys_macros.h"
 #include "accel/tcg/cpu-ldst.h"
 #include "qemu/main-loop.h"
+#include "hex_interrupts.h"
+#include "hexswi.h"
 #endif
 
 static void hexagon_v66_cpu_init(Object *obj) { }
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
new file mode 100644
index 0000000000..373133ed7f
--- /dev/null
+++ b/target/hexagon/hexswi.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "cpu_helper.h"
+#include "exec/helper-proto.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "arch.h"
+#include "internal.h"
+#include "macros.h"
+#include "sys_macros.h"
+#include "tcg/tcg-op.h"
+#include "hex_mmu.h"
+#include "hexswi.h"
+
+#ifdef CONFIG_USER_ONLY
+#error "This file is only used in system emulation"
+#endif
+
+static void set_addresses(CPUHexagonState *env, target_ulong pc_offset,
+                          target_ulong exception_index)
+
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t evb = cpu->globalregs ?
+        arch_get_system_reg(env, HEX_SREG_EVB) :
+        cpu->boot_addr;
+    arch_set_system_reg(env, HEX_SREG_ELR,
+                        arch_get_thread_reg(env, HEX_REG_PC) + pc_offset);
+    arch_set_thread_reg(env, HEX_REG_PC, evb | (exception_index << 2));
+}
+
+static const char *event_name[] = {
+    [HEX_EVENT_RESET] = "HEX_EVENT_RESET",
+    [HEX_EVENT_IMPRECISE] = "HEX_EVENT_IMPRECISE",
+    [HEX_EVENT_TLB_MISS_X] = "HEX_EVENT_TLB_MISS_X",
+    [HEX_EVENT_TLB_MISS_RW] = "HEX_EVENT_TLB_MISS_RW",
+    [HEX_EVENT_TRAP0] = "HEX_EVENT_TRAP0",
+    [HEX_EVENT_TRAP1] = "HEX_EVENT_TRAP1",
+    [HEX_EVENT_FPTRAP] = "HEX_EVENT_FPTRAP",
+    [HEX_EVENT_DEBUG] = "HEX_EVENT_DEBUG",
+    [HEX_EVENT_INT0] = "HEX_EVENT_INT0",
+    [HEX_EVENT_INT1] = "HEX_EVENT_INT1",
+    [HEX_EVENT_INT2] = "HEX_EVENT_INT2",
+    [HEX_EVENT_INT3] = "HEX_EVENT_INT3",
+    [HEX_EVENT_INT4] = "HEX_EVENT_INT4",
+    [HEX_EVENT_INT5] = "HEX_EVENT_INT5",
+    [HEX_EVENT_INT6] = "HEX_EVENT_INT6",
+    [HEX_EVENT_INT7] = "HEX_EVENT_INT7",
+    [HEX_EVENT_INT8] = "HEX_EVENT_INT8",
+    [HEX_EVENT_INT9] = "HEX_EVENT_INT9",
+    [HEX_EVENT_INTA] = "HEX_EVENT_INTA",
+    [HEX_EVENT_INTB] = "HEX_EVENT_INTB",
+    [HEX_EVENT_INTC] = "HEX_EVENT_INTC",
+    [HEX_EVENT_INTD] = "HEX_EVENT_INTD",
+    [HEX_EVENT_INTE] = "HEX_EVENT_INTE",
+    [HEX_EVENT_INTF] = "HEX_EVENT_INTF"
+};
+
+void hexagon_cpu_do_interrupt(CPUState *cs)
+
+{
+    CPUHexagonState *env = cpu_env(cs);
+    uint32_t ssr;
+
+    BQL_LOCK_GUARD();
+
+    qemu_log_mask(CPU_LOG_INT, "\t%s: event 0x%x:%s, cause 0x%x(%d)\n",
+                  __func__, cs->exception_index,
+                  event_name[cs->exception_index], env->cause_code,
+                  env->cause_code);
+
+    env->llsc_addr = ~0;
+
+    ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+    if (GET_SSR_FIELD(SSR_EX, ssr) == 1) {
+        arch_set_system_reg(env, HEX_SREG_DIAG, env->cause_code);
+        env->cause_code = HEX_CAUSE_DOUBLE_EXCEPT;
+        cs->exception_index = HEX_EVENT_PRECISE;
+    }
+
+    switch (cs->exception_index) {
+    case HEX_EVENT_TRAP0:
+        if (env->cause_code == 0) {
+            qemu_log_mask(LOG_UNIMP,
+                          "trap0 is unhandled, no semihosting available\n");
+        }
+
+        hexagon_ssr_set_cause(env, env->cause_code);
+        set_addresses(env, 4, cs->exception_index);
+        break;
+
+    case HEX_EVENT_TRAP1:
+        hexagon_ssr_set_cause(env, env->cause_code);
+        set_addresses(env, 4, cs->exception_index);
+        break;
+
+    case HEX_EVENT_TLB_MISS_X:
+        switch (env->cause_code) {
+        case HEX_CAUSE_TLBMISSX_CAUSE_NORMAL:
+        case HEX_CAUSE_TLBMISSX_CAUSE_NEXTPAGE:
+            qemu_log_mask(CPU_LOG_MMU,
+                          "TLB miss EX exception (0x%x) caught: "
+                          "Cause code (0x%x) "
+                          "TID = 0x%" PRIx32 ", PC = 0x%" PRIx32
+                          ", BADVA = 0x%" PRIx32 "\n",
+                          cs->exception_index, env->cause_code, env->threadId,
+                          arch_get_thread_reg(env, HEX_REG_PC),
+                          arch_get_system_reg(env, HEX_SREG_BADVA));
+
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 0, cs->exception_index);
+            break;
+
+        default:
+            cpu_abort(cs,
+                      "1:Hexagon exception %d/0x%x: "
+                      "Unknown cause code %d/0x%x\n",
+                      cs->exception_index, cs->exception_index, env->cause_code,
+                      env->cause_code);
+            break;
+        }
+        break;
+
+    case HEX_EVENT_TLB_MISS_RW:
+        switch (env->cause_code) {
+        case HEX_CAUSE_TLBMISSRW_CAUSE_READ:
+        case HEX_CAUSE_TLBMISSRW_CAUSE_WRITE:
+            qemu_log_mask(CPU_LOG_MMU,
+                          "TLB miss RW exception (0x%x) caught: "
+                          "Cause code (0x%x) "
+                          "TID = 0x%" PRIx32 ", PC = 0x%" PRIx32
+                          ", BADVA = 0x%" PRIx32 "\n",
+                          cs->exception_index, env->cause_code, env->threadId,
+                          env->gpr[HEX_REG_PC],
+                          arch_get_system_reg(env, HEX_SREG_BADVA));
+
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 0, cs->exception_index);
+            /* env->sreg[HEX_SREG_BADVA] is set when the exception is raised */
+            break;
+
+        default:
+            cpu_abort(cs,
+                      "2:Hexagon exception %d/0x%x: "
+                      "Unknown cause code %d/0x%x\n",
+                      cs->exception_index, cs->exception_index, env->cause_code,
+                      env->cause_code);
+            break;
+        }
+        break;
+
+    case HEX_EVENT_FPTRAP:
+        hexagon_ssr_set_cause(env, env->cause_code);
+        arch_set_thread_reg(env, HEX_REG_PC,
+                            arch_get_system_reg(env, HEX_SREG_EVB) |
+                                (cs->exception_index << 2));
+        break;
+
+    case HEX_EVENT_DEBUG:
+        hexagon_ssr_set_cause(env, env->cause_code);
+        set_addresses(env, 0, cs->exception_index);
+        qemu_log_mask(LOG_UNIMP, "single-step exception is not handled\n");
+        break;
+
+    case HEX_EVENT_PRECISE:
+        switch (env->cause_code) {
+        case HEX_CAUSE_FETCH_NO_XPAGE:
+        case HEX_CAUSE_FETCH_NO_UPAGE:
+        case HEX_CAUSE_PRIV_NO_READ:
+        case HEX_CAUSE_PRIV_NO_UREAD:
+        case HEX_CAUSE_PRIV_NO_WRITE:
+        case HEX_CAUSE_PRIV_NO_UWRITE:
+        case HEX_CAUSE_MISALIGNED_LOAD:
+        case HEX_CAUSE_MISALIGNED_STORE:
+        case HEX_CAUSE_PC_NOT_ALIGNED:
+            qemu_log_mask(CPU_LOG_MMU,
+                          "MMU permission exception (0x%x) caught: "
+                          "Cause code (0x%x) "
+                          "TID = 0x%" PRIx32 ", PC = 0x%" PRIx32
+                          ", BADVA = 0x%" PRIx32 "\n",
+                          cs->exception_index, env->cause_code, env->threadId,
+                          env->gpr[HEX_REG_PC],
+                          arch_get_system_reg(env, HEX_SREG_BADVA));
+
+
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 0, cs->exception_index);
+            /* env->sreg[HEX_SREG_BADVA] is set when the exception is raised */
+            break;
+
+        case HEX_CAUSE_DOUBLE_EXCEPT:
+        case HEX_CAUSE_PRIV_USER_NO_SINSN:
+        case HEX_CAUSE_PRIV_USER_NO_GINSN:
+        case HEX_CAUSE_INVALID_OPCODE:
+        case HEX_CAUSE_NO_COPROC_ENABLE:
+        case HEX_CAUSE_NO_COPROC2_ENABLE:
+        case HEX_CAUSE_UNSUPORTED_HVX_64B:
+        case HEX_CAUSE_REG_WRITE_CONFLICT:
+        case HEX_CAUSE_VWCTRL_WINDOW_MISS:
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 0, cs->exception_index);
+            break;
+
+        case HEX_CAUSE_COPROC_LDST:
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 0, cs->exception_index);
+            break;
+
+        case HEX_CAUSE_STACK_LIMIT:
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 0, cs->exception_index);
+            break;
+
+        default:
+            cpu_abort(cs,
+                      "3:Hexagon exception %d/0x%x: "
+                      "Unknown cause code %d/0x%x\n",
+                      cs->exception_index, cs->exception_index, env->cause_code,
+                      env->cause_code);
+            break;
+        }
+        break;
+
+    case HEX_EVENT_IMPRECISE:
+        qemu_log_mask(LOG_UNIMP,
+                "Imprecise exception: this case is not yet handled");
+        break;
+
+    default:
+        qemu_log_mask(LOG_UNIMP,
+                "Hexagon Unsupported exception 0x%x/0x%x\n",
+                  cs->exception_index, env->cause_code);
+        break;
+    }
+
+    cs->exception_index = HEX_EVENT_NONE;
+}
+
+void register_trap_exception(CPUHexagonState *env, int traptype, int imm,
+                             target_ulong PC)
+{
+    CPUState *cs = env_cpu(env);
+
+    cs->exception_index = (traptype == 0) ? HEX_EVENT_TRAP0 : HEX_EVENT_TRAP1;
+    ASSERT_DIRECT_TO_GUEST_UNSET(env, cs->exception_index);
+
+    env->cause_code = imm;
+    env->gpr[HEX_REG_PC] = PC;
+    cpu_loop_exit(cs);
+}
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 53bf0591ec..569e8271b3 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -40,6 +40,7 @@
 #include "hex_mmu.h"
 #include "hw/intc/l2vic.h"
 #include "hex_interrupts.h"
+#include "hexswi.h"
 #endif
 
 #define SF_BIAS        127
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 17/39] target/hexagon: Implement exec_interrupt, set_irq
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (15 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 16/39] target/hexagon: Implement software interrupt Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 18/39] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
                   ` (21 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h |  5 +++
 target/hexagon/cpu.c | 81 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 354e9e9cbf..1491313d06 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -209,6 +209,11 @@ G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
                                             uintptr_t pc);
 
 #ifndef CONFIG_USER_ONLY
+/*
+ * @return true if the @a thread_env hardware thread is
+ * not stopped.
+ */
+bool hexagon_thread_is_enabled(CPUHexagonState *thread_env);
 uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg);
 uint32_t hexagon_sreg_read(CPUHexagonState *env, uint32_t reg);
 void hexagon_gdb_sreg_write(CPUHexagonState *env, uint32_t reg, uint32_t val);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 22e21d401b..85ccf9893a 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -30,11 +30,13 @@
 #include "hex_mmu.h"
 
 #ifndef CONFIG_USER_ONLY
+#include "macros.h"
 #include "sys_macros.h"
 #include "accel/tcg/cpu-ldst.h"
 #include "qemu/main-loop.h"
 #include "hex_interrupts.h"
 #include "hexswi.h"
+#include "exec/cpu-interrupt.h"
 #endif
 
 static void hexagon_v66_cpu_init(Object *obj) { }
@@ -310,6 +312,34 @@ static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
     cpu_env(cs)->gpr[HEX_REG_PC] = tb->pc;
 }
 
+#ifndef CONFIG_USER_ONLY
+bool hexagon_thread_is_enabled(CPUHexagonState *env)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    if (!cpu->globalregs) {
+        return true;
+    }
+    target_ulong modectl = arch_get_system_reg(env, HEX_SREG_MODECTL);
+    uint32_t thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
+    bool E_bit = thread_enabled_mask & (0x1 << env->threadId);
+
+    return E_bit;
+}
+#endif
+
+static bool hexagon_cpu_has_work(CPUState *cs)
+{
+#ifndef CONFIG_USER_ONLY
+    CPUHexagonState *env = cpu_env(cs);
+
+    return hexagon_thread_is_enabled(env) &&
+        (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI
+            | CPU_INTERRUPT_K0_UNLOCK | CPU_INTERRUPT_TLB_UNLOCK));
+#else
+    return true;
+#endif
+}
+
 static void hexagon_restore_state_to_opc(CPUState *cs,
                                          const TranslationBlock *tb,
                                          const uint64_t *data)
@@ -431,10 +461,58 @@ static int hexagon_cpu_mmu_index(CPUState *cs, bool ifetch)
     return MMU_USER_IDX;
 }
 
+#if !defined(CONFIG_USER_ONLY)
+static void hexagon_cpu_set_irq(void *opaque, int irq, int level)
+{
+    HexagonCPU *cpu = HEXAGON_CPU(opaque);
+    CPUState *cs = CPU(cpu);
+    CPUHexagonState *env = cpu_env(cs);
+
+    switch (irq) {
+    case HEXAGON_CPU_IRQ_0 ... HEXAGON_CPU_IRQ_7:
+        qemu_log_mask(CPU_LOG_INT, "%s: irq %d, level %d\n",
+                      __func__, irq, level);
+        if (level) {
+            hex_raise_interrupts(env, 1 << irq, CPU_INTERRUPT_HARD);
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+#endif
+
 static void hexagon_cpu_init(Object *obj)
 {
+#if !defined(CONFIG_USER_ONLY)
+    HexagonCPU *cpu = HEXAGON_CPU(obj);
+    qdev_init_gpio_in(DEVICE(cpu), hexagon_cpu_set_irq, 8);
+#endif
 }
 
+#ifndef CONFIG_USER_ONLY
+
+static bool hexagon_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+    CPUHexagonState *env = cpu_env(cs);
+    if (interrupt_request & CPU_INTERRUPT_TLB_UNLOCK) {
+        cs->halted = false;
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_TLB_UNLOCK);
+        return true;
+    }
+    if (interrupt_request & CPU_INTERRUPT_K0_UNLOCK) {
+        cs->halted = false;
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_K0_UNLOCK);
+        return true;
+    }
+    if (interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI)) {
+        return hex_check_interrupts(env);
+    }
+    return false;
+}
+
+#endif
+
 static const TCGCPUOps hexagon_tcg_ops = {
     /* MTTCG not yet supported: require strict ordering */
     .guest_default_memory_order = TCG_MO_ALL,
@@ -445,6 +523,9 @@ static const TCGCPUOps hexagon_tcg_ops = {
     .synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
     .restore_state_to_opc = hexagon_restore_state_to_opc,
     .mmu_index = hexagon_cpu_mmu_index,
+#if !defined(CONFIG_USER_ONLY)
+    .cpu_exec_interrupt = hexagon_cpu_exec_interrupt,
+#endif /* !CONFIG_USER_ONLY */
 };
 
 static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 18/39] target/hexagon: add simple cpu_exec_reset and pointer_wrap
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (16 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 17/39] target/hexagon: Implement exec_interrupt, set_irq Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 19/39] target/hexagon: Implement hexagon_tlb_fill() Brian Cain
                   ` (20 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning

From: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>

Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
---
 target/hexagon/cpu.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 85ccf9893a..0445146f2b 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -511,6 +511,12 @@ static bool hexagon_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
     return false;
 }
 
+static vaddr hexagon_pointer_wrap(CPUState *cs, int mmu_idx,
+                                  vaddr result, vaddr base)
+{
+    return result;
+}
+
 #endif
 
 static const TCGCPUOps hexagon_tcg_ops = {
@@ -525,6 +531,8 @@ static const TCGCPUOps hexagon_tcg_ops = {
     .mmu_index = hexagon_cpu_mmu_index,
 #if !defined(CONFIG_USER_ONLY)
     .cpu_exec_interrupt = hexagon_cpu_exec_interrupt,
+    .pointer_wrap = hexagon_pointer_wrap,
+    .cpu_exec_reset = cpu_reset,
 #endif /* !CONFIG_USER_ONLY */
 };
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 19/39] target/hexagon: Implement hexagon_tlb_fill()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (17 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 18/39] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 20/39] target/hexagon: Implement siad inst Brian Cain
                   ` (19 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.c | 134 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 133 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 0445146f2b..2ae6874841 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -37,6 +37,8 @@
 #include "hex_interrupts.h"
 #include "hexswi.h"
 #include "exec/cpu-interrupt.h"
+#include "exec/target_page.h"
+#include "hw/hexagon/hexagon_globalreg.h"
 #endif
 
 static void hexagon_v66_cpu_init(Object *obj) { }
@@ -490,7 +492,136 @@ static void hexagon_cpu_init(Object *obj)
 #endif
 }
 
-#ifndef CONFIG_USER_ONLY
+#if !defined(CONFIG_USER_ONLY)
+static bool get_physical_address(CPUHexagonState *env, hwaddr *phys, int *prot,
+                                 int *size, int32_t *excp, target_ulong address,
+                                 MMUAccessType access_type, int mmu_idx)
+
+{
+    if (hexagon_cpu_mmu_enabled(env)) {
+        return hex_tlb_find_match(env, address, access_type, phys, prot, size,
+                                  excp, mmu_idx);
+    } else {
+        *phys = address & 0xFFFFFFFF;
+        *prot = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        *size = TARGET_PAGE_SIZE;
+        return true;
+    }
+}
+
+/* qemu seems to only want to know about TARGET_PAGE_SIZE pages */
+static void find_qemu_subpage(vaddr *addr, hwaddr *phys, int page_size)
+{
+    vaddr page_start = *addr & ~((vaddr)(page_size - 1));
+    vaddr offset = ((*addr - page_start) / TARGET_PAGE_SIZE) * TARGET_PAGE_SIZE;
+    *addr = page_start + offset;
+    *phys += offset;
+}
+
+
+#define INVALID_BADVA 0xbadabada
+
+static void set_badva_regs(CPUHexagonState *env, target_ulong VA, int slot,
+                           MMUAccessType access_type)
+{
+    arch_set_system_reg(env, HEX_SREG_BADVA, VA);
+
+    if (access_type == MMU_INST_FETCH || slot == 0) {
+        arch_set_system_reg(env, HEX_SREG_BADVA0, VA);
+        arch_set_system_reg(env, HEX_SREG_BADVA1, INVALID_BADVA);
+        SET_SSR_FIELD(env, SSR_V0, 1);
+        SET_SSR_FIELD(env, SSR_V1, 0);
+        SET_SSR_FIELD(env, SSR_BVS, 0);
+    } else if (slot == 1) {
+        arch_set_system_reg(env, HEX_SREG_BADVA0, INVALID_BADVA);
+        arch_set_system_reg(env, HEX_SREG_BADVA1, VA);
+        SET_SSR_FIELD(env, SSR_V0, 0);
+        SET_SSR_FIELD(env, SSR_V1, 1);
+        SET_SSR_FIELD(env, SSR_BVS, 1);
+    } else {
+        g_assert_not_reached();
+    }
+}
+
+static void raise_tlbmiss_exception(CPUState *cs, target_ulong VA, int slot,
+                                    MMUAccessType access_type)
+{
+    CPUHexagonState *env = cpu_env(cs);
+
+    set_badva_regs(env, VA, slot, access_type);
+
+    switch (access_type) {
+    case MMU_INST_FETCH:
+        cs->exception_index = HEX_EVENT_TLB_MISS_X;
+        if ((VA & ~TARGET_PAGE_MASK) == 0) {
+            env->cause_code = HEX_CAUSE_TLBMISSX_CAUSE_NEXTPAGE;
+        } else {
+            env->cause_code = HEX_CAUSE_TLBMISSX_CAUSE_NORMAL;
+        }
+        break;
+    case MMU_DATA_LOAD:
+        cs->exception_index = HEX_EVENT_TLB_MISS_RW;
+        env->cause_code = HEX_CAUSE_TLBMISSRW_CAUSE_READ;
+        break;
+    case MMU_DATA_STORE:
+        cs->exception_index = HEX_EVENT_TLB_MISS_RW;
+        env->cause_code = HEX_CAUSE_TLBMISSRW_CAUSE_WRITE;
+        break;
+    }
+}
+
+static void raise_perm_exception(CPUState *cs, target_ulong VA, int slot,
+                                 MMUAccessType access_type, int32_t excp)
+{
+    CPUHexagonState *env = cpu_env(cs);
+
+    set_badva_regs(env, VA, slot, access_type);
+    cs->exception_index = excp;
+}
+
+static const char *access_type_names[] = { "MMU_DATA_LOAD ", "MMU_DATA_STORE",
+                                           "MMU_INST_FETCH" };
+
+static const char *mmu_idx_names[] = { "MMU_USER_IDX", "MMU_GUEST_IDX",
+                                       "MMU_KERNEL_IDX" };
+
+static bool hexagon_tlb_fill(CPUState *cs, vaddr address, int size,
+                             MMUAccessType access_type, int mmu_idx, bool probe,
+                             uintptr_t retaddr)
+{
+    CPUHexagonState *env = cpu_env(cs);
+    static int slot = 0 /* This is always zero for now */;
+    hwaddr phys;
+    int prot = 0;
+    int page_size = 0;
+    int32_t excp = 0;
+    bool ret = 0;
+
+    qemu_log_mask(
+        CPU_LOG_MMU,
+        "%s: tid = 0x%x, pc = 0x%08" PRIx32 ", vaddr = 0x%08" VADDR_PRIx
+        ", size = %d, %s,\tprobe = %d, %s\n",
+        __func__, env->threadId, env->gpr[HEX_REG_PC], address, size,
+        access_type_names[access_type], probe, mmu_idx_names[mmu_idx]);
+    ret = get_physical_address(env, &phys, &prot, &page_size, &excp, address,
+                               access_type, mmu_idx);
+    if (ret) {
+        if (!excp) {
+            find_qemu_subpage(&address, &phys, page_size);
+            tlb_set_page(cs, address, phys, prot, mmu_idx, TARGET_PAGE_SIZE);
+            return ret;
+        } else {
+            raise_perm_exception(cs, address, slot, access_type, excp);
+            do_raise_exception(env, cs->exception_index, env->gpr[HEX_REG_PC],
+                               retaddr);
+        }
+    }
+    if (probe) {
+        return false;
+    }
+    raise_tlbmiss_exception(cs, address, slot, access_type);
+    do_raise_exception(env, cs->exception_index, env->gpr[HEX_REG_PC], retaddr);
+}
 
 static bool hexagon_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
@@ -533,6 +664,7 @@ static const TCGCPUOps hexagon_tcg_ops = {
     .cpu_exec_interrupt = hexagon_cpu_exec_interrupt,
     .pointer_wrap = hexagon_pointer_wrap,
     .cpu_exec_reset = cpu_reset,
+    .tlb_fill = hexagon_tlb_fill,
 #endif /* !CONFIG_USER_ONLY */
 };
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 20/39] target/hexagon: Implement siad inst
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (18 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 19/39] target/hexagon: Implement hexagon_tlb_fill() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 21/39] target/hexagon: Implement hexagon_resume_threads() Brian Cain
                   ` (18 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

siad is the 'Set interrupt auto disable' instruction.


Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 569e8271b3..b887302d3c 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1385,7 +1385,15 @@ void HELPER(ciad)(CPUHexagonState *env, uint32_t mask)
 
 void HELPER(siad)(CPUHexagonState *env, uint32_t mask)
 {
-    g_assert_not_reached();
+    uint32_t ipendad;
+    uint32_t iad;
+
+    BQL_LOCK_GUARD();
+    ipendad = READ_SREG(HEX_SREG_IPENDAD);
+    iad = fGET_FIELD(ipendad, IPENDAD_IAD);
+    fSET_FIELD(ipendad, IPENDAD_IAD, iad | mask);
+    arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+    hex_interrupt_update(env);
 }
 
 void HELPER(swi)(CPUHexagonState *env, uint32_t mask)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 21/39] target/hexagon: Implement hexagon_resume_threads()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (19 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 20/39] target/hexagon: Implement siad inst Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 22/39] target/hexagon: Implement setprio, resched Brian Cain
                   ` (17 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.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 | 76 +++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c  |  3 +-
 4 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 1491313d06..92b32f434b 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -51,6 +51,7 @@ typedef struct CPUHexagonTLBContext CPUHexagonTLBContext;
 #define PRED_WRITES_MAX 5                   /* 4 insns + endloop */
 #define VSTORES_MAX 2
 #define MAX_TLB_ENTRIES 1024
+#define THREADS_MAX 8
 
 #define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
 #ifndef CONFIG_USER_ONLY
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index f7400031ef..c8b0a37b7f 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 f540eadef4..18c929bf5f 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -146,6 +146,82 @@ void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
     }
 }
 
+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 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);
+            }
+        }
+    }
+}
+
 void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
 {
     g_assert(bql_locked());
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index b887302d3c..63b9dda9a3 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1483,7 +1483,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



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 22/39] target/hexagon: Implement setprio, resched
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (20 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 21/39] target/hexagon: Implement hexagon_resume_threads() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 23/39] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug() Brian Cain
                   ` (16 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

The hardware-assisted scheduler helps manage tasks on the run queue
and interrupt steering.

This instruction is defined in the Qualcomm Hexagon V71 Programmer's Reference
Manual -
https://docs.qualcomm.com/bundle/publicresource/80-N2040-51_REV_AB_Hexagon_V71_ProgrammerS_Reference_Manual.pdf
See §11.9.2 SYSTEM MONITOR.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 71 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 69 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 63b9dda9a3..37a5b45e75 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1472,6 +1472,57 @@ void HELPER(stop)(CPUHexagonState *env)
     hexagon_stop_thread(env);
 }
 
+static inline QEMU_ALWAYS_INLINE void resched(CPUHexagonState *env)
+{
+    uint32_t schedcfg;
+    uint32_t schedcfg_en;
+    int int_number;
+    CPUState *cs;
+    uint32_t lowest_th_prio = 0; /* 0 is highest prio */
+    uint32_t bestwait_reg;
+    uint32_t best_prio;
+
+    BQL_LOCK_GUARD();
+    qemu_log_mask(CPU_LOG_INT, "%s: check resched\n", __func__);
+    schedcfg = arch_get_system_reg(env, HEX_SREG_SCHEDCFG);
+    schedcfg_en = GET_FIELD(SCHEDCFG_EN, schedcfg);
+    int_number = GET_FIELD(SCHEDCFG_INTNO, schedcfg);
+
+    if (!schedcfg_en) {
+        return;
+    }
+
+    CPU_FOREACH(cs) {
+        HexagonCPU *thread = HEXAGON_CPU(cs);
+        CPUHexagonState *thread_env = &(thread->env);
+        uint32_t th_prio = GET_FIELD(
+            STID_PRIO, arch_get_system_reg(thread_env, HEX_SREG_STID));
+        if (!hexagon_thread_is_enabled(thread_env)) {
+            continue;
+        }
+
+        lowest_th_prio = (lowest_th_prio > th_prio)
+            ? lowest_th_prio
+            : th_prio;
+    }
+
+    bestwait_reg = arch_get_system_reg(env, HEX_SREG_BESTWAIT);
+    best_prio = GET_FIELD(BESTWAIT_PRIO, bestwait_reg);
+
+    /*
+     * If the lowest priority thread is lower priority than the
+     * value in the BESTWAIT register, we must raise the reschedule
+     * interrupt on the lowest priority thread.
+     */
+    if (lowest_th_prio > best_prio) {
+        qemu_log_mask(CPU_LOG_INT,
+                "%s: raising resched int %d, cur PC 0x" TARGET_FMT_lx "\n",
+                __func__, int_number, arch_get_thread_reg(env, HEX_REG_PC));
+        SET_SYSTEM_FIELD(env, HEX_SREG_BESTWAIT, BESTWAIT_PRIO, ~0);
+        hex_raise_interrupts(env, 1 << int_number, CPU_INTERRUPT_SWI);
+    }
+}
+
 void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
 {
     BQL_LOCK_GUARD();
@@ -1495,7 +1546,8 @@ uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
         CPUHexagonState *found_env = &found_cpu->env;
         if (found_env->threadId == tid) {
             target_ulong imask = arch_get_system_reg(found_env, HEX_SREG_IMASK);
-            qemu_log_mask(CPU_LOG_INT, "%s: tid %d imask = 0x%x\n",
+            qemu_log_mask(CPU_LOG_INT,
+                          "%s: tid " TARGET_FMT_lx " imask = 0x%x\n",
                           __func__, env->threadId,
                           (unsigned)GET_FIELD(IMASK_MASK, imask));
             return GET_FIELD(IMASK_MASK, imask);
@@ -1515,7 +1567,7 @@ void HELPER(setimask)(CPUHexagonState *env, uint32_t pred, uint32_t imask)
 
         if (pred == found_env->threadId) {
             SET_SYSTEM_FIELD(found_env, HEX_SREG_IMASK, IMASK_MASK, imask);
-            qemu_log_mask(CPU_LOG_INT, "%s: tid %d imask 0x%x\n",
+            qemu_log_mask(CPU_LOG_INT, "%s: tid " TARGET_FMT_lx " imask 0x%x\n",
                           __func__, found_env->threadId, imask);
             hex_interrupt_update(env);
             return;
@@ -1764,6 +1816,21 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
 
 void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
 {
+    CPUState *cs;
+
+    BQL_LOCK_GUARD();
+    CPU_FOREACH(cs) {
+        HexagonCPU *found_cpu = HEXAGON_CPU(cs);
+        CPUHexagonState *found_env = &found_cpu->env;
+        if (thread == found_env->threadId) {
+            SET_SYSTEM_FIELD(found_env, HEX_SREG_STID, STID_PRIO, prio);
+            qemu_log_mask(CPU_LOG_INT,
+                          "%s: tid " TARGET_FMT_lx " prio = 0x%x\n",
+                          __func__, found_env->threadId, prio);
+            resched(env);
+            return;
+        }
+    }
     g_assert_not_reached();
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 23/39] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (21 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 22/39] target/hexagon: Implement setprio, resched Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 24/39] target/hexagon: Add exec-start-addr prop Brian Cain
                   ` (15 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 2ae6874841..2af0b4089e 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -19,6 +19,7 @@
 #include "qemu/qemu-print.h"
 #include "cpu.h"
 #include "internal.h"
+#include "exec/cputlb.h"
 #include "exec/translation-block.h"
 #include "qapi/error.h"
 #include "hw/qdev-properties.h"
@@ -518,6 +519,24 @@ static void find_qemu_subpage(vaddr *addr, hwaddr *phys, int page_size)
     *phys += offset;
 }
 
+static hwaddr hexagon_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+    CPUHexagonState *env = cpu_env(cs);
+    hwaddr phys_addr;
+    int prot;
+    int page_size = 0;
+    int32_t excp = 0;
+    int mmu_idx = MMU_KERNEL_IDX;
+
+    if (get_physical_address(env, &phys_addr, &prot, &page_size, &excp,
+                             addr, 0, mmu_idx)) {
+        find_qemu_subpage(&addr, &phys_addr, page_size);
+        return phys_addr;
+    }
+
+    return -1;
+}
+
 
 #define INVALID_BADVA 0xbadabada
 
@@ -623,6 +642,13 @@ static bool hexagon_tlb_fill(CPUState *cs, vaddr address, int size,
     do_raise_exception(env, cs->exception_index, env->gpr[HEX_REG_PC], retaddr);
 }
 
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps hexagon_sysemu_ops = {
+    .has_work = hexagon_cpu_has_work,
+    .get_phys_page_debug = hexagon_cpu_get_phys_page_debug,
+};
+
 static bool hexagon_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
     CPUHexagonState *env = cpu_env(cs);
@@ -665,6 +691,8 @@ static const TCGCPUOps hexagon_tcg_ops = {
     .pointer_wrap = hexagon_pointer_wrap,
     .cpu_exec_reset = cpu_reset,
     .tlb_fill = hexagon_tlb_fill,
+    .cpu_exec_halt = hexagon_cpu_has_work,
+    .do_interrupt = hexagon_cpu_do_interrupt,
 #endif /* !CONFIG_USER_ONLY */
 };
 
@@ -692,9 +720,12 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
     cc->gdb_core_xml_file = "hexagon-core.xml";
     cc->disas_set_info = hexagon_cpu_disas_set_info;
 #ifndef CONFIG_USER_ONLY
+    cc->sysemu_ops = &hexagon_sysemu_ops;
     dc->vmsd = &vmstate_hexagon_cpu;
 #endif
+#ifdef CONFIG_TCG
     cc->tcg_ops = &hexagon_tcg_ops;
+#endif
 }
 
 #ifndef CONFIG_USER_ONLY
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 24/39] target/hexagon: Add exec-start-addr prop
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (22 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 23/39] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 25/39] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu Brian Cain
                   ` (14 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h | 1 +
 target/hexagon/cpu.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 92b32f434b..39d6983263 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -196,6 +196,7 @@ struct ArchCPU {
 #ifndef CONFIG_USER_ONLY
     uint32_t num_tlbs;
     uint32_t l2vic_base_addr;
+    uint32_t boot_addr;
 #endif
 };
 
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 2af0b4089e..8afa7e55e6 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -69,6 +69,7 @@ static const Property hexagon_cpu_properties[] = {
     DEFINE_PROP_UINT32("jtlb-entries", HexagonCPU, num_tlbs, MAX_TLB_ENTRIES),
     DEFINE_PROP_UINT32("l2vic-base-addr", HexagonCPU, l2vic_base_addr,
         0xffffffffULL),
+    DEFINE_PROP_UINT32("exec-start-addr", HexagonCPU, boot_addr, 0xffffffffULL),
 #endif
     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust, 0,
@@ -409,6 +410,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     env->next_PC = 0;
     env->wait_next_pc = 0;
     env->cause_code = HEX_EVENT_NONE;
+    arch_set_thread_reg(env, HEX_REG_PC, cpu->boot_addr);
 #endif
     env->cause_code = HEX_EVENT_NONE;
 }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 25/39] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (23 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 24/39] target/hexagon: Add exec-start-addr prop Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 26/39] target/hexagon: Decode trap1, rte as COF Brian Cain
                   ` (13 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.h |  1 +
 target/hexagon/cpu.c        | 26 ++++++++++++++++++-----
 target/hexagon/cpu_helper.c | 41 +++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index c8b0a37b7f..9f2eb27e63 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -15,6 +15,7 @@ void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t);
 void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env, uint32_t);
 void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env, uint32_t);
 void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old);
+int get_cpu_mode(CPUHexagonState *env);
 int get_exe_mode(CPUHexagonState *env);
 void clear_wait_mode(CPUHexagonState *env);
 void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 8afa7e55e6..6d2013ce89 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -329,20 +329,16 @@ bool hexagon_thread_is_enabled(CPUHexagonState *env)
 
     return E_bit;
 }
-#endif
 
 static bool hexagon_cpu_has_work(CPUState *cs)
 {
-#ifndef CONFIG_USER_ONLY
     CPUHexagonState *env = cpu_env(cs);
 
     return hexagon_thread_is_enabled(env) &&
         (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI
             | CPU_INTERRUPT_K0_UNLOCK | CPU_INTERRUPT_TLB_UNLOCK));
-#else
-    return true;
-#endif
 }
+#endif
 
 static void hexagon_restore_state_to_opc(CPUState *cs,
                                          const TranslationBlock *tb,
@@ -463,6 +459,26 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
 
 static int hexagon_cpu_mmu_index(CPUState *cs, bool ifetch)
 {
+#ifndef CONFIG_USER_ONLY
+    BQL_LOCK_GUARD();
+    CPUHexagonState *env = cpu_env(cs);
+    HexagonCPU *cpu = HEXAGON_CPU(cs);
+    if (cpu->globalregs) {
+        uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+        uint8_t mmuen = GET_SYSCFG_FIELD(SYSCFG_MMUEN, syscfg);
+        if (!mmuen) {
+            return MMU_KERNEL_IDX;
+        }
+    }
+
+    int cpu_mode = get_cpu_mode(env);
+    if (cpu_mode == HEX_CPU_MODE_MONITOR) {
+        return MMU_KERNEL_IDX;
+    } else if (cpu_mode == HEX_CPU_MODE_GUEST) {
+        return MMU_GUEST_IDX;
+    }
+#endif
+
     return MMU_USER_IDX;
 }
 
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 18c929bf5f..5d0ba23d02 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -389,4 +389,45 @@ void hexagon_stop_thread(CPUHexagonState *env)
     }
 }
 
+static int sys_in_monitor_mode_ssr(uint32_t ssr)
+{
+    if ((GET_SSR_FIELD(SSR_EX, ssr) != 0) ||
+       ((GET_SSR_FIELD(SSR_EX, ssr) == 0) && (GET_SSR_FIELD(SSR_UM, ssr) == 0)))
+        return 1;
+    return 0;
+}
+
+static int sys_in_guest_mode_ssr(uint32_t ssr)
+{
+    if ((GET_SSR_FIELD(SSR_EX, ssr) == 0) &&
+        (GET_SSR_FIELD(SSR_UM, ssr) != 0) &&
+        (GET_SSR_FIELD(SSR_GM, ssr) != 0))
+        return 1;
+    return 0;
+}
+
+static int sys_in_user_mode_ssr(uint32_t ssr)
+{
+    if ((GET_SSR_FIELD(SSR_EX, ssr) == 0) &&
+        (GET_SSR_FIELD(SSR_UM, ssr) != 0) &&
+        (GET_SSR_FIELD(SSR_GM, ssr) == 0))
+        return 1;
+   return 0;
+}
+
+int get_cpu_mode(CPUHexagonState *env)
+
+{
+    uint32_t ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+
+    if (sys_in_monitor_mode_ssr(ssr)) {
+        return HEX_CPU_MODE_MONITOR;
+    } else if (sys_in_guest_mode_ssr(ssr)) {
+        return HEX_CPU_MODE_GUEST;
+    } else if (sys_in_user_mode_ssr(ssr)) {
+        return HEX_CPU_MODE_USER;
+    }
+    return HEX_CPU_MODE_MONITOR;
+}
+
 #endif
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 26/39] target/hexagon: Decode trap1, rte as COF
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (24 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 25/39] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 27/39] target/hexagon: Implement hexagon_find_last_irq() Brian Cain
                   ` (12 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Also: handle rte instructions at the end of the packet.


Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/decode.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 23deba2426..5d0beeeaf2 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -193,6 +193,8 @@ static bool decode_opcode_can_jump(int opcode)
     if ((GET_ATTRIB(opcode, A_JUMP)) ||
         (GET_ATTRIB(opcode, A_CALL)) ||
         (opcode == J2_trap0) ||
+        (opcode == J2_trap1) ||
+        (opcode == J2_rte) ||
         (opcode == J2_pause)) {
         /* Exception to A_JUMP attribute */
         if (opcode == J4_hintjumpr) {
@@ -371,6 +373,18 @@ static void decode_shuffle_for_execution(Packet *packet)
             break;
         }
     }
+    /*
+     * And at the very very very end, move any RTE's, since they update
+     * user/supervisor mode.
+     */
+#if !defined(CONFIG_USER_ONLY)
+    for (i = 0; i < last_insn; i++) {
+        if (packet->insn[i].opcode == J2_rte) {
+            decode_send_insn_to(packet, i, last_insn);
+            break;
+        }
+    }
+#endif
 }
 
 static void
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 27/39] target/hexagon: Implement hexagon_find_last_irq()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (25 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 26/39] target/hexagon: Decode trap1, rte as COF Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 28/39] target/hexagon: Implement modify_ssr, resched, pending_interrupt Brian Cain
                   ` (11 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 37a5b45e75..5196226f02 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1643,7 +1643,13 @@ static void modify_syscfg(CPUHexagonState *env, uint32_t val)
 
 static uint32_t hexagon_find_last_irq(CPUHexagonState *env, uint32_t vid)
 {
-    g_assert_not_reached();
+    int offset = (vid ==  HEX_SREG_VID) ? L2VIC_VID_0 : L2VIC_VID_1;
+    CPUState *cs = env_cpu(env);
+    HexagonCPU *cpu = HEXAGON_CPU(cs);
+    const hwaddr pend_mem = cpu->l2vic_base_addr + offset;
+    uint32_t irq;
+    cpu_physical_memory_read(pend_mem, &irq, sizeof(irq));
+    return irq;
 }
 
 static void hexagon_read_timer(CPUHexagonState *env, uint32_t *low,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 28/39] target/hexagon: Implement modify_ssr, resched, pending_interrupt
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (26 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 27/39] target/hexagon: Implement hexagon_find_last_irq() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 29/39] target/hexagon: Add pkt_ends_tb to translation Brian Cain
                   ` (10 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/helper.h    |  5 +++++
 target/hexagon/op_helper.c | 20 ++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 730eaf8b9a..e107d74609 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -129,4 +129,9 @@ DEF_HELPER_1(stop, void, env)
 DEF_HELPER_2(wait, void, env, i32)
 DEF_HELPER_2(resume, void, env, i32)
 DEF_HELPER_2(nmi, void, env, i32)
+DEF_HELPER_1(resched, void, env)
+DEF_HELPER_3(modify_ssr, void, env, i32, i32)
+DEF_HELPER_1(pending_interrupt, void, env)
+DEF_HELPER_3(sreg_write_masked, void, env, i32, i32)
+DEF_HELPER_3(sreg_write_pair_masked, void, env, i32, i64)
 #endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 5196226f02..e283c5c809 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1180,6 +1180,15 @@ float64 HELPER(dfmpyhh)(CPUHexagonState *env, float64 RxxV,
     return RxxV;
 }
 
+#ifndef CONFIG_USER_ONLY
+void HELPER(modify_ssr)(CPUHexagonState *env, uint32_t new, uint32_t old)
+{
+    BQL_LOCK_GUARD();
+    hexagon_modify_ssr(env, new, old);
+}
+#endif
+
+
 /* Histogram instructions */
 
 void HELPER(vhist)(CPUHexagonState *env)
@@ -1523,6 +1532,11 @@ static inline QEMU_ALWAYS_INLINE void resched(CPUHexagonState *env)
     }
 }
 
+void HELPER(resched)(CPUHexagonState *env)
+{
+    resched(env);
+}
+
 void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
 {
     BQL_LOCK_GUARD();
@@ -1844,6 +1858,12 @@ void HELPER(nmi)(CPUHexagonState *env, uint32_t thread_mask)
 {
     g_assert_not_reached();
 }
+
+void HELPER(pending_interrupt)(CPUHexagonState *env)
+{
+    BQL_LOCK_GUARD();
+    hex_interrupt_update(env);
+}
 #endif
 
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 29/39] target/hexagon: Add pkt_ends_tb to translation
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (27 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 28/39] target/hexagon: Implement modify_ssr, resched, pending_interrupt Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 30/39] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
                   ` (9 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.h |   1 +
 target/hexagon/translate.c | 102 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 0bdf526a9e..08194a3309 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -84,6 +84,7 @@ typedef struct DisasContext {
     TCGv branch_taken;
     TCGv dczero_addr;
     bool pcycle_enabled;
+    bool pkt_ends_tb;
     uint32_t num_cycles;
 } DisasContext;
 
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index a71fa33ccf..92adc60d1a 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -258,6 +258,16 @@ static bool check_for_attrib(Packet *pkt, int attrib)
     return false;
 }
 
+static bool check_for_opcode(Packet *pkt, uint16_t opcode)
+{
+    for (int i = 0; i < pkt->num_insns; i++) {
+        if (pkt->insn[i].opcode == opcode) {
+            return true;
+        }
+    }
+    return false;
+}
+
 static bool need_slot_cancelled(Packet *pkt)
 {
     /* We only need slot_cancelled for conditional store instructions */
@@ -271,6 +281,90 @@ static bool need_slot_cancelled(Packet *pkt)
     return false;
 }
 
+#ifndef CONFIG_USER_ONLY
+static bool sreg_write_to_global(int reg_num)
+{
+    return reg_num == HEX_SREG_SSR ||
+           reg_num == HEX_SREG_STID ||
+           reg_num == HEX_SREG_IMASK ||
+           reg_num == HEX_SREG_IPENDAD ||
+           reg_num == HEX_SREG_BESTWAIT ||
+           reg_num == HEX_SREG_SCHEDCFG;
+}
+
+static bool has_sreg_write_to_global(Packet const *pkt)
+{
+    for (int i = 0; i < pkt->num_insns; i++) {
+        Insn const *insn = &pkt->insn[i];
+        uint16_t opcode = insn->opcode;
+        if (opcode == Y2_tfrsrcr) {
+            /* Write to a single sreg */
+            int reg_num = insn->regno[0];
+            if (sreg_write_to_global(reg_num)) {
+                return true;
+            }
+        } else if (opcode == Y4_tfrspcp) {
+            /* Write to a sreg pair */
+            int reg_num = insn->regno[0];
+            if (sreg_write_to_global(reg_num)) {
+                return true;
+            }
+            if (sreg_write_to_global(reg_num + 1)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+#endif
+
+static bool pkt_ends_tb(Packet *pkt)
+{
+    if (pkt->pkt_has_cof) {
+        return true;
+    }
+#ifndef CONFIG_USER_ONLY
+    /* System mode instructions that end TLB */
+    if (check_for_opcode(pkt, Y2_swi) ||
+        check_for_opcode(pkt, Y2_cswi) ||
+        check_for_opcode(pkt, Y2_ciad) ||
+        check_for_opcode(pkt, Y4_siad) ||
+        check_for_opcode(pkt, Y2_wait) ||
+        check_for_opcode(pkt, Y2_resume) ||
+        check_for_opcode(pkt, Y2_iassignw) ||
+        check_for_opcode(pkt, Y2_setimask) ||
+        check_for_opcode(pkt, Y4_nmi) ||
+        check_for_opcode(pkt, Y2_setprio) ||
+        check_for_opcode(pkt, Y2_start) ||
+        check_for_opcode(pkt, Y2_stop) ||
+        check_for_opcode(pkt, Y2_k0lock) ||
+        check_for_opcode(pkt, Y2_k0unlock) ||
+        check_for_opcode(pkt, Y2_tlblock) ||
+        check_for_opcode(pkt, Y2_tlbunlock) ||
+        check_for_opcode(pkt, Y2_break) ||
+        check_for_opcode(pkt, Y2_isync) ||
+        check_for_opcode(pkt, Y2_syncht) ||
+        check_for_opcode(pkt, Y2_tlbp) ||
+        check_for_opcode(pkt, Y2_tlbw) ||
+        check_for_opcode(pkt, Y5_ctlbw) ||
+        check_for_opcode(pkt, Y5_tlbasidi)) {
+        return true;
+    }
+
+    /*
+     * Check for sreg writes that would end the TB
+     */
+    if (check_for_attrib(pkt, A_IMPLICIT_WRITES_SSR)) {
+        return true;
+    }
+    if (has_sreg_write_to_global(pkt)) {
+        return true;
+    }
+#endif
+    return false;
+}
+
+
 static bool need_next_PC(DisasContext *ctx)
 {
     Packet *pkt = ctx->pkt;
@@ -426,7 +520,10 @@ static void analyze_packet(DisasContext *ctx)
 static void gen_start_packet(DisasContext *ctx)
 {
     Packet *pkt = ctx->pkt;
-    target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
+    target_ulong next_PC = (check_for_opcode(pkt, Y2_k0lock) ||
+                            check_for_opcode(pkt, Y2_tlblock)) ?
+                               ctx->base.pc_next :
+                               ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
     int i;
 
     /* Clear out the disassembly context */
@@ -472,6 +569,7 @@ static void gen_start_packet(DisasContext *ctx)
         tcg_gen_movi_tl(hex_slot_cancelled, 0);
     }
     ctx->branch_taken = NULL;
+    ctx->pkt_ends_tb = pkt_ends_tb(pkt);
     if (pkt->pkt_has_cof) {
         ctx->branch_taken = tcg_temp_new();
         if (pkt->pkt_has_multi_cof) {
@@ -926,7 +1024,7 @@ static void gen_commit_packet(DisasContext *ctx)
         pkt->vhist_insn->generate(ctx);
     }
 
-    if (pkt->pkt_has_cof) {
+    if (ctx->pkt_ends_tb || ctx->base.is_jmp == DISAS_NORETURN) {
         gen_end_tb(ctx);
     }
 }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 30/39] target/hexagon: Add next_PC, {s,g}reg writes
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (28 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 29/39] target/hexagon: Add pkt_ends_tb to translation Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 31/39] target/hexagon: Add implicit sysreg writes Brian Cain
                   ` (8 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.h |   2 +
 target/hexagon/genptr.c    |   7 +-
 target/hexagon/translate.c | 134 ++++++++++++++++++++++++++++++++-----
 3 files changed, 123 insertions(+), 20 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 08194a3309..95f570c02a 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -85,6 +85,7 @@ typedef struct DisasContext {
     TCGv dczero_addr;
     bool pcycle_enabled;
     bool pkt_ends_tb;
+    bool need_next_pc;
     uint32_t num_cycles;
 } DisasContext;
 
@@ -306,6 +307,7 @@ static inline void ctx_log_qreg_read(DisasContext *ctx,
 }
 
 extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
+extern TCGv hex_next_PC;
 extern TCGv hex_pred[NUM_PREGS];
 extern TCGv hex_slot_cancelled;
 extern TCGv hex_new_value_usr;
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 0648daefb6..ca41ddf0e9 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -613,14 +613,15 @@ static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
         tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
     }
 
+    TCGv PC_wr = ctx->need_next_pc ? hex_next_PC : hex_gpr[HEX_REG_PC];
     if (ctx->pkt->pkt_has_multi_cof) {
         /* If there are multiple branches in a packet, ignore the second one */
-        tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
+        tcg_gen_movcond_tl(TCG_COND_NE, PC_wr,
                            ctx->branch_taken, tcg_constant_tl(0),
-                           hex_gpr[HEX_REG_PC], addr);
+                           PC_wr, addr);
         tcg_gen_movi_tl(ctx->branch_taken, 1);
     } else {
-        tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
+        tcg_gen_mov_tl(PC_wr, addr);
     }
 
     if (cond != TCG_COND_ALWAYS) {
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 92adc60d1a..70e0a1ff33 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -49,6 +49,7 @@ static const AnalyzeInsn opcode_analyze[XX_LAST_OPCODE] = {
 TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
 TCGv hex_pred[NUM_PREGS];
 TCGv hex_slot_cancelled;
+TCGv hex_next_PC;
 TCGv hex_new_value_usr;
 TCGv hex_store_addr[STORES_MAX];
 TCGv hex_store_width[STORES_MAX];
@@ -61,6 +62,7 @@ TCGv_i64 hex_cycle_count;
 TCGv hex_vstore_addr[VSTORES_MAX];
 TCGv hex_vstore_size[VSTORES_MAX];
 TCGv hex_vstore_pending[VSTORES_MAX];
+static bool need_next_PC(DisasContext *ctx);
 
 #ifndef CONFIG_USER_ONLY
 TCGv hex_greg[NUM_GREGS];
@@ -183,6 +185,9 @@ static void gen_end_tb(DisasContext *ctx)
 
     gen_exec_counters(ctx);
 
+    if (ctx->need_next_pc) {
+        tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
+    }
     if (ctx->branch_cond != TCG_COND_NEVER) {
         if (ctx->branch_cond != TCG_COND_ALWAYS) {
             TCGLabel *skip = gen_new_label();
@@ -368,18 +373,24 @@ static bool pkt_ends_tb(Packet *pkt)
 static bool need_next_PC(DisasContext *ctx)
 {
     Packet *pkt = ctx->pkt;
-
-    /* Check for conditional control flow or HW loop end */
-    for (int i = 0; i < pkt->num_insns; i++) {
-        uint16_t opcode = pkt->insn[i].opcode;
-        if (GET_ATTRIB(opcode, A_CONDEXEC) && GET_ATTRIB(opcode, A_COF)) {
-            return true;
-        }
-        if (GET_ATTRIB(opcode, A_HWLOOP0_END) ||
-            GET_ATTRIB(opcode, A_HWLOOP1_END)) {
-            return true;
+    if (pkt->pkt_has_cof || ctx->pkt_ends_tb) {
+        for (int i = 0; i < pkt->num_insns; i++) {
+            uint16_t opcode = pkt->insn[i].opcode;
+            if ((GET_ATTRIB(opcode, A_CONDEXEC) && GET_ATTRIB(opcode, A_COF)) ||
+                GET_ATTRIB(opcode, A_HWLOOP0_END) ||
+                GET_ATTRIB(opcode, A_HWLOOP1_END)) {
+                return true;
+            }
         }
     }
+    /*
+     * We end the TB on some instructions that do not change the flow (for
+     * other reasons). In these cases, we must set pc too, as the insn won't
+     * do it themselves.
+     */
+    if (ctx->pkt_ends_tb && !check_for_attrib(pkt, A_COF)) {
+        return true;
+    }
     return false;
 }
 
@@ -531,6 +542,10 @@ static void gen_start_packet(DisasContext *ctx)
     ctx->reg_log_idx = 0;
     bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
     bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
+#ifndef CONFIG_USER_ONLY
+    ctx->greg_log_idx = 0;
+    ctx->sreg_log_idx = 0;
+#endif
     ctx->preg_log_idx = 0;
     bitmap_zero(ctx->pregs_written, NUM_PREGS);
     ctx->future_vregs_idx = 0;
@@ -563,21 +578,41 @@ static void gen_start_packet(DisasContext *ctx)
      * gen phase, so clear it again.
      */
     bitmap_zero(ctx->pregs_written, NUM_PREGS);
+#ifndef CONFIG_USER_ONLY
+    for (i = 0; i < NUM_SREGS; i++) {
+        ctx->t_sreg_new_value[i] = NULL;
+    }
+    for (i = 0; i < ctx->sreg_log_idx; i++) {
+        int reg_num = ctx->sreg_log[i];
+        if (reg_num < HEX_SREG_GLB_START) {
+            ctx->t_sreg_new_value[reg_num] = tcg_temp_new();
+            tcg_gen_mov_tl(ctx->t_sreg_new_value[reg_num], hex_t_sreg[reg_num]);
+        }
+    }
+    for (i = 0; i < NUM_GREGS; i++) {
+        ctx->greg_new_value[i] = NULL;
+    }
+    for (i = 0; i < ctx->greg_log_idx; i++) {
+        int reg_num = ctx->greg_log[i];
+        ctx->greg_new_value[reg_num] = tcg_temp_new();
+    }
+#endif
 
     /* Initialize the runtime state for packet semantics */
     if (need_slot_cancelled(pkt)) {
         tcg_gen_movi_tl(hex_slot_cancelled, 0);
     }
     ctx->branch_taken = NULL;
-    ctx->pkt_ends_tb = pkt_ends_tb(pkt);
     if (pkt->pkt_has_cof) {
         ctx->branch_taken = tcg_temp_new();
-        if (pkt->pkt_has_multi_cof) {
-            tcg_gen_movi_tl(ctx->branch_taken, 0);
-        }
-        if (need_next_PC(ctx)) {
-            tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], next_PC);
-        }
+    }
+    if (pkt->pkt_has_multi_cof) {
+        tcg_gen_movi_tl(ctx->branch_taken, 0);
+    }
+    ctx->pkt_ends_tb = pkt_ends_tb(pkt);
+    ctx->need_next_pc = need_next_PC(ctx);
+    if (ctx->need_next_pc) {
+        tcg_gen_movi_tl(hex_next_PC, next_PC);
     }
 
     /* Preload the predicated registers into get_result_gpr(ctx, i) */
@@ -713,6 +748,59 @@ static void gen_reg_writes(DisasContext *ctx)
     }
 }
 
+#ifndef CONFIG_USER_ONLY
+static void gen_greg_writes(DisasContext *ctx)
+{
+    int i;
+
+    for (i = 0; i < ctx->greg_log_idx; i++) {
+        int reg_num = ctx->greg_log[i];
+
+        tcg_gen_mov_tl(hex_greg[reg_num], ctx->greg_new_value[reg_num]);
+    }
+}
+
+
+static void gen_sreg_writes(DisasContext *ctx)
+{
+    int i;
+
+    TCGv old_reg = tcg_temp_new();
+    for (i = 0; i < ctx->sreg_log_idx; i++) {
+        int reg_num = ctx->sreg_log[i];
+
+        if (reg_num == HEX_SREG_SSR) {
+            tcg_gen_mov_tl(old_reg, hex_t_sreg[reg_num]);
+            tcg_gen_mov_tl(hex_t_sreg[reg_num], ctx->t_sreg_new_value[reg_num]);
+            gen_helper_modify_ssr(tcg_env, ctx->t_sreg_new_value[reg_num],
+                                  old_reg);
+            /* This can change processor state, so end the TB */
+            ctx->base.is_jmp = DISAS_NORETURN;
+        } else if ((reg_num == HEX_SREG_STID) ||
+                   (reg_num == HEX_SREG_IMASK) ||
+                   (reg_num == HEX_SREG_IPENDAD)) {
+            if (reg_num < HEX_SREG_GLB_START) {
+                tcg_gen_mov_tl(old_reg, hex_t_sreg[reg_num]);
+                tcg_gen_mov_tl(hex_t_sreg[reg_num],
+                               ctx->t_sreg_new_value[reg_num]);
+            }
+            /* This can change the interrupt state, so end the TB */
+            gen_helper_pending_interrupt(tcg_env);
+            ctx->base.is_jmp = DISAS_NORETURN;
+        } else if ((reg_num == HEX_SREG_BESTWAIT) ||
+                   (reg_num == HEX_SREG_SCHEDCFG)) {
+            /* This can trigger resched interrupt, so end the TB */
+            gen_helper_resched(tcg_env);
+            ctx->base.is_jmp = DISAS_NORETURN;
+        }
+
+        if (reg_num < HEX_SREG_GLB_START) {
+            tcg_gen_mov_tl(hex_t_sreg[reg_num], ctx->t_sreg_new_value[reg_num]);
+        }
+    }
+}
+#endif
+
 static void gen_pred_writes(DisasContext *ctx)
 {
     /* Early exit if not needed or the log is empty */
@@ -1012,6 +1100,10 @@ static void gen_commit_packet(DisasContext *ctx)
     process_store_log(ctx);
 
     gen_reg_writes(ctx);
+#if !defined(CONFIG_USER_ONLY)
+    gen_greg_writes(ctx);
+    gen_sreg_writes(ctx);
+#endif
     gen_pred_writes(ctx);
     if (pkt->pkt_has_hvx) {
         gen_commit_hvx(ctx);
@@ -1073,6 +1165,7 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
     ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
     ctx->short_circuit = hex_cpu->short_circuit;
     ctx->pcycle_enabled = FIELD_EX32(hex_flags, TB_FLAGS, PCYCLE_ENABLED);
+    ctx->need_next_pc = false;
 }
 
 static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
@@ -1201,6 +1294,13 @@ void hexagon_translate_init(void)
         offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
     hex_cycle_count = tcg_global_mem_new_i64(tcg_env,
             offsetof(CPUHexagonState, t_cycle_count), "t_cycle_count");
+#ifndef CONFIG_USER_ONLY
+    hex_cause_code = tcg_global_mem_new(tcg_env,
+        offsetof(CPUHexagonState, cause_code), "cause_code");
+#endif
+    hex_next_PC = tcg_global_mem_new(tcg_env,
+        offsetof(CPUHexagonState, next_PC), "next_PC");
+
     for (i = 0; i < STORES_MAX; i++) {
         snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
         hex_store_addr[i] = tcg_global_mem_new(tcg_env,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 31/39] target/hexagon: Add implicit sysreg writes
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (29 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 30/39] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 32/39] target/hexagon: Define system, guest reg names Brian Cain
                   ` (7 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 70e0a1ff33..743c96e6e1 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -422,6 +422,16 @@ static void mark_implicit_reg_write(DisasContext *ctx, int attrib, int rnum)
     }
 }
 
+#ifndef CONFIG_USER_ONLY
+static void mark_implicit_sreg_write(DisasContext *ctx, int attrib, int snum)
+{
+    uint16_t opcode = ctx->insn->opcode;
+    if (GET_ATTRIB(opcode, attrib)) {
+        ctx_log_sreg_write(ctx, snum);
+    }
+}
+#endif
+
 static void mark_implicit_reg_writes(DisasContext *ctx)
 {
     mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_FP,  HEX_REG_FP);
@@ -433,6 +443,12 @@ static void mark_implicit_reg_writes(DisasContext *ctx)
     mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
     mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_USR, HEX_REG_USR);
     mark_implicit_reg_write(ctx, A_FPOP, HEX_REG_USR);
+
+#ifndef CONFIG_USER_ONLY
+    mark_implicit_sreg_write(ctx, A_IMPLICIT_WRITES_SGP0, HEX_SREG_SGP0);
+    mark_implicit_sreg_write(ctx, A_IMPLICIT_WRITES_SGP1, HEX_SREG_SGP1);
+    mark_implicit_sreg_write(ctx, A_IMPLICIT_WRITES_SSR, HEX_SREG_SSR);
+#endif
 }
 
 static void mark_implicit_pred_write(DisasContext *ctx, int attrib, int pnum)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 32/39] target/hexagon: Define system, guest reg names
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (30 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 31/39] target/hexagon: Add implicit sysreg writes Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 33/39] target/hexagon: initialize sys/guest reg TCGvs Brian Cain
                   ` (6 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/internal.h |  2 ++
 target/hexagon/cpu.c      | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 94e5e502a9..a9eb5645f1 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -34,6 +34,8 @@ void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
 void hexagon_debug(CPUHexagonState *env);
 
 extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
+extern const char * const hexagon_sregnames[];
+extern const char * const hexagon_gregnames[];
 
 void G_NORETURN do_raise_exception(CPUHexagonState *env,
         uint32_t exception,
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 6d2013ce89..122761e657 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -88,6 +88,35 @@ const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = {
   "c24", "c25", "c26", "c27", "c28",  "c29", "c30", "c31",
 };
 
+#ifndef CONFIG_USER_ONLY
+const char * const hexagon_sregnames[] = {
+    "sgp0",       "sgp1",       "stid",       "elr",        "badva0",
+    "badva1",     "ssr",        "ccr",        "htid",       "badva",
+    "imask",      "gevb",       "vwctrl",     "s13",        "s14",
+    "s15",        "evb",        "modectl",    "syscfg",     "segment",
+    "ipendad",    "vid",        "vid1",       "bestwait",   "s24",
+    "schedcfg",   "s26",        "cfgbase",    "diag",       "rev",
+    "pcyclelo",   "pcyclehi",   "isdbst",     "isdbcfg0",   "isdbcfg1",
+    "livelock",   "brkptpc0",   "brkptcfg0",  "brkptpc1",   "brkptcfg1",
+    "isdbmbxin",  "isdbmbxout", "isdben",     "isdbgpr",    "pmucnt4",
+    "pmucnt5",    "pmucnt6",    "pmucnt7",    "pmucnt0",    "pmucnt1",
+    "pmucnt2",    "pmucnt3",    "pmuevtcfg",  "pmustid0",   "pmuevtcfg1",
+    "pmustid1",   "timerlo",    "timerhi",    "pmucfg",     "rgdr2",
+    "rgdr",       "turkey",     "duck",       "chicken",
+};
+
+G_STATIC_ASSERT(NUM_SREGS == ARRAY_SIZE(hexagon_sregnames));
+
+const char * const hexagon_gregnames[] = {
+    "gelr",       "gsr",       "gosp",      "gbadva",    "gcommit1t",
+    "gcommit2t",  "gcommit3t", "gcommit4t", "gcommit5t", "gcommit6t",
+    "gpcycle1t",  "gpcycle2t", "gpcycle3t", "gpcycle4t", "gpcycle5t",
+    "gpcycle6t",  "gpmucnt4",  "gpmucnt5",  "gpmucnt6",  "gpmucnt7",
+    "gcommit7t",  "gcommit8t", "gpcycle7t", "gpcycle8t", "gpcyclelo",
+    "gpcyclehi",  "gpmucnt0",  "gpmucnt1",  "gpmucnt2",  "gpmucnt3",
+    "g30",        "g31",
+};
+#endif
 /*
  * One of the main debugging techniques is to use "-d cpu" and compare against
  * LLDB output when single stepping.  However, the target and qemu put the
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 33/39] target/hexagon: initialize sys/guest reg TCGvs
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (31 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 32/39] target/hexagon: Define system, guest reg names Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 34/39] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
                   ` (5 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 743c96e6e1..01a236d108 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -1287,6 +1287,20 @@ void hexagon_translate_init(void)
 
     opcode_init();
 
+#ifndef CONFIG_USER_ONLY
+    for (i = 0; i < NUM_GREGS; i++) {
+            hex_greg[i] = tcg_global_mem_new(tcg_env,
+                offsetof(CPUHexagonState, greg[i]),
+                hexagon_gregnames[i]);
+    }
+    for (i = 0; i < NUM_SREGS; i++) {
+        if (i < HEX_SREG_GLB_START) {
+            hex_t_sreg[i] = tcg_global_mem_new(tcg_env,
+                offsetof(CPUHexagonState, t_sreg[i]),
+                hexagon_sregnames[i]);
+        }
+    }
+#endif
     for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
         hex_gpr[i] = tcg_global_mem_new(tcg_env,
             offsetof(CPUHexagonState, gpr[i]),
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 34/39] target/hexagon: Add TLB, k0 {un,}lock
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (32 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 33/39] target/hexagon: initialize sys/guest reg TCGvs Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 35/39] target/hexagon: Define gen_precise_exception() Brian Cain
                   ` (4 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/sys_macros.h |   8 +--
 target/hexagon/op_helper.c  | 104 ++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
index 3c4c3c7aa5..e5dc1ce0ab 100644
--- a/target/hexagon/sys_macros.h
+++ b/target/hexagon/sys_macros.h
@@ -143,11 +143,11 @@
 #define fDCINVIDX(REG)
 #define fDCINVA(REG) do { REG = REG; } while (0) /* Nothing to do in qemu */
 
-#define fSET_TLB_LOCK()       g_assert_not_reached()
-#define fCLEAR_TLB_LOCK()     g_assert_not_reached()
+#define fSET_TLB_LOCK()       hex_tlb_lock(env);
+#define fCLEAR_TLB_LOCK()     hex_tlb_unlock(env);
 
-#define fSET_K0_LOCK()        g_assert_not_reached()
-#define fCLEAR_K0_LOCK()      g_assert_not_reached()
+#define fSET_K0_LOCK()        hex_k0_lock(env);
+#define fCLEAR_K0_LOCK()      hex_k0_unlock(env);
 
 #define fTLB_IDXMASK(INDEX) \
     ((INDEX) & (fPOW2_ROUNDUP(fCAST4u(env_archcpu(env)->num_tlbs)) - 1))
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index e283c5c809..5efd644fa7 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1186,6 +1186,110 @@ void HELPER(modify_ssr)(CPUHexagonState *env, uint32_t new, uint32_t old)
     BQL_LOCK_GUARD();
     hexagon_modify_ssr(env, new, old);
 }
+
+static void hex_k0_lock(CPUHexagonState *env)
+{
+    BQL_LOCK_GUARD();
+    g_assert((env->k0_lock_count == 0) || (env->k0_lock_count == 1));
+
+    uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+    if (GET_SYSCFG_FIELD(SYSCFG_K0LOCK, syscfg)) {
+        if (env->k0_lock_state == HEX_LOCK_QUEUED) {
+            env->next_PC += 4;
+            env->k0_lock_count++;
+            env->k0_lock_state = HEX_LOCK_OWNER;
+            SET_SYSCFG_FIELD(env, SYSCFG_K0LOCK, 1);
+            return;
+        }
+        if (env->k0_lock_state == HEX_LOCK_OWNER) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "Double k0lock at PC: 0x%x, thread may hang\n",
+                          env->next_PC);
+            env->next_PC += 4;
+            CPUState *cs = env_cpu(env);
+            cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+            return;
+        }
+        env->k0_lock_state = HEX_LOCK_WAITING;
+        CPUState *cs = env_cpu(env);
+        cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+    } else {
+        env->next_PC += 4;
+        env->k0_lock_count++;
+        env->k0_lock_state = HEX_LOCK_OWNER;
+        SET_SYSCFG_FIELD(env, SYSCFG_K0LOCK, 1);
+    }
+
+}
+
+static void hex_k0_unlock(CPUHexagonState *env)
+{
+    BQL_LOCK_GUARD();
+    g_assert((env->k0_lock_count == 0) || (env->k0_lock_count == 1));
+
+    /* Nothing to do if the k0 isn't locked by this thread */
+    uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+    if ((GET_SYSCFG_FIELD(SYSCFG_K0LOCK, syscfg) == 0) ||
+        (env->k0_lock_state != HEX_LOCK_OWNER)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "thread %d attempted to unlock k0 without having the "
+                      "lock, k0_lock state = %d, syscfg:k0 = %d\n",
+                      env->threadId, env->k0_lock_state,
+                      GET_SYSCFG_FIELD(SYSCFG_K0LOCK, syscfg));
+        g_assert(env->k0_lock_state != HEX_LOCK_WAITING);
+        return;
+    }
+
+    env->k0_lock_count--;
+    env->k0_lock_state = HEX_LOCK_UNLOCKED;
+    SET_SYSCFG_FIELD(env, SYSCFG_K0LOCK, 0);
+
+    /* Look for a thread to unlock */
+    unsigned int this_threadId = env->threadId;
+    CPUHexagonState *unlock_thread = NULL;
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        CPUHexagonState *thread = cpu_env(cs);
+
+        /*
+         * The hardware implements round-robin fairness, so we look for threads
+         * starting at env->threadId + 1 and incrementing modulo the number of
+         * threads.
+         *
+         * To implement this, we check if thread is a earlier in the modulo
+         * sequence than unlock_thread.
+         *     if unlock thread is higher than this thread
+         *         thread must be between this thread and unlock_thread
+         *     else
+         *         thread higher than this thread is ahead of unlock_thread
+         *         thread must be lower then unlock thread
+         */
+        if (thread->k0_lock_state == HEX_LOCK_WAITING) {
+            if (!unlock_thread) {
+                unlock_thread = thread;
+            } else if (unlock_thread->threadId > this_threadId) {
+                if (this_threadId < thread->threadId &&
+                    thread->threadId < unlock_thread->threadId) {
+                    unlock_thread = thread;
+                }
+            } else {
+                if (thread->threadId > this_threadId) {
+                    unlock_thread = thread;
+                }
+                if (thread->threadId < unlock_thread->threadId) {
+                    unlock_thread = thread;
+                }
+            }
+        }
+    }
+    if (unlock_thread) {
+        cs = env_cpu(unlock_thread);
+        unlock_thread->k0_lock_state = HEX_LOCK_QUEUED;
+        SET_SYSCFG_FIELD(unlock_thread, SYSCFG_K0LOCK, 1);
+        cpu_interrupt(cs, CPU_INTERRUPT_K0_UNLOCK);
+    }
+
+}
 #endif
 
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 35/39] target/hexagon: Define gen_precise_exception()
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (33 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 34/39] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 36/39] target/hexagon: Add TCG overrides for transfer insts Brian Cain
                   ` (3 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Add PC to raise_exception helper

Replace the fGEN_TCG_J2_trap0 macro override with the fTRAP()-generated
system helper instead.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_tcg.h   |  7 -------
 target/hexagon/helper.h    |  2 +-
 target/hexagon/op_helper.c | 10 ++++------
 target/hexagon/translate.c | 13 ++++++++-----
 4 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 71f8a0e2d0..146aadc737 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1370,13 +1370,6 @@
 #define fGEN_TCG_S2_storew_rl_st_vi(SHORTCODE)          SHORTCODE
 #define fGEN_TCG_S4_stored_rl_st_vi(SHORTCODE)          SHORTCODE
 
-#define fGEN_TCG_J2_trap0(SHORTCODE) \
-    do { \
-        uiV = uiV; \
-        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->pkt->pc); \
-        TCGv excp = tcg_constant_tl(HEX_EVENT_TRAP0); \
-        gen_helper_raise_exception(tcg_env, excp); \
-    } while (0)
 #endif
 
 #define fGEN_TCG_A2_nop(SHORTCODE) do { } while (0)
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index e107d74609..bd75c72abd 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -18,7 +18,7 @@
 #include "internal.h"
 #include "helper_protos_generated.h.inc"
 
-DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_RETURN, noreturn, env, i32)
+DEF_HELPER_FLAGS_3(raise_exception, TCG_CALL_NO_RETURN, noreturn, env, i32, i32)
 DEF_HELPER_2(commit_store, void, env, int)
 DEF_HELPER_3(gather_store, void, env, i32, int)
 DEF_HELPER_1(commit_hvx_stores, void, env)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 5efd644fa7..6783e1e7d1 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -71,15 +71,13 @@ G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
                                             uint32_t exception,
                                             uintptr_t pc)
 {
-    CPUState *cs = env_cpu(env);
-    qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
-    cs->exception_index = exception;
-    cpu_loop_exit_restore(cs, pc);
+    do_raise_exception(env, exception, pc, 0);
 }
 
-G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp)
+G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp,
+                                        target_ulong PC)
 {
-    hexagon_raise_exception_err(env, excp, 0);
+    hexagon_raise_exception_err(env, excp, PC);
 }
 
 void log_store32(CPUHexagonState *env, target_ulong addr,
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 01a236d108..38c2037c47 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -122,9 +122,10 @@ intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
     return offset;
 }
 
-static void gen_exception_raw(int excp)
+static void gen_exception(int excp, target_ulong PC)
 {
-    gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
+    gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp),
+                               tcg_constant_tl(PC));
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -219,9 +220,11 @@ static void gen_end_tb(DisasContext *ctx)
 
 void hex_gen_exception_end_tb(DisasContext *ctx, int excp)
 {
-    gen_exec_counters(ctx);
-    tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
-    gen_exception_raw(excp);
+#ifdef CONFIG_USER_ONLY
+    gen_exception(excp, ctx->pkt->pc);
+#else
+    gen_precise_exception(excp, ctx->pkt->pc);
+#endif
     ctx->base.is_jmp = DISAS_NORETURN;
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 36/39] target/hexagon: Add TCG overrides for transfer insts
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (34 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 35/39] target/hexagon: Define gen_precise_exception() Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 37/39] target/hexagon: Add support for loadw_phys Brian Cain
                   ` (2 subsequent siblings)
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_tcg_sys.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
index 6d73a18db4..e56553462f 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -81,6 +81,31 @@
         gen_helper_stop(tcg_env); \
     } while (0)
 
+#define fGEN_TCG_Y2_tfrscrr(SHORTCODE) \
+    tcg_gen_mov_tl(RdV, SsV)
+
+#define fGEN_TCG_Y2_tfrsrcr(SHORTCODE) \
+    tcg_gen_mov_tl(SdV, RsV)
+
+#define fGEN_TCG_Y4_tfrscpp(SHORTCODE) \
+    tcg_gen_mov_i64(RddV, SssV)
+
+#define fGEN_TCG_Y4_tfrspcp(SHORTCODE) \
+    tcg_gen_mov_i64(SddV, RssV)
+
+#define fGEN_TCG_G4_tfrgcrr(SHORTCODE) \
+    tcg_gen_mov_tl(RdV, GsV)
+
+#define fGEN_TCG_G4_tfrgrcr(SHORTCODE) \
+    tcg_gen_mov_tl(GdV, RsV)
+
+#define fGEN_TCG_G4_tfrgcpp(SHORTCODE) \
+    tcg_gen_mov_i64(RddV, GssV)
+
+#define fGEN_TCG_G4_tfrgpcp(SHORTCODE) \
+    tcg_gen_mov_i64(GddV, RssV)
+
+
 /*
  * rte (return from exception)
  *     Clear the EX bit in SSR
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 37/39] target/hexagon: Add support for loadw_phys
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (35 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 36/39] target/hexagon: Add TCG overrides for transfer insts Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 38/39] target/hexagon: Add guest reg reading functionality Brian Cain
  2025-09-02  3:48 ` [PATCH v2 39/39] target/hexagon: Add pcycle setting functionality Brian Cain
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/hex_common.py          | 3 +++
 target/hexagon/imported/encode_pp.def | 1 +
 target/hexagon/imported/ldst.idef     | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 39451e6d88..2770b0638b 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -265,6 +265,9 @@ def need_slot(tag):
         and "A_CVI_GATHER" not in attribdict[tag]
         and ("A_STORE" in attribdict[tag]
              or "A_LOAD" in attribdict[tag])
+        and tag != "L4_loadw_phys"
+        and tag != "L6_memcpy"
+        and tag != "Y6_dmlink"
     ):
         return 1
     else:
diff --git a/target/hexagon/imported/encode_pp.def b/target/hexagon/imported/encode_pp.def
index 37faf62b1b..41e4ab9e3a 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -388,6 +388,7 @@ DEF_ENC32(L4_return_fnew_pnt, ICLASS_LD" 011 0 000 sssss PP1010vv ---ddddd")
 
 /** Load Acquire Store Release Encoding **/
 
+DEF_ENC32(L4_loadw_phys,      ICLASS_LD" 001 0 000 sssss PP1ttttt -00ddddd")
 DEF_ENC32(L2_loadw_locked,    ICLASS_LD" 001 0 000 sssss PP000--- 000ddddd")
 DEF_ENC32(L4_loadd_locked,    ICLASS_LD" 001 0 000 sssss PP010--- 000ddddd")
 
diff --git a/target/hexagon/imported/ldst.idef b/target/hexagon/imported/ldst.idef
index 53198176a9..4e1e5d5326 100644
--- a/target/hexagon/imported/ldst.idef
+++ b/target/hexagon/imported/ldst.idef
@@ -203,6 +203,9 @@ Q6INSN(S2_storew_locked,"memw_locked(Rs32,Pd4)=Rt32", ATTRIBS(A_REGWRSIZE_4B,A_M
 Q6INSN(L4_loadd_locked,"Rdd32=memd_locked(Rs32)", ATTRIBS(A_REGWRSIZE_8B,A_MEMSIZE_8B,A_LOAD,A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK), "Load double with lock",
 { fEA_REG(RsV); fLOAD_LOCKED(1,8,u,EA,RddV) })
 
+Q6INSN(L4_loadw_phys,"Rd32=memw_phys(Rs32,Rt32)", ATTRIBS(A_REGWRSIZE_4B,A_PRIV,A_RESTRICT_SLOT0ONLY,A_NOTE_PRIV,A_MEMSIZE_4B,A_LOAD,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Load word from physical address",
+{ fLOAD_PHYS(1,4,u,RsV,RtV,RdV); })
+
 Q6INSN(S4_stored_locked,"memd_locked(Rs32,Pd4)=Rtt32", ATTRIBS(A_REGWRSIZE_8B,A_MEMSIZE_8B,A_STORE,A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK,A_RESTRICT_LATEPRED,A_NOTE_LATEPRED), "Store word with lock",
 { fEA_REG(RsV); fSTORE_LOCKED(1,8,EA,RttV,PdV) })
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 38/39] target/hexagon: Add guest reg reading functionality
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (36 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 37/39] target/hexagon: Add support for loadw_phys Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  2025-09-02  3:48 ` [PATCH v2 39/39] target/hexagon: Add pcycle setting functionality Brian Cain
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Matheus Tavares Bernardino

From: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>

Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
---
 target/hexagon/cpu.c       | 19 ++++++++++++++++++-
 target/hexagon/op_helper.c | 19 +++++++++++++++++--
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 122761e657..751ba613cc 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -778,7 +778,24 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
 #ifndef CONFIG_USER_ONLY
 uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg)
 {
-    g_assert_not_reached();
+    target_ulong ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+    int ssr_ce = GET_SSR_FIELD(SSR_CE, ssr);
+
+    if (reg <= HEX_GREG_G3) {
+        return env->greg[reg];
+    }
+    switch (reg) {
+    case HEX_GREG_GPCYCLELO:
+        return ssr_ce ? hexagon_get_sys_pcycle_count_low(env) : 0;
+
+    case HEX_GREG_GPCYCLEHI:
+        return ssr_ce ? hexagon_get_sys_pcycle_count_high(env) : 0;
+
+    default:
+        qemu_log_mask(LOG_UNIMP, "reading greg %" PRId32
+                " not yet supported.\n", reg);
+        return 0;
+    }
 }
 #endif
 
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 6783e1e7d1..1bc32769c6 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1927,13 +1927,28 @@ uint64_t HELPER(sreg_read_pair)(CPUHexagonState *env, uint32_t reg)
 }
 
 uint32_t HELPER(greg_read)(CPUHexagonState *env, uint32_t reg)
+
 {
-    g_assert_not_reached();
+    return hexagon_greg_read(env, reg);
 }
 
 uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
+
 {
-    g_assert_not_reached();
+    if (reg == HEX_GREG_G0 || reg == HEX_GREG_G2) {
+        return (uint64_t)(env->greg[reg]) |
+               (((uint64_t)(env->greg[reg + 1])) << 32);
+    }
+    switch (reg) {
+    case HEX_GREG_GPCYCLELO: {
+        target_ulong ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+        int ssr_ce = GET_SSR_FIELD(SSR_CE, ssr);
+        return ssr_ce ? hexagon_get_sys_pcycle_count(env) : 0;
+    }
+    default:
+        return (uint64_t)hexagon_greg_read(env, reg) |
+               ((uint64_t)(hexagon_greg_read(env, reg + 1)) << 32);
+    }
 }
 
 void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 39/39] target/hexagon: Add pcycle setting functionality
  2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
                   ` (37 preceding siblings ...)
  2025-09-02  3:48 ` [PATCH v2 38/39] target/hexagon: Add guest reg reading functionality Brian Cain
@ 2025-09-02  3:48 ` Brian Cain
  38 siblings, 0 replies; 40+ messages in thread
From: Brian Cain @ 2025-09-02  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
	anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
	sid.manning, Matheus Tavares Bernardino

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
---
 target/hexagon/cpu_helper.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 5d0ba23d02..447421cdd0 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -120,13 +120,18 @@ uint32_t hexagon_get_sys_pcycle_count_low(CPUHexagonState *env)
 void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env,
         uint32_t cycles_hi)
 {
-    g_assert_not_reached();
+    uint64_t cur_cycles = hexagon_get_sys_pcycle_count(env);
+    uint64_t cycles =
+        ((uint64_t)cycles_hi << 32) | extract64(cur_cycles, 0, 32);
+    hexagon_set_sys_pcycle_count(env, cycles);
 }
 
 void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env,
         uint32_t cycles_lo)
 {
-    g_assert_not_reached();
+    uint64_t cur_cycles = hexagon_get_sys_pcycle_count(env);
+    uint64_t cycles = extract64(cur_cycles, 32, 32) | cycles_lo;
+    hexagon_set_sys_pcycle_count(env, cycles);
 }
 
 void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2025-09-02  4:15 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-02  3:48 [PATCH v2 00/39] hexagon system emulation v2, part 2/3 Brian Cain
2025-09-02  3:48 ` [PATCH v2 01/39] target/hexagon: Implement ciad helper Brian Cain
2025-09-02  3:48 ` [PATCH v2 02/39] target/hexagon: Implement {c,}swi helpers Brian Cain
2025-09-02  3:48 ` [PATCH v2 03/39] target/hexagon: Implement iassign{r,w} helpers Brian Cain
2025-09-02  3:48 ` [PATCH v2 04/39] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
2025-09-02  3:48 ` [PATCH v2 05/39] target/hexagon: Implement modify SSR Brian Cain
2025-09-02  3:48 ` [PATCH v2 06/39] target/hexagon: Implement {g,s}etimask helpers Brian Cain
2025-09-02  3:48 ` [PATCH v2 07/39] target/hexagon: Implement wait helper Brian Cain
2025-09-02  3:48 ` [PATCH v2 08/39] target/hexagon: Implement get_exe_mode() Brian Cain
2025-09-02  3:48 ` [PATCH v2 09/39] target/hexagon: Implement arch_get_system_reg() Brian Cain
2025-09-02  3:48 ` [PATCH v2 10/39] target/hexagon: Implement arch_{s, g}et_{thread, system}_reg() Brian Cain via
2025-09-02  3:48 ` [PATCH v2 11/39] target/hexagon: Add representation to count cycles Brian Cain
2025-09-02  3:48 ` [PATCH v2 12/39] target/hexagon: Add implementation of cycle counters Brian Cain
2025-09-02  3:48 ` [PATCH v2 13/39] target/hexagon: Implement modify_syscfg() Brian Cain
2025-09-02  3:48 ` [PATCH v2 14/39] target/hexagon: Implement hex_tlb_entry_get_perm() Brian Cain
2025-09-02  3:48 ` [PATCH v2 15/39] target/hexagon: Implement hex_tlb_lookup_by_asid() Brian Cain
2025-09-02  3:48 ` [PATCH v2 16/39] target/hexagon: Implement software interrupt Brian Cain
2025-09-02  3:48 ` [PATCH v2 17/39] target/hexagon: Implement exec_interrupt, set_irq Brian Cain
2025-09-02  3:48 ` [PATCH v2 18/39] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
2025-09-02  3:48 ` [PATCH v2 19/39] target/hexagon: Implement hexagon_tlb_fill() Brian Cain
2025-09-02  3:48 ` [PATCH v2 20/39] target/hexagon: Implement siad inst Brian Cain
2025-09-02  3:48 ` [PATCH v2 21/39] target/hexagon: Implement hexagon_resume_threads() Brian Cain
2025-09-02  3:48 ` [PATCH v2 22/39] target/hexagon: Implement setprio, resched Brian Cain
2025-09-02  3:48 ` [PATCH v2 23/39] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug() Brian Cain
2025-09-02  3:48 ` [PATCH v2 24/39] target/hexagon: Add exec-start-addr prop Brian Cain
2025-09-02  3:48 ` [PATCH v2 25/39] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu Brian Cain
2025-09-02  3:48 ` [PATCH v2 26/39] target/hexagon: Decode trap1, rte as COF Brian Cain
2025-09-02  3:48 ` [PATCH v2 27/39] target/hexagon: Implement hexagon_find_last_irq() Brian Cain
2025-09-02  3:48 ` [PATCH v2 28/39] target/hexagon: Implement modify_ssr, resched, pending_interrupt Brian Cain
2025-09-02  3:48 ` [PATCH v2 29/39] target/hexagon: Add pkt_ends_tb to translation Brian Cain
2025-09-02  3:48 ` [PATCH v2 30/39] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
2025-09-02  3:48 ` [PATCH v2 31/39] target/hexagon: Add implicit sysreg writes Brian Cain
2025-09-02  3:48 ` [PATCH v2 32/39] target/hexagon: Define system, guest reg names Brian Cain
2025-09-02  3:48 ` [PATCH v2 33/39] target/hexagon: initialize sys/guest reg TCGvs Brian Cain
2025-09-02  3:48 ` [PATCH v2 34/39] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
2025-09-02  3:48 ` [PATCH v2 35/39] target/hexagon: Define gen_precise_exception() Brian Cain
2025-09-02  3:48 ` [PATCH v2 36/39] target/hexagon: Add TCG overrides for transfer insts Brian Cain
2025-09-02  3:48 ` [PATCH v2 37/39] target/hexagon: Add support for loadw_phys Brian Cain
2025-09-02  3:48 ` [PATCH v2 38/39] target/hexagon: Add guest reg reading functionality Brian Cain
2025-09-02  3:48 ` [PATCH v2 39/39] target/hexagon: Add pcycle setting functionality Brian Cain

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).