* [PATCH v3 00/32] Hexagon system emulation - Part 2/3
@ 2026-03-11 4:07 Brian Cain
2026-03-11 4:07 ` [PATCH v3 01/32] target/hexagon: Implement {c,}swi helpers Brian Cain
` (31 more replies)
0 siblings, 32 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo
This is Part 2 of the hexagon system emulation (sysemu) patch series,
building on the infrastructure from Part 1 to implement the runtime
helpers and CPU operations needed for full-system emulation.
This part adds:
- Helper implementations for system instructions: swi, cswi,
iassign, start/stop, wait/resume, setprio, resched
- SSR (System Status Register) modification and exe mode support
- Cycle counter implementation
- TLB operations: tlb_fill, tlb_entry_get_perm
- Interrupt handling: exec_interrupt, set_irq, software interrupt
- Stack overflow exception (fFRAMECHECK / FRAMELIMIT check)
- CPU execution support: cpu_exec_reset, pointer_wrap, sysemu_ops
- Translation support: pkt_ends_tb, implicit sysreg writes, next_PC
- System/guest register name definitions
- TCG overrides for transfer and load_phys instructions
- Guest register and pcycle reading functionality
Changes since v2:
- Dropped "Implement ciad helper" (l2vic deferred to a future series)
- Dropped "Implement arch_get_system_reg()" and "Implement
arch_{s,g}et_{thread,system}_reg()" -- the arch_*_system_reg
abstraction layer is no longer introduced (callers use
globalreg_read/write directly)
- Dropped "Implement modify_syscfg()", "Implement
hex_tlb_lookup_by_asid()", "Implement hexagon_find_last_irq()",
"Initialize sys/guest reg TCGvs"
- Dropped "Add exec-start-addr prop" (folded into Part 3 commit)
- Renamed "Define gen_precise_exception()" to "Add PC to
raise_exception, use fTRAP() helper"
- Added "Implement stack overflow exception" commit
- Moved TLB lock macros (fSET_TLB_LOCK, fCLEAR_TLB_LOCK) to Part 1;
"Add TLB, k0 {un,}lock" now only adds K0 lock macros
- Removed CONFIG_USER_ONLY guards from cpu_helper.c (file in
hexagon_softmmu_ss)
Previous versions:
v2: https://lore.kernel.org/qemu-devel/20250902034847.1948010-1-brian.cain@oss.qualcomm.com/
v1: https://lore.kernel.org/qemu-devel/20250301052845.1012069-1-brian.cain@oss.qualcomm.com/
Brian Cain (30):
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: Add representation to count cycles
target/hexagon: Add implementation of cycle counters
target/hexagon: Implement hex_tlb_entry_get_perm()
target/hexagon: Implement software interrupt
target/hexagon: Implement stack overflow exception
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: extend hexagon_cpu_mmu_index() for sysemu
target/hexagon: Decode trap1, rte as COF
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: Add TLB, k0 {un,}lock
target/hexagon: Add PC to raise_exception, use fTRAP() helper
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 | 20 +-
target/hexagon/cpu_helper.h | 5 +
target/hexagon/gen_tcg.h | 7 -
target/hexagon/gen_tcg_sys.h | 25 ++
target/hexagon/helper.h | 6 +-
target/hexagon/hexswi.h | 17 +
target/hexagon/internal.h | 4 +
target/hexagon/macros.h | 3 -
target/hexagon/sys_macros.h | 7 +
target/hexagon/translate.h | 5 +
target/hexagon/reg_fields_def.h.inc | 11 +
linux-user/hexagon/cpu_loop.c | 7 +
target/hexagon/cpu.c | 368 ++++++++++++++++++++-
target/hexagon/cpu_helper.c | 282 +++++++++++++++-
target/hexagon/decode.c | 14 +
target/hexagon/genptr.c | 18 +-
target/hexagon/hexswi.c | 260 +++++++++++++++
target/hexagon/op_helper.c | 443 ++++++++++++++++++++++++--
target/hexagon/translate.c | 248 +++++++++++++-
target/hexagon/hex_common.py | 3 +
target/hexagon/imported/encode_pp.def | 1 +
target/hexagon/imported/ldst.idef | 3 +
22 files changed, 1696 insertions(+), 61 deletions(-)
create mode 100644 target/hexagon/hexswi.h
create mode 100644 target/hexagon/hexswi.c
--
2.34.1
^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v3 01/32] target/hexagon: Implement {c,}swi helpers
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 02/32] target/hexagon: Implement iassign{r,w} helpers Brian Cain
` (30 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 3517f3768fd..712638defcf 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -23,6 +23,7 @@
#include "cpu.h"
#include "exec/helper-proto.h"
#include "fpu/softfloat.h"
+#include "exec/cpu-interrupt.h"
#include "internal.h"
#include "macros.h"
#include "sys_macros.h"
@@ -35,6 +36,7 @@
#include "cpu_helper.h"
#include "translate.h"
#ifndef CONFIG_USER_ONLY
+#include "hex_interrupts.h"
#include "hexswi.h"
#endif
@@ -1402,12 +1404,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] 52+ messages in thread
* [PATCH v3 02/32] target/hexagon: Implement iassign{r,w} helpers
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
2026-03-11 4:07 ` [PATCH v3 01/32] target/hexagon: Implement {c,}swi helpers Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
` (29 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 54 ++++++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 712638defcf..6ae07cc68e5 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1416,12 +1416,62 @@ 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();
+ HexagonCPU *hex_cpu = env_archcpu(env);
+ modectl = hex_cpu->globalregs ?
+ hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId) : 0;
+ 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 = thread_env->t_sreg[HEX_SREG_IMASK];
+ uint32_t intbitpos = (src >> 16) & 0xF;
+ uint32_t val = (src >> thread_env->threadId) & 0x1;
+ imask = deposit32(imask, intbitpos, 1, val);
+ thread_env->t_sreg[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();
+ HexagonCPU *hex_cpu = env_archcpu(env);
+ modectl = hex_cpu->globalregs ?
+ hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId) : 0;
+ 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 = thread_env->t_sreg[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] 52+ messages in thread
* [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
2026-03-11 4:07 ` [PATCH v3 01/32] target/hexagon: Implement {c,}swi helpers Brian Cain
2026-03-11 4:07 ` [PATCH v3 02/32] target/hexagon: Implement iassign{r,w} helpers Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-12 21:37 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 04/32] target/hexagon: Implement modify SSR Brian Cain
` (28 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu.h | 7 +++
target/hexagon/cpu_helper.h | 3 ++
target/hexagon/cpu.c | 26 +++++++++-
target/hexagon/cpu_helper.c | 100 ++++++++++++++++++++++++++++++++++++
target/hexagon/op_helper.c | 4 +-
5 files changed, 136 insertions(+), 4 deletions(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 0017be9dff7..1a3c9014455 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -207,6 +207,13 @@ G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
uint32_t exception,
uintptr_t pc);
+#ifndef CONFIG_USER_ONLY
+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;
void hexagon_translate_init(void);
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index d15385daf83..72f83d62a54 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -17,5 +17,8 @@ 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);
#endif
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 938492897fd..20c4b82a970 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -33,6 +33,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) { }
@@ -316,6 +317,26 @@ static void hexagon_restore_state_to_opc(CPUState *cs,
}
+#ifndef CONFIG_USER_ONLY
+void hexagon_cpu_soft_reset(CPUHexagonState *env)
+{
+ BQL_LOCK_GUARD();
+ env->t_sreg[HEX_SREG_SSR] = 0;
+ hexagon_ssr_set_cause(env, HEX_CAUSE_RESET);
+
+ HexagonCPU *cpu = env_archcpu(env);
+ if (cpu->globalregs) {
+ uint32_t evb =
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_EVB,
+ env->threadId);
+ env->gpr[HEX_REG_PC] = evb;
+ } else {
+ env->gpr[HEX_REG_PC] = cpu->boot_addr;
+ }
+}
+#endif
+
+
static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
@@ -343,9 +364,10 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
HexagonCPU *cpu = HEXAGON_CPU(cs);
env->t_sreg[HEX_SREG_HTID] = cpu->htid;
env->threadId = cpu->htid;
- env->gpr[HEX_REG_PC] = cpu->boot_addr;
-#endif
+ hexagon_cpu_soft_reset(env);
env->cause_code = HEX_EVENT_NONE;
+ env->gpr[HEX_REG_PC] = cpu->boot_addr;
+#endif
}
static void hexagon_cpu_disas_set_info(const CPUState *cs,
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 6fbf5fc8e2f..c251790e5a5 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -10,6 +10,7 @@
#include "system/cpus.h"
#include "hw/core/boards.h"
#include "hw/hexagon/hexagon.h"
+#include "system/runstate.h"
#include "exec/cpu-interrupt.h"
#include "exec/target_page.h"
#include "accel/tcg/cpu-ldst.h"
@@ -79,7 +80,106 @@ void clear_wait_mode(CPUHexagonState *env)
}
}
+void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause)
+{
+ g_assert(bql_locked());
+
+ const uint32_t old = env->t_sreg[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 = env->t_sreg[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());
+
+ HexagonCPU *cpu = env_archcpu(env);
+ const uint32_t modectl = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId) : 0;
+ 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());
+
+ HexagonCPU *cpu = env_archcpu(env);
+ const uint32_t modectl = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId) : 0;
+ 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 uint32_t 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, request shutdown */
+ qemu_system_shutdown_request_with_code(
+ SHUTDOWN_CAUSE_GUEST_SHUTDOWN, get_thread0_r2());
+ }
+}
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 6ae07cc68e5..82605f1d4aa 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1476,12 +1476,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] 52+ messages in thread
* [PATCH v3 04/32] target/hexagon: Implement modify SSR
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (2 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-12 21:39 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 05/32] target/hexagon: Implement {g,s}etimask helpers Brian Cain
` (27 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 c251790e5a5..c7375de39f4 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -10,6 +10,9 @@
#include "system/cpus.h"
#include "hw/core/boards.h"
#include "hw/hexagon/hexagon.h"
+#include "hw/hexagon/hexagon_globalreg.h"
+#include "hex_interrupts.h"
+#include "hex_mmu.h"
#include "system/runstate.h"
#include "exec/cpu-interrupt.h"
#include "exec/target_page.h"
@@ -62,7 +65,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] 52+ messages in thread
* [PATCH v3 05/32] target/hexagon: Implement {g,s}etimask helpers
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (3 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 04/32] target/hexagon: Implement modify SSR Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-12 21:42 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 06/32] target/hexagon: Implement wait helper Brian Cain
` (26 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/op_helper.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 82605f1d4aa..161c7eaf31f 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1496,12 +1496,43 @@ void HELPER(resume)(CPUHexagonState *env, uint32_t mask)
uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
{
- 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 (found_env->threadId == tid) {
+ uint32_t imask = found_env->t_sreg[HEX_SREG_IMASK];
+ 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);
+ }
+ }
+ return 0;
}
void HELPER(setimask)(CPUHexagonState *env, uint32_t tid, 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 (tid == found_env->threadId) {
+ SET_SYSTEM_FIELD(found_env, HEX_SREG_IMASK, IMASK_MASK, imask);
+ qemu_log_mask(CPU_LOG_INT, "%s: tid " TARGET_FMT_lx
+ " imask 0x%x\n",
+ __func__, found_env->threadId, imask);
+ hex_interrupt_update(found_env);
+ return;
+ }
+ }
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "setimask used with an invalid tid near PC: 0x%x\n",
+ env->next_PC);
}
void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 06/32] target/hexagon: Implement wait helper
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (4 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 05/32] target/hexagon: Implement {g,s}etimask helpers Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-12 21:47 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 07/32] target/hexagon: Implement get_exe_mode() Brian Cain
` (25 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/op_helper.c | 51 ++++++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 161c7eaf31f..6dfc1269809 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1484,9 +1484,56 @@ void HELPER(stop)(CPUHexagonState *env)
hexagon_stop_thread(env);
}
-void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
+static void set_wait_mode(CPUHexagonState *env)
{
- g_assert_not_reached();
+ g_assert(bql_locked());
+
+ HexagonCPU *cpu = env_archcpu(env);
+ const uint32_t modectl = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId) : 0;
+ 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);
+}
+
+static void hexagon_wait_thread(CPUHexagonState *env, uint32_t 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);
+}
+
+void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
+{
+ 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] 52+ messages in thread
* [PATCH v3 07/32] target/hexagon: Implement get_exe_mode()
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (5 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 06/32] target/hexagon: Implement wait helper Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 08/32] target/hexagon: Add representation to count cycles Brian Cain
` (24 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 28 ++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/target/hexagon/reg_fields_def.h.inc b/target/hexagon/reg_fields_def.h.inc
index 9b112ccec64..d2c706d56b5 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 c7375de39f4..4860e4a6ab0 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -126,6 +126,34 @@ void hexagon_ssr_set_cause(CPUHexagonState *env, uint32_t cause)
int get_exe_mode(CPUHexagonState *env)
{
+ g_assert(bql_locked());
+
+ HexagonCPU *cpu = env_archcpu(env);
+ uint32_t modectl = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId) : 0;
+ 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);
+ uint32_t isdbst = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_ISDBST,
+ env->threadId) : 0;
+ 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] 52+ messages in thread
* [PATCH v3 08/32] target/hexagon: Add representation to count cycles
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (6 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 07/32] target/hexagon: Implement get_exe_mode() Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-12 21:49 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 09/32] target/hexagon: Add implementation of cycle counters Brian Cain
` (23 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 1a3c9014455..ee2e5eeece2 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -129,7 +129,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. */
uint32_t t_sreg[NUM_SREGS];
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 09/32] target/hexagon: Add implementation of cycle counters
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (7 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 08/32] target/hexagon: Add representation to count cycles Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-14 23:42 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 10/32] target/hexagon: Implement hex_tlb_entry_get_perm() Brian Cain
` (22 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 5 +++--
target/hexagon/translate.h | 2 ++
target/hexagon/cpu.c | 14 ++++++++++++++
target/hexagon/cpu_helper.c | 32 ++++++++++++++++++++++++++++----
target/hexagon/translate.c | 21 +++++++++++++++++++++
5 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index ee2e5eeece2..da96b52bd2a 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -30,6 +30,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/core/registerfields.h"
@@ -38,8 +39,7 @@
#error "Hexagon does not support system emulation"
#endif
-#ifndef CONFIG_USER_ONLY
-#endif
+#include "reg_fields.h"
#define NUM_PREGS 4
#define TOTAL_PER_THREAD_REGS 64
@@ -202,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 7e528379db6..e7acbae9ffa 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -84,6 +84,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 20c4b82a970..1c8a188dec4 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -293,9 +293,23 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
}
#ifndef CONFIG_USER_ONLY
+ HexagonCPU *cpu = env_archcpu(env);
+ uint32_t syscfg = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+ env->threadId) : 0;
+
+ 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 4860e4a6ab0..729ffa47eed 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -33,17 +33,31 @@ uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index)
uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env)
{
- g_assert_not_reached();
+ BQL_LOCK_GUARD();
+ uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
+ if (!GET_SSR_FIELD(SSR_CE, ssr)) {
+ return 0;
+ }
+ uint64_t cycles = 0;
+ CPUState *cs;
+ CPU_FOREACH(cs) {
+ CPUHexagonState *thread_env = cpu_env(cs);
+ cycles += thread_env->t_cycle_count;
+ }
+ HexagonCPU *cpu = env_archcpu(env);
+ uint64_t base = cpu->globalregs ?
+ hexagon_globalreg_get_pcycle_base(cpu->globalregs) : 0;
+ return base + cycles;
}
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,
@@ -60,7 +74,17 @@ 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();
+ HexagonCPU *cpu = env_archcpu(env);
+ if (cpu->globalregs) {
+ hexagon_globalreg_set_pcycle_base(cpu->globalregs, cycles);
+ }
+
+ 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 4df4226cbcb..e4d4dad8ffd 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -61,6 +61,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];
@@ -128,6 +129,16 @@ 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_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],
@@ -136,6 +147,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)
@@ -821,6 +836,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;
@@ -840,6 +856,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;
}
@@ -989,11 +1006,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)
@@ -1136,6 +1155,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] 52+ messages in thread
* [PATCH v3 10/32] target/hexagon: Implement hex_tlb_entry_get_perm()
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (8 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 09/32] target/hexagon: Add implementation of cycle counters Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 11/32] target/hexagon: Implement software interrupt Brian Cain
` (21 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain,
Laurent Vivier, Pierrick Bouvier
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 +++++++
1 file changed, 7 insertions(+)
diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 9f54c7b3f96..0958c51fbb3 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:
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 11/32] target/hexagon: Implement software interrupt
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (9 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 10/32] target/hexagon: Implement hex_tlb_entry_get_perm() Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-14 23:52 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 12/32] target/hexagon: Implement stack overflow exception Brian Cain
` (20 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 1 +
target/hexagon/hexswi.c | 260 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 278 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 00000000000..48c1ae6e4c1
--- /dev/null
+++ b/target/hexagon/hexswi.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * 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,
+ uint32_t PC);
+
+#endif /* HEXSWI_H */
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 1c8a188dec4..2964d8a63f6 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -34,6 +34,7 @@
#include "sys_macros.h"
#include "accel/tcg/cpu-ldst.h"
#include "qemu/main-loop.h"
+#include "hex_interrupts.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 00000000000..77a4dd5bc43
--- /dev/null
+++ b/target/hexagon/hexswi.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * 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"
+#include "hw/hexagon/hexagon_globalreg.h"
+
+#ifdef CONFIG_USER_ONLY
+#error "This file is only used in system emulation"
+#endif
+
+static void set_addresses(CPUHexagonState *env, uint32_t pc_offset,
+ uint32_t exception_index)
+
+{
+ HexagonCPU *cpu = env_archcpu(env);
+ uint32_t evb = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_EVB,
+ env->threadId) :
+ cpu->boot_addr;
+ env->t_sreg[HEX_SREG_ELR] = env->gpr[HEX_REG_PC] + pc_offset;
+ env->gpr[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_PRECISE] = "HEX_EVENT_PRECISE",
+ [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 = env->t_sreg[HEX_SREG_SSR];
+ if (GET_SSR_FIELD(SSR_EX, ssr) == 1) {
+ HexagonCPU *cpu = env_archcpu(env);
+ if (cpu->globalregs) {
+ hexagon_globalreg_write(cpu->globalregs, HEX_SREG_DIAG,
+ env->cause_code, env->threadId);
+ }
+ 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,
+ env->gpr[HEX_REG_PC],
+ env->t_sreg[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],
+ env->t_sreg[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);
+ set_addresses(env, 0, cs->exception_index);
+ 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],
+ env->t_sreg[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_UNSUPPORTED_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,
+ uint32_t 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);
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 12/32] target/hexagon: Implement stack overflow exception
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (10 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 11/32] target/hexagon: Implement software interrupt Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-15 0:02 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 13/32] target/hexagon: Implement exec_interrupt, set_irq Brian Cain
` (19 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo
Implement the frame limit check for system emulation mode. When
allocframe computes a new stack pointer below FRAMELIMIT, raise a
precise exception (HEX_CAUSE_STACK_LIMIT). The check is skipped in
monitor mode.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/helper.h | 1 +
target/hexagon/macros.h | 3 ---
target/hexagon/sys_macros.h | 4 ++++
target/hexagon/translate.h | 2 ++
target/hexagon/genptr.c | 18 +++++++++++-------
target/hexagon/op_helper.c | 34 ++++++++++++++++++++++++++++++++++
6 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 9ca87acfe63..ebcd471ec0a 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -109,6 +109,7 @@ DEF_HELPER_2(probe_hvx_stores, void, env, int)
DEF_HELPER_2(probe_pkt_scalar_hvx_stores, void, env, int)
#if !defined(CONFIG_USER_ONLY)
+DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32)
DEF_HELPER_2(swi, void, env, i32)
DEF_HELPER_2(cswi, void, env, i32)
DEF_HELPER_2(ciad, void, env, i32)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 26d3f7d8a4b..d3f2105c932 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -538,9 +538,6 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
#ifdef CONFIG_USER_ONLY
#define fFRAMECHECK(ADDR, EA) do { } while (0) /* Not modelled in linux-user */
-#else
-/* System mode not implemented yet */
-#define fFRAMECHECK(ADDR, EA) g_assert_not_reached();
#endif
#ifdef QEMU_GENERATE
diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
index 364fcde7383..cbc857fa2f5 100644
--- a/target/hexagon/sys_macros.h
+++ b/target/hexagon/sys_macros.h
@@ -95,6 +95,10 @@
#define fTRAP(TRAPTYPE, IMM) \
register_trap_exception(env, TRAPTYPE, IMM, PC)
+#ifdef QEMU_GENERATE
+#define fFRAMECHECK(ADDR, EA) gen_framecheck(ctx, ADDR, EA)
+#endif
+
#define fVIRTINSN_SPSWAP(IMM, REG)
#define fVIRTINSN_GETIE(IMM, REG) { REG = 0xdeafbeef; }
#define fVIRTINSN_SETIE(IMM, REG)
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index e7acbae9ffa..82b327312ec 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -339,4 +339,6 @@ FIELD(PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED, 3, 1)
FIELD(PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED, 4, 1)
FIELD(PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX, 5, 2)
+void gen_framecheck(DisasContext *ctx, TCGv_i32 addr, TCGv_i32 ea);
+
#endif
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index bac63a42def..f32890f85c7 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -897,26 +897,30 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_LE | MO_UQ);
}
-#ifndef CONFIG_HEXAGON_IDEF_PARSER
/* Stack overflow check */
-static void gen_framecheck(TCGv EA, int framesize)
+void gen_framecheck(DisasContext *ctx, TCGv_i32 addr, TCGv_i32 ea)
{
- /* Not modelled in linux-user mode */
- /* Placeholder for system mode */
#ifndef CONFIG_USER_ONLY
- g_assert_not_reached();
+ TCGLabel *ok = gen_new_label();
+ tcg_gen_brcond_i32(TCG_COND_GEU, addr, hex_gpr[HEX_REG_FRAMELIMIT], ok);
+ gen_helper_raise_stack_overflow(tcg_env,
+ tcg_constant_i32(ctx->insn->slot), ea);
+ gen_set_label(ok);
#endif
}
+#ifndef CONFIG_HEXAGON_IDEF_PARSER
static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize)
{
TCGv r30 = get_result_gpr(ctx, HEX_REG_FP);
+ TCGv_i32 new_r29 = tcg_temp_new_i32();
TCGv_i64 frame;
tcg_gen_addi_tl(r30, r29, -8);
frame = gen_frame_scramble();
gen_store8(tcg_env, r30, frame, ctx->insn->slot);
- gen_framecheck(r30, framesize);
- tcg_gen_subi_tl(r29, r30, framesize);
+ tcg_gen_subi_tl(new_r29, r30, framesize);
+ gen_framecheck(ctx, new_r29, hex_gpr[HEX_REG_PC]);
+ tcg_gen_mov_tl(r29, new_r29);
}
static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 6dfc1269809..c5c638c132e 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1392,6 +1392,40 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
}
#ifndef CONFIG_USER_ONLY
+void HELPER(raise_stack_overflow)(CPUHexagonState *env, uint32_t slot,
+ uint32_t badva)
+{
+ /*
+ * Per section 7.3.1 of the V67 Programmer's Reference,
+ * stack limit exception isn't raised in monitor mode.
+ */
+ uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
+ if (GET_SSR_FIELD(SSR_EX, ssr) ||
+ !GET_SSR_FIELD(SSR_UM, ssr)) {
+ return;
+ }
+
+ CPUState *cs = env_cpu(env);
+ cs->exception_index = HEX_EVENT_PRECISE;
+ env->cause_code = HEX_CAUSE_STACK_LIMIT;
+ ASSERT_DIRECT_TO_GUEST_UNSET(env, cs->exception_index);
+
+ if (slot == 0) {
+ env->t_sreg[HEX_SREG_BADVA0] = 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) {
+ env->t_sreg[HEX_SREG_BADVA1] = badva;
+ 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();
+ }
+ cpu_loop_exit_restore(cs, 0);
+}
+
void HELPER(ciad)(CPUHexagonState *env, uint32_t mask)
{
g_assert_not_reached();
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 13/32] target/hexagon: Implement exec_interrupt, set_irq
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (11 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 12/32] target/hexagon: Implement stack overflow exception Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 14/32] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
` (18 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 80 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index da96b52bd2a..3446910feb6 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 2964d8a63f6..cc2b4c18001 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -16,6 +16,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "qemu/qemu-print.h"
#include "cpu.h"
#include "internal.h"
@@ -31,10 +32,12 @@
#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 "exec/cpu-interrupt.h"
#endif
static void hexagon_v66_cpu_init(Object *obj) { }
@@ -324,6 +327,32 @@ 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;
+ }
+ uint32_t modectl =
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
+ env->threadId);
+ uint32_t thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
+ bool E_bit = thread_enabled_mask & (0x1 << env->threadId);
+
+ return E_bit;
+}
+
+static bool hexagon_cpu_has_work(CPUState *cs)
+{
+ 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));
+}
+#endif
+
static void hexagon_restore_state_to_opc(CPUState *cs,
const TranslationBlock *tb,
const uint64_t *data)
@@ -419,10 +448,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,
@@ -433,6 +510,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] 52+ messages in thread
* [PATCH v3 14/32] target/hexagon: add simple cpu_exec_reset and pointer_wrap
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (12 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 13/32] target/hexagon: Implement exec_interrupt, set_irq Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 16:29 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 15/32] target/hexagon: Implement hexagon_tlb_fill() Brian Cain
` (17 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo
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 cc2b4c18001..f439dff1c20 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -498,6 +498,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 = {
@@ -512,6 +518,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] 52+ messages in thread
* [PATCH v3 15/32] target/hexagon: Implement hexagon_tlb_fill()
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (13 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 14/32] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 16/32] target/hexagon: Implement siad inst Brian Cain
` (16 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 135 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index f439dff1c20..c5ec478ef40 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -38,6 +38,8 @@
#include "qemu/main-loop.h"
#include "hex_interrupts.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) { }
@@ -478,6 +480,138 @@ static void hexagon_cpu_init(Object *obj)
}
#ifndef CONFIG_USER_ONLY
+static bool get_physical_address(CPUHexagonState *env, hwaddr *phys, int *prot,
+ uint64_t *size, int32_t *excp,
+ uint32_t 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, uint64_t 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, uint32_t VA, int slot,
+ MMUAccessType access_type)
+{
+ env->t_sreg[HEX_SREG_BADVA] = VA;
+
+ if (access_type == MMU_INST_FETCH || slot == 0) {
+ env->t_sreg[HEX_SREG_BADVA0] = VA;
+ env->t_sreg[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) {
+ env->t_sreg[HEX_SREG_BADVA0] = INVALID_BADVA;
+ env->t_sreg[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, uint32_t 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, uint32_t 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);
+ int slot = 0;
+ hwaddr phys;
+ int prot = 0;
+ uint64_t 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;
+ }
+ if (probe) {
+ return false;
+ }
+ 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)
{
@@ -520,6 +654,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] 52+ messages in thread
* [PATCH v3 16/32] target/hexagon: Implement siad inst
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (14 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 15/32] target/hexagon: Implement hexagon_tlb_fill() Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 17/32] target/hexagon: Implement hexagon_resume_threads() Brian Cain
` (15 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index c5c638c132e..dff6092dd8a 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1433,7 +1433,21 @@ 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();
+ HexagonCPU *cpu = env_archcpu(env);
+ ipendad = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+ env->threadId) : 0;
+ iad = fGET_FIELD(ipendad, IPENDAD_IAD);
+ fSET_FIELD(ipendad, IPENDAD_IAD, iad | mask);
+ if (cpu->globalregs) {
+ hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
+ ipendad, env->threadId);
+ }
+ hex_interrupt_update(env);
}
void HELPER(swi)(CPUHexagonState *env, uint32_t mask)
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 17/32] target/hexagon: Implement hexagon_resume_threads()
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (15 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 16/32] target/hexagon: Implement siad inst Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 18/32] target/hexagon: Implement setprio, resched Brian Cain
` (14 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 36 ++++++++++++++++++++++++++++++++++++
target/hexagon/op_helper.c | 3 ++-
4 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 3446910feb6..6168fea3b5f 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -50,6 +50,7 @@
#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 72f83d62a54..dc99b4c294b 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -20,5 +20,6 @@ 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_resume_threads(CPUHexagonState *env, uint32_t mask);
#endif
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 729ffa47eed..dcb07283494 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -87,6 +87,42 @@ void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
}
}
+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 dff6092dd8a..9090a5c20ab 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1586,7 +1586,8 @@ void HELPER(wait)(CPUHexagonState *env, uint32_t 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] 52+ messages in thread
* [PATCH v3 18/32] target/hexagon: Implement setprio, resched
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (16 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 17/32] target/hexagon: Implement hexagon_resume_threads() Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 16:49 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 19/32] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug() Brian Cain
` (13 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 75 ++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 9090a5c20ab..36822219b4b 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1575,6 +1575,62 @@ static void hexagon_wait_thread(CPUHexagonState *env, uint32_t PC)
cpu_interrupt(cs, CPU_INTERRUPT_HALT);
}
+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__);
+ HexagonCPU *cpu = env_archcpu(env);
+ schedcfg = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SCHEDCFG,
+ env->threadId) : 0;
+ 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, thread_env->t_sreg[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 = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_BESTWAIT,
+ env->threadId) : 0;
+ 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, env->gpr[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, uint32_t PC)
{
BQL_LOCK_GUARD();
@@ -1680,8 +1736,27 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
g_assert_not_reached();
}
+/*
+ * setprio/resched - See the Hexagon V73 Programmer's Reference Manual,
+ * Section 6.4 "Interrupt and Thread Scheduling"
+ */
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] 52+ messages in thread
* [PATCH v3 19/32] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug()
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (17 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 18/32] target/hexagon: Implement setprio, resched Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 20/32] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu Brian Cain
` (12 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index c5ec478ef40..6849dc7966b 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -20,6 +20,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/core/qdev-properties.h"
@@ -37,6 +38,7 @@
#include "accel/tcg/cpu-ldst.h"
#include "qemu/main-loop.h"
#include "hex_interrupts.h"
+#include "hexswi.h"
#include "exec/cpu-interrupt.h"
#include "exec/target_page.h"
#include "hw/hexagon/hexagon_globalreg.h"
@@ -506,6 +508,24 @@ static void find_qemu_subpage(vaddr *addr, hwaddr *phys, uint64_t 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;
+ uint64_t 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
@@ -613,6 +633,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);
@@ -655,6 +682,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 */
};
@@ -682,9 +711,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
}
#define DEFINE_CPU(type_name, initfn) \
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 20/32] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (18 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 19/32] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug() Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 21/32] target/hexagon: Decode trap1, rte as COF Brian Cain
` (11 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 22 +++++++++++++++++++
target/hexagon/cpu_helper.c | 44 +++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index dc99b4c294b..7d7cf58acc8 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 6849dc7966b..cec06daed73 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -449,6 +449,28 @@ 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 =
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+ env->threadId);
+ 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 dcb07283494..0521c01c84c 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -302,3 +302,47 @@ void hexagon_stop_thread(CPUHexagonState *env)
SHUTDOWN_CAUSE_GUEST_SHUTDOWN, get_thread0_r2());
}
}
+
+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 = env->t_sreg[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;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 21/32] target/hexagon: Decode trap1, rte as COF
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (19 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 20/32] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 22/32] target/hexagon: Implement modify_ssr, resched, pending_interrupt Brian Cain
` (10 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 dbc9c630e82..ce93e6bdd8f 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -185,6 +185,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) {
@@ -363,6 +365,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] 52+ messages in thread
* [PATCH v3 22/32] target/hexagon: Implement modify_ssr, resched, pending_interrupt
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (20 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 21/32] target/hexagon: Decode trap1, rte as COF Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 23/32] target/hexagon: Add pkt_ends_tb to translation Brian Cain
` (9 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 3 +++
target/hexagon/op_helper.c | 20 ++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index ebcd471ec0a..17e74b12f3c 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -129,4 +129,7 @@ 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)
#endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 36822219b4b..1ade66df9d4 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1226,6 +1226,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)
@@ -1631,6 +1640,11 @@ static inline QEMU_ALWAYS_INLINE void resched(CPUHexagonState *env)
}
}
+void HELPER(resched)(CPUHexagonState *env)
+{
+ resched(env);
+}
+
void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
{
BQL_LOCK_GUARD();
@@ -1764,6 +1778,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] 52+ messages in thread
* [PATCH v3 23/32] target/hexagon: Add pkt_ends_tb to translation
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (21 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 22/32] target/hexagon: Implement modify_ssr, resched, pending_interrupt Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 16:55 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 24/32] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
` (8 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 82b327312ec..4e090565aac 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -85,6 +85,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 e4d4dad8ffd..953b34b7891 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -272,6 +272,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 */
@@ -285,6 +295,90 @@ static bool need_slot_cancelled(Packet *pkt)
return false;
}
+#ifndef CONFIG_USER_ONLY
+static bool sreg_write_ends_tb(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_ends_tb(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_ends_tb(reg_num)) {
+ return true;
+ }
+ } else if (opcode == Y4_tfrspcp) {
+ /* Write to a sreg pair */
+ int reg_num = insn->regno[0];
+ if (sreg_write_ends_tb(reg_num)) {
+ return true;
+ }
+ if (sreg_write_ends_tb(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_ends_tb(pkt)) {
+ return true;
+ }
+#endif
+ return false;
+}
+
+
static bool need_next_PC(DisasContext *ctx)
{
Packet *pkt = ctx->pkt;
@@ -447,7 +541,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;
+ uint32_t 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 */
@@ -493,6 +590,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) {
@@ -958,7 +1056,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] 52+ messages in thread
* [PATCH v3 24/32] target/hexagon: Add next_PC, {s,g}reg writes
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (22 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 23/32] target/hexagon: Add pkt_ends_tb to translation Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 17:14 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 25/32] target/hexagon: Add implicit sysreg writes Brian Cain
` (7 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/translate.c | 89 ++++++++++++++++++++++++++++++++++++--
1 file changed, 85 insertions(+), 4 deletions(-)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 953b34b7891..79027e8a327 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -552,6 +552,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;
@@ -584,6 +588,25 @@ 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)) {
@@ -744,6 +767,60 @@ 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_i32 old_reg = tcg_temp_new_i32();
+ 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;
+ continue;
+ } 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 */
@@ -1044,6 +1121,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);
@@ -1255,6 +1336,10 @@ 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_i32(tcg_env,
+ offsetof(CPUHexagonState, cause_code), "cause_code");
+#endif
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,
@@ -1292,8 +1377,4 @@ void hexagon_translate_init(void)
offsetof(CPUHexagonState, vstore_pending[i]),
vstore_pending_names[i]);
}
-#ifndef CONFIG_USER_ONLY
- hex_cause_code = tcg_global_mem_new(tcg_env,
- offsetof(CPUHexagonState, cause_code), "cause_code");
-#endif
}
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 25/32] target/hexagon: Add implicit sysreg writes
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (23 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 24/32] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 26/32] target/hexagon: Define system, guest reg names Brian Cain
` (6 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 79027e8a327..ddf328e0a62 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -428,6 +428,16 @@ static void mark_implicit_usr_write(DisasContext *ctx, int attrib)
}
}
+#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);
@@ -440,6 +450,12 @@ static void mark_implicit_reg_writes(DisasContext *ctx)
mark_implicit_usr_write(ctx, A_IMPLICIT_WRITES_USR);
mark_implicit_usr_write(ctx, A_FPOP);
+
+#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] 52+ messages in thread
* [PATCH v3 26/32] target/hexagon: Define system, guest reg names
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (24 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 25/32] target/hexagon: Add implicit sysreg writes Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 17:41 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 27/32] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
` (5 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/internal.h | 4 ++++
target/hexagon/cpu.c | 29 +++++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 4338914efb5..00b37aea7af 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -30,6 +30,10 @@ void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
void hexagon_debug(CPUHexagonState *env);
extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
+#ifndef CONFIG_USER_ONLY
+extern const char * const hexagon_sregnames[];
+extern const char * const hexagon_gregnames[];
+#endif
void G_NORETURN do_raise_exception(CPUHexagonState *env,
uint32_t exception,
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index cec06daed73..a19cdf84a92 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -92,6 +92,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", "s59",
+ "s60", "s61", "s62", "s63",
+};
+
+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] 52+ messages in thread
* [PATCH v3 27/32] target/hexagon: Add TLB, k0 {un,}lock
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (25 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 26/32] target/hexagon: Define system, guest reg names Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 17:24 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 28/32] target/hexagon: Add PC to raise_exception, use fTRAP() helper Brian Cain
` (4 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/sys_macros.h | 3 +
target/hexagon/op_helper.c | 117 ++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
index cbc857fa2f5..37aae71adce 100644
--- a/target/hexagon/sys_macros.h
+++ b/target/hexagon/sys_macros.h
@@ -146,6 +146,9 @@
#define fSET_TLB_LOCK() hex_tlb_lock(env);
#define fCLEAR_TLB_LOCK() hex_tlb_unlock(env);
+#define fSET_K0_LOCK() hex_k0_lock(env);
+#define fCLEAR_K0_LOCK() hex_k0_unlock(env);
+
#define fTLB_IDXMASK(INDEX) \
((INDEX) & (fPOW2_ROUNDUP( \
fCAST4u(hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))) - 1))
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 1ade66df9d4..89712bf8e09 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -36,6 +36,9 @@
#include "cpu_helper.h"
#include "translate.h"
#ifndef CONFIG_USER_ONLY
+#include "hw/hexagon/hexagon_globalreg.h"
+#include "hex_mmu.h"
+#include "hw/hexagon/hexagon_tlb.h"
#include "hex_interrupts.h"
#include "hexswi.h"
#endif
@@ -1232,6 +1235,120 @@ 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)
+{
+ HexagonCPU *cpu = env_archcpu(env);
+ CPUState *cs = env_cpu(env);
+ target_ulong syscfg;
+
+ BQL_LOCK_GUARD();
+ g_assert((env->k0_lock_count == 0) || (env->k0_lock_count == 1));
+
+ syscfg = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+ env->threadId) : 0;
+ 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;
+ cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+ cpu_loop_exit(cs);
+ return;
+ }
+ env->k0_lock_state = HEX_LOCK_WAITING;
+ cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+ cpu_loop_exit(cs);
+ } 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)
+{
+ HexagonCPU *cpu = env_archcpu(env);
+ unsigned int this_threadId = env->threadId;
+ CPUHexagonState *unlock_thread = NULL;
+ CPUState *cs;
+ target_ulong syscfg;
+
+ 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 */
+ syscfg = cpu->globalregs ?
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+ env->threadId) : 0;
+ 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 */
+ 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] 52+ messages in thread
* [PATCH v3 28/32] target/hexagon: Add PC to raise_exception, use fTRAP() helper
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (26 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 27/32] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 17:35 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 29/32] target/hexagon: Add TCG overrides for transfer insts Brian Cain
` (3 subsequent siblings)
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 | 20 +++++++++++++++-----
4 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index bd04386d860..507d529c4b2 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1369,13 +1369,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 17e74b12f3c..a89758b5df5 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 89712bf8e09..3720f2679da 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -65,15 +65,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,
+ uint32_t 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 ddf328e0a62..e4a0993c88a 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -124,12 +124,19 @@ 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, uint32_t PC)
{
- gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
+ gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp),
+ tcg_constant_i32(PC));
}
#ifndef CONFIG_USER_ONLY
+static inline void gen_precise_exception(int excp, uint32_t PC)
+{
+ tcg_gen_movi_i32(hex_cause_code, excp);
+ gen_exception(HEX_EVENT_PRECISE, PC);
+}
+
static inline void gen_pcycle_counters(DisasContext *ctx)
{
if (ctx->pcycle_enabled) {
@@ -213,8 +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;
}
@@ -228,7 +238,7 @@ static void gen_exception_decode_fail(DisasContext *ctx, int nwords, int excp)
gen_exec_counters(ctx);
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], fail_pc);
- gen_exception_raw(excp);
+ gen_exception(excp, fail_pc);
ctx->base.is_jmp = DISAS_NORETURN;
ctx->base.pc_next = fail_pc;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 29/32] target/hexagon: Add TCG overrides for transfer insts
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (27 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 28/32] target/hexagon: Add PC to raise_exception, use fTRAP() helper Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 30/32] target/hexagon: Add support for loadw_phys Brian Cain
` (2 subsequent siblings)
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 04406db6a4b..c4d7c21b890 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -80,6 +80,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] 52+ messages in thread
* [PATCH v3 30/32] target/hexagon: Add support for loadw_phys
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (28 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 29/32] target/hexagon: Add TCG overrides for transfer insts Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 31/32] target/hexagon: Add guest reg reading functionality Brian Cain
2026-03-11 4:07 ` [PATCH v3 32/32] target/hexagon: Add pcycle setting functionality Brian Cain
31 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo, 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 9986f47114e..8ef8e36852c 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -264,6 +264,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 04e911f59c8..1c64495d519 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -384,6 +384,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 53198176a99..4e1e5d5326d 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] 52+ messages in thread
* [PATCH v3 31/32] target/hexagon: Add guest reg reading functionality
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (29 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 30/32] target/hexagon: Add support for loadw_phys Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 17:44 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 32/32] target/hexagon: Add pcycle setting functionality Brian Cain
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo,
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 | 21 +++++++++++++++++++++
target/hexagon/op_helper.c | 16 ++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index a19cdf84a92..f6a8b23d28d 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -770,6 +770,27 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
#endif
}
+#ifndef CONFIG_USER_ONLY
+uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg)
+{
+ if (reg <= HEX_GREG_G3) {
+ return env->greg[reg];
+ }
+ switch (reg) {
+ case HEX_GREG_GPCYCLELO:
+ return hexagon_get_sys_pcycle_count_low(env);
+
+ case HEX_GREG_GPCYCLEHI:
+ return hexagon_get_sys_pcycle_count_high(env);
+
+ default:
+ qemu_log_mask(LOG_UNIMP, "reading greg %" PRId32
+ " not yet supported.\n", reg);
+ return 0;
+ }
+}
+#endif
+
#define DEFINE_CPU(type_name, initfn) \
{ \
.name = type_name, \
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 3720f2679da..457817b2e1c 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1856,13 +1856,25 @@ 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:
+ return hexagon_get_sys_pcycle_count(env);
+ default:
+ return (uint64_t)hexagon_greg_read(env, reg) |
+ ((uint64_t)(hexagon_greg_read(env, reg + 1)) << 32);
+ }
}
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v3 32/32] target/hexagon: Add pcycle setting functionality
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
` (30 preceding siblings ...)
2026-03-11 4:07 ` [PATCH v3 31/32] target/hexagon: Add guest reg reading functionality Brian Cain
@ 2026-03-11 4:07 ` Brian Cain
2026-03-16 17:46 ` Taylor Simpson
31 siblings, 1 reply; 52+ messages in thread
From: Brian Cain @ 2026-03-11 4:07 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
marco.liebel, quic_mburton, sid.manning, ale, anjo,
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 0521c01c84c..43b558b6e68 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -63,13 +63,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) << 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] 52+ messages in thread
* Re: [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset
2026-03-11 4:07 ` [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
@ 2026-03-12 21:37 ` Taylor Simpson
2026-03-14 21:49 ` Brian Cain
0 siblings, 1 reply; 52+ messages in thread
From: Taylor Simpson @ 2026-03-12 21:37 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 2695 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Brian Cain <bcain@quicinc.com>
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/cpu.h | 7 +++
> target/hexagon/cpu_helper.h | 3 ++
> target/hexagon/cpu.c | 26 +++++++++-
> target/hexagon/cpu_helper.c | 100 ++++++++++++++++++++++++++++++++++++
> target/hexagon/op_helper.c | 4 +-
> 5 files changed, 136 insertions(+), 4 deletions(-)
>
> diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
> index 0017be9dff7..1a3c9014455 100644
> --- a/target/hexagon/cpu.h
> +++ b/target/hexagon/cpu.h
> @@ -207,6 +207,13 @@ G_NORETURN void
> hexagon_raise_exception_err(CPUHexagonState *env,
> uint32_t exception,
> uintptr_t pc);
>
> +#ifndef CONFIG_USER_ONLY
> +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
> +
>
The first three above belong in a different patch.
> diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
> index 6fbf5fc8e2f..c251790e5a5 100644
> +static void set_enable_mask(CPUHexagonState *env)
> +{
> + g_assert(bql_locked());
> +
> + HexagonCPU *cpu = env_archcpu(env);
> + const uint32_t modectl = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
> + env->threadId) : 0;
> + 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);
>
Do you want to set modectl when cpu->globalregs is false?
> +}
> +
> +static uint32_t clear_enable_mask(CPUHexagonState *env)
> +{
> + g_assert(bql_locked());
> +
> + HexagonCPU *cpu = env_archcpu(env);
> + const uint32_t modectl = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
> + env->threadId) : 0;
> + 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);
>
Ditto
> + return thread_enabled_mask;
>
It's strange that set_enable_mask returns void and clear_enable_mask
returns the new mask.
Thanks,
Taylor
[-- Attachment #2: Type: text/html, Size: 3996 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 04/32] target/hexagon: Implement modify SSR
2026-03-11 4:07 ` [PATCH v3 04/32] target/hexagon: Implement modify SSR Brian Cain
@ 2026-03-12 21:39 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-12 21:39 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 601 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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(-)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 1162 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 05/32] target/hexagon: Implement {g,s}etimask helpers
2026-03-11 4:07 ` [PATCH v3 05/32] target/hexagon: Implement {g,s}etimask helpers Brian Cain
@ 2026-03-12 21:42 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-12 21:42 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 1978 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Brian Cain <bcain@quicinc.com>
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/op_helper.c | 35 +++++++++++++++++++++++++++++++++--
> 1 file changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> index 82605f1d4aa..161c7eaf31f 100644
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -1496,12 +1496,43 @@ void HELPER(resume)(CPUHexagonState *env, uint32_t
> mask)
>
> uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
> {
> - 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 (found_env->threadId == tid) {
> + uint32_t imask = found_env->t_sreg[HEX_SREG_IMASK];
> + qemu_log_mask(CPU_LOG_INT, "%s: tid " TARGET_FMT_lx
> + " imask = 0x%x\n", __func__, env->threadId,
>
Don't use %x
> + (unsigned)GET_FIELD(IMASK_MASK, imask));
> + return GET_FIELD(IMASK_MASK, imask);
> + }
> + }
> + return 0;
> }
>
> void HELPER(setimask)(CPUHexagonState *env, uint32_t tid, 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 (tid == found_env->threadId) {
> + SET_SYSTEM_FIELD(found_env, HEX_SREG_IMASK, IMASK_MASK,
> imask);
> + qemu_log_mask(CPU_LOG_INT, "%s: tid " TARGET_FMT_lx
> + " imask 0x%x\n",
>
Ditto
Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 3002 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 06/32] target/hexagon: Implement wait helper
2026-03-11 4:07 ` [PATCH v3 06/32] target/hexagon: Implement wait helper Brian Cain
@ 2026-03-12 21:47 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-12 21:47 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 2719 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Brian Cain <bcain@quicinc.com>
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/op_helper.c | 51 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 49 insertions(+), 2 deletions(-)
>
> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> index 161c7eaf31f..6dfc1269809 100644
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -1484,9 +1484,56 @@ void HELPER(stop)(CPUHexagonState *env)
> hexagon_stop_thread(env);
> }
>
> -void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
> +static void set_wait_mode(CPUHexagonState *env)
> {
> - g_assert_not_reached();
> + g_assert(bql_locked());
> +
> + HexagonCPU *cpu = env_archcpu(env);
> + const uint32_t modectl = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
> + env->threadId) : 0;
> + 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);
>
Do you want to set modectl when cpu->globalregs is false?
> +}
> +
> +static void hexagon_wait_thread(CPUHexagonState *env, uint32_t 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",
>
Don't use %d
> + __func__, env->threadId);
> + return;
> + }
> + set_wait_mode(env);
> + env->wait_next_pc = PC + 4;
> +
> + cpu_interrupt(cs, CPU_INTERRUPT_HALT);
> +}
> +
> +void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
+{
> + 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
>
Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 4095 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 08/32] target/hexagon: Add representation to count cycles
2026-03-11 4:07 ` [PATCH v3 08/32] target/hexagon: Add representation to count cycles Brian Cain
@ 2026-03-12 21:49 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-12 21:49 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 807 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
> index 1a3c9014455..ee2e5eeece2 100644
> --- a/target/hexagon/cpu.h
> +++ b/target/hexagon/cpu.h
> @@ -129,7 +129,7 @@ typedef struct CPUArchState {
> target_ulong stack_start;
>
> uint8_t slot_cancelled;
> -
> + uint64_t t_cycle_count;
>
Should this be guarded by #ifndef CONFIG_USER_ONLY?
Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 1439 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset
2026-03-12 21:37 ` Taylor Simpson
@ 2026-03-14 21:49 ` Brian Cain
0 siblings, 0 replies; 52+ messages in thread
From: Brian Cain @ 2026-03-14 21:49 UTC (permalink / raw)
To: Taylor Simpson
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 3389 bytes --]
On Thu, Mar 12, 2026 at 4:37 PM Taylor Simpson <ltaylorsimpson@gmail.com>
wrote:
>
>
> On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
> wrote:
>
>> From: Brian Cain <bcain@quicinc.com>
>>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>> target/hexagon/cpu.h | 7 +++
>> target/hexagon/cpu_helper.h | 3 ++
>> target/hexagon/cpu.c | 26 +++++++++-
>> target/hexagon/cpu_helper.c | 100 ++++++++++++++++++++++++++++++++++++
>> target/hexagon/op_helper.c | 4 +-
>> 5 files changed, 136 insertions(+), 4 deletions(-)
>>
>> diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
>> index 0017be9dff7..1a3c9014455 100644
>> --- a/target/hexagon/cpu.h
>> +++ b/target/hexagon/cpu.h
>> @@ -207,6 +207,13 @@ G_NORETURN void
>> hexagon_raise_exception_err(CPUHexagonState *env,
>> uint32_t exception,
>> uintptr_t pc);
>>
>> +#ifndef CONFIG_USER_ONLY
>> +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
>> +
>>
>
> The first three above belong in a different patch.
>
I'll fix this.
>
>
>
>> diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
>> index 6fbf5fc8e2f..c251790e5a5 100644
>> +static void set_enable_mask(CPUHexagonState *env)
>> +{
>> + g_assert(bql_locked());
>> +
>> + HexagonCPU *cpu = env_archcpu(env);
>> + const uint32_t modectl = cpu->globalregs ?
>> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
>> + env->threadId) : 0;
>> + 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);
>>
>
> Do you want to set modectl when cpu->globalregs is false?
>
IMO it's near meaningless to consider what it means to be a Hexagon DSP
when globalregs is false. But since there's tests that exercise the "null"
machine configuration without anything connected, it doesn't always make
sense to assert globalregs either.
So ... sure - I can skip modectl or just early return, because ... *shrug*
what does this thing do without that integral piece? Who knows?
>
>
>> +}
>> +
>> +static uint32_t clear_enable_mask(CPUHexagonState *env)
>> +{
>> + g_assert(bql_locked());
>> +
>> + HexagonCPU *cpu = env_archcpu(env);
>> + const uint32_t modectl = cpu->globalregs ?
>> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
>> + env->threadId) : 0;
>> + 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);
>>
>
> Ditto
>
>
>> + return thread_enabled_mask;
>>
>
> It's strange that set_enable_mask returns void and clear_enable_mask
> returns the new mask.
>
>
I'll rethink the interface and review the callers.
> Thanks,
> Taylor
>
>
[-- Attachment #2: Type: text/html, Size: 5962 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 09/32] target/hexagon: Add implementation of cycle counters
2026-03-11 4:07 ` [PATCH v3 09/32] target/hexagon: Add implementation of cycle counters Brian Cain
@ 2026-03-14 23:42 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-14 23:42 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain, Sid Manning
[-- Attachment #1: Type: text/plain, Size: 7868 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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 | 5 +++--
> target/hexagon/translate.h | 2 ++
> target/hexagon/cpu.c | 14 ++++++++++++++
> target/hexagon/cpu_helper.c | 32 ++++++++++++++++++++++++++++----
> target/hexagon/translate.c | 21 +++++++++++++++++++++
> 5 files changed, 68 insertions(+), 6 deletions(-)
>
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index 20c4b82a970..1c8a188dec4 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -293,9 +293,23 @@ static TCGTBCPUState
> hexagon_get_tb_cpu_state(CPUState *cs)
> }
>
> #ifndef CONFIG_USER_ONLY
> + HexagonCPU *cpu = env_archcpu(env);
> + uint32_t syscfg = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
> + env->threadId) : 0;
> +
> + 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);
>
I notice we are setting pcycle-enabled here under CONFIG_USER_ONLY. See
below ...
> 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 4860e4a6ab0..729ffa47eed 100644
> --- a/target/hexagon/cpu_helper.c
> +++ b/target/hexagon/cpu_helper.c
> @@ -33,17 +33,31 @@ uint32_t hexagon_get_pmu_counter(CPUHexagonState
> *cur_env, int index)
>
> uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env)
> {
> - g_assert_not_reached();
> + BQL_LOCK_GUARD();
> + uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
> + if (!GET_SSR_FIELD(SSR_CE, ssr)) {
> + return 0;
> + }
> + uint64_t cycles = 0;
> + CPUState *cs;
> + CPU_FOREACH(cs) {
> + CPUHexagonState *thread_env = cpu_env(cs);
> + cycles += thread_env->t_cycle_count;
> + }
> + HexagonCPU *cpu = env_archcpu(env);
> + uint64_t base = cpu->globalregs ?
> + hexagon_globalreg_get_pcycle_base(cpu->globalregs) : 0;
> + return base + cycles;
> }
>
> 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,
> @@ -60,7 +74,17 @@ 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();
> + HexagonCPU *cpu = env_archcpu(env);
> + if (cpu->globalregs) {
> + hexagon_globalreg_set_pcycle_base(cpu->globalregs, cycles);
> + }
> +
> + 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 4df4226cbcb..e4d4dad8ffd 100644
> --- a/target/hexagon/translate.c
> +++ b/target/hexagon/translate.c
> @@ -61,6 +61,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];
> @@ -128,6 +129,16 @@ 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_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
> +
>
But here, this is guarded by #ifndef CONFIG_USER_ONLY.
> static void gen_exec_counters(DisasContext *ctx)
> {
> tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
> @@ -136,6 +147,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
>
And here
Since much of the above won't work under CONFIG_USER_ONLY (e.g.,
CPU_FOREACH), it's best to keep all of this guarded by #ifndef
CONFIG_USER_ONLY.
> }
>
> static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
> @@ -821,6 +836,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;
> @@ -840,6 +856,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;
> }
> @@ -989,11 +1006,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)
> @@ -1136,6 +1155,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");
>
The t_cycle_count was added to CPUHexagonState in a different patch. The
above statement as well as t_cycle_count should be guarded by #ifndef
CONFIG_USER_ONLY.
Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 9912 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 11/32] target/hexagon: Implement software interrupt
2026-03-11 4:07 ` [PATCH v3 11/32] target/hexagon: Implement software interrupt Brian Cain
@ 2026-03-14 23:52 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-14 23:52 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain, Mike Lambert
[-- Attachment #1: Type: text/plain, Size: 12090 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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 | 1 +
> target/hexagon/hexswi.c | 260 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 278 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 00000000000..48c1ae6e4c1
> --- /dev/null
> +++ b/target/hexagon/hexswi.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * 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,
> + uint32_t PC);
> +
> +#endif /* HEXSWI_H */
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index 1c8a188dec4..2964d8a63f6 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -34,6 +34,7 @@
> #include "sys_macros.h"
> #include "accel/tcg/cpu-ldst.h"
> #include "qemu/main-loop.h"
> +#include "hex_interrupts.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 00000000000..77a4dd5bc43
> --- /dev/null
> +++ b/target/hexagon/hexswi.c
> @@ -0,0 +1,260 @@
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * 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"
> +#include "hw/hexagon/hexagon_globalreg.h"
> +
> +#ifdef CONFIG_USER_ONLY
> +#error "This file is only used in system emulation"
> +#endif
> +
> +static void set_addresses(CPUHexagonState *env, uint32_t pc_offset,
> + uint32_t exception_index)
> +
> +{
> + HexagonCPU *cpu = env_archcpu(env);
> + uint32_t evb = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_EVB,
> + env->threadId) :
> + cpu->boot_addr;
> + env->t_sreg[HEX_SREG_ELR] = env->gpr[HEX_REG_PC] + pc_offset;
> + env->gpr[HEX_REG_PC] = evb | (exception_index << 2);
>
Does this work when globalregs is false and evb is set to cpu->boot_addr?
> +}
> +
> +static const char *event_name[] = {
> + [HEX_EVENT_RESET] = "HEX_EVENT_RESET",
> + [HEX_EVENT_IMPRECISE] = "HEX_EVENT_IMPRECISE",
> + [HEX_EVENT_PRECISE] = "HEX_EVENT_PRECISE",
> + [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",
>
Don't use %x or %d in format strings.
> + __func__, cs->exception_index,
> + event_name[cs->exception_index], env->cause_code,
> + env->cause_code);
> +
> + env->llsc_addr = ~0;
> +
> + ssr = env->t_sreg[HEX_SREG_SSR];
> + if (GET_SSR_FIELD(SSR_EX, ssr) == 1) {
> + HexagonCPU *cpu = env_archcpu(env);
> + if (cpu->globalregs) {
> + hexagon_globalreg_write(cpu->globalregs, HEX_SREG_DIAG,
> + env->cause_code, env->threadId);
> + }
> + 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) "
>
Don't use %x
> + "TID = 0x%" PRIx32 ", PC = 0x%" PRIx32
> + ", BADVA = 0x%" PRIx32 "\n",
> + cs->exception_index, env->cause_code,
> env->threadId,
> + env->gpr[HEX_REG_PC],
> + env->t_sreg[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",
>
Don't use %x
> + 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) "
>
Don't use %x
> + "TID = 0x%" PRIx32 ", PC = 0x%" PRIx32
> + ", BADVA = 0x%" PRIx32 "\n",
> + cs->exception_index, env->cause_code,
> env->threadId,
> + env->gpr[HEX_REG_PC],
> + env->t_sreg[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);
> + set_addresses(env, 0, cs->exception_index);
> + 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) "
>
Don't use %x
> + "TID = 0x%" PRIx32 ", PC = 0x%" PRIx32
> + ", BADVA = 0x%" PRIx32 "\n",
> + cs->exception_index, env->cause_code,
> env->threadId,
> + env->gpr[HEX_REG_PC],
> + env->t_sreg[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_UNSUPPORTED_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",
>
Don't use %x
> + 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",
>
Don't use %x
> + cs->exception_index, env->cause_code);
> + break;
> + }
> +
> + cs->exception_index = HEX_EVENT_NONE;
> +}
> +
> +void register_trap_exception(CPUHexagonState *env, int traptype, int imm,
> + uint32_t 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);
> +}
> --
> 2.34.1
>
>
[-- Attachment #2: Type: text/html, Size: 16641 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 12/32] target/hexagon: Implement stack overflow exception
2026-03-11 4:07 ` [PATCH v3 12/32] target/hexagon: Implement stack overflow exception Brian Cain
@ 2026-03-15 0:02 ` Taylor Simpson
2026-03-16 16:23 ` Taylor Simpson
0 siblings, 1 reply; 52+ messages in thread
From: Taylor Simpson @ 2026-03-15 0:02 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo
[-- Attachment #1: Type: text/plain, Size: 787 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> Implement the frame limit check for system emulation mode. When
> allocframe computes a new stack pointer below FRAMELIMIT, raise a
> precise exception (HEX_CAUSE_STACK_LIMIT). The check is skipped in
> monitor mode.
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/helper.h | 1 +
> target/hexagon/macros.h | 3 ---
> target/hexagon/sys_macros.h | 4 ++++
> target/hexagon/translate.h | 2 ++
> target/hexagon/genptr.c | 18 +++++++++++-------
> target/hexagon/op_helper.c | 34 ++++++++++++++++++++++++++++++++++
> 6 files changed, 52 insertions(+), 10 deletions(-)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 1326 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 12/32] target/hexagon: Implement stack overflow exception
2026-03-15 0:02 ` Taylor Simpson
@ 2026-03-16 16:23 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 16:23 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo
[-- Attachment #1: Type: text/plain, Size: 1021 bytes --]
On Sat, Mar 14, 2026 at 6:02 PM Taylor Simpson <ltaylorsimpson@gmail.com>
wrote:
>
>
> On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
> wrote:
>
>> Implement the frame limit check for system emulation mode. When
>> allocframe computes a new stack pointer below FRAMELIMIT, raise a
>> precise exception (HEX_CAUSE_STACK_LIMIT). The check is skipped in
>> monitor mode.
>>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>> target/hexagon/helper.h | 1 +
>> target/hexagon/macros.h | 3 ---
>> target/hexagon/sys_macros.h | 4 ++++
>> target/hexagon/translate.h | 2 ++
>> target/hexagon/genptr.c | 18 +++++++++++-------
>> target/hexagon/op_helper.c | 34 ++++++++++++++++++++++++++++++++++
>> 6 files changed, 52 insertions(+), 10 deletions(-)
>>
>
> Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
>
Looked at this again and wondering where is the implementation when
idef-parser is enabled.
Thanks,
Taylor
[-- Attachment #2: Type: text/html, Size: 1918 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 14/32] target/hexagon: add simple cpu_exec_reset and pointer_wrap
2026-03-11 4:07 ` [PATCH v3 14/32] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
@ 2026-03-16 16:29 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 16:29 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo
[-- Attachment #1: Type: text/plain, Size: 393 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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(+)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 966 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 18/32] target/hexagon: Implement setprio, resched
2026-03-11 4:07 ` [PATCH v3 18/32] target/hexagon: Implement setprio, resched Brian Cain
@ 2026-03-16 16:49 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 16:49 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 4457 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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.
>
This document doesn't have a section 11.9.2.
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/op_helper.c | 75 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 75 insertions(+)
>
> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> index 9090a5c20ab..36822219b4b 100644
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -1575,6 +1575,62 @@ static void hexagon_wait_thread(CPUHexagonState
> *env, uint32_t PC)
> cpu_interrupt(cs, CPU_INTERRUPT_HALT);
> }
>
> +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__);
> + HexagonCPU *cpu = env_archcpu(env);
> + schedcfg = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SCHEDCFG,
> + env->threadId) : 0;
> + 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, thread_env->t_sreg[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 = cpu->globalregs ?
> + hexagon_globalreg_read(cpu->globalregs, HEX_SREG_BESTWAIT,
> + env->threadId) : 0;
> + 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",
>
Don't use %d
> + __func__, int_number, env->gpr[HEX_REG_PC]);
> + SET_SYSTEM_FIELD(env, HEX_SREG_BESTWAIT, BESTWAIT_PRIO, ~0);
>
Is ~0 the correct value here? Seems like it should be best_prio.
> + hex_raise_interrupts(env, 1 << int_number, CPU_INTERRUPT_SWI);
> + }
> +}
> +
> void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
> {
> BQL_LOCK_GUARD();
> @@ -1680,8 +1736,27 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState
> *env, uint32_t reg)
> g_assert_not_reached();
> }
>
> +/*
> + * setprio/resched - See the Hexagon V73 Programmer's Reference Manual,
> + * Section 6.4 "Interrupt and Thread Scheduling"
>
Neither the V71 (mentioned above) or V73 PRM contain section 6.4.
> + */
> 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",
>
Don't use %x
> + __func__, found_env->threadId, prio);
> + resched(env);
> + return;
> + }
> + }
> g_assert_not_reached();
> }
>
> --
> 2.34.1
>
>
[-- Attachment #2: Type: text/html, Size: 6516 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 23/32] target/hexagon: Add pkt_ends_tb to translation
2026-03-11 4:07 ` [PATCH v3 23/32] target/hexagon: Add pkt_ends_tb to translation Brian Cain
@ 2026-03-16 16:55 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 16:55 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 1099 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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 82b327312ec..4e090565aac 100644
> --- a/target/hexagon/translate.h
> +++ b/target/hexagon/translate.h
> @@ -85,6 +85,7 @@ typedef struct DisasContext {
> TCGv branch_taken;
> TCGv dczero_addr;
> bool pcycle_enabled;
> + bool pkt_ends_tb;
>
You don't need this as part of DisasContext
> uint32_t num_cycles;
> } DisasContext;
>
> diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
>
> - if (pkt->pkt_has_cof) {
> + if (ctx->pkt_ends_tb || ctx->base.is_jmp == DISAS_NORETURN) {
>
Just call pkt_ends_tb() here
Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 1911 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 24/32] target/hexagon: Add next_PC, {s,g}reg writes
2026-03-11 4:07 ` [PATCH v3 24/32] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
@ 2026-03-16 17:14 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 17:14 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 6077 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Brian Cain <bcain@quicinc.com>
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/translate.c | 89 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 85 insertions(+), 4 deletions(-)
>
> diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
> index 953b34b7891..79027e8a327 100644
> --- a/target/hexagon/translate.c
> +++ b/target/hexagon/translate.c
> @@ -552,6 +552,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;
> @@ -584,6 +588,25 @@ 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++) {
>
Use HEX_SREG_GLB_START instead of NUM_SREGS.
Also, size the t_sreg_new_value array with HEX_SREG_GLB_START.
> + 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]);
>
You only need this assignment if the writes can be predicated.
> + }
> + }
> + 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)) {
> @@ -744,6 +767,60 @@ 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_i32 old_reg = tcg_temp_new_i32();
> + 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;
>
Isn't this taken care of in pkt_ends_tb from earlier patch?
> + continue;
> + } 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]);
>
Don't need to set old_reg here
> + 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;
>
Already taken care of.
> + } 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;
>
Already taken care of.
> + }
> +
> + if (reg_num < HEX_SREG_GLB_START) {
> + tcg_gen_mov_tl(hex_t_sreg[reg_num],
> ctx->t_sreg_new_value[reg_num]);
> + }
>
Put this under an else as we've already done the assignment for specific
cases above
> + }
> +}
> +#endif
> +
> static void gen_pred_writes(DisasContext *ctx)
> {
> /* Early exit if not needed or the log is empty */
> @@ -1044,6 +1121,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);
> @@ -1255,6 +1336,10 @@ 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_i32(tcg_env,
> + offsetof(CPUHexagonState, cause_code), "cause_code");
> +#endif
>
Seems strange to add this here and remove it below
> 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,
> @@ -1292,8 +1377,4 @@ void hexagon_translate_init(void)
> offsetof(CPUHexagonState, vstore_pending[i]),
> vstore_pending_names[i]);
> }
> -#ifndef CONFIG_USER_ONLY
> - hex_cause_code = tcg_global_mem_new(tcg_env,
> - offsetof(CPUHexagonState, cause_code), "cause_code");
> -#endif
> }
> --
> 2.34.1
>
>
[-- Attachment #2: Type: text/html, Size: 8714 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 27/32] target/hexagon: Add TLB, k0 {un,}lock
2026-03-11 4:07 ` [PATCH v3 27/32] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
@ 2026-03-16 17:24 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 17:24 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 1166 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Brian Cain <bcain@quicinc.com>
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/sys_macros.h | 3 +
> target/hexagon/op_helper.c | 117 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 120 insertions(+)
>
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -1232,6 +1235,120 @@ void HELPER(modify_ssr)(CPUHexagonState *env,
> uint32_t new, uint32_t old)
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "Double k0lock at PC: 0x%x, thread may hang\n",
>
Don't use %x
> + 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));
>
Don't use %d
The patch description mentions TLB, but this patch only implements k0
Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 2086 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 28/32] target/hexagon: Add PC to raise_exception, use fTRAP() helper
2026-03-11 4:07 ` [PATCH v3 28/32] target/hexagon: Add PC to raise_exception, use fTRAP() helper Brian Cain
@ 2026-03-16 17:35 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 17:35 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 642 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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 | 20 +++++++++++++++-----
> 4 files changed, 20 insertions(+), 19 deletions(-)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 1231 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 26/32] target/hexagon: Define system, guest reg names
2026-03-11 4:07 ` [PATCH v3 26/32] target/hexagon: Define system, guest reg names Brian Cain
@ 2026-03-16 17:41 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 17:41 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Brian Cain
[-- Attachment #1: Type: text/plain, Size: 400 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Brian Cain <bcain@quicinc.com>
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
> target/hexagon/internal.h | 4 ++++
> target/hexagon/cpu.c | 29 +++++++++++++++++++++++++++++
> 2 files changed, 33 insertions(+)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 969 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 31/32] target/hexagon: Add guest reg reading functionality
2026-03-11 4:07 ` [PATCH v3 31/32] target/hexagon: Add guest reg reading functionality Brian Cain
@ 2026-03-16 17:44 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 17:44 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Matheus Tavares Bernardino
[-- Attachment #1: Type: text/plain, Size: 460 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> From: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
>
> Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
> ---
> target/hexagon/cpu.c | 21 +++++++++++++++++++++
> target/hexagon/op_helper.c | 16 ++++++++++++++--
> 2 files changed, 35 insertions(+), 2 deletions(-)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 1035 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v3 32/32] target/hexagon: Add pcycle setting functionality
2026-03-11 4:07 ` [PATCH v3 32/32] target/hexagon: Add pcycle setting functionality Brian Cain
@ 2026-03-16 17:46 ` Taylor Simpson
0 siblings, 0 replies; 52+ messages in thread
From: Taylor Simpson @ 2026-03-16 17:46 UTC (permalink / raw)
To: Brian Cain
Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
quic_mburton, sid.manning, ale, anjo, Matheus Tavares Bernardino
[-- Attachment #1: Type: text/plain, Size: 385 bytes --]
On Tue, Mar 10, 2026 at 10:08 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:
> 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(-)
>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
[-- Attachment #2: Type: text/html, Size: 952 bytes --]
^ permalink raw reply [flat|nested] 52+ messages in thread
end of thread, other threads:[~2026-03-16 17:47 UTC | newest]
Thread overview: 52+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 4:07 [PATCH v3 00/32] Hexagon system emulation - Part 2/3 Brian Cain
2026-03-11 4:07 ` [PATCH v3 01/32] target/hexagon: Implement {c,}swi helpers Brian Cain
2026-03-11 4:07 ` [PATCH v3 02/32] target/hexagon: Implement iassign{r,w} helpers Brian Cain
2026-03-11 4:07 ` [PATCH v3 03/32] target/hexagon: Implement start/stop helpers, soft reset Brian Cain
2026-03-12 21:37 ` Taylor Simpson
2026-03-14 21:49 ` Brian Cain
2026-03-11 4:07 ` [PATCH v3 04/32] target/hexagon: Implement modify SSR Brian Cain
2026-03-12 21:39 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 05/32] target/hexagon: Implement {g,s}etimask helpers Brian Cain
2026-03-12 21:42 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 06/32] target/hexagon: Implement wait helper Brian Cain
2026-03-12 21:47 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 07/32] target/hexagon: Implement get_exe_mode() Brian Cain
2026-03-11 4:07 ` [PATCH v3 08/32] target/hexagon: Add representation to count cycles Brian Cain
2026-03-12 21:49 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 09/32] target/hexagon: Add implementation of cycle counters Brian Cain
2026-03-14 23:42 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 10/32] target/hexagon: Implement hex_tlb_entry_get_perm() Brian Cain
2026-03-11 4:07 ` [PATCH v3 11/32] target/hexagon: Implement software interrupt Brian Cain
2026-03-14 23:52 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 12/32] target/hexagon: Implement stack overflow exception Brian Cain
2026-03-15 0:02 ` Taylor Simpson
2026-03-16 16:23 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 13/32] target/hexagon: Implement exec_interrupt, set_irq Brian Cain
2026-03-11 4:07 ` [PATCH v3 14/32] target/hexagon: add simple cpu_exec_reset and pointer_wrap Brian Cain
2026-03-16 16:29 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 15/32] target/hexagon: Implement hexagon_tlb_fill() Brian Cain
2026-03-11 4:07 ` [PATCH v3 16/32] target/hexagon: Implement siad inst Brian Cain
2026-03-11 4:07 ` [PATCH v3 17/32] target/hexagon: Implement hexagon_resume_threads() Brian Cain
2026-03-11 4:07 ` [PATCH v3 18/32] target/hexagon: Implement setprio, resched Brian Cain
2026-03-16 16:49 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 19/32] target/hexagon: Add sysemu_ops, cpu_get_phys_page_debug() Brian Cain
2026-03-11 4:07 ` [PATCH v3 20/32] target/hexagon: extend hexagon_cpu_mmu_index() for sysemu Brian Cain
2026-03-11 4:07 ` [PATCH v3 21/32] target/hexagon: Decode trap1, rte as COF Brian Cain
2026-03-11 4:07 ` [PATCH v3 22/32] target/hexagon: Implement modify_ssr, resched, pending_interrupt Brian Cain
2026-03-11 4:07 ` [PATCH v3 23/32] target/hexagon: Add pkt_ends_tb to translation Brian Cain
2026-03-16 16:55 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 24/32] target/hexagon: Add next_PC, {s,g}reg writes Brian Cain
2026-03-16 17:14 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 25/32] target/hexagon: Add implicit sysreg writes Brian Cain
2026-03-11 4:07 ` [PATCH v3 26/32] target/hexagon: Define system, guest reg names Brian Cain
2026-03-16 17:41 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 27/32] target/hexagon: Add TLB, k0 {un,}lock Brian Cain
2026-03-16 17:24 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 28/32] target/hexagon: Add PC to raise_exception, use fTRAP() helper Brian Cain
2026-03-16 17:35 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 29/32] target/hexagon: Add TCG overrides for transfer insts Brian Cain
2026-03-11 4:07 ` [PATCH v3 30/32] target/hexagon: Add support for loadw_phys Brian Cain
2026-03-11 4:07 ` [PATCH v3 31/32] target/hexagon: Add guest reg reading functionality Brian Cain
2026-03-16 17:44 ` Taylor Simpson
2026-03-11 4:07 ` [PATCH v3 32/32] target/hexagon: Add pcycle setting functionality Brian Cain
2026-03-16 17:46 ` Taylor Simpson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox