* [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler
@ 2026-10-07 9:44 Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int' Philippe Mathieu-Daudé
` (26 more replies)
0 siblings, 27 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé
Add qemu_excp_name() to resolve QEMU internal exception
values.
Add a common CPUClass::exception_name() callback so the
generic exception logger can resolve architecture-specific
exception values to human-readable names.
Re-use existing methods (expose prototype or refactor) when
available otherwise implement new ones (AVR, X86, MicroBlaze,
S390x, TriCore and Xtensa).
This series is the base for consolidating exception management
in accel/tcg/ (more series to be posted on top).
Philippe Mathieu-Daudé (25):
cpus: Add helper to log raised exceptions with '-d int'
cpus: Introduce CPUClass::exception_name() handler
target/alpha: Register CPUClass::exception_name() handler
target/arm: Register CPUClass::exception_name() handler
target/avr: Implement and register CPUClass::exception_name()
target/hexagon: Register CPUClass::exception_name() handler
target/hppa: Register CPUClass::exception_name() handler
target/i386: Replace magic value by proper EXCP0E_PAGE definition
target/i386: Implement and register CPUClass::exception_name()
target/loongarch: Register CPUClass::exception_name() handler
target/m68k: Register CPUClass::exception_name() handler
target/microblaze: Implement and register CPUClass::exception_name()
target/mips: Remove unuseful EXCP_LAST definition
target/mips: Register CPUClass::exception_name() handler
target/or1k: Register CPUClass::exception_name() handler
target/ppc: Register CPUClass::exception_name() handler
target/riscv: Register CPUClass::exception_name() handler
target/rx: Unify BRK and INT trap handling
target/rx: Register CPUClass::exception_name() handler
target/s390x: Implement and register CPUClass::exception_name()
target/sh4: Register CPUClass::exception_name() handler
target/sparc: Remove well tested DEBUG_PCALL definition
target/sparc: Register CPUClass::exception_name() handler
target/tricore: Implement and register CPUClass::exception_name()
target/xtensa: Implement and register CPUClass::exception_name()
Yonggang Luo (2):
target/rx: Define exception vector constants
target/sh4: Define exception vector constants
include/hw/core/cpu.h | 2 +
target/alpha/cpu.h | 1 +
target/arm/cpu.h | 2 +
target/avr/cpu.h | 2 +
target/hexagon/cpu_bits.h | 2 +
target/hppa/cpu.h | 2 +
target/i386/cpu.h | 2 +
target/loongarch/internals.h | 2 +
target/m68k/cpu.h | 2 +
target/microblaze/cpu.h | 2 +
target/mips/cpu.h | 4 +-
target/mips/tcg/tcg-internal.h | 2 -
target/or1k/cpu.h | 2 +
target/ppc/cpu.h | 2 +
target/riscv/cpu.h | 1 +
target/rx/cpu.h | 14 ++++
target/rx/helper.h | 3 +-
target/s390x/cpu.h | 2 +
target/sh4/cpu.h | 21 +++++
target/sparc/cpu.h | 1 +
target/tricore/cpu.h | 2 +
target/xtensa/cpu.h | 2 +
accel/tcg/cpu-exec-common.c | 38 ++++++++++
target/alpha/cpu.c | 1 +
target/alpha/helper.c | 82 +++++++++++---------
target/arm/cpu.c | 1 +
target/arm/helper.c | 79 +++++++++----------
target/avr/cpu.c | 19 +++++
target/hexagon/cpu.c | 37 +++++++++
target/hexagon/hexswi.c | 30 +-------
target/hppa/int_helper.c | 91 +++++++++++-----------
target/i386/cpu.c | 33 ++++++++
target/i386/tcg/excp_helper.c | 5 +-
target/i386/tcg/seg_helper.c | 8 +-
target/loongarch/cpu.c | 38 ++++++++++
target/loongarch/tcg/tcg_cpu.c | 45 -----------
target/m68k/cpu.c | 1 +
target/m68k/op_helper.c | 8 +-
target/microblaze/cpu.c | 17 +++++
target/mips/cpu.c | 1 +
target/mips/tcg/exception.c | 12 +--
target/or1k/cpu.c | 1 +
target/or1k/exception.c | 24 ++++++
target/or1k/interrupt.c | 19 +----
target/ppc/cpu_init.c | 1 +
target/ppc/excp_helper.c | 5 +-
target/riscv/cpu.c | 29 ++++---
target/riscv/tcg/op_helper.c | 2 +-
target/rx/cpu.c | 1 +
target/rx/helper.c | 62 +++++++++------
target/rx/op_helper.c | 17 ++---
target/rx/translate.c | 23 +++---
target/s390x/cpu.c | 1 +
target/s390x/interrupt.c | 18 +++++
target/s390x/tcg/excp_helper.c | 6 +-
target/s390x/tcg/misc_helper.c | 3 +-
target/sh4/helper.c | 135 +++++++++++++++++----------------
target/sh4/op_helper.c | 16 ++--
target/sparc/cpu.c | 1 +
target/sparc/int32_helper.c | 23 +++---
target/sparc/int64_helper.c | 42 +++++-----
target/tricore/cpu.c | 21 +++++
target/xtensa/cpu.c | 26 +++++++
target/xtensa/exc_helper.c | 3 +-
64 files changed, 692 insertions(+), 408 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int'
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 10:47 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 02/27] cpus: Introduce CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (25 subsequent siblings)
26 siblings, 1 reply; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé
Add log_raise_exception(), a common helper cpu_loop_*() can
call to log a raised exception when '-d int' is used, and
qemu_excp_name() to resolve QEMU-internal exceptions to names.
Use it in cpu_loop_exit_atomic() to log the EXCP_ATOMIC reason.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
accel/tcg/cpu-exec-common.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
index 68077c8fd9d..2ac8380d0bb 100644
--- a/accel/tcg/cpu-exec-common.c
+++ b/accel/tcg/cpu-exec-common.c
@@ -89,6 +89,37 @@ void tcg_update_all_cflags(void)
}
}
+#define EXCP_QEMU_INTERNAL 0x10000
+
+static const char *qemu_excp_name(int excp)
+{
+ static const char *excp_name[] = {
+ [EXCP_INTERRUPT - EXCP_QEMU_INTERNAL] = "async interruption",
+ [EXCP_HLT - EXCP_QEMU_INTERNAL] = "hlt instruction",
+ [EXCP_DEBUG - EXCP_QEMU_INTERNAL] = "debug",
+ [EXCP_HALTED - EXCP_QEMU_INTERNAL] = "halted",
+ [EXCP_YIELD - EXCP_QEMU_INTERNAL] = "yield",
+ [EXCP_ATOMIC - EXCP_QEMU_INTERNAL] = "emulate atomic",
+ };
+ assert(excp >= EXCP_QEMU_INTERNAL);
+ excp -= EXCP_QEMU_INTERNAL;
+ if ((excp < ARRAY_SIZE(excp_name)) && excp_name[excp]) {
+ return excp_name[excp];
+ }
+ return "undocumented";
+}
+
+static void log_raise_exception(const CPUState *cpu, int excp)
+{
+ if (!qemu_loglevel_mask(CPU_LOG_INT)) {
+ return;
+ }
+ if (excp >= EXCP_QEMU_INTERNAL) {
+ qemu_log_mask(CPU_LOG_INT, "raise exception: 0x%x (internal: %s)\n",
+ excp, qemu_excp_name(excp));
+ }
+}
+
/* exit the current TB, but without causing any exception to be raised */
void cpu_loop_exit_noexc(CPUState *cpu)
{
@@ -118,5 +149,6 @@ void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc)
/* Prevent looping if already executing in a serial context. */
g_assert(!cpu_in_serial_context(cpu));
cpu->exception_index = EXCP_ATOMIC;
+ log_raise_exception(cpu, EXCP_ATOMIC);
cpu_loop_exit_restore(cpu, pc);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 02/27] cpus: Introduce CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int' Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 03/27] target/alpha: Register " Philippe Mathieu-Daudé
` (24 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Zhao Liu
Have targets register a helper to resolve their exceptions.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/core/cpu.h | 2 ++
accel/tcg/cpu-exec-common.c | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 328e30045ce..1d73cc69af8 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -105,6 +105,7 @@ struct SysemuCPUOps;
* @list_cpus: list available CPU models and flags.
* @parse_features: Callback to parse command line arguments.
* @reset_dump_flags: #CPUDumpFlags to use for reset logging.
+ * @exception_name: Callback for getting architecture exception name.
* @memory_rw_debug: Callback for GDB memory access.
* @dump_state: Callback for dumping state.
* @query_cpu_fast:
@@ -175,6 +176,7 @@ struct CPUClass {
const char * (*gdb_arch_name)(CPUState *cpu);
const char * (*gdb_get_core_xml_file)(CPUState *cpu);
+ const char *(*exception_name)(int exception);
void (*disas_set_info)(const CPUState *cpu, disassemble_info *info);
const char *deprecation_note;
diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
index 2ac8380d0bb..12cac8aec3c 100644
--- a/accel/tcg/cpu-exec-common.c
+++ b/accel/tcg/cpu-exec-common.c
@@ -117,6 +117,12 @@ static void log_raise_exception(const CPUState *cpu, int excp)
if (excp >= EXCP_QEMU_INTERNAL) {
qemu_log_mask(CPU_LOG_INT, "raise exception: 0x%x (internal: %s)\n",
excp, qemu_excp_name(excp));
+ } else {
+ const CPUClass *cc = cpu->cc;
+ const char *name = cc->exception_name ? cc->exception_name(excp)
+ : "undocumented";
+
+ qemu_log_mask(CPU_LOG_INT, "raise exception: %d (%s)\n", excp, name);
}
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 03/27] target/alpha: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int' Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 02/27] cpus: Introduce CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 04/27] target/arm: " Philippe Mathieu-Daudé
` (23 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé
Factor alpha_exception_name() out of alpha_cpu_do_interrupt()
and register it as the CPUClass::exception_name() handler, so
the common exception logging can resolve Alpha exception codes
to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/alpha/cpu.h | 1 +
target/alpha/cpu.c | 1 +
target/alpha/helper.c | 82 ++++++++++++++++++++++++-------------------
3 files changed, 48 insertions(+), 36 deletions(-)
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 378bd96d941..8f780502476 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -284,6 +284,7 @@ void alpha_cpu_do_interrupt(CPUState *cpu);
bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr alpha_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
#endif /* !CONFIG_USER_ONLY */
+const char *alpha_exception_name(int exception);
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index 12e86021663..f9936315fa2 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -283,6 +283,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, const void *data)
&acc->parent_realize);
cc->class_by_name = alpha_cpu_class_by_name;
+ cc->exception_name = alpha_exception_name;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
cc->get_pc = alpha_cpu_get_pc;
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index c3614ecafda..cedb0006892 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -35,6 +35,51 @@
#define CONVERT_BIT(X, SRC, DST) \
(SRC > DST ? (X) / (SRC / DST) & (DST) : ((X) & SRC) * (DST / SRC))
+const char *alpha_exception_name(int excp)
+{
+ const char *name;
+
+ switch (excp) {
+ case EXCP_RESET:
+ name = "reset";
+ break;
+ case EXCP_MCHK:
+ name = "mchk";
+ break;
+ case EXCP_SMP_INTERRUPT:
+ name = "smp_interrupt";
+ break;
+ case EXCP_CLK_INTERRUPT:
+ name = "clk_interrupt";
+ break;
+ case EXCP_DEV_INTERRUPT:
+ name = "dev_interrupt";
+ break;
+ case EXCP_MMFAULT:
+ name = "mmfault";
+ break;
+ case EXCP_UNALIGN:
+ name = "unalign";
+ break;
+ case EXCP_OPCDEC:
+ name = "opcdec";
+ break;
+ case EXCP_ARITH:
+ name = "arith";
+ break;
+ case EXCP_FEN:
+ name = "fen";
+ break;
+ case EXCP_CALL_PAL:
+ name = "call_pal";
+ break;
+ default:
+ name = "<unknown>";
+ break;
+ }
+ return name;
+}
+
uint64_t cpu_alpha_load_fpcr(CPUAlphaState *env)
{
return (uint64_t)env->fpcr << 32;
@@ -343,43 +388,8 @@ void alpha_cpu_do_interrupt(CPUState *cs)
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static int count;
- const char *name = "<unknown>";
+ const char *name = alpha_exception_name(i);
- switch (i) {
- case EXCP_RESET:
- name = "reset";
- break;
- case EXCP_MCHK:
- name = "mchk";
- break;
- case EXCP_SMP_INTERRUPT:
- name = "smp_interrupt";
- break;
- case EXCP_CLK_INTERRUPT:
- name = "clk_interrupt";
- break;
- case EXCP_DEV_INTERRUPT:
- name = "dev_interrupt";
- break;
- case EXCP_MMFAULT:
- name = "mmfault";
- break;
- case EXCP_UNALIGN:
- name = "unalign";
- break;
- case EXCP_OPCDEC:
- name = "opcdec";
- break;
- case EXCP_ARITH:
- name = "arith";
- break;
- case EXCP_FEN:
- name = "fen";
- break;
- case EXCP_CALL_PAL:
- name = "call_pal";
- break;
- }
qemu_log("INT %6d: %s(%#x) cpu=%d pc=%016"
PRIx64 " sp=%016" PRIx64 "\n",
++count, name, env->error_code, cs->cpu_index,
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 04/27] target/arm: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 03/27] target/alpha: Register " Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 05/27] target/avr: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
` (22 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, qemu-arm
Factor arm_exception_name() out of arm_log_exception() and
register it as the CPUClass::exception_name() handler, so
the common exception logging can resolve ARM exception codes
to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/arm/cpu.h | 2 ++
target/arm/cpu.c | 1 +
target/arm/helper.c | 79 +++++++++++++++++++++++----------------------
3 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 06ebed4a8fd..b4b4ca52d19 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -67,6 +67,8 @@
#define EXCP_MON_TRAP 29 /* AArch32 trap to Monitor mode */
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
+const char *arm_exception_name(int excp);
+
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
#define ARMV7M_EXCP_HARD 3
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 10ac6c98318..b12bb07b59b 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2647,6 +2647,7 @@ static void arm_cpu_class_init(ObjectClass *oc, const void *data)
&acc->parent_phases);
cc->class_by_name = arm_cpu_class_by_name;
+ cc->exception_name = arm_exception_name;
cc->dump_state = arm_cpu_dump_state;
cc->set_pc = arm_cpu_set_pc;
cc->get_pc = arm_cpu_get_pc;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ff0b766b73d..94c05121214 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8802,46 +8802,8 @@ void arm_log_exception(CPUState *cs)
int idx = cs->exception_index;
if (qemu_loglevel_mask(CPU_LOG_INT)) {
- const char *exc = NULL;
- static const char * const excnames[] = {
- [EXCP_UDEF] = "Undefined Instruction",
- [EXCP_SWI] = "SVC",
- [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
- [EXCP_DATA_ABORT] = "Data Abort",
- [EXCP_IRQ] = "IRQ",
- [EXCP_FIQ] = "FIQ",
- [EXCP_BKPT] = "Breakpoint",
- [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
- [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
- [EXCP_HVC] = "Hypervisor Call",
- [EXCP_HYP_TRAP] = "Hypervisor Trap",
- [EXCP_SMC] = "Secure Monitor Call",
- [EXCP_VIRQ] = "Virtual IRQ",
- [EXCP_VFIQ] = "Virtual FIQ",
- [EXCP_SEMIHOST] = "Semihosting call",
- [EXCP_NOCP] = "v7M NOCP UsageFault",
- [EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
- [EXCP_STKOF] = "v8M STKOF UsageFault",
- [EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
- [EXCP_LSERR] = "v8M LSERR UsageFault",
- [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
- [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
- [EXCP_VSERR] = "Virtual SERR",
- [EXCP_GPC] = "Granule Protection Check",
- [EXCP_NMI] = "NMI",
- [EXCP_VINMI] = "Virtual IRQ NMI",
- [EXCP_VFNMI] = "Virtual FIQ NMI",
- [EXCP_MON_TRAP] = "Monitor Trap",
- };
-
- if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
- exc = excnames[idx];
- }
- if (!exc) {
- exc = "unknown";
- }
qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s] on CPU %d\n",
- idx, exc, cs->cpu_index);
+ idx, arm_exception_name(idx), cs->cpu_index);
}
}
@@ -9928,6 +9890,45 @@ void arm_cpu_do_interrupt(CPUState *cs)
}
#endif /* !CONFIG_USER_ONLY */
+const char *arm_exception_name(int excp)
+{
+ static const char * const excnames[] = {
+ [EXCP_UDEF] = "Undefined Instruction",
+ [EXCP_SWI] = "SVC",
+ [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
+ [EXCP_DATA_ABORT] = "Data Abort",
+ [EXCP_IRQ] = "IRQ",
+ [EXCP_FIQ] = "FIQ",
+ [EXCP_BKPT] = "Breakpoint",
+ [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
+ [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
+ [EXCP_HVC] = "Hypervisor Call",
+ [EXCP_HYP_TRAP] = "Hypervisor Trap",
+ [EXCP_SMC] = "Secure Monitor Call",
+ [EXCP_VIRQ] = "Virtual IRQ",
+ [EXCP_VFIQ] = "Virtual FIQ",
+ [EXCP_SEMIHOST] = "Semihosting call",
+ [EXCP_NOCP] = "v7M NOCP UsageFault",
+ [EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
+ [EXCP_STKOF] = "v8M STKOF UsageFault",
+ [EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
+ [EXCP_LSERR] = "v8M LSERR UsageFault",
+ [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
+ [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
+ [EXCP_VSERR] = "Virtual SERR",
+ [EXCP_GPC] = "Granule Protection Check",
+ [EXCP_NMI] = "NMI",
+ [EXCP_VINMI] = "Virtual IRQ NMI",
+ [EXCP_VFNMI] = "Virtual FIQ NMI",
+ [EXCP_MON_TRAP] = "Monitor Trap",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excnames) || !excnames[excp]) {
+ return "unknown";
+ }
+ return excnames[excp];
+}
+
uint64_t arm_sctlr(CPUARMState *env, int el)
{
/* Only EL0 needs to be adjusted for EL1&0 or EL2&0 or EL3&0 */
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 05/27] target/avr: Implement and register CPUClass::exception_name()
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 04/27] target/arm: " Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 06/27] target/hexagon: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (21 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Michael Rolnik
Implement avr_exception_name() and register it as
the CPUClass::exception_name() handler, so the common
exception logging can resolve AVR exception codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/avr/cpu.h | 2 ++
target/avr/cpu.c | 19 +++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index 1e4e839bd83..b1b5b637617 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -44,6 +44,8 @@
#define EXCP_RESET 1
#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
+const char *avr_exception_name(int excp);
+
/* Number of CPU registers */
#define NUMBER_OF_CPU_REGISTERS 32
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index f8409f32ab9..6cfd19dfa81 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -258,6 +258,24 @@ static const TCGCPUOps avr_tcg_ops = {
.pointer_wrap = cpu_pointer_wrap_uint32,
};
+const char *avr_exception_name(int excp)
+{
+ static const char * const excp_names[] = {
+ [EXCP_RESET] = "RESET",
+ [EXCP_INT(0)] = "INT#0",
+ [EXCP_INT(1)] = "INT#1",
+ [EXCP_INT(2)] = "INT#2",
+ [EXCP_INT(3)] = "INT#3",
+ [EXCP_INT(4)] = "INT#4",
+ [EXCP_INT(5)] = "INT#5",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
+ return "unknown";
+ }
+ return excp_names[excp];
+}
+
static void avr_cpu_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -273,6 +291,7 @@ static void avr_cpu_class_init(ObjectClass *oc, const void *data)
&mcc->parent_phases);
cc->class_by_name = avr_cpu_class_by_name;
+ cc->exception_name = avr_exception_name;
cc->dump_state = avr_cpu_dump_state;
cc->set_pc = avr_cpu_set_pc;
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 06/27] target/hexagon: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 05/27] target/avr: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-09 1:34 ` Brian Cain
2026-10-07 9:44 ` [PATCH 07/27] target/hppa: " Philippe Mathieu-Daudé
` (20 subsequent siblings)
26 siblings, 1 reply; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Brian Cain, Pierrick Bouvier
Expose the hexagon event_name[] array via a hexagon_event_name()
helper and register it as the CPUClass::exception_name() handler,
so the common exception logging can resolve Hexagon exception
codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/hexagon/cpu_bits.h | 2 ++
target/hexagon/cpu.c | 37 +++++++++++++++++++++++++++++++++++++
target/hexagon/hexswi.c | 30 +-----------------------------
3 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
index a8fba4aa188..7d1bdfcbc71 100644
--- a/target/hexagon/cpu_bits.h
+++ b/target/hexagon/cpu_bits.h
@@ -61,6 +61,8 @@ enum hex_event {
HEX_EVENT_INTF = 0x1f,
};
+const char *hexagon_event_name(int event);
+
enum hex_cause {
HEX_CAUSE_NONE = -1,
HEX_CAUSE_RESET = 0x000,
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 1f7d8a8df70..be286b1f2ee 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -318,6 +318,42 @@ void hexagon_debug(CPUHexagonState *env)
hexagon_dump(env, stdout, CPU_DUMP_FPU);
}
+const char *hexagon_event_name(int event)
+{
+ 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",
+ };
+
+ if (event < 0 || event >= ARRAY_SIZE(event_name) || !event_name[event]) {
+ return "unknown";
+ }
+ return event_name[event];
+}
+
static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
{
cpu_env(cs)->gpr[HEX_REG_PC] = value;
@@ -826,6 +862,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
&mcc->parent_phases);
cc->class_by_name = hexagon_cpu_class_by_name;
+ cc->exception_name = hexagon_event_name;
cc->dump_state = hexagon_dump_state;
cc->set_pc = hexagon_cpu_set_pc;
cc->get_pc = hexagon_cpu_get_pc;
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 4705e915aea..be366d7a373 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -729,34 +729,6 @@ static void set_addresses(CPUHexagonState *env, uint32_t 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)
{
@@ -769,7 +741,7 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
qemu_log_mask(CPU_LOG_INT,
"\t%s: event 0x%02x:%s, cause 0x%" PRIx32 "(%" PRIu32 ")\n",
__func__, (unsigned)cs->exception_index,
- event_name[cs->exception_index], env->cause_code,
+ hexagon_event_name(cs->exception_index), env->cause_code,
env->cause_code);
env->llsc_addr = ~0;
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 07/27] target/hppa: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 06/27] target/hexagon: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 08/27] target/i386: Replace magic value by proper EXCP0E_PAGE definition Philippe Mathieu-Daudé
` (19 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Helge Deller
Factor hppa_exception_name() out of hppa_cpu_do_interrupt()
and register it as the CPUClass::exception_name() handler,
so the common exception logging can resolve HPPA exception
codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/hppa/cpu.h | 2 +
target/hppa/int_helper.c | 91 ++++++++++++++++++++--------------------
2 files changed, 48 insertions(+), 45 deletions(-)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index f453444d7f9..3914b3285c5 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -98,6 +98,8 @@
/* Emulated hardware TOC button */
#define EXCP_TOC 32 /* TOC = Transfer of control (NMI) */
+const char *hppa_exception_name(int excp);
+
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 /* TOC */
/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 3e87b9a0011..ad240ab8b2e 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -90,6 +90,49 @@ void HELPER(write_eirr)(CPUHPPAState *env, target_ulong val)
bql_unlock();
}
+const char *hppa_exception_name(int excp)
+{
+ static const char * const excp_names[] = {
+ [EXCP_HPMC] = "high priority machine check",
+ [EXCP_POWER_FAIL] = "power fail interrupt",
+ [EXCP_RC] = "recovery counter trap",
+ [EXCP_EXT_INTERRUPT] = "external interrupt",
+ [EXCP_LPMC] = "low priority machine check",
+ [EXCP_ITLB_MISS] = "instruction tlb miss fault",
+ [EXCP_IMP] = "instruction memory protection trap",
+ [EXCP_ILL] = "illegal instruction trap",
+ [EXCP_BREAK] = "break instruction trap",
+ [EXCP_PRIV_OPR] = "privileged operation trap",
+ [EXCP_PRIV_REG] = "privileged register trap",
+ [EXCP_OVERFLOW] = "overflow trap",
+ [EXCP_COND] = "conditional trap",
+ [EXCP_ASSIST] = "assist exception trap",
+ [EXCP_DTLB_MISS] = "data tlb miss fault",
+ [EXCP_NA_ITLB_MISS] = "non-access instruction tlb miss",
+ [EXCP_NA_DTLB_MISS] = "non-access data tlb miss",
+ [EXCP_DMP] = "data memory protection trap",
+ [EXCP_DMB] = "data memory break trap",
+ [EXCP_TLB_DIRTY] = "tlb dirty bit trap",
+ [EXCP_PAGE_REF] = "page reference trap",
+ [EXCP_ASSIST_EMU] = "assist emulation trap",
+ [EXCP_HPT] = "high-privilege transfer trap",
+ [EXCP_LPT] = "low-privilege transfer trap",
+ [EXCP_TB] = "taken branch trap",
+ [EXCP_DMAR] = "data memory access rights trap",
+ [EXCP_DMPI] = "data memory protection id trap",
+ [EXCP_UNALIGN] = "unaligned data reference trap",
+ [EXCP_PER_INTERRUPT] = "performance monitor interrupt",
+ [EXCP_SYSCALL] = "syscall",
+ [EXCP_SYSCALL_LWS] = "syscall-lws",
+ [EXCP_TOC] = "TOC (transfer of control)",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
+ return "unknown";
+ }
+ return excp_names[excp];
+}
+
void hppa_cpu_do_interrupt(CPUState *cs)
{
HPPACPU *cpu = HPPA_CPU(cs);
@@ -235,53 +278,11 @@ void hppa_cpu_do_interrupt(CPUState *cs)
}
if (qemu_loglevel_mask(CPU_LOG_INT)) {
- static const char * const names[] = {
- [EXCP_HPMC] = "high priority machine check",
- [EXCP_POWER_FAIL] = "power fail interrupt",
- [EXCP_RC] = "recovery counter trap",
- [EXCP_EXT_INTERRUPT] = "external interrupt",
- [EXCP_LPMC] = "low priority machine check",
- [EXCP_ITLB_MISS] = "instruction tlb miss fault",
- [EXCP_IMP] = "instruction memory protection trap",
- [EXCP_ILL] = "illegal instruction trap",
- [EXCP_BREAK] = "break instruction trap",
- [EXCP_PRIV_OPR] = "privileged operation trap",
- [EXCP_PRIV_REG] = "privileged register trap",
- [EXCP_OVERFLOW] = "overflow trap",
- [EXCP_COND] = "conditional trap",
- [EXCP_ASSIST] = "assist exception trap",
- [EXCP_DTLB_MISS] = "data tlb miss fault",
- [EXCP_NA_ITLB_MISS] = "non-access instruction tlb miss",
- [EXCP_NA_DTLB_MISS] = "non-access data tlb miss",
- [EXCP_DMP] = "data memory protection trap",
- [EXCP_DMB] = "data memory break trap",
- [EXCP_TLB_DIRTY] = "tlb dirty bit trap",
- [EXCP_PAGE_REF] = "page reference trap",
- [EXCP_ASSIST_EMU] = "assist emulation trap",
- [EXCP_HPT] = "high-privilege transfer trap",
- [EXCP_LPT] = "low-privilege transfer trap",
- [EXCP_TB] = "taken branch trap",
- [EXCP_DMAR] = "data memory access rights trap",
- [EXCP_DMPI] = "data memory protection id trap",
- [EXCP_UNALIGN] = "unaligned data reference trap",
- [EXCP_PER_INTERRUPT] = "performance monitor interrupt",
- [EXCP_SYSCALL] = "syscall",
- [EXCP_SYSCALL_LWS] = "syscall-lws",
- [EXCP_TOC] = "TOC (transfer of control)",
- };
-
FILE *logfile = qemu_log_trylock();
if (logfile) {
- const char *name = NULL;
-
- if (i >= 0 && i < ARRAY_SIZE(names)) {
- name = names[i];
- }
- if (name) {
- fprintf(logfile, "INT: cpu %d %s\n", cs->cpu_index, name);
- } else {
- fprintf(logfile, "INT: cpu %d unknown %d\n", cs->cpu_index, i);
- }
+ const char *name = hppa_exception_name(i);
+ fprintf(logfile, "INT: cpu %d excp %d (%s)\n",
+ cs->cpu_index, i, name);
hppa_cpu_dump_state(cs, logfile, 0);
qemu_log_unlock(logfile);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 08/27] target/i386: Replace magic value by proper EXCP0E_PAGE definition
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 07/27] target/hppa: " Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 09/27] target/i386: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
` (18 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé
No functional change: EXCP0E_PAGE is the 0x0e page-fault vector.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/i386/tcg/seg_helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 6d424349a58..138d2384b18 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -1215,7 +1215,7 @@ void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
env->segs[R_CS].selector, env->eip,
(int)env->segs[R_CS].base + env->eip,
env->segs[R_SS].selector, env->regs[R_ESP]);
- if (intno == 0x0e) {
+ if (intno == EXCP0E_PAGE) {
qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
} else {
qemu_log(" env->regs[R_EAX]=" TARGET_FMT_lx, env->regs[R_EAX]);
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 09/27] target/i386: Implement and register CPUClass::exception_name()
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 08/27] target/i386: Replace magic value by proper EXCP0E_PAGE definition Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 10/27] target/loongarch: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (17 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Zhao Liu
Implement x86_exception_name() and register it as
the CPUClass::exception_name() handler, so the common
exception logging can resolve X86 exception codes to names.
Use the new helper in check_exception() and do_interrupt_all().
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/i386/cpu.h | 2 ++
target/i386/cpu.c | 33 +++++++++++++++++++++++++++++++++
target/i386/tcg/excp_helper.c | 5 +++--
target/i386/tcg/seg_helper.c | 6 ++++--
4 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 786957fadd0..4f5e4f56acc 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1515,6 +1515,8 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
#define EXCP_SYSCALL 0x101 /* only for user emulation */
#define EXCP_VSYSCALL 0x102 /* only for user emulation */
+const char *x86_exception_name(int excp);
+
/* i386-specific interrupt pending bits. */
#define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f3bc6911c10..885fd0ded16 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -9371,6 +9371,38 @@ static bool cpuid_has_xsave_feature(CPUX86State *env, const ExtSaveArea *esa)
return false;
}
+const char *x86_exception_name(int excp)
+{
+ static const char * const excp_names[] = {
+ [EXCP00_DIVZ] = "DIV#0",
+ [EXCP01_DB] = "DB",
+ [EXCP02_NMI] = "NMI",
+ [EXCP03_INT3] = "INT3",
+ [EXCP04_INTO] = "INTO",
+ [EXCP05_BOUND] = "BOUND",
+ [EXCP06_ILLOP] = "ILLOP",
+ [EXCP07_PREX] = "PREX",
+ [EXCP08_DBLE] = "DBLE",
+ [EXCP09_XERR] = "XERR",
+ [EXCP0A_TSS] = "TSS",
+ [EXCP0B_NOSEG] = "NOSEG",
+ [EXCP0C_STACK] = "STACK",
+ [EXCP0D_GPF] = "GPF",
+ [EXCP0E_PAGE] = "PAGE",
+ [EXCP10_COPR] = "COPR",
+ [EXCP11_ALGN] = "ALGN",
+ [EXCP12_MCHK] = "MCHK",
+ [EXCP_VMEXIT] = "VMEXIT",
+ [EXCP_SYSCALL] = "SYSCALL",
+ [EXCP_VSYSCALL] = "VSYSCALL",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
+ return "unknown";
+ }
+ return excp_names[excp];
+}
+
static void x86_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
@@ -10921,6 +10953,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, const void *data)
cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
cc->class_by_name = x86_cpu_class_by_name;
+ cc->exception_name = x86_exception_name;
cc->list_cpus = x86_cpu_list;
cc->parse_features = x86_cpu_parse_featurestr;
cc->dump_state = x86_cpu_dump_state;
diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c
index 1eaa602c91d..34776de6a50 100644
--- a/target/i386/tcg/excp_helper.c
+++ b/target/i386/tcg/excp_helper.c
@@ -51,8 +51,9 @@ static int check_exception(CPUX86State *env, int intno, int *error_code,
int second_contributory = intno == 0 ||
(intno >= 10 && intno <= 13);
- qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
- env->old_exception, intno);
+ qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x (%s) new 0x%x (%s)\n",
+ env->old_exception, x86_exception_name(env->old_exception),
+ intno, x86_exception_name(intno));
#if !defined(CONFIG_USER_ONLY)
if (env->old_exception == EXCP08_DBLE) {
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 138d2384b18..494898e5caa 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -1208,9 +1208,11 @@ void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
if ((env->cr[0] & CR0_PE_MASK)) {
static int count;
- qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx
+ qemu_log("%6d: v=%02x (%s) e=%04x i=%d"
+ " cpl=%d IP=%04x:" TARGET_FMT_lx
" pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
- count, intno, error_code, is_int,
+ count, intno, x86_exception_name(intno),
+ error_code, is_int,
env->hflags & HF_CPL_MASK,
env->segs[R_CS].selector, env->eip,
(int)env->segs[R_CS].base + env->eip,
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 10/27] target/loongarch: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (8 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 09/27] target/i386: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-08 1:31 ` Bibo Mao
2026-10-07 9:44 ` [PATCH 11/27] target/m68k: " Philippe Mathieu-Daudé
` (16 subsequent siblings)
26 siblings, 1 reply; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Song Gao, Bibo Mao, Xianglai Li
Move loongarch_exception_name() out of tcg_cpu.c and expose
the prototype so non-TCG code path can access it. Register
it as the CPUClass::exception_name() handler, so the common
exception logging can resolve LoongArch exception codes to
names. Remove the qemu_log_mask() call in do_raise_exception()
because it would duplicate the one in log_raise_exception().
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/loongarch/internals.h | 2 ++
target/loongarch/cpu.c | 38 ++++++++++++++++++++++++++++
target/loongarch/tcg/tcg_cpu.c | 45 ----------------------------------
3 files changed, 40 insertions(+), 45 deletions(-)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index ff956823fd7..e7fed3afde5 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -42,6 +42,8 @@ bool loongarch_cpu_has_work(CPUState *cs);
bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env);
#endif /* !CONFIG_USER_ONLY */
+const char *loongarch_exception_name(int exception);
+
uint64_t read_fcc(CPULoongArchState *env);
void write_fcc(CPULoongArchState *env, uint64_t val);
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 54c26998979..fc9c5ab5ac2 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -835,6 +835,43 @@ static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
}
+static const struct {
+ int32_t exccode;
+ const char * const name;
+} excp_names[] = {
+ {EXCCODE_INT, "Interrupt"},
+ {EXCCODE_PIL, "Page invalid exception for load"},
+ {EXCCODE_PIS, "Page invalid exception for store"},
+ {EXCCODE_PIF, "Page invalid exception for fetch"},
+ {EXCCODE_PME, "Page modified exception"},
+ {EXCCODE_PNR, "Page Not Readable exception"},
+ {EXCCODE_PNX, "Page Not Executable exception"},
+ {EXCCODE_PPI, "Page Privilege error"},
+ {EXCCODE_ADEF, "Address error for instruction fetch"},
+ {EXCCODE_ADEM, "Address error for Memory access"},
+ {EXCCODE_SYS, "Syscall"},
+ {EXCCODE_BRK, "Break"},
+ {EXCCODE_INE, "Instruction Non-Existent"},
+ {EXCCODE_IPE, "Instruction privilege error"},
+ {EXCCODE_FPD, "Floating Point Disabled"},
+ {EXCCODE_FPE, "Floating Point Exception"},
+ {EXCCODE_DBP, "Debug breakpoint"},
+ {EXCCODE_BCE, "Bound Check Exception"},
+ {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
+ {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
+ {EXCP_HLT, "EXCP_HLT"},
+};
+
+const char *loongarch_exception_name(int exception)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(excp_names); i++) {
+ if (excp_names[i].exccode == exception) {
+ return excp_names[i].name;
+ }
+ }
+ return "Unknown";
+}
+
#ifndef CONFIG_USER_ONLY
#include "hw/core/sysemu-cpu-ops.h"
@@ -875,6 +912,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, const void *data)
&lacc->parent_phases);
cc->class_by_name = loongarch_cpu_class_by_name;
+ cc->exception_name = loongarch_exception_name;
cc->dump_state = loongarch_cpu_dump_state;
cc->set_pc = loongarch_cpu_set_pc;
cc->get_pc = loongarch_cpu_get_pc;
diff --git a/target/loongarch/tcg/tcg_cpu.c b/target/loongarch/tcg/tcg_cpu.c
index 4b1d44a1644..933b9b2d221 100644
--- a/target/loongarch/tcg/tcg_cpu.c
+++ b/target/loongarch/tcg/tcg_cpu.c
@@ -18,57 +18,12 @@
#include "tcg_loongarch.h"
#include "internals.h"
-struct TypeExcp {
- int32_t exccode;
- const char * const name;
-};
-
-static const struct TypeExcp excp_names[] = {
- {EXCCODE_INT, "Interrupt"},
- {EXCCODE_PIL, "Page invalid exception for load"},
- {EXCCODE_PIS, "Page invalid exception for store"},
- {EXCCODE_PIF, "Page invalid exception for fetch"},
- {EXCCODE_PME, "Page modified exception"},
- {EXCCODE_PNR, "Page Not Readable exception"},
- {EXCCODE_PNX, "Page Not Executable exception"},
- {EXCCODE_PPI, "Page Privilege error"},
- {EXCCODE_ADEF, "Address error for instruction fetch"},
- {EXCCODE_ADEM, "Address error for Memory access"},
- {EXCCODE_SYS, "Syscall"},
- {EXCCODE_BRK, "Break"},
- {EXCCODE_INE, "Instruction Non-Existent"},
- {EXCCODE_IPE, "Instruction privilege error"},
- {EXCCODE_FPD, "Floating Point Disabled"},
- {EXCCODE_FPE, "Floating Point Exception"},
- {EXCCODE_DBP, "Debug breakpoint"},
- {EXCCODE_BCE, "Bound Check Exception"},
- {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
- {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
- {EXCP_HLT, "EXCP_HLT"},
-};
-
-static const char *loongarch_exception_name(int32_t exception)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(excp_names); i++) {
- if (excp_names[i].exccode == exception) {
- return excp_names[i].name;
- }
- }
- return "Unknown";
-}
-
void G_NORETURN do_raise_exception(CPULoongArchState *env,
uint32_t exception,
uintptr_t pc)
{
CPUState *cs = env_cpu(env);
- qemu_log_mask(CPU_LOG_INT, "%s: exception: %d (%s)\n",
- __func__,
- exception,
- loongarch_exception_name(exception));
cs->exception_index = exception;
cpu_loop_exit_restore(cs, pc);
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 11/27] target/m68k: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (9 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 10/27] target/loongarch: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:44 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 12/27] target/microblaze: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
` (15 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:44 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Laurent Vivier
Expose m68k_exception_name() prototype and register it
as the CPUClass::exception_name() handler, so the common
exception logging can resolve M68k exception codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/m68k/cpu.h | 2 ++
target/m68k/cpu.c | 1 +
target/m68k/op_helper.c | 8 ++++++--
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 7cf3791108c..44b4afc41c6 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -69,6 +69,8 @@
#define EXCP_RTE 0x100
#define EXCP_SEMIHOSTING 0x101
+const char *m68k_exception_name(int excp);
+
#define M68K_DTTR0 0
#define M68K_DTTR1 1
#define M68K_ITTR0 2
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 9b52ad5fc23..7d5dfd8e529 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -730,6 +730,7 @@ static void m68k_cpu_class_init(ObjectClass *c, const void *data)
&mcc->parent_phases);
cc->class_by_name = m68k_cpu_class_by_name;
+ cc->exception_name = m68k_exception_name;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
cc->get_pc = m68k_cpu_get_pc;
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 38f7a689814..c600f83ddbf 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -80,9 +80,11 @@ throwaway:
cpu_m68k_set_sr(env, sr);
}
-static const char *m68k_exception_name(int index)
+#endif /* !CONFIG_USER_ONLY */
+
+const char *m68k_exception_name(int excp)
{
- switch (index) {
+ switch (excp) {
case EXCP_ACCESS:
return "Access Fault";
case EXCP_ADDRESS:
@@ -185,6 +187,8 @@ static const char *m68k_exception_name(int index)
return "Unassigned";
}
+#ifndef CONFIG_USER_ONLY
+
static void do_plugin_vcpu_interrupt_cb(CPUState *cs, uint64_t from)
{
switch (cs->exception_index) {
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 12/27] target/microblaze: Implement and register CPUClass::exception_name()
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (10 preceding siblings ...)
2026-10-07 9:44 ` [PATCH 11/27] target/m68k: " Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 13/27] target/mips: Remove unuseful EXCP_LAST definition Philippe Mathieu-Daudé
` (14 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Edgar E. Iglesias
Implement microblaze_exception_name() and register it as the
CPUClass::exception_name() handler, so the common exception
logging can resolve MicroBlaze exception codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/microblaze/cpu.h | 2 ++
target/microblaze/cpu.c | 17 +++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index b9602f72b94..fc2783693e3 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -36,6 +36,8 @@ typedef struct CPUArchState CPUMBState;
#define EXCP_HW_BREAK 4
#define EXCP_HW_EXCP 5
+const char *microblaze_exception_name(int excp);
+
/* MicroBlaze-specific interrupt pending bits. */
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 389a5124b12..224f1052f70 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -79,6 +79,22 @@ static const struct {
/* If no specific version gets selected, default to the following. */
#define DEFAULT_CPU_VERSION "10.0"
+const char *microblaze_exception_name(int excp)
+{
+ static const char * const excp_names[] = {
+ [EXCP_MMU] = "mmu",
+ [EXCP_IRQ] = "irq",
+ [EXCP_SYSCALL] = "syscall",
+ [EXCP_HW_BREAK] = "hw break",
+ [EXCP_HW_EXCP] = "hw excp",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
+ return "unknown";
+ }
+ return excp_names[excp];
+}
+
static void mb_cpu_set_pc(CPUState *cs, vaddr value)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
@@ -469,6 +485,7 @@ static void mb_cpu_class_init(ObjectClass *oc, const void *data)
&mcc->parent_phases);
cc->class_by_name = mb_cpu_class_by_name;
+ cc->exception_name = microblaze_exception_name;
cc->dump_state = mb_cpu_dump_state;
cc->set_pc = mb_cpu_set_pc;
cc->get_pc = mb_cpu_get_pc;
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 13/27] target/mips: Remove unuseful EXCP_LAST definition
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (11 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 12/27] target/microblaze: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 14/27] target/mips: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (13 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Aurelien Jarno, Jiaxun Yang,
Aleksandar Rikalo
Check array boundary with ARRAY_SIZE() macro.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/cpu.h | 2 --
target/mips/tcg/exception.c | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 32549791a18..5d8b78a70b8 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1347,8 +1347,6 @@ enum {
EXCP_TLBXI,
EXCP_TLBRI,
EXCP_SEMIHOST,
-
- EXCP_LAST = EXCP_SEMIHOST,
};
/*
diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c
index 630b8b809fa..2f02f9be877 100644
--- a/target/mips/tcg/exception.c
+++ b/target/mips/tcg/exception.c
@@ -88,7 +88,7 @@ void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb)
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
}
-static const char * const excp_names[EXCP_LAST + 1] = {
+static const char * const excp_names[] = {
[EXCP_RESET] = "reset",
[EXCP_SRESET] = "soft reset",
[EXCP_DSS] = "debug single step",
@@ -131,7 +131,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
const char *mips_exception_name(int32_t exception)
{
- if (exception < 0 || exception > EXCP_LAST) {
+ if (exception < 0 || exception >= ARRAY_SIZE(excp_names)) {
return "unknown";
}
return excp_names[exception];
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 14/27] target/mips: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (12 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 13/27] target/mips: Remove unuseful EXCP_LAST definition Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 15/27] target/or1k: " Philippe Mathieu-Daudé
` (12 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Aurelien Jarno, Jiaxun Yang,
Aleksandar Rikalo
Register mips_exception_name() as the CPUClass::exception_name()
handler, so the common exception logging can resolve MIPS exception
codes to names. Return "unknown" for missing array entries.
Remove the qemu_log_mask() call in do_raise_exception_err()
because it would duplicate the one in log_raise_exception().
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/mips/cpu.h | 2 ++
target/mips/tcg/tcg-internal.h | 2 --
target/mips/cpu.c | 1 +
target/mips/tcg/exception.c | 10 +++-------
4 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 5d8b78a70b8..b080c5de4de 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1349,6 +1349,8 @@ enum {
EXCP_SEMIHOST,
};
+const char *mips_exception_name(int excp);
+
/*
* This is an internally generated WAKE request line.
* It is driven by the CPU itself. Raised when the MT
diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h
index 950e6afc3f2..9f230e757d6 100644
--- a/target/mips/tcg/tcg-internal.h
+++ b/target/mips/tcg/tcg-internal.h
@@ -27,8 +27,6 @@ void mips_restore_state_to_opc(CPUState *cs,
const TranslationBlock *tb,
const uint64_t *data);
-const char *mips_exception_name(int32_t exception);
-
G_NORETURN void do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
int error_code, uintptr_t pc);
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 0fead20d651..528d926d16c 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -742,6 +742,7 @@ static void mips_cpu_class_init(ObjectClass *c, const void *data)
&mcc->parent_phases);
cc->class_by_name = mips_cpu_class_by_name;
+ cc->exception_name = mips_exception_name;
cc->dump_state = mips_cpu_dump_state;
cc->set_pc = mips_cpu_set_pc;
cc->get_pc = mips_cpu_get_pc;
diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c
index 2f02f9be877..e698def0640 100644
--- a/target/mips/tcg/exception.c
+++ b/target/mips/tcg/exception.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include "qemu/log.h"
#include "cpu.h"
#include "internal.h"
#include "exec/helper-proto.h"
@@ -129,12 +128,12 @@ static const char * const excp_names[] = {
[EXCP_SEMIHOST] = "Semihosting",
};
-const char *mips_exception_name(int32_t exception)
+const char *mips_exception_name(int excp)
{
- if (exception < 0 || exception >= ARRAY_SIZE(excp_names)) {
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
return "unknown";
}
- return excp_names[exception];
+ return excp_names[excp];
}
void do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
@@ -142,9 +141,6 @@ void do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
{
CPUState *cs = env_cpu(env);
- qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n",
- __func__, exception, mips_exception_name(exception),
- error_code);
cs->exception_index = exception;
env->error_code = error_code;
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 15/27] target/or1k: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (13 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 14/27] target/mips: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 16/27] target/ppc: " Philippe Mathieu-Daudé
` (11 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Stafford Horne
Factor openrisc_excp_name() out of openrisc_cpu_do_interrupt()
and register it as the CPUClass::exception_name() handler, so
the common exception logging can resolve OpenRISC exception
codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/or1k/cpu.h | 2 ++
target/or1k/cpu.c | 1 +
target/or1k/exception.c | 24 ++++++++++++++++++++++++
target/or1k/interrupt.c | 19 +------------------
4 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/target/or1k/cpu.h b/target/or1k/cpu.h
index fc4387ce7ae..96ed1779fae 100644
--- a/target/or1k/cpu.h
+++ b/target/or1k/cpu.h
@@ -155,6 +155,8 @@ enum {
EXCP_NR,
};
+const char *openrisc_excp_name(int excp);
+
/* Supervisor register */
enum {
SR_SM = (1 << 0),
diff --git a/target/or1k/cpu.c b/target/or1k/cpu.c
index 66c00c0930c..e15f6bb5e71 100644
--- a/target/or1k/cpu.c
+++ b/target/or1k/cpu.c
@@ -285,6 +285,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, const void *data)
&occ->parent_phases);
cc->class_by_name = openrisc_cpu_class_by_name;
+ cc->exception_name = openrisc_excp_name;
cc->dump_state = openrisc_cpu_dump_state;
cc->set_pc = openrisc_cpu_set_pc;
cc->get_pc = openrisc_cpu_get_pc;
diff --git a/target/or1k/exception.c b/target/or1k/exception.c
index 0479a069592..388bf6dbab8 100644
--- a/target/or1k/exception.c
+++ b/target/or1k/exception.c
@@ -22,6 +22,30 @@
#include "cpu.h"
#include "exception.h"
+const char *openrisc_excp_name(int excp)
+{
+ static const char * const excp_name[EXCP_NR] = {
+ [EXCP_RESET] = "RESET",
+ [EXCP_BUSERR] = "BUSERR (bus error)",
+ [EXCP_DPF] = "DFP (data protection fault)",
+ [EXCP_IPF] = "IPF (code protection fault)",
+ [EXCP_TICK] = "TICK (timer interrupt)",
+ [EXCP_ALIGN] = "ALIGN",
+ [EXCP_ILLEGAL] = "ILLEGAL",
+ [EXCP_INT] = "INT (device interrupt)",
+ [EXCP_DTLBMISS] = "DTLBMISS (data tlb miss)",
+ [EXCP_ITLBMISS] = "ITLBMISS (code tlb miss)",
+ [EXCP_RANGE] = "RANGE",
+ [EXCP_SYSCALL] = "SYSCALL",
+ [EXCP_FPE] = "FPE",
+ [EXCP_TRAP] = "TRAP",
+ };
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_name) || !excp_name[excp]) {
+ return "(unknown)";
+ }
+ return excp_name[excp];
+}
+
G_NORETURN void raise_exception(OpenRISCCPU *cpu, uint32_t excp)
{
CPUState *cs = CPU(cpu);
diff --git a/target/or1k/interrupt.c b/target/or1k/interrupt.c
index 6e89157639a..399c98e3881 100644
--- a/target/or1k/interrupt.c
+++ b/target/or1k/interrupt.c
@@ -66,26 +66,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
}
if (exception > 0 && exception < EXCP_NR) {
- static const char * const int_name[EXCP_NR] = {
- [EXCP_RESET] = "RESET",
- [EXCP_BUSERR] = "BUSERR (bus error)",
- [EXCP_DPF] = "DFP (data protection fault)",
- [EXCP_IPF] = "IPF (code protection fault)",
- [EXCP_TICK] = "TICK (timer interrupt)",
- [EXCP_ALIGN] = "ALIGN",
- [EXCP_ILLEGAL] = "ILLEGAL",
- [EXCP_INT] = "INT (device interrupt)",
- [EXCP_DTLBMISS] = "DTLBMISS (data tlb miss)",
- [EXCP_ITLBMISS] = "ITLBMISS (code tlb miss)",
- [EXCP_RANGE] = "RANGE",
- [EXCP_SYSCALL] = "SYSCALL",
- [EXCP_FPE] = "FPE",
- [EXCP_TRAP] = "TRAP",
- };
-
qemu_log_mask(CPU_LOG_INT, "CPU: %d INT: %s\n",
cs->cpu_index,
- int_name[exception]);
+ openrisc_excp_name(exception));
hwaddr vect_pc = exception << 8;
if (env->cpucfgr & CPUCFGR_EVBARP) {
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 16/27] target/ppc: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (14 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 15/27] target/or1k: " Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 17/27] target/riscv: " Philippe Mathieu-Daudé
` (10 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Chinmay Rath, Nicholas Piggin,
Glenn Miles, Harsh Prateek Bora, qemu-ppc
Expose powerpc_excp_name() prototype and register it
as the CPUClass::exception_name() handler, so the common
exception logging can resolve PPC exception codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/ppc/cpu.h | 2 ++
target/ppc/cpu_init.c | 1 +
target/ppc/excp_helper.c | 5 +++--
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 3fb51bbeb82..4eb7db3d727 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -153,6 +153,8 @@ enum {
POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */
};
+const char *powerpc_excp_name(int excp);
+
/* Exceptions error codes */
enum {
/* Exception subtypes for POWERPC_EXCP_ALIGN */
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index b711f9c0a85..d5f9ac28020 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7529,6 +7529,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, const void *data)
&pcc->parent_phases);
cc->class_by_name = ppc_cpu_class_by_name;
+ cc->exception_name = powerpc_excp_name;
cc->list_cpus = ppc_cpu_list;
cc->dump_state = ppc_cpu_dump_state;
cc->set_pc = ppc_cpu_set_pc;
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 6d05b865058..ab7518363af 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -33,9 +33,8 @@
/*****************************************************************************/
/* Exception processing */
-#ifndef CONFIG_USER_ONLY
-static const char *powerpc_excp_name(int excp)
+const char *powerpc_excp_name(int excp)
{
switch (excp) {
case POWERPC_EXCP_CRITICAL: return "CRITICAL";
@@ -105,6 +104,8 @@ static const char *powerpc_excp_name(int excp)
}
}
+#ifndef CONFIG_USER_ONLY
+
static void dump_syscall(CPUPPCState *env)
{
qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 17/27] target/riscv: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (15 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 16/27] target/ppc: " Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 18/27] target/rx: Unify BRK and INT trap handling Philippe Mathieu-Daudé
` (9 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Palmer Dabbelt, Alistair Francis,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, Chao Liu,
qemu-riscv
Factor riscv_excp_name() and riscv_intr_name() out of
riscv_cpu_get_trap_name(). Register riscv_excp_name()
as the CPUClass::exception_name() handler, so the common
exception logging can resolve RISCV exception codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/riscv/cpu.h | 1 +
target/riscv/cpu.c | 29 ++++++++++++++++++-----------
target/riscv/tcg/op_helper.c | 2 +-
3 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 8c8ffe94cd8..61bd0299dde 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -670,6 +670,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
char *riscv_isa_string(RISCVCPU *cpu);
int riscv_cpu_max_xlen(RISCVCPUClass *mcc);
bool riscv_cpu_option_set(RISCVCPU *cpu, const char *optname);
+const char *riscv_excp_name(int excp);
#ifndef CONFIG_USER_ONLY
void riscv_cpu_do_interrupt(CPUState *cpu);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index da4c1a090b9..0f236b0f4b2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -394,6 +394,14 @@ static const char * const riscv_excp_names[] = {
[RISCV_EXCP_SEMIHOST] = "semihost",
};
+const char *riscv_excp_name(int excp)
+{
+ if ((excp < ARRAY_SIZE(riscv_excp_names)) && riscv_excp_names[excp]) {
+ return riscv_excp_names[excp];
+ }
+ return "(unknown)";
+}
+
static const char * const riscv_intr_names[] = {
[IRQ_U_SOFT] = "u_software",
[IRQ_S_SOFT] = "s_software",
@@ -411,19 +419,17 @@ static const char * const riscv_intr_names[] = {
[IRQ_PMU_OVF] = "counter_overflow",
};
+static const char *riscv_intr_name(int intr)
+{
+ if ((intr < ARRAY_SIZE(riscv_intr_names)) && riscv_intr_names[intr]) {
+ return riscv_intr_names[intr];
+ }
+ return "(unknown)";
+}
+
const char *riscv_cpu_get_trap_name(uint64_t cause, bool async)
{
- if (async) {
- if ((cause < ARRAY_SIZE(riscv_intr_names)) && riscv_intr_names[cause]) {
- return riscv_intr_names[cause];
- }
- } else {
- if ((cause < ARRAY_SIZE(riscv_excp_names)) && riscv_excp_names[cause]) {
- return riscv_excp_names[cause];
- }
- }
-
- return "(unknown)";
+ return async ? riscv_intr_name(cause) : riscv_excp_name(cause);
}
void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext)
@@ -3039,6 +3045,7 @@ static void riscv_cpu_common_class_init(ObjectClass *c, const void *data)
&mcc->parent_phases);
cc->class_by_name = riscv_cpu_class_by_name;
+ cc->exception_name = riscv_excp_name;
cc->dump_state = riscv_cpu_dump_state;
cc->set_pc = riscv_cpu_set_pc;
cc->get_pc = riscv_cpu_get_pc;
diff --git a/target/riscv/tcg/op_helper.c b/target/riscv/tcg/op_helper.c
index b67c7718db4..ddc603759f2 100644
--- a/target/riscv/tcg/op_helper.c
+++ b/target/riscv/tcg/op_helper.c
@@ -44,7 +44,7 @@ G_NORETURN void riscv_raise_exception(CPURISCVState *env,
CPUState *cs = env_cpu(env);
trace_riscv_exception(exception,
- riscv_cpu_get_trap_name(exception, false),
+ riscv_excp_name(exception),
env->pc);
cs->exception_index = exception;
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 18/27] target/rx: Unify BRK and INT trap handling
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (16 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 17/27] target/riscv: " Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 19/27] target/rx: Define exception vector constants Philippe Mathieu-Daudé
` (8 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Yoshinori Sato
BRK is equivalent to INT #0, so route both instructions
through the same trap helper.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
---
target/rx/helper.h | 3 +--
target/rx/op_helper.c | 7 +------
target/rx/translate.c | 21 ++++++++++-----------
3 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/target/rx/helper.h b/target/rx/helper.h
index 8cc38b0cb71..f3897ce7619 100644
--- a/target/rx/helper.h
+++ b/target/rx/helper.h
@@ -2,8 +2,7 @@ DEF_HELPER_1(raise_illegal_instruction, noreturn, env)
DEF_HELPER_1(raise_access_fault, noreturn, env)
DEF_HELPER_1(raise_privilege_violation, noreturn, env)
DEF_HELPER_1(wait, noreturn, env)
-DEF_HELPER_2(rxint, noreturn, env, i32)
-DEF_HELPER_1(rxbrk, noreturn, env)
+DEF_HELPER_2(trap, noreturn, env, i32)
DEF_HELPER_3(fadd, f32, env, f32, f32)
DEF_HELPER_3(fsub, f32, env, f32, f32)
DEF_HELPER_3(fmul, f32, env, f32, f32)
diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c
index 36df7d377e5..6782912247e 100644
--- a/target/rx/op_helper.c
+++ b/target/rx/op_helper.c
@@ -455,12 +455,7 @@ G_NORETURN void helper_wait(CPURXState *env)
raise_exception(env, EXCP_HLT, 0);
}
-G_NORETURN void helper_rxint(CPURXState *env, uint32_t vec)
+G_NORETURN void helper_trap(CPURXState *env, uint32_t vec)
{
raise_exception(env, 0x100 + vec, 0);
}
-
-G_NORETURN void helper_rxbrk(CPURXState *env)
-{
- raise_exception(env, 0x100, 0);
-}
diff --git a/target/rx/translate.c b/target/rx/translate.c
index 132d495710c..d0910fbf8e7 100644
--- a/target/rx/translate.c
+++ b/target/rx/translate.c
@@ -2170,26 +2170,25 @@ static bool trans_RTE(DisasContext *ctx, arg_RTE *a)
return true;
}
+static bool do_trap(DisasContext *ctx, uint8_t vec)
+{
+ tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
+ gen_helper_trap(tcg_env, tcg_constant_i32(vec));
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return true;
+}
+
/* brk */
static bool trans_BRK(DisasContext *ctx, arg_BRK *a)
{
- tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
- gen_helper_rxbrk(tcg_env);
- ctx->base.is_jmp = DISAS_NORETURN;
- return true;
+ return do_trap(ctx, 0);
}
/* int #imm */
static bool trans_INT(DisasContext *ctx, arg_INT *a)
{
- TCGv_i32 vec;
-
tcg_debug_assert(a->imm < 0x100);
- vec = tcg_constant_i32(a->imm);
- tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
- gen_helper_rxint(tcg_env, vec);
- ctx->base.is_jmp = DISAS_NORETURN;
- return true;
+ return do_trap(ctx, a->imm);
}
/* wait */
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 19/27] target/rx: Define exception vector constants
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (17 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 18/27] target/rx: Unify BRK and INT trap handling Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 20/27] target/rx: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (7 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell, Yonggang Luo,
Philippe Mathieu-Daudé, Yoshinori Sato
From: Yonggang Luo <luoyonggang@gmail.com>
Name RX exception vectors and trap ranges, and use the
definitions throughout exception handling and exception
raising.
Assert that exception indexes remain within the defined
range before accessing their vector tables.
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Co-developed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
---
target/rx/cpu.h | 13 +++++++++++++
target/rx/helper.c | 21 +++++++++++----------
target/rx/op_helper.c | 10 +++++-----
target/rx/translate.c | 2 +-
4 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
index 64ba48a7329..0d9f4898a26 100644
--- a/target/rx/cpu.h
+++ b/target/rx/cpu.h
@@ -71,6 +71,19 @@ enum {
NUM_REGS = 16,
};
+#define RX_EXCP_TRAP_COUNT 0x100
+
+enum {
+ RX_EXCP_PRIVILEGE_VIOLATION = 20,
+ RX_EXCP_ACCESS = 21,
+ RX_EXCP_ILLEGAL_INSTRUCTION = 23,
+ RX_EXCP_FPU = 25,
+ RX_EXCP_NMI = 30,
+ RX_EXCP_TRAP_BASE = 0x100, /* Up to RX_EXCP_TRAP_COUNT */
+};
+
+#define RX_EXCP_COUNT (RX_EXCP_TRAP_BASE + RX_EXCP_TRAP_COUNT)
+
typedef struct CPUArchState {
/* CPU registers */
uint32_t regs[NUM_REGS]; /* general registers */
diff --git a/target/rx/helper.c b/target/rx/helper.c
index 0f99279bbaa..bc76dd28ab3 100644
--- a/target/rx/helper.c
+++ b/target/rx/helper.c
@@ -86,13 +86,14 @@ void rx_cpu_do_interrupt(CPUState *cs)
env->isp -= 4;
cpu_stl_le_data(env, env->isp, env->pc);
- if (vec < 0x100) {
- env->pc = cpu_ldl_le_data(env, 0xffffff80 + vec * 4);
- } else {
+ assert(vec < RX_EXCP_COUNT);
+ if (vec >= RX_EXCP_TRAP_BASE) {
env->pc = cpu_ldl_le_data(env, env->intb + (vec & 0xff) * 4);
+ } else {
+ env->pc = cpu_ldl_le_data(env, 0xffffff80 + vec * 4);
}
- if (vec == 30) {
+ if (vec == RX_EXCP_NMI) {
/* Non-maskable interrupt */
qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
} else {
@@ -100,22 +101,22 @@ void rx_cpu_do_interrupt(CPUState *cs)
}
switch (vec) {
- case 20:
+ case RX_EXCP_PRIVILEGE_VIOLATION:
expname = "privilege violation";
break;
- case 21:
+ case RX_EXCP_ACCESS:
expname = "access exception";
break;
- case 23:
+ case RX_EXCP_ILLEGAL_INSTRUCTION:
expname = "illegal instruction";
break;
- case 25:
+ case RX_EXCP_FPU:
expname = "fpu exception";
break;
- case 30:
+ case RX_EXCP_NMI:
expname = "non-maskable interrupt";
break;
- case 0x100 ... 0x1ff:
+ case RX_EXCP_TRAP_BASE ... RX_EXCP_TRAP_BASE + RX_EXCP_TRAP_COUNT - 1:
expname = "unconditional trap";
}
qemu_log_mask(CPU_LOG_INT, "exception 0x%02x [%s] raised\n",
diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c
index 6782912247e..d4e9ac2f192 100644
--- a/target/rx/op_helper.c
+++ b/target/rx/op_helper.c
@@ -115,7 +115,7 @@ static void update_fpsw(CPURXState *env, float32 ret, uintptr_t retaddr)
enable = FIELD_EX32(env->fpsw, FPSW, ENABLE);
enable |= 1 << 5; /* CE always enabled */
if (cause & enable) {
- raise_exception(env, 21, retaddr);
+ raise_exception(env, RX_EXCP_ACCESS, retaddr);
}
}
}
@@ -432,17 +432,17 @@ void raise_exception(CPURXState *env, int index,
G_NORETURN void helper_raise_privilege_violation(CPURXState *env)
{
- raise_exception(env, 20, GETPC());
+ raise_exception(env, RX_EXCP_PRIVILEGE_VIOLATION, GETPC());
}
G_NORETURN void helper_raise_access_fault(CPURXState *env)
{
- raise_exception(env, 21, GETPC());
+ raise_exception(env, RX_EXCP_ACCESS, GETPC());
}
G_NORETURN void helper_raise_illegal_instruction(CPURXState *env)
{
- raise_exception(env, 23, GETPC());
+ raise_exception(env, RX_EXCP_ILLEGAL_INSTRUCTION, GETPC());
}
G_NORETURN void helper_wait(CPURXState *env)
@@ -457,5 +457,5 @@ G_NORETURN void helper_wait(CPURXState *env)
G_NORETURN void helper_trap(CPURXState *env, uint32_t vec)
{
- raise_exception(env, 0x100 + vec, 0);
+ raise_exception(env, RX_EXCP_TRAP_BASE + vec, 0);
}
diff --git a/target/rx/translate.c b/target/rx/translate.c
index d0910fbf8e7..1bacc7adf92 100644
--- a/target/rx/translate.c
+++ b/target/rx/translate.c
@@ -2187,7 +2187,7 @@ static bool trans_BRK(DisasContext *ctx, arg_BRK *a)
/* int #imm */
static bool trans_INT(DisasContext *ctx, arg_INT *a)
{
- tcg_debug_assert(a->imm < 0x100);
+ tcg_debug_assert(a->imm < RX_EXCP_TRAP_COUNT);
return do_trap(ctx, a->imm);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 20/27] target/rx: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (18 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 19/27] target/rx: Define exception vector constants Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 21/27] target/s390x: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
` (6 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Yoshinori Sato
Factor rx_exception_name() out of rx_cpu_do_interrupt()
and register it as the CPUClass::exception_name() handler,
so the common exception logging can resolve RX exception
codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/rx/cpu.h | 1 +
target/rx/cpu.c | 1 +
target/rx/helper.c | 53 ++++++++++++++++++++++++++++------------------
3 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
index 0d9f4898a26..06208380621 100644
--- a/target/rx/cpu.h
+++ b/target/rx/cpu.h
@@ -147,6 +147,7 @@ struct RXCPUClass {
#define CPU_RESOLVING_TYPE TYPE_RX_CPU
const char *rx_crname(uint8_t cr);
+const char *rx_exception_name(int excp);
void rx_cpu_do_interrupt(CPUState *cpu);
bool rx_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr rx_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index 9b8473d71cf..bcaf6659ac5 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -245,6 +245,7 @@ static void rx_cpu_class_init(ObjectClass *klass, const void *data)
&rcc->parent_phases);
cc->class_by_name = rx_cpu_class_by_name;
+ cc->exception_name = rx_exception_name;
cc->dump_state = rx_cpu_dump_state;
cc->set_pc = rx_cpu_set_pc;
cc->get_pc = rx_cpu_get_pc;
diff --git a/target/rx/helper.c b/target/rx/helper.c
index bc76dd28ab3..fd662b1b5b9 100644
--- a/target/rx/helper.c
+++ b/target/rx/helper.c
@@ -24,6 +24,37 @@
#include "hw/core/irq.h"
#include "qemu/plugin.h"
+const char *rx_exception_name(int excp)
+{
+ const char *name;
+
+ switch (excp) {
+ case RX_EXCP_PRIVILEGE_VIOLATION:
+ name = "privilege violation";
+ break;
+ case RX_EXCP_ACCESS:
+ name = "access exception";
+ break;
+ case RX_EXCP_ILLEGAL_INSTRUCTION:
+ name = "illegal instruction";
+ break;
+ case RX_EXCP_FPU:
+ name = "fpu exception";
+ break;
+ case RX_EXCP_NMI:
+ name = "non-maskable interrupt";
+ break;
+ case RX_EXCP_TRAP_BASE ... RX_EXCP_TRAP_BASE + RX_EXCP_TRAP_COUNT - 1:
+ name = "unconditional trap";
+ break;
+ default:
+ name = "unknown exception";
+ break;
+ }
+
+ return name;
+}
+
void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte)
{
if (env->psw_pm == 0) {
@@ -79,7 +110,6 @@ void rx_cpu_do_interrupt(CPUState *cs)
qemu_log_mask(CPU_LOG_INT, "interrupt 0x%02x raised\n", env->ack_irq);
} else {
uint32_t vec = cs->exception_index;
- const char *expname = "unknown exception";
env->isp -= 4;
cpu_stl_le_data(env, env->isp, save_psw);
@@ -100,27 +130,8 @@ void rx_cpu_do_interrupt(CPUState *cs)
qemu_plugin_vcpu_exception_cb(cs, last_pc);
}
- switch (vec) {
- case RX_EXCP_PRIVILEGE_VIOLATION:
- expname = "privilege violation";
- break;
- case RX_EXCP_ACCESS:
- expname = "access exception";
- break;
- case RX_EXCP_ILLEGAL_INSTRUCTION:
- expname = "illegal instruction";
- break;
- case RX_EXCP_FPU:
- expname = "fpu exception";
- break;
- case RX_EXCP_NMI:
- expname = "non-maskable interrupt";
- break;
- case RX_EXCP_TRAP_BASE ... RX_EXCP_TRAP_BASE + RX_EXCP_TRAP_COUNT - 1:
- expname = "unconditional trap";
- }
qemu_log_mask(CPU_LOG_INT, "exception 0x%02x [%s] raised\n",
- (vec & 0xff), expname);
+ (vec & 0xff), rx_exception_name(vec));
}
env->regs[0] = env->isp;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 21/27] target/s390x: Implement and register CPUClass::exception_name()
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (19 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 20/27] target/rx: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 22/27] target/sh4: Define exception vector constants Philippe Mathieu-Daudé
` (5 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Ilya Leoshkevich, David Hildenbrand,
Cornelia Huck, Eric Farman, Matthew Rosato, qemu-s390x
Implement s390x_exception_name() and register it as the
CPUClass::exception_name() handler, so the common exception
logging can resolve s390x exception codes to names.
Use the new helper in s390_cpu_do_interrupt() and helper_exception().
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/s390x/cpu.h | 2 ++
target/s390x/cpu.c | 1 +
target/s390x/interrupt.c | 18 ++++++++++++++++++
target/s390x/tcg/excp_helper.c | 6 ++++--
target/s390x/tcg/misc_helper.c | 3 ++-
5 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index ef73b15218e..37b6e541312 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -437,6 +437,8 @@ QEMU_BUILD_BUG_ON(FLAG_MASK_PER_IFETCH_NULLIFY !=
#define EXCP_IO 7 /* I/O interrupt */
#define EXCP_MCHK 8 /* machine check */
+const char *s390x_exception_name(int excp);
+
#define INTERRUPT_EXT_CPU_TIMER (1 << 3)
#define INTERRUPT_EXT_CLOCK_COMPARATOR (1 << 4)
#define INTERRUPT_EXTERNAL_CALL (1 << 5)
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 85afc5dec9a..275cc6cd53b 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -408,6 +408,7 @@ static void s390_cpu_class_init(ObjectClass *oc, const void *data)
&scc->parent_phases);
cc->class_by_name = s390_cpu_class_by_name;
+ cc->exception_name = s390x_exception_name;
cc->list_cpus = s390_cpu_list;
cc->dump_state = s390_cpu_dump_state;
cc->query_cpu_fast = s390_query_cpu_fast;
diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c
index d7e3fd45e4b..c02f7cd2e7d 100644
--- a/target/s390x/interrupt.c
+++ b/target/s390x/interrupt.c
@@ -19,6 +19,24 @@
#include "hw/s390x/s390_flic.h"
#endif
+const char *s390x_exception_name(int excp)
+{
+ static const char * const excp_names[] = {
+ [EXCP_EXT] = "external interrupt",
+ [EXCP_SVC] = "supervisor call",
+ [EXCP_PGM] = "program interruption",
+ [EXCP_RESTART] = "restart interrupt",
+ [EXCP_STOP] = "stop interrupt",
+ [EXCP_IO] = "I/O interrupt",
+ [EXCP_MCHK] = "machine check",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
+ return "unknown";
+ }
+ return excp_names[excp];
+}
+
/* Ensure to exit the TB after this call! */
void trigger_pgm_exception(CPUS390XState *env, uint32_t code)
{
diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
index d952bb20cf1..83fe65e1f8c 100644
--- a/target/s390x/tcg/excp_helper.c
+++ b/target/s390x/tcg/excp_helper.c
@@ -508,8 +508,10 @@ void s390_cpu_do_interrupt(CPUState *cs)
bool stopped = false;
uint64_t last_pc = cpu->env.psw.addr;
- qemu_log_mask(CPU_LOG_INT, "%s: %d at psw=%" PRIx64 ":%" PRIx64 "\n",
- __func__, cs->exception_index, env->psw.mask, env->psw.addr);
+ qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) at psw=%" PRIx64 ":%" PRIx64 "\n",
+ __func__, cs->exception_index,
+ s390x_exception_name(cs->exception_index),
+ env->psw.mask, env->psw.addr);
try_deliver:
/* handle machine checks */
diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c
index f1c8563af00..a01c5d894e7 100644
--- a/target/s390x/tcg/misc_helper.c
+++ b/target/s390x/tcg/misc_helper.c
@@ -61,7 +61,8 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
CPUState *cs = env_cpu(env);
- HELPER_LOG("%s: exception %d\n", __func__, excp);
+ HELPER_LOG("%s: exception %d (%s)\n", __func__, excp,
+ s390x_exception_name(excp));
cs->exception_index = excp;
cpu_loop_exit(cs);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 22/27] target/sh4: Define exception vector constants
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (20 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 21/27] target/s390x: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 23/27] target/sh4: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (4 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell, Yonggang Luo,
Yonggang Luo, Philippe Mathieu-Daudé, Yoshinori Sato
From: Yonggang Luo <luoyonggang@gmail.com>
Name SH4 exception vectors and use the definitions throughout
exception handling and exception raising.
Signed-off-by: Yonggang Luo <yonggang@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/sh4/cpu.h | 21 +++++++++++++++
target/sh4/helper.c | 60 +++++++++++++++++++++---------------------
target/sh4/op_helper.c | 16 +++++------
3 files changed, 59 insertions(+), 38 deletions(-)
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 6984bb462fb..a1e9049b7be 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -135,6 +135,27 @@ typedef struct memory_content {
struct memory_content *next;
} memory_content;
+/* Guest trap numbers. */
+enum {
+ SH4_EXCP_RESET = 0x000,
+ SH4_EXCP_MANUAL_RESET = 0x020,
+ SH4_EXCP_TLB_MISS = 0x040,
+ SH4_EXCP_DTLB_MISS_WRITE = 0x060,
+ SH4_EXCP_INITIAL_PAGE_WRITE = 0x080,
+ SH4_EXCP_TLB_VIOLATION = 0x0a0,
+ SH4_EXCP_DTLB_VIOLATION_WRITE = 0x0c0,
+ SH4_EXCP_ADDR_ERROR = 0x0e0,
+ SH4_EXCP_DATA_WRITE = 0x100,
+ SH4_EXCP_FPU = 0x120,
+ SH4_EXCP_TLB_MULTIPLE = 0x140,
+ SH4_EXCP_TRAPA = 0x160,
+ SH4_EXCP_ILLEGAL_INSTRUCTION = 0x180,
+ SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION = 0x1a0,
+ SH4_EXCP_USER_BREAK = 0x1e0,
+ SH4_EXCP_FPU_DISABLE = 0x800,
+ SH4_EXCP_SLOT_FPU_DISABLE = 0x820,
+};
+
typedef struct CPUArchState {
uint32_t flags; /* general execution flags */
uint32_t gregs[24]; /* general registers */
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index b6b057f104b..0fbd613f333 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -70,7 +70,7 @@ void superh_cpu_do_interrupt(CPUState *cs)
do_irq = do_irq && (cs->exception_index == -1);
if (env->sr & (1u << SR_BL)) {
- if (do_exp && cs->exception_index != 0x1e0) {
+ if (do_exp && cs->exception_index != SH4_EXCP_USER_BREAK) {
/* In theory a masked exception generates a reset exception,
which in turn jumps to the reset vector. However this only
works when using a bootloader. When using a kernel and an
@@ -97,43 +97,43 @@ void superh_cpu_do_interrupt(CPUState *cs)
if (qemu_loglevel_mask(CPU_LOG_INT)) {
const char *expname;
switch (cs->exception_index) {
- case 0x0e0:
+ case SH4_EXCP_ADDR_ERROR:
expname = "addr_error";
break;
- case 0x040:
+ case SH4_EXCP_TLB_MISS:
expname = "tlb_miss";
break;
- case 0x0a0:
+ case SH4_EXCP_TLB_VIOLATION:
expname = "tlb_violation";
break;
- case 0x180:
+ case SH4_EXCP_ILLEGAL_INSTRUCTION:
expname = "illegal_instruction";
break;
- case 0x1a0:
+ case SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION:
expname = "slot_illegal_instruction";
break;
- case 0x800:
+ case SH4_EXCP_FPU_DISABLE:
expname = "fpu_disable";
break;
- case 0x820:
+ case SH4_EXCP_SLOT_FPU_DISABLE:
expname = "slot_fpu";
break;
- case 0x100:
+ case SH4_EXCP_DATA_WRITE:
expname = "data_write";
break;
- case 0x060:
+ case SH4_EXCP_DTLB_MISS_WRITE:
expname = "dtlb_miss_write";
break;
- case 0x0c0:
+ case SH4_EXCP_DTLB_VIOLATION_WRITE:
expname = "dtlb_violation_write";
break;
- case 0x120:
+ case SH4_EXCP_FPU:
expname = "fpu_exception";
break;
- case 0x080:
+ case SH4_EXCP_INITIAL_PAGE_WRITE:
expname = "initial_page_write";
break;
- case 0x160:
+ case SH4_EXCP_TRAPA:
expname = "trapa";
break;
default:
@@ -161,18 +161,18 @@ void superh_cpu_do_interrupt(CPUState *cs)
if (do_exp) {
env->expevt = cs->exception_index;
switch (cs->exception_index) {
- case 0x000:
- case 0x020:
- case 0x140:
+ case SH4_EXCP_RESET:
+ case SH4_EXCP_MANUAL_RESET:
+ case SH4_EXCP_TLB_MULTIPLE:
env->sr &= ~(1u << SR_FD);
env->sr |= 0xf << 4; /* IMASK */
env->pc = 0xa0000000;
break;
- case 0x040:
- case 0x060:
+ case SH4_EXCP_TLB_MISS:
+ case SH4_EXCP_DTLB_MISS_WRITE:
env->pc = env->vbr + 0x400;
break;
- case 0x160:
+ case SH4_EXCP_TRAPA:
env->spc += 2; /* special case for TRAPA */
/* fall through */
default:
@@ -632,7 +632,7 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr,
CPUState *cs = env_cpu(s);
/* Multiple TLB Exception */
- cs->exception_index = 0x140;
+ cs->exception_index = SH4_EXCP_TLB_MULTIPLE;
s->tea = addr;
break;
}
@@ -828,33 +828,33 @@ bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
switch (ret) {
case MMU_ITLB_MISS:
case MMU_DTLB_MISS_READ:
- cs->exception_index = 0x040;
+ cs->exception_index = SH4_EXCP_TLB_MISS;
break;
case MMU_DTLB_MULTIPLE:
case MMU_ITLB_MULTIPLE:
- cs->exception_index = 0x140;
+ cs->exception_index = SH4_EXCP_TLB_MULTIPLE;
break;
case MMU_ITLB_VIOLATION:
- cs->exception_index = 0x0a0;
+ cs->exception_index = SH4_EXCP_TLB_VIOLATION;
break;
case MMU_DTLB_MISS_WRITE:
- cs->exception_index = 0x060;
+ cs->exception_index = SH4_EXCP_DTLB_MISS_WRITE;
break;
case MMU_DTLB_INITIAL_WRITE:
- cs->exception_index = 0x080;
+ cs->exception_index = SH4_EXCP_INITIAL_PAGE_WRITE;
break;
case MMU_DTLB_VIOLATION_READ:
- cs->exception_index = 0x0a0;
+ cs->exception_index = SH4_EXCP_TLB_VIOLATION;
break;
case MMU_DTLB_VIOLATION_WRITE:
- cs->exception_index = 0x0c0;
+ cs->exception_index = SH4_EXCP_DTLB_VIOLATION_WRITE;
break;
case MMU_IADDR_ERROR:
case MMU_DADDR_ERROR_READ:
- cs->exception_index = 0x0e0;
+ cs->exception_index = SH4_EXCP_ADDR_ERROR;
break;
case MMU_DADDR_ERROR_WRITE:
- cs->exception_index = 0x100;
+ cs->exception_index = SH4_EXCP_DATA_WRITE;
break;
default:
cpu_abort(cs, "Unhandled MMU fault");
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index 777380f8e40..8beac9ca034 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -33,10 +33,10 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
switch (access_type) {
case MMU_INST_FETCH:
case MMU_DATA_LOAD:
- cs->exception_index = 0x0e0;
+ cs->exception_index = SH4_EXCP_ADDR_ERROR;
break;
case MMU_DATA_STORE:
- cs->exception_index = 0x100;
+ cs->exception_index = SH4_EXCP_DATA_WRITE;
break;
default:
g_assert_not_reached();
@@ -67,22 +67,22 @@ void raise_exception(CPUSH4State *env, int index,
void helper_raise_illegal_instruction(CPUSH4State *env)
{
- raise_exception(env, 0x180, 0);
+ raise_exception(env, SH4_EXCP_ILLEGAL_INSTRUCTION, 0);
}
void helper_raise_slot_illegal_instruction(CPUSH4State *env)
{
- raise_exception(env, 0x1a0, 0);
+ raise_exception(env, SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION, 0);
}
void helper_raise_fpu_disable(CPUSH4State *env)
{
- raise_exception(env, 0x800, 0);
+ raise_exception(env, SH4_EXCP_FPU_DISABLE, 0);
}
void helper_raise_slot_fpu_disable(CPUSH4State *env)
{
- raise_exception(env, 0x820, 0);
+ raise_exception(env, SH4_EXCP_SLOT_FPU_DISABLE, 0);
}
void helper_sleep(CPUSH4State *env)
@@ -97,7 +97,7 @@ void helper_sleep(CPUSH4State *env)
void helper_trapa(CPUSH4State *env, uint32_t tra)
{
env->tra = tra << 2;
- raise_exception(env, 0x160, 0);
+ raise_exception(env, SH4_EXCP_TRAPA, 0);
}
void helper_exclusive(CPUSH4State *env)
@@ -255,7 +255,7 @@ static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
if (cause & enable) {
- raise_exception(env, 0x120, retaddr);
+ raise_exception(env, SH4_EXCP_FPU, retaddr);
}
}
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 23/27] target/sh4: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (21 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 22/27] target/sh4: Define exception vector constants Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 24/27] target/sparc: Remove well tested DEBUG_PCALL definition Philippe Mathieu-Daudé
` (3 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Yoshinori Sato
Factor sh4_exception_name() out of superh_cpu_do_interrupt()
and register it as the CPUClass::exception_name() handler,
so the common exception logging can resolve SH-4 exception
codes to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/sh4/helper.c | 101 +++++++++++++++++++++++---------------------
1 file changed, 54 insertions(+), 47 deletions(-)
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 0fbd613f333..66d6b612138 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -57,6 +57,58 @@ int cpu_sh4_is_cached(CPUSH4State *env, uint32_t addr)
#else /* !CONFIG_USER_ONLY */
+static const char *sh4_exception_name(int excp)
+{
+ const char *name;
+
+ switch (excp) {
+ case SH4_EXCP_ADDR_ERROR:
+ name = "addr_error";
+ break;
+ case SH4_EXCP_TLB_MISS:
+ name = "tlb_miss";
+ break;
+ case SH4_EXCP_TLB_VIOLATION:
+ name = "tlb_violation";
+ break;
+ case SH4_EXCP_ILLEGAL_INSTRUCTION:
+ name = "illegal_instruction";
+ break;
+ case SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION:
+ name = "slot_illegal_instruction";
+ break;
+ case SH4_EXCP_FPU_DISABLE:
+ name = "fpu_disable";
+ break;
+ case SH4_EXCP_SLOT_FPU_DISABLE:
+ name = "slot_fpu";
+ break;
+ case SH4_EXCP_DATA_WRITE:
+ name = "data_write";
+ break;
+ case SH4_EXCP_DTLB_MISS_WRITE:
+ name = "dtlb_miss_write";
+ break;
+ case SH4_EXCP_DTLB_VIOLATION_WRITE:
+ name = "dtlb_violation_write";
+ break;
+ case SH4_EXCP_FPU:
+ name = "fpu_exception";
+ break;
+ case SH4_EXCP_INITIAL_PAGE_WRITE:
+ name = "initial_page_write";
+ break;
+ case SH4_EXCP_TRAPA:
+ name = "trapa";
+ break;
+ default:
+ name = "???";
+ break;
+ }
+
+ return name;
+}
+
void superh_cpu_do_interrupt(CPUState *cs)
{
CPUSH4State *env = cpu_env(cs);
@@ -95,53 +147,8 @@ void superh_cpu_do_interrupt(CPUState *cs)
}
if (qemu_loglevel_mask(CPU_LOG_INT)) {
- const char *expname;
- switch (cs->exception_index) {
- case SH4_EXCP_ADDR_ERROR:
- expname = "addr_error";
- break;
- case SH4_EXCP_TLB_MISS:
- expname = "tlb_miss";
- break;
- case SH4_EXCP_TLB_VIOLATION:
- expname = "tlb_violation";
- break;
- case SH4_EXCP_ILLEGAL_INSTRUCTION:
- expname = "illegal_instruction";
- break;
- case SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION:
- expname = "slot_illegal_instruction";
- break;
- case SH4_EXCP_FPU_DISABLE:
- expname = "fpu_disable";
- break;
- case SH4_EXCP_SLOT_FPU_DISABLE:
- expname = "slot_fpu";
- break;
- case SH4_EXCP_DATA_WRITE:
- expname = "data_write";
- break;
- case SH4_EXCP_DTLB_MISS_WRITE:
- expname = "dtlb_miss_write";
- break;
- case SH4_EXCP_DTLB_VIOLATION_WRITE:
- expname = "dtlb_violation_write";
- break;
- case SH4_EXCP_FPU:
- expname = "fpu_exception";
- break;
- case SH4_EXCP_INITIAL_PAGE_WRITE:
- expname = "initial_page_write";
- break;
- case SH4_EXCP_TRAPA:
- expname = "trapa";
- break;
- default:
- expname = do_irq ? "interrupt" : "???";
- break;
- }
- qemu_log("exception 0x%03x [%s] raised\n",
- irq_vector, expname);
+ qemu_log("exception 0x%03x [%s] raised\n", irq_vector,
+ do_irq ? "interrupt" : sh4_exception_name(cs->exception_index));
log_cpu_state(cs, 0);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 24/27] target/sparc: Remove well tested DEBUG_PCALL definition
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (22 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 23/27] target/sh4: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 25/27] target/sparc: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (2 subsequent siblings)
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Mark Cave-Ayland, Artyom Tarasenko
DEBUG_PCALL has been unconditionally defined for 14 years now
(see commit b884fc5ecaa "target-sparc: Make CPU_LOG_INT useful
by default"), so the #ifdef guards around the exception name
table and the CPU_LOG_INT block are always taken. Remove the
define and the now-redundant guards.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/sparc/int64_helper.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index 60ab0478fc6..10341e0c282 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -26,9 +26,6 @@
#include "trace.h"
#include "qemu/plugin.h"
-#define DEBUG_PCALL
-
-#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
[TT_TFAULT] = "Instruction Access Fault",
[TT_TMISS] = "Instruction Access MMU Miss",
@@ -62,7 +59,6 @@ static const char * const excp_names[0x80] = {
[TT_EXTINT | 0xe] = "External Interrupt 14",
[TT_EXTINT | 0xf] = "External Interrupt 15",
};
-#endif
#if !defined(CONFIG_USER_ONLY)
void cpu_check_irqs(CPUSPARCState *env)
@@ -138,7 +134,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
int intno = cs->exception_index;
trap_state *tsptr;
-#ifdef DEBUG_PCALL
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static int count;
const char *name;
@@ -177,7 +172,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
#endif
count++;
}
-#endif
#if !defined(CONFIG_USER_ONLY)
if (env->tl >= env->maxtl) {
cpu_abort(cs, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 25/27] target/sparc: Register CPUClass::exception_name() handler
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (23 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 24/27] target/sparc: Remove well tested DEBUG_PCALL definition Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 26/27] target/tricore: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 27/27] target/xtensa: " Philippe Mathieu-Daudé
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Mark Cave-Ayland, Artyom Tarasenko
For each SPARC / SPARC64 target:
factor sparc_exception_name() out of sparc_cpu_do_interrupt()
and register it as the CPUClass::exception_name() handler, so
the common exception logging can resolve SPARC exception codes
to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/sparc/cpu.h | 1 +
target/sparc/cpu.c | 1 +
target/sparc/int32_helper.c | 23 ++++++++++-------------
target/sparc/int64_helper.c | 36 ++++++++++++++++++------------------
4 files changed, 30 insertions(+), 31 deletions(-)
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 31a16c2af03..3c1ba223eb2 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -583,6 +583,7 @@ extern const VMStateDescription vmstate_sparc_cpu;
hwaddr sparc_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
#endif
+const char *sparc_exception_name(int excp);
void sparc_cpu_do_interrupt(CPUState *cpu);
int sparc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index ae9bdca9df8..1f9a62a8c76 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -1098,6 +1098,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, const void *data)
&scc->parent_phases);
cc->class_by_name = sparc_cpu_class_by_name;
+ cc->exception_name = sparc_exception_name;
cc->list_cpus = sparc_cpu_list,
cc->parse_features = sparc_cpu_parse_features;
cc->dump_state = sparc_cpu_dump_state;
diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
index d6bb3fa1e54..2bb40d3905f 100644
--- a/target/sparc/int32_helper.c
+++ b/target/sparc/int32_helper.c
@@ -58,12 +58,16 @@ static const char * const excp_names[0x80] = {
[TT_NCP_INSN] = "Coprocessor Disabled",
};
-static const char *excp_name_str(int32_t exception_index)
+const char *sparc_exception_name(int excp)
{
- if (exception_index < 0 || exception_index >= ARRAY_SIZE(excp_names)) {
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(excp_names) > 0x100);
+ if (excp < 0 || excp >= 0x100) {
return "Unknown";
}
- return excp_names[exception_index];
+ if (excp >= 0x80) {
+ return "Trap Instruction";
+ }
+ return excp_names[excp] ?: "Unknown";
}
#if !defined(CONFIG_USER_ONLY)
@@ -107,15 +111,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static int count;
- const char *name;
-
- if (intno < 0 || intno >= 0x100) {
- name = "Unknown";
- } else if (intno >= 0x80) {
- name = "Trap Instruction";
- } else {
- name = excp_name_str(intno);
- }
+ const char *name = sparc_exception_name(intno);
qemu_log("%6d: %s (v=%02x)\n", count, name, intno);
log_cpu_state(cs, 0);
@@ -129,7 +125,8 @@ void sparc_cpu_do_interrupt(CPUState *cs)
} else {
cpu_abort(cs, "Trap 0x%02x (%s) while interrupts disabled, "
"Error state",
- cs->exception_index, excp_name_str(cs->exception_index));
+ cs->exception_index,
+ sparc_exception_name(cs->exception_index));
}
return;
}
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index 10341e0c282..da5e214b11b 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -60,6 +60,23 @@ static const char * const excp_names[0x80] = {
[TT_EXTINT | 0xf] = "External Interrupt 15",
};
+const char *sparc_exception_name(int excp)
+{
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(excp_names) > 0x200);
+ if (excp < 0 || excp >= 0x200) {
+ return "Unknown";
+ } else if (excp >= 0x180) {
+ return "Hyperprivileged Trap Instruction";
+ } else if (excp >= 0x100) {
+ return "Trap Instruction";
+ } else if (excp >= 0xc0) {
+ return "Window Fill";
+ } else if (excp >= 0x80) {
+ return "Window Spill";
+ }
+ return excp_names[excp] ?: "Unknown";
+}
+
#if !defined(CONFIG_USER_ONLY)
void cpu_check_irqs(CPUSPARCState *env)
{
@@ -136,24 +153,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static int count;
- const char *name;
-
- if (intno < 0 || intno >= 0x1ff) {
- name = "Unknown";
- } else if (intno >= 0x180) {
- name = "Hyperprivileged Trap Instruction";
- } else if (intno >= 0x100) {
- name = "Trap Instruction";
- } else if (intno >= 0xc0) {
- name = "Window Fill";
- } else if (intno >= 0x80) {
- name = "Window Spill";
- } else {
- name = excp_names[intno];
- if (!name) {
- name = "Unknown";
- }
- }
+ const char *name = sparc_exception_name(intno);
qemu_log("%6d: %s (v=%04x)\n", count, name, intno);
log_cpu_state(cs, 0);
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 26/27] target/tricore: Implement and register CPUClass::exception_name()
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (24 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 25/27] target/sparc: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 27/27] target/xtensa: " Philippe Mathieu-Daudé
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé
Implement tricore_trap_name() and register it as the
CPUClass::exception_name() handler, so the common exception
logging can resolve TriCore trop numbers to names.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/tricore/cpu.h | 2 ++
target/tricore/cpu.c | 21 +++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index 12e497d2a7a..fb8d2fd1011 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -178,6 +178,8 @@ enum {
TRAPC_IRQ = 8
};
+const char *tricore_trap_name(int trap);
+
/* Class 0 TIN */
enum {
TIN0_VAF = 0,
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index 84a05e3d363..d550b8b0b8e 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -36,6 +36,26 @@ static const gchar *tricore_gdb_arch_name(CPUState *cs)
return "tricore";
}
+const char *tricore_trap_name(int trap)
+{
+ static const char * const trap_names[] = {
+ [TRAPC_MMU] = "mmu",
+ [TRAPC_PROT] = "prot",
+ [TRAPC_INSN_ERR] = "insn err",
+ [TRAPC_CTX_MNG] = "ctx mng",
+ [TRAPC_SYSBUS] = "sysbus",
+ [TRAPC_ASSERT] = "assert",
+ [TRAPC_SYSCALL] = "syscall",
+ [TRAPC_NMI] = "NMI",
+ [TRAPC_IRQ] = "IRQ",
+ };
+
+ if (trap < 0 || trap >= ARRAY_SIZE(trap_names) || !trap_names[trap]) {
+ return "unknown";
+ }
+ return trap_names[trap];
+}
+
static void tricore_disas_set_info(const CPUState *cpu, disassemble_info *info)
{
CPUTriCoreState *env = cpu_env((CPUState *)cpu);
@@ -240,6 +260,7 @@ static void tricore_cpu_class_init(ObjectClass *c, const void *data)
resettable_class_set_parent_phases(rc, NULL, tricore_cpu_reset_hold, NULL,
&mcc->parent_phases);
cc->class_by_name = tricore_cpu_class_by_name;
+ cc->exception_name = tricore_trap_name;
cc->gdb_read_register = tricore_cpu_gdb_read_register;
cc->gdb_write_register = tricore_cpu_gdb_write_register;
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 27/27] target/xtensa: Implement and register CPUClass::exception_name()
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
` (25 preceding siblings ...)
2026-10-07 9:45 ` [PATCH 26/27] target/tricore: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
@ 2026-10-07 9:45 ` Philippe Mathieu-Daudé
26 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 9:45 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell,
Philippe Mathieu-Daudé, Max Filippov
Implement xtensa_exception_name() and register it as the
CPUClass::exception_name() handler, so the common exception
logging can resolve Xtensa exception codes to names.
Use the new helper in xtensa_cpu_do_interrupt().
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
target/xtensa/cpu.h | 2 ++
target/xtensa/cpu.c | 26 ++++++++++++++++++++++++++
target/xtensa/exc_helper.c | 3 ++-
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 49d6ad9083d..3440c27862b 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -262,6 +262,8 @@ enum {
EXC_MAX
};
+const char *xtensa_exception_name(int excp);
+
enum {
ILLEGAL_INSTRUCTION_CAUSE = 0,
SYSCALL_CAUSE,
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 7c25b9ab707..d5ad9466c0d 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -239,6 +239,31 @@ static void xtensa_cpu_disas_set_info(const CPUState *cs,
: BFD_ENDIAN_LITTLE;
}
+const char *xtensa_exception_name(int excp)
+{
+ static const char * const excp_names[] = {
+ [EXC_RESET0] = "reset",
+ [EXC_RESET1] = "reset",
+ [EXC_MEMORY_ERROR] = "memory error",
+ [EXC_WINDOW_OVERFLOW4] = "window overflow",
+ [EXC_WINDOW_UNDERFLOW4] = "window underflow",
+ [EXC_WINDOW_OVERFLOW8] = "window overflow",
+ [EXC_WINDOW_UNDERFLOW8] = "window underflow",
+ [EXC_WINDOW_OVERFLOW12] = "window overflow",
+ [EXC_WINDOW_UNDERFLOW12] = "window underflow",
+ [EXC_IRQ] = "interrupt",
+ [EXC_KERNEL] = "kernel",
+ [EXC_USER] = "user",
+ [EXC_DOUBLE] = "double",
+ [EXC_DEBUG] = "debug",
+ };
+
+ if (excp < 0 || excp >= ARRAY_SIZE(excp_names) || !excp_names[excp]) {
+ return "unknown";
+ }
+ return excp_names[excp];
+}
+
static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -348,6 +373,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, const void *data)
&xcc->parent_phases);
cc->class_by_name = xtensa_cpu_class_by_name;
+ cc->exception_name = xtensa_exception_name;
cc->dump_state = xtensa_cpu_dump_state;
cc->set_pc = xtensa_cpu_set_pc;
cc->get_pc = xtensa_cpu_get_pc;
diff --git a/target/xtensa/exc_helper.c b/target/xtensa/exc_helper.c
index 7cb67d179a8..ff71e5d6462 100644
--- a/target/xtensa/exc_helper.c
+++ b/target/xtensa/exc_helper.c
@@ -236,9 +236,10 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
case EXC_USER:
case EXC_DOUBLE:
case EXC_DEBUG:
- qemu_log_mask(CPU_LOG_INT, "%s(%d) "
+ qemu_log_mask(CPU_LOG_INT, "%s(%d:%s) "
"pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n",
__func__, cs->exception_index,
+ xtensa_exception_name(cs->exception_index),
env->pc, env->regs[0], env->sregs[PS],
env->sregs[CCOUNT]);
if (env->config->exception_vector[cs->exception_index]) {
--
2.55.0
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int'
2026-10-07 9:44 ` [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int' Philippe Mathieu-Daudé
@ 2026-10-07 10:47 ` Philippe Mathieu-Daudé
2026-10-07 11:00 ` Daniel P. Berrangé
0 siblings, 1 reply; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-10-07 10:47 UTC (permalink / raw)
To: qemu-devel, Daniel P. Berrangé
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell
On 7/10/26 11:44, Philippe Mathieu-Daudé wrote:
> Add log_raise_exception(), a common helper cpu_loop_*() can
> call to log a raised exception when '-d int' is used, and
> qemu_excp_name() to resolve QEMU-internal exceptions to names.
>
> Use it in cpu_loop_exit_atomic() to log the EXCP_ATOMIC reason.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
> accel/tcg/cpu-exec-common.c | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
> index 68077c8fd9d..2ac8380d0bb 100644
> --- a/accel/tcg/cpu-exec-common.c
> +++ b/accel/tcg/cpu-exec-common.c
> @@ -89,6 +89,37 @@ void tcg_update_all_cflags(void)
> }
> }
>
> +#define EXCP_QEMU_INTERNAL 0x10000
> +
> +static const char *qemu_excp_name(int excp)
> +{
> + static const char *excp_name[] = {
> + [EXCP_INTERRUPT - EXCP_QEMU_INTERNAL] = "async interruption",
> + [EXCP_HLT - EXCP_QEMU_INTERNAL] = "hlt instruction",
> + [EXCP_DEBUG - EXCP_QEMU_INTERNAL] = "debug",
> + [EXCP_HALTED - EXCP_QEMU_INTERNAL] = "halted",
> + [EXCP_YIELD - EXCP_QEMU_INTERNAL] = "yield",
> + [EXCP_ATOMIC - EXCP_QEMU_INTERNAL] = "emulate atomic",
> + };
> + assert(excp >= EXCP_QEMU_INTERNAL);
> + excp -= EXCP_QEMU_INTERNAL;
> + if ((excp < ARRAY_SIZE(excp_name)) && excp_name[excp]) {
> + return excp_name[excp];
> + }
> + return "undocumented";
> +}
> +
> +static void log_raise_exception(const CPUState *cpu, int excp)
> +{
> + if (!qemu_loglevel_mask(CPU_LOG_INT)) {
> + return;
> + }
> + if (excp >= EXCP_QEMU_INTERNAL) {
> + qemu_log_mask(CPU_LOG_INT, "raise exception: 0x%x (internal: %s)\n",
> + excp, qemu_excp_name(excp));
Daniel suggested on IRC we can use target_name() here to distinguish
between different kinds of vCPUs. Alternatively we can add a
CPUClass::log_friendly_format_name() defaulting to current "%p index:%d"
but overwritable i.e. as "accel:%s target:%s cluster:%d index:%u", so
each time we log something on a vCPU context we have an unified prefix
format to parse.
> + }
> +}
> +
> /* exit the current TB, but without causing any exception to be raised */
> void cpu_loop_exit_noexc(CPUState *cpu)
> {
> @@ -118,5 +149,6 @@ void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc)
> /* Prevent looping if already executing in a serial context. */
> g_assert(!cpu_in_serial_context(cpu));
> cpu->exception_index = EXCP_ATOMIC;
> + log_raise_exception(cpu, EXCP_ATOMIC);
> cpu_loop_exit_restore(cpu, pc);
> }
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int'
2026-10-07 10:47 ` Philippe Mathieu-Daudé
@ 2026-10-07 11:00 ` Daniel P. Berrangé
2026-10-07 15:24 ` Yonggang Luo
0 siblings, 1 reply; 33+ messages in thread
From: Daniel P. Berrangé @ 2026-10-07 11:00 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Richard Henderson, Paolo Bonzini, Peter Maydell
On Wed, Oct 07, 2026 at 12:47:24PM +0200, Philippe Mathieu-Daudé wrote:
> On 7/10/26 11:44, Philippe Mathieu-Daudé wrote:
> > Add log_raise_exception(), a common helper cpu_loop_*() can
> > call to log a raised exception when '-d int' is used, and
> > qemu_excp_name() to resolve QEMU-internal exceptions to names.
> >
> > Use it in cpu_loop_exit_atomic() to log the EXCP_ATOMIC reason.
> >
> > Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> > ---
> > accel/tcg/cpu-exec-common.c | 32 ++++++++++++++++++++++++++++++++
> > 1 file changed, 32 insertions(+)
> >
> > diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
> > index 68077c8fd9d..2ac8380d0bb 100644
> > --- a/accel/tcg/cpu-exec-common.c
> > +++ b/accel/tcg/cpu-exec-common.c
> > @@ -89,6 +89,37 @@ void tcg_update_all_cflags(void)
> > }
> > }
> > +#define EXCP_QEMU_INTERNAL 0x10000
> > +
> > +static const char *qemu_excp_name(int excp)
> > +{
> > + static const char *excp_name[] = {
> > + [EXCP_INTERRUPT - EXCP_QEMU_INTERNAL] = "async interruption",
> > + [EXCP_HLT - EXCP_QEMU_INTERNAL] = "hlt instruction",
> > + [EXCP_DEBUG - EXCP_QEMU_INTERNAL] = "debug",
> > + [EXCP_HALTED - EXCP_QEMU_INTERNAL] = "halted",
> > + [EXCP_YIELD - EXCP_QEMU_INTERNAL] = "yield",
> > + [EXCP_ATOMIC - EXCP_QEMU_INTERNAL] = "emulate atomic",
> > + };
> > + assert(excp >= EXCP_QEMU_INTERNAL);
> > + excp -= EXCP_QEMU_INTERNAL;
> > + if ((excp < ARRAY_SIZE(excp_name)) && excp_name[excp]) {
> > + return excp_name[excp];
> > + }
> > + return "undocumented";
> > +}
> > +
> > +static void log_raise_exception(const CPUState *cpu, int excp)
> > +{
> > + if (!qemu_loglevel_mask(CPU_LOG_INT)) {
> > + return;
> > + }
> > + if (excp >= EXCP_QEMU_INTERNAL) {
> > + qemu_log_mask(CPU_LOG_INT, "raise exception: 0x%x (internal: %s)\n",
> > + excp, qemu_excp_name(excp));
>
> Daniel suggested on IRC we can use target_name() here to distinguish
> between different kinds of vCPUs. Alternatively we can add a
> CPUClass::log_friendly_format_name() defaulting to current "%p index:%d"
> but overwritable i.e. as "accel:%s target:%s cluster:%d index:%u", so
> each time we log something on a vCPU context we have an unified prefix
> format to parse.
That would be problematic. Those two different format strings have
different args. Also since it is not a static string, it can't be
concatenated with the format strnig being passed to qemu_log_mask().
So that would imply sprintf'ing the CPU format string prefix first
with whatever args it needs, before passing the result into the
qemu_log_mask() call.
g_autofree char *prefix = g_strdup_printf(
"accel:%s target:%s cluster:%d index:%u",
accel, targe,t cluster, index);
cpu_log_mask(CPU_LOG_INT,
"%s raise exception: 0x%x (internal: %s)\n",
prefix, excp, qemu_excp_name(excp));
the double layers of printf makes logging quite unpleasant,
and while it could be hidden in a macro, the runtime overhead
still exists.
On IRC, I suggested an approach that would work at the preprocessor
level to concatenate the arch target name at compile time on to the
front of all log messages, so there is no runtime impact at all,
nor any code impact beyond s/qemu_log_mask/qemu_log_mask_target/.
#define qemu_log_mask_target(MASK, FMT, ...) \
do { \
if (unlikely(qemu_loglevel_mask(MASK))) { \
qemu_log(TARGET_NAME # FMT, ## __VA_ARGS__);\
} \
} while (0)
Note, TARGE_NAME is poisoned, so we can't add this to to main
include/qemu/log.h file. It would need to live in a header file
that is built per-target, and thus only used from target specific
code like the TCG impls.
As a slight variation, *if* we can assume each target arch's VCPUs
are in a separate thread, we could avoid using TARGET_NAME directly
and instead use a thread local
__thread const char *target_name;
...which would be initialized to TARGET_NAME when the vcpu's thread
starts.
Then we would change the macro to be
#define qemu_log_mask_target(MASK, FMT, ...) \
do { \
if (unlikely(qemu_loglevel_mask(MASK))) { \
qemu_log("%s" # FMT, target_name, ## __VA_ARGS__);\
} \
} while (0)
That would make it possible to include more dynamic information
by adding more thread-locals and hiding more fmt args in the
macro.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int'
2026-10-07 11:00 ` Daniel P. Berrangé
@ 2026-10-07 15:24 ` Yonggang Luo
0 siblings, 0 replies; 33+ messages in thread
From: Yonggang Luo @ 2026-10-07 15:24 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: Philippe Mathieu-Daudé, qemu-devel, Richard Henderson,
Paolo Bonzini, Peter Maydell
On Wed, Oct 7, 2026 at 7:02 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Wed, Oct 07, 2026 at 12:47:24PM +0200, Philippe Mathieu-Daudé wrote:
> > On 7/10/26 11:44, Philippe Mathieu-Daudé wrote:
> > > Add log_raise_exception(), a common helper cpu_loop_*() can
> > > call to log a raised exception when '-d int' is used, and
> > > qemu_excp_name() to resolve QEMU-internal exceptions to names.
> > >
> > > Use it in cpu_loop_exit_atomic() to log the EXCP_ATOMIC reason.
> > >
> > > Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> > > ---
> > > accel/tcg/cpu-exec-common.c | 32 ++++++++++++++++++++++++++++++++
> > > 1 file changed, 32 insertions(+)
> > >
> > > diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
> > > index 68077c8fd9d..2ac8380d0bb 100644
> > > --- a/accel/tcg/cpu-exec-common.c
> > > +++ b/accel/tcg/cpu-exec-common.c
> > > @@ -89,6 +89,37 @@ void tcg_update_all_cflags(void)
> > > }
> > > }
> > > +#define EXCP_QEMU_INTERNAL 0x10000
> > > +
> > > +static const char *qemu_excp_name(int excp)
> > > +{
> > > + static const char *excp_name[] = {
> > > + [EXCP_INTERRUPT - EXCP_QEMU_INTERNAL] = "async interruption",
> > > + [EXCP_HLT - EXCP_QEMU_INTERNAL] = "hlt instruction",
> > > + [EXCP_DEBUG - EXCP_QEMU_INTERNAL] = "debug",
> > > + [EXCP_HALTED - EXCP_QEMU_INTERNAL] = "halted",
> > > + [EXCP_YIELD - EXCP_QEMU_INTERNAL] = "yield",
> > > + [EXCP_ATOMIC - EXCP_QEMU_INTERNAL] = "emulate atomic",
> > > + };
> > > + assert(excp >= EXCP_QEMU_INTERNAL);
> > > + excp -= EXCP_QEMU_INTERNAL;
> > > + if ((excp < ARRAY_SIZE(excp_name)) && excp_name[excp]) {
> > > + return excp_name[excp];
> > > + }
> > > + return "undocumented";
> > > +}
> > > +
> > > +static void log_raise_exception(const CPUState *cpu, int excp)
> > > +{
> > > + if (!qemu_loglevel_mask(CPU_LOG_INT)) {
> > > + return;
> > > + }
> > > + if (excp >= EXCP_QEMU_INTERNAL) {
> > > + qemu_log_mask(CPU_LOG_INT, "raise exception: 0x%x (internal: %s)\n",
> > > + excp, qemu_excp_name(excp));
> >
> > Daniel suggested on IRC we can use target_name() here to distinguish
> > between different kinds of vCPUs. Alternatively we can add a
> > CPUClass::log_friendly_format_name() defaulting to current "%p index:%d"
> > but overwritable i.e. as "accel:%s target:%s cluster:%d index:%u", so
> > each time we log something on a vCPU context we have an unified prefix
> > format to parse.
>
> That would be problematic. Those two different format strings have
> different args. Also since it is not a static string, it can't be
> concatenated with the format strnig being passed to qemu_log_mask().
> So that would imply sprintf'ing the CPU format string prefix first
> with whatever args it needs, before passing the result into the
> qemu_log_mask() call.
>
> g_autofree char *prefix = g_strdup_printf(
> "accel:%s target:%s cluster:%d index:%u",
> accel, targe,t cluster, index);
> cpu_log_mask(CPU_LOG_INT,
> "%s raise exception: 0x%x (internal: %s)\n",
> prefix, excp, qemu_excp_name(excp));
>
> the double layers of printf makes logging quite unpleasant,
> and while it could be hidden in a macro, the runtime overhead
> still exists.
>
> On IRC, I suggested an approach that would work at the preprocessor
> level to concatenate the arch target name at compile time on to the
> front of all log messages, so there is no runtime impact at all,
> nor any code impact beyond s/qemu_log_mask/qemu_log_mask_target/.
>
> #define qemu_log_mask_target(MASK, FMT, ...) \
> do { \
> if (unlikely(qemu_loglevel_mask(MASK))) { \
> qemu_log(TARGET_NAME # FMT, ## __VA_ARGS__);\
> } \
> } while (0)
>
> Note, TARGE_NAME is poisoned, so we can't add this to to main
> include/qemu/log.h file. It would need to live in a header file
> that is built per-target, and thus only used from target specific
> code like the TCG impls.
>
> As a slight variation, *if* we can assume each target arch's VCPUs
> are in a separate thread, we could avoid using TARGET_NAME directly
> and instead use a thread local
>
> __thread const char *target_name;
I'm a bit confused, we already have target_name(), we can directly use
that, is that costing for logging?
the __thread things can be hidden in target_name() function wrapper.
>
> ...which would be initialized to TARGET_NAME when the vcpu's thread
> starts.
>
> Then we would change the macro to be
>
> #define qemu_log_mask_target(MASK, FMT, ...) \
> do { \
> if (unlikely(qemu_loglevel_mask(MASK))) { \
> qemu_log("%s" # FMT, target_name, ## __VA_ARGS__);\
> } \
> } while (0)
>
> That would make it possible to include more dynamic information
> by adding more thread-locals and hiding more fmt args in the
> macro.
>
> With regards,
> Daniel
> --
> |: https://berrange.com ~~ https://hachyderm.io/@berrange :|
> |: https://libvirt.org ~~ https://entangle-photo.org :|
> |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
>
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 10/27] target/loongarch: Register CPUClass::exception_name() handler
2026-10-07 9:44 ` [PATCH 10/27] target/loongarch: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-08 1:31 ` Bibo Mao
0 siblings, 0 replies; 33+ messages in thread
From: Bibo Mao @ 2026-10-08 1:31 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell, Song Gao,
Xianglai Li
On 2026/10/7 下午5:44, Philippe Mathieu-Daudé wrote:
> Move loongarch_exception_name() out of tcg_cpu.c and expose
> the prototype so non-TCG code path can access it. Register
> it as the CPUClass::exception_name() handler, so the common
> exception logging can resolve LoongArch exception codes to
> names. Remove the qemu_log_mask() call in do_raise_exception()
> because it would duplicate the one in log_raise_exception().
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
> target/loongarch/internals.h | 2 ++
> target/loongarch/cpu.c | 38 ++++++++++++++++++++++++++++
> target/loongarch/tcg/tcg_cpu.c | 45 ----------------------------------
> 3 files changed, 40 insertions(+), 45 deletions(-)
>
> diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
> index ff956823fd7..e7fed3afde5 100644
> --- a/target/loongarch/internals.h
> +++ b/target/loongarch/internals.h
> @@ -42,6 +42,8 @@ bool loongarch_cpu_has_work(CPUState *cs);
> bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env);
> #endif /* !CONFIG_USER_ONLY */
>
> +const char *loongarch_exception_name(int exception);
> +
> uint64_t read_fcc(CPULoongArchState *env);
> void write_fcc(CPULoongArchState *env, uint64_t val);
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 54c26998979..fc9c5ab5ac2 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -835,6 +835,43 @@ static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> }
> }
>
> +static const struct {
> + int32_t exccode;
> + const char * const name;
> +} excp_names[] = {
> + {EXCCODE_INT, "Interrupt"},
> + {EXCCODE_PIL, "Page invalid exception for load"},
> + {EXCCODE_PIS, "Page invalid exception for store"},
> + {EXCCODE_PIF, "Page invalid exception for fetch"},
> + {EXCCODE_PME, "Page modified exception"},
> + {EXCCODE_PNR, "Page Not Readable exception"},
> + {EXCCODE_PNX, "Page Not Executable exception"},
> + {EXCCODE_PPI, "Page Privilege error"},
> + {EXCCODE_ADEF, "Address error for instruction fetch"},
> + {EXCCODE_ADEM, "Address error for Memory access"},
> + {EXCCODE_SYS, "Syscall"},
> + {EXCCODE_BRK, "Break"},
> + {EXCCODE_INE, "Instruction Non-Existent"},
> + {EXCCODE_IPE, "Instruction privilege error"},
> + {EXCCODE_FPD, "Floating Point Disabled"},
> + {EXCCODE_FPE, "Floating Point Exception"},
> + {EXCCODE_DBP, "Debug breakpoint"},
> + {EXCCODE_BCE, "Bound Check Exception"},
> + {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
> + {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
> + {EXCP_HLT, "EXCP_HLT"},
> +};
> +
> +const char *loongarch_exception_name(int exception)
> +{
> + for (size_t i = 0; i < ARRAY_SIZE(excp_names); i++) {
> + if (excp_names[i].exccode == exception) {
> + return excp_names[i].name;
> + }
> + }
> + return "Unknown";
> +}
> +
> #ifndef CONFIG_USER_ONLY
> #include "hw/core/sysemu-cpu-ops.h"
>
> @@ -875,6 +912,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, const void *data)
> &lacc->parent_phases);
>
> cc->class_by_name = loongarch_cpu_class_by_name;
> + cc->exception_name = loongarch_exception_name;
> cc->dump_state = loongarch_cpu_dump_state;
> cc->set_pc = loongarch_cpu_set_pc;
> cc->get_pc = loongarch_cpu_get_pc;
> diff --git a/target/loongarch/tcg/tcg_cpu.c b/target/loongarch/tcg/tcg_cpu.c
> index 4b1d44a1644..933b9b2d221 100644
> --- a/target/loongarch/tcg/tcg_cpu.c
> +++ b/target/loongarch/tcg/tcg_cpu.c
> @@ -18,57 +18,12 @@
> #include "tcg_loongarch.h"
> #include "internals.h"
>
> -struct TypeExcp {
> - int32_t exccode;
> - const char * const name;
> -};
> -
> -static const struct TypeExcp excp_names[] = {
> - {EXCCODE_INT, "Interrupt"},
> - {EXCCODE_PIL, "Page invalid exception for load"},
> - {EXCCODE_PIS, "Page invalid exception for store"},
> - {EXCCODE_PIF, "Page invalid exception for fetch"},
> - {EXCCODE_PME, "Page modified exception"},
> - {EXCCODE_PNR, "Page Not Readable exception"},
> - {EXCCODE_PNX, "Page Not Executable exception"},
> - {EXCCODE_PPI, "Page Privilege error"},
> - {EXCCODE_ADEF, "Address error for instruction fetch"},
> - {EXCCODE_ADEM, "Address error for Memory access"},
> - {EXCCODE_SYS, "Syscall"},
> - {EXCCODE_BRK, "Break"},
> - {EXCCODE_INE, "Instruction Non-Existent"},
> - {EXCCODE_IPE, "Instruction privilege error"},
> - {EXCCODE_FPD, "Floating Point Disabled"},
> - {EXCCODE_FPE, "Floating Point Exception"},
> - {EXCCODE_DBP, "Debug breakpoint"},
> - {EXCCODE_BCE, "Bound Check Exception"},
> - {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
> - {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
> - {EXCP_HLT, "EXCP_HLT"},
> -};
> -
> -static const char *loongarch_exception_name(int32_t exception)
> -{
> - int i;
> -
> - for (i = 0; i < ARRAY_SIZE(excp_names); i++) {
> - if (excp_names[i].exccode == exception) {
> - return excp_names[i].name;
> - }
> - }
> - return "Unknown";
> -}
> -
> void G_NORETURN do_raise_exception(CPULoongArchState *env,
> uint32_t exception,
> uintptr_t pc)
> {
> CPUState *cs = env_cpu(env);
>
> - qemu_log_mask(CPU_LOG_INT, "%s: exception: %d (%s)\n",
> - __func__,
> - exception,
> - loongarch_exception_name(exception));
> cs->exception_index = exception;
>
> cpu_loop_exit_restore(cs, pc);
>
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 06/27] target/hexagon: Register CPUClass::exception_name() handler
2026-10-07 9:44 ` [PATCH 06/27] target/hexagon: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
@ 2026-10-09 1:34 ` Brian Cain
0 siblings, 0 replies; 33+ messages in thread
From: Brian Cain @ 2026-10-09 1:34 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Richard Henderson, Paolo Bonzini, Peter Maydell, Pierrick Bouvier
On 10/7/2026 4:44 AM, Philippe Mathieu-Daudé wrote:
> Expose the hexagon event_name[] array via a hexagon_event_name()
> helper and register it as the CPUClass::exception_name() handler,
> so the common exception logging can resolve Hexagon exception
> codes to names.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
> target/hexagon/cpu_bits.h | 2 ++
> target/hexagon/cpu.c | 37 +++++++++++++++++++++++++++++++++++++
> target/hexagon/hexswi.c | 30 +-----------------------------
> 3 files changed, 40 insertions(+), 29 deletions(-)
>
> diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
> index a8fba4aa188..7d1bdfcbc71 100644
> --- a/target/hexagon/cpu_bits.h
> +++ b/target/hexagon/cpu_bits.h
> @@ -61,6 +61,8 @@ enum hex_event {
> HEX_EVENT_INTF = 0x1f,
> };
>
> +const char *hexagon_event_name(int event);
> +
> enum hex_cause {
> HEX_CAUSE_NONE = -1,
> HEX_CAUSE_RESET = 0x000,
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index 1f7d8a8df70..be286b1f2ee 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -318,6 +318,42 @@ void hexagon_debug(CPUHexagonState *env)
> hexagon_dump(env, stdout, CPU_DUMP_FPU);
> }
>
> +const char *hexagon_event_name(int event)
> +{
> + 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",
> + };
> +
> + if (event < 0 || event >= ARRAY_SIZE(event_name) || !event_name[event]) {
> + return "unknown";
> + }
> + return event_name[event];
> +}
> +
> static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
> {
> cpu_env(cs)->gpr[HEX_REG_PC] = value;
> @@ -826,6 +862,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
> &mcc->parent_phases);
>
> cc->class_by_name = hexagon_cpu_class_by_name;
> + cc->exception_name = hexagon_event_name;
> cc->dump_state = hexagon_dump_state;
> cc->set_pc = hexagon_cpu_set_pc;
> cc->get_pc = hexagon_cpu_get_pc;
> diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
> index 4705e915aea..be366d7a373 100644
> --- a/target/hexagon/hexswi.c
> +++ b/target/hexagon/hexswi.c
> @@ -729,34 +729,6 @@ static void set_addresses(CPUHexagonState *env, uint32_t 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)
>
> {
> @@ -769,7 +741,7 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
> qemu_log_mask(CPU_LOG_INT,
> "\t%s: event 0x%02x:%s, cause 0x%" PRIx32 "(%" PRIu32 ")\n",
> __func__, (unsigned)cs->exception_index,
> - event_name[cs->exception_index], env->cause_code,
> + hexagon_event_name(cs->exception_index), env->cause_code,
> env->cause_code);
>
> env->llsc_addr = ~0;
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2026-10-09 1:36 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07 9:44 [PATCH 00/27] cpus: Add common CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 01/27] cpus: Add helper to log raised exceptions with '-d int' Philippe Mathieu-Daudé
2026-10-07 10:47 ` Philippe Mathieu-Daudé
2026-10-07 11:00 ` Daniel P. Berrangé
2026-10-07 15:24 ` Yonggang Luo
2026-10-07 9:44 ` [PATCH 02/27] cpus: Introduce CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 03/27] target/alpha: Register " Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 04/27] target/arm: " Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 05/27] target/avr: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 06/27] target/hexagon: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-09 1:34 ` Brian Cain
2026-10-07 9:44 ` [PATCH 07/27] target/hppa: " Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 08/27] target/i386: Replace magic value by proper EXCP0E_PAGE definition Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 09/27] target/i386: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
2026-10-07 9:44 ` [PATCH 10/27] target/loongarch: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-08 1:31 ` Bibo Mao
2026-10-07 9:44 ` [PATCH 11/27] target/m68k: " Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 12/27] target/microblaze: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 13/27] target/mips: Remove unuseful EXCP_LAST definition Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 14/27] target/mips: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 15/27] target/or1k: " Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 16/27] target/ppc: " Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 17/27] target/riscv: " Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 18/27] target/rx: Unify BRK and INT trap handling Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 19/27] target/rx: Define exception vector constants Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 20/27] target/rx: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 21/27] target/s390x: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 22/27] target/sh4: Define exception vector constants Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 23/27] target/sh4: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 24/27] target/sparc: Remove well tested DEBUG_PCALL definition Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 25/27] target/sparc: Register CPUClass::exception_name() handler Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 26/27] target/tricore: Implement and register CPUClass::exception_name() Philippe Mathieu-Daudé
2026-10-07 9:45 ` [PATCH 27/27] target/xtensa: " Philippe Mathieu-Daudé
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.