Commit 9aaba2ef58 for qemu.org
commit 9aaba2ef584d0eedfcf45875e25a1519bf3a7bfb
Author: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
Date: Mon Aug 24 08:58:20 2026 -0700
target/hexagon: add COREDUMP semihosting operation
Baremetal Hexagon programs invoke SYS_COREDUMP (0xCD)
through semihosting to dump CPU state on a fatal exception.
Implement the handler to decode the SSR cause field and
print the full register file, matching hexagon-sim behavior.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 7067e5b70f..47e3683d75 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -235,7 +235,7 @@ void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
print_qreg(stdout, env, regnum, false);
}
-static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
+void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
{
HexagonCPU *cpu = env_archcpu(env);
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 28e251f899..6bb4881d14 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -186,6 +186,138 @@ static void common_semi_ftell_cb(CPUState *cs, uint64_t ret, int err)
common_semi_cb(cs, ret, err);
}
+static void coredump(CPUHexagonState *env)
+{
+ uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
+ FILE *f = qemu_log_trylock();
+
+ if (!f) {
+ return;
+ }
+
+ fprintf(f, "CRASH!\n");
+ fprintf(f, "I think the exception was: ");
+ switch (GET_SSR_FIELD(SSR_CAUSE, ssr)) {
+ case 0x43:
+ fprintf(f, "0x43, NMI");
+ break;
+ case 0x42:
+ fprintf(f, "0x42, Data abort");
+ break;
+ case 0x44:
+ fprintf(f, "0x44, Multi TLB match");
+ break;
+ case HEX_CAUSE_BIU_PRECISE:
+ fprintf(f, "0x%x, Bus Error (Precise BIU error)",
+ HEX_CAUSE_BIU_PRECISE);
+ break;
+ case HEX_CAUSE_DOUBLE_EXCEPT:
+ fprintf(f, "0x%x, Exception observed when EX = 1"
+ " (double exception)",
+ HEX_CAUSE_DOUBLE_EXCEPT);
+ break;
+ case HEX_CAUSE_FETCH_NO_XPAGE:
+ fprintf(f, "0x%x, Privilege violation: User/Guest mode execute"
+ " to page with no execute permissions",
+ HEX_CAUSE_FETCH_NO_XPAGE);
+ break;
+ case HEX_CAUSE_FETCH_NO_UPAGE:
+ fprintf(f, "0x%x, Privilege violation: "
+ "User mode execute to page with no user permissions",
+ HEX_CAUSE_FETCH_NO_UPAGE);
+ break;
+ case HEX_CAUSE_INVALID_PACKET:
+ fprintf(f, "0x%x, Invalid packet",
+ HEX_CAUSE_INVALID_PACKET);
+ break;
+ case HEX_CAUSE_PRIV_USER_NO_GINSN:
+ fprintf(f, "0x%x, Privilege violation:"
+ " guest mode insn in user mode",
+ HEX_CAUSE_PRIV_USER_NO_GINSN);
+ break;
+ case HEX_CAUSE_PRIV_USER_NO_SINSN:
+ fprintf(f, "0x%x, Privilege violation: "
+ "monitor mode insn in user/guest mode",
+ HEX_CAUSE_PRIV_USER_NO_SINSN);
+ break;
+ case HEX_CAUSE_REG_WRITE_CONFLICT:
+ fprintf(f, "0x%x, Multiple writes to same register",
+ HEX_CAUSE_REG_WRITE_CONFLICT);
+ break;
+ case HEX_CAUSE_PC_NOT_ALIGNED:
+ fprintf(f, "0x%x, PC not aligned",
+ HEX_CAUSE_PC_NOT_ALIGNED);
+ break;
+ case HEX_CAUSE_MISALIGNED_LOAD:
+ fprintf(f, "0x%x, Misaligned Load @ 0x%" PRIx32,
+ HEX_CAUSE_MISALIGNED_LOAD, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_MISALIGNED_STORE:
+ fprintf(f, "0x%x, Misaligned Store @ 0x%" PRIx32,
+ HEX_CAUSE_MISALIGNED_STORE, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_PRIV_NO_READ:
+ fprintf(f, "0x%x, Privilege violation: "
+ "user/guest read permission @ 0x%" PRIx32,
+ HEX_CAUSE_PRIV_NO_READ, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_PRIV_NO_WRITE:
+ fprintf(f, "0x%x, Privilege violation: "
+ "user/guest write permission @ 0x%" PRIx32,
+ HEX_CAUSE_PRIV_NO_WRITE, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_PRIV_NO_UREAD:
+ fprintf(f, "0x%x, Privilege violation:"
+ " user read permission @ 0x%" PRIx32,
+ HEX_CAUSE_PRIV_NO_UREAD, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_PRIV_NO_UWRITE:
+ fprintf(f, "0x%x, Privilege violation:"
+ " user write permission @ 0x%" PRIx32,
+ HEX_CAUSE_PRIV_NO_UWRITE, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_COPROC_LDST:
+ fprintf(f, "0x%x, Coprocessor VMEM address error @ 0x%" PRIx32,
+ HEX_CAUSE_COPROC_LDST, env->t_sreg[HEX_SREG_BADVA]);
+ break;
+ case HEX_CAUSE_STACK_LIMIT:
+ fprintf(f, "0x%x, Stack limit check error",
+ HEX_CAUSE_STACK_LIMIT);
+ break;
+ case HEX_CAUSE_FPTRAP_CAUSE_BADFLOAT:
+ fprintf(f, "0x%x, Floating-Point: Execution of Floating-Point "
+ "instruction resulted in exception",
+ HEX_CAUSE_FPTRAP_CAUSE_BADFLOAT);
+ break;
+ case HEX_CAUSE_NO_COPROC_ENABLE:
+ fprintf(f, "0x%x, Illegal Execution of Coprocessor Instruction",
+ HEX_CAUSE_NO_COPROC_ENABLE);
+ break;
+ case HEX_CAUSE_NO_COPROC2_ENABLE:
+ fprintf(f, "0x%x, Illegal Execution of Secondary"
+ " Coprocessor Instruction",
+ HEX_CAUSE_NO_COPROC2_ENABLE);
+ break;
+ case HEX_CAUSE_UNSUPPORTED_HVX_64B:
+ fprintf(f, "0x%x, Unsupported Execution of"
+ " Coprocessor Instruction with 64bits Mode On",
+ HEX_CAUSE_UNSUPPORTED_HVX_64B);
+ break;
+ case HEX_CAUSE_VWCTRL_WINDOW_MISS:
+ fprintf(f, "0x%x, Thread accessing a region"
+ " outside VWCTRL window",
+ HEX_CAUSE_VWCTRL_WINDOW_MISS);
+ break;
+ default:
+ fprintf(f, "unknown cause 0x%" PRIx32,
+ GET_SSR_FIELD(SSR_CAUSE, ssr));
+ break;
+ }
+ fprintf(f, "\nRegister Dump:\n");
+ hexagon_dump(env, f, 0);
+ qemu_log_unlock(f);
+}
+
static void sim_handle_trap0(CPUHexagonState *env)
{
target_ulong what_swi, swi_info;
@@ -455,6 +587,10 @@ static void sim_handle_trap0(CPUHexagonState *env)
}
break;
+ case HEX_SYS_COREDUMP:
+ coredump(env);
+ break;
+
case HEX_SYS_FTELL:
{
int fd;
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 00b37aea7a..05d1129916 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -28,6 +28,7 @@ int hexagon_hvx_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n);
void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
void hexagon_debug(CPUHexagonState *env);
+void hexagon_dump(CPUHexagonState *env, FILE *f, int flags);
extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
#ifndef CONFIG_USER_ONLY