* [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
@ 2025-09-04 20:46 Julian Ganz
2025-09-04 20:46 ` [PATCH v6 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
` (26 more replies)
0 siblings, 27 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz
Some analysis greatly benefits, or depends on, information about
certain types of dicontinuities such as interrupts. For example, we may
need to handle the execution of a new translation block differently if
it is not the result of normal program flow but of an interrupt.
Even with the existing interfaces, it is more or less possible to
discern these situations, e.g. as done by the cflow plugin. However,
this process poses a considerable overhead to the core analysis one may
intend to perform.
These changes introduce a generic and easy-to-use interface for plugin
authors in the form of a callback for discontinuities. Patch 1 defines
an enumeration of some trap-related discontinuities including somewhat
narrow definitions of the discontinuity evetns and a callback type.
Patch 2 defines the callback registration function. Patch 3 adds some
hooks for triggering the callbacks. Patch 4 adds an example plugin
showcasing the new API.
Patches 5 through 22 call the hooks for all architectures but hexagon,
mapping architecture specific events to the three categories defined in
patch 1. We don't plan to add hooks for hexagon since despite having
exceptions apparently doesn't have any discontinuities associated with
them.
Patch 23 supplies a test plugin asserting some behavior of the plugin
API w.r.t. the PCs reported by the new API. Finally, patches 24 and 25
add new tests for riscv which serve as test-cases for the test plugin.
Sidenote: I'm likely doing something wrong for one architecture or
the other. These patches are untested for most of them.
Richard Henderson proposed streamlining interrupts and exceptions for
all targets and calling the hooks from a higher level rather than in
each target code. However, there are a few obstacled and I decided to
not do this as part of this series.
Since v5:
- The internal function plugin_vcpu_cb__discon now takes the
qemu_plugin_event as a parameter instead of determining the event
from the discon type.
- Fixed computation of the last PC for ARM platforms.
- Code mapping ARM exception index to discon type is now shared
between m- and a-profile.
- Fixed mapping of interrupt number to discon type for HPPA platforms.
- Removed exception hook for some internal events for Motorola 68000.
- Call hook for unaligned access exceptions on MicroBlaze platforms.
- Prevented calling of exception hooks for resets on OpenRISC.
- Made the discon test plugin compare hardware addesses transpated
with qemu_plugin_translate_vaddr when comparing addresses. Before
we'd use a crude bitmask.
Since v4:
- Fixed a typo in the documentation of the
qemu_plugin_vcpu_discon_cb_t function type (pointed out by Pierrick
Bouvier)
- Fixed a reference in the documentation of the
qemu_plugin_vcpu_discon_cb_t function type
- Added hooks for SuperH and TriCore targets
- Fixed typos in commit messages (pointed out by Daniel Henrique
Barboza)
Since v3 (RFC):
- Switched to shifting 1 notation for qemu_plugin_discon_type values
(as requested by Pierrick Bouvier)
- Added missing documentation of function parameters of function
pointer type qemu_plugin_vcpu_discon_cb_t
- Added missing documentation of function parameters of
qemu_plugin_register_vcpu_discon_cb
- Eliminated "to" argument from hooks called from target specific
code, i.e. qemu_plugin_vcpu_interrupt_cb and friends, determine "to"
address using CPUClass::get_pc
- Replaced comment declaring switch-case unreachable with
g_assert_not_reached()
- Call qemu_plugin_register_vcpu_discon_cb with QEMU_PLUGIN_DISCON_ALL
rather than QEMU_PLUGIN_DISCON_TRAPS in "traps" example plugin
- Take max_vcpus from qemu_info_t in "traps" example plugin, don't
determine it based on VCPU activation
- Added a description of the "traps" example plugin (as requested by
Pierrick Bouvier)
- Added section for the "traps" example plugin in documentation's
"Emulation" chapter
- Fixed messed-up switch-case in alpha_cpu_do_interrupt
- Added hooks for PA-RISC, x86, loongarch, Motorola 68000, MicroBlaze,
OpenRISC, Power PC, Renesas Xtreme, IBM System/390 and xtensa
targets.
- Made "discon" test plugin check PCs in vcpu_discon callback (as
requested by Pierrick Bouvier)
- Added parameter to "discon" test plugin for controlling which
address bits are compared to cope with TBs being used under
different virtual addresses
- Added parameter to "discon" test plugin for printing a full
instruction trace for debugging purposes
- Made "discon" test plugin abort by default on address mismatches
- Added test-cases for RISC-V
Since v2 (tcg-plugins: add hooks for interrupts, exceptions and traps):
- Switched from traps as core concept to more generic discontinuities
- Switched from semihosting to hostcall as term for emulated traps
- Added enumeration of events and dedicated callback type
- Make callback receive event type as well as origin and target PC
(as requested by Pierrick Bouvier)
- Combined registration functions for different traps into a single
one for all types of discontinuities (as requested by Pierrick
Bouvier)
- Migrated records in example plugin from fully pre-allocated to a
scoreboard (as suggested by Pierrick Bouvier)
- Handle PSCI calls as hostcall (as pointed out by Peter Maydell)
- Added hooks for ARM Cortex M arches (as pointed out by Peter
Maydell)
- Added hooks for Alpha targets
- Added hooks for MIPS targets
- Added a plugin for testing some of the interface behaviour
Since v1:
- Split the one callback into multiple callbacks
- Added a target-agnostic definition of the relevant event(s)
- Call hooks from architecture-code rather than accel/tcg/cpu-exec.c
- Added a plugin showcasing API usage
Julian Ganz (25):
plugins: add types for callbacks related to certain discontinuities
plugins: add API for registering discontinuity callbacks
plugins: add hooks for new discontinuity related callbacks
contrib/plugins: add plugin showcasing new dicontinuity related API
target/alpha: call plugin trap callbacks
target/arm: call plugin trap callbacks
target/avr: call plugin trap callbacks
target/hppa: call plugin trap callbacks
target/i386: call plugin trap callbacks
target/loongarch: call plugin trap callbacks
target/m68k: call plugin trap callbacks
target/microblaze: call plugin trap callbacks
target/mips: call plugin trap callbacks
target/openrisc: call plugin trap callbacks
target/ppc: call plugin trap callbacks
target/riscv: call plugin trap callbacks
target/rx: call plugin trap callbacks
target/s390x: call plugin trap callbacks
target/sh4: call plugin trap callbacks
target/sparc: call plugin trap callbacks
target/tricore: call plugin trap callbacks
target/xtensa: call plugin trap callbacks
tests: add plugin asserting correctness of discon event's to_pc
tests: add test for double-traps on rv64
tests: add test with interrupted memory accesses on rv64
contrib/plugins/meson.build | 3 +-
contrib/plugins/traps.c | 84 +++++++++
docs/about/emulation.rst | 8 +
include/qemu/plugin-event.h | 3 +
include/qemu/plugin.h | 13 ++
include/qemu/qemu-plugin.h | 60 +++++++
plugins/core.c | 57 ++++++
target/alpha/helper.c | 13 ++
target/arm/helper.c | 24 +++
target/arm/internals.h | 1 +
target/arm/tcg/m_helper.c | 5 +
target/avr/helper.c | 3 +
target/hppa/int_helper.c | 44 +++++
target/i386/tcg/excp_helper.c | 3 +
target/i386/tcg/seg_helper.c | 4 +
target/loongarch/cpu.c | 4 +
target/m68k/op_helper.c | 22 +++
target/microblaze/helper.c | 10 ++
target/mips/tcg/system/tlb_helper.c | 11 ++
target/openrisc/interrupt.c | 15 ++
target/ppc/excp_helper.c | 41 +++++
target/riscv/cpu_helper.c | 9 +
target/rx/helper.c | 12 ++
target/s390x/tcg/excp_helper.c | 8 +
target/sh4/helper.c | 4 +
target/sparc/int32_helper.c | 7 +
target/sparc/int64_helper.c | 10 ++
target/tricore/op_helper.c | 5 +
target/xtensa/exc_helper.c | 6 +
tests/tcg/plugins/discons.c | 210 ++++++++++++++++++++++
tests/tcg/plugins/meson.build | 2 +-
tests/tcg/riscv64/Makefile.softmmu-target | 12 ++
tests/tcg/riscv64/doubletrap.S | 73 ++++++++
tests/tcg/riscv64/interruptedmemory.S | 67 +++++++
34 files changed, 851 insertions(+), 2 deletions(-)
create mode 100644 contrib/plugins/traps.c
create mode 100644 tests/tcg/plugins/discons.c
create mode 100644 tests/tcg/riscv64/doubletrap.S
create mode 100644 tests/tcg/riscv64/interruptedmemory.S
--
2.49.1
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v6 01/25] plugins: add types for callbacks related to certain discontinuities
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
` (25 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Pierrick Bouvier, Richard Henderson
The plugin API allows registration of callbacks for a variety of VCPU
related events, such as VCPU reset, idle and resume. However, traps of
any kind, i.e. interrupts or exceptions, were previously not covered.
These kinds of events are arguably quite significant and usually go hand
in hand with a PC discontinuity. On most platforms, the discontinuity
also includes a transition from some "mode" to another. Thus, plugins
for the analysis of (virtualized) embedded systems may benefit from or
even require the possiblity to perform work on the occurance of an
interrupt or exception.
This change introduces the concept of such a discontinuity event in the
form of an enumeration. Currently only traps are covered. Specifically
we (loosely) define interrupts, exceptions and host calls across all
platforms. In addition, this change introduces a type to use for
callback functions related to such events. Since possible modes and the
enumeration of interupts and exceptions vary greatly between different
architectures, the callback type only receives the VCPU id, the type of
event as well as the old and new PC.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
include/qemu/plugin.h | 1 +
include/qemu/qemu-plugin.h | 44 ++++++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index f355c7cb8a..8cf20cd96f 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -59,6 +59,7 @@ union qemu_plugin_cb_sig {
qemu_plugin_udata_cb_t udata;
qemu_plugin_vcpu_simple_cb_t vcpu_simple;
qemu_plugin_vcpu_udata_cb_t vcpu_udata;
+ qemu_plugin_vcpu_discon_cb_t vcpu_discon;
qemu_plugin_vcpu_tb_trans_cb_t vcpu_tb_trans;
qemu_plugin_vcpu_mem_cb_t vcpu_mem;
qemu_plugin_vcpu_syscall_cb_t vcpu_syscall;
diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index c450106af1..08bf366e36 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -161,6 +161,50 @@ typedef void (*qemu_plugin_vcpu_simple_cb_t)(qemu_plugin_id_t id,
typedef void (*qemu_plugin_vcpu_udata_cb_t)(unsigned int vcpu_index,
void *userdata);
+
+/**
+ * enum qemu_plugin_discon_type - type of a (potential) PC discontinuity
+ *
+ * @QEMU_PLUGIN_DISCON_INTERRUPT: an interrupt, defined across all architectures
+ * as an asynchronous event, usually originating
+ * from outside the CPU
+ * @QEMU_PLUGIN_DISCON_EXCEPTION: an exception, defined across all architectures
+ * as a synchronous event in response to a
+ * specific instruction being executed
+ * @QEMU_PLUGIN_DISCON_HOSTCALL: a host call, functionally a special kind of
+ * exception that is not handled by code run by
+ * the vCPU but machinery outside the vCPU
+ * @QEMU_PLUGIN_DISCON_ALL: all types of disconinuity events currently covered
+ */
+enum qemu_plugin_discon_type {
+ QEMU_PLUGIN_DISCON_INTERRUPT = 1 << 0,
+ QEMU_PLUGIN_DISCON_EXCEPTION = 1 << 1,
+ QEMU_PLUGIN_DISCON_HOSTCALL = 1 << 2,
+ QEMU_PLUGIN_DISCON_ALL = -1
+};
+
+/**
+ * typedef qemu_plugin_vcpu_discon_cb_t - vcpu discontinuity callback
+ * @id: plugin ID
+ * @vcpu_index: the current vcpu context
+ * @type: the type of discontinuity
+ * @from_pc: the source of the discontinuity, e.g. the PC before the
+ * transition
+ * @to_pc: the PC pointing to the next instruction to be executed
+ *
+ * The exact semantics of @from_pc depends on the @type of discontinuity. For
+ * interrupts, @from_pc will point to the next instruction which would have
+ * been executed. For exceptions and host calls, @from_pc will point to the
+ * instruction that caused the exception or issued the host call. Note that
+ * in the case of exceptions, the instruction may not be retired and thus not
+ * observable via general instruction exec callbacks. The same may be the case
+ * for some host calls such as hypervisor call "exceptions".
+ */
+typedef void (*qemu_plugin_vcpu_discon_cb_t)(qemu_plugin_id_t id,
+ unsigned int vcpu_index,
+ enum qemu_plugin_discon_type type,
+ uint64_t from_pc, uint64_t to_pc);
+
/**
* qemu_plugin_uninstall() - Uninstall a plugin
* @id: this plugin's opaque ID
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 02/25] plugins: add API for registering discontinuity callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
2025-09-04 20:46 ` [PATCH v6 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
` (24 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Pierrick Bouvier, Richard Henderson,
Alex Bennée, Alexandre Iooss, Mahmoud Mandour
The plugin API allows registration of callbacks for a variety of VCPU
related events, such as VCPU reset, idle and resume. In addition to
those events, we recently defined discontinuity events, which include
traps.
This change introduces a function to register callbacks for these
events. We define one distinct plugin event type for each type of
discontinuity, granting fine control to plugins in term of which events
they receive.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
include/qemu/plugin-event.h | 3 +++
include/qemu/qemu-plugin.h | 16 ++++++++++++++++
plugins/core.c | 15 +++++++++++++++
3 files changed, 34 insertions(+)
diff --git a/include/qemu/plugin-event.h b/include/qemu/plugin-event.h
index 7056d8427b..1100dae212 100644
--- a/include/qemu/plugin-event.h
+++ b/include/qemu/plugin-event.h
@@ -20,6 +20,9 @@ enum qemu_plugin_event {
QEMU_PLUGIN_EV_VCPU_SYSCALL_RET,
QEMU_PLUGIN_EV_FLUSH,
QEMU_PLUGIN_EV_ATEXIT,
+ QEMU_PLUGIN_EV_VCPU_INTERRUPT,
+ QEMU_PLUGIN_EV_VCPU_EXCEPTION,
+ QEMU_PLUGIN_EV_VCPU_HOSTCALL,
QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */
};
diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index 08bf366e36..60de4fdd3f 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -281,6 +281,22 @@ QEMU_PLUGIN_API
void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id,
qemu_plugin_vcpu_simple_cb_t cb);
+/**
+ * qemu_plugin_register_vcpu_discon_cb() - register a discontinuity callback
+ * @id: plugin ID
+ * @type: types of discontinuities for which to call the callback
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU receives a discontinuity event
+ * of the specified type(s), after the vCPU was prepared to handle the event.
+ * Preparation entails updating the PC, usually to some interrupt handler or
+ * trap vector entry.
+ */
+QEMU_PLUGIN_API
+void qemu_plugin_register_vcpu_discon_cb(qemu_plugin_id_t id,
+ enum qemu_plugin_discon_type type,
+ qemu_plugin_vcpu_discon_cb_t cb);
+
/** struct qemu_plugin_tb - Opaque handle for a translation block */
struct qemu_plugin_tb;
/** struct qemu_plugin_insn - Opaque handle for a translated instruction */
diff --git a/plugins/core.c b/plugins/core.c
index c6e9ef1478..a04cb2392d 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -569,6 +569,21 @@ void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id,
plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_RESUME, cb);
}
+void qemu_plugin_register_vcpu_discon_cb(qemu_plugin_id_t id,
+ enum qemu_plugin_discon_type type,
+ qemu_plugin_vcpu_discon_cb_t cb)
+{
+ if (type & QEMU_PLUGIN_DISCON_INTERRUPT) {
+ plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INTERRUPT, cb);
+ }
+ if (type & QEMU_PLUGIN_DISCON_EXCEPTION) {
+ plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXCEPTION, cb);
+ }
+ if (type & QEMU_PLUGIN_DISCON_HOSTCALL) {
+ plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_HOSTCALL, cb);
+ }
+}
+
void qemu_plugin_register_flush_cb(qemu_plugin_id_t id,
qemu_plugin_simple_cb_t cb)
{
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
2025-09-04 20:46 ` [PATCH v6 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
2025-09-04 20:46 ` [PATCH v6 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-22 11:34 ` Philippe Mathieu-Daudé
2025-09-04 20:46 ` [PATCH v6 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API Julian Ganz
` (23 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Alex Bennée, Alexandre Iooss, Mahmoud Mandour,
Pierrick Bouvier
The plugin API allows registration of callbacks for a variety of VCPU
related events, such as VCPU reset, idle and resume. In addition, we
recently introduced API for registering callbacks for discontinuity
events, specifically for interrupts, exceptions and host calls.
This change introduces the corresponding hooks called from target
specific code inside qemu.
Signed-off-by: Julian Ganz <neither@nut.email>
---
include/qemu/plugin.h | 12 ++++++++++++
plugins/core.c | 42 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index 8cf20cd96f..cea0a68858 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -161,6 +161,9 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu);
void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb);
void qemu_plugin_vcpu_idle_cb(CPUState *cpu);
void qemu_plugin_vcpu_resume_cb(CPUState *cpu);
+void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from);
+void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from);
+void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from);
void
qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1,
uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5,
@@ -258,6 +261,15 @@ static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
{ }
+static inline void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
+{ }
+
+static inline void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
+{ }
+
+static inline void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
+{ }
+
static inline void
qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6,
diff --git a/plugins/core.c b/plugins/core.c
index a04cb2392d..1f0ddebcbf 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -105,6 +105,30 @@ static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev)
}
}
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
+static void plugin_vcpu_cb__discon(CPUState *cpu,
+ enum qemu_plugin_event ev,
+ enum qemu_plugin_discon_type type,
+ uint64_t from)
+{
+ struct qemu_plugin_cb *cb, *next;
+ uint64_t to = cpu->cc->get_pc(cpu);
+
+ if (cpu->cpu_index < plugin.num_vcpus) {
+ /* iterate safely; plugins might uninstall themselves at any time */
+ QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
+ qemu_plugin_vcpu_discon_cb_t func = cb->f.vcpu_discon;
+
+ func(cb->ctx->id, cpu->cpu_index, type, from, to);
+ }
+ }
+}
+
/*
* Disable CFI checks.
* The callback function has been loaded from an external library so we do not
@@ -557,6 +581,24 @@ void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
}
}
+void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
+{
+ plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_INTERRUPT,
+ QEMU_PLUGIN_DISCON_INTERRUPT, from);
+}
+
+void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
+{
+ plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_EXCEPTION,
+ QEMU_PLUGIN_DISCON_EXCEPTION, from);
+}
+
+void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
+{
+ plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_HOSTCALL,
+ QEMU_PLUGIN_DISCON_HOSTCALL, from);
+}
+
void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id,
qemu_plugin_vcpu_simple_cb_t cb)
{
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (2 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 05/25] target/alpha: call plugin trap callbacks Julian Ganz
` (22 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Pierrick Bouvier, Alex Bennée, Alexandre Iooss,
Mahmoud Mandour
We recently introduced new plugin API for registration of discontinuity
related callbacks. This change introduces a minimal plugin showcasing
the new API. It simply counts the occurances of interrupts, exceptions
and host calls per CPU and reports the counts when exitting.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
contrib/plugins/meson.build | 3 +-
contrib/plugins/traps.c | 84 +++++++++++++++++++++++++++++++++++++
docs/about/emulation.rst | 8 ++++
3 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 contrib/plugins/traps.c
diff --git a/contrib/plugins/meson.build b/contrib/plugins/meson.build
index 1876bc7843..85d3520f0c 100644
--- a/contrib/plugins/meson.build
+++ b/contrib/plugins/meson.build
@@ -1,5 +1,6 @@
contrib_plugins = ['bbv', 'cache', 'cflow', 'drcov', 'execlog', 'hotblocks',
- 'hotpages', 'howvec', 'hwprofile', 'ips', 'stoptrigger']
+ 'hotpages', 'howvec', 'hwprofile', 'ips', 'stoptrigger',
+ 'traps']
if host_os != 'windows'
# lockstep uses socket.h
contrib_plugins += 'lockstep'
diff --git a/contrib/plugins/traps.c b/contrib/plugins/traps.c
new file mode 100644
index 0000000000..c8672d8b1b
--- /dev/null
+++ b/contrib/plugins/traps.c
@@ -0,0 +1,84 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2025, Julian Ganz <neither@nut.email>
+ *
+ * Traps - count traps
+ *
+ * Count the number of interrupts (asyncronous events), exceptions (synchronous
+ * events) and host calls (e.g. semihosting) per cpu and report those counts on
+ * exit.
+ */
+
+#include <stdio.h>
+
+#include <qemu-plugin.h>
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+typedef struct {
+ uint64_t interrupts;
+ uint64_t exceptions;
+ uint64_t hostcalls;
+} TrapCounters;
+
+static struct qemu_plugin_scoreboard *traps;
+
+static void vcpu_discon(qemu_plugin_id_t id, unsigned int vcpu_index,
+ enum qemu_plugin_discon_type type, uint64_t from_pc,
+ uint64_t to_pc)
+{
+ TrapCounters *rec = qemu_plugin_scoreboard_find(traps, vcpu_index);
+ switch (type) {
+ case QEMU_PLUGIN_DISCON_INTERRUPT:
+ rec->interrupts++;
+ break;
+ case QEMU_PLUGIN_DISCON_EXCEPTION:
+ rec->exceptions++;
+ break;
+ case QEMU_PLUGIN_DISCON_HOSTCALL:
+ rec->hostcalls++;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+ g_autoptr(GString) report;
+ report = g_string_new("VCPU, interrupts, exceptions, hostcalls\n");
+ int max_vcpus = qemu_plugin_num_vcpus();
+ int vcpu;
+
+ for (vcpu = 0; vcpu < max_vcpus; vcpu++) {
+ TrapCounters *rec = qemu_plugin_scoreboard_find(traps, vcpu);
+ g_string_append_printf(report,
+ "% 4d, % 10"PRId64", % 10"PRId64", % 10"PRId64
+ "\n", vcpu, rec->interrupts, rec->exceptions,
+ rec->hostcalls);
+ }
+
+ qemu_plugin_outs(report->str);
+ qemu_plugin_scoreboard_free(traps);
+}
+
+QEMU_PLUGIN_EXPORT
+int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
+ int argc, char **argv)
+{
+ if (!info->system_emulation) {
+ fputs("trap plugin can only be used in system emulation mode.\n",
+ stderr);
+ return -1;
+ }
+
+ traps = qemu_plugin_scoreboard_new(sizeof(TrapCounters));
+
+ qemu_plugin_register_vcpu_discon_cb(id, QEMU_PLUGIN_DISCON_ALL,
+ vcpu_discon);
+
+ qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
+
+ return 0;
+}
diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst
index 456d01d5b0..fb99563c04 100644
--- a/docs/about/emulation.rst
+++ b/docs/about/emulation.rst
@@ -816,6 +816,14 @@ This plugin can limit the number of Instructions Per Second that are executed::
The lower the number the more accurate time will be, but the less efficient the plugin.
Defaults to ips/10
+Count traps
+...........
+
+``contrib/plugins/traps.c``
+
+This plugin counts the number of interrupts (asyncronous events), exceptions
+(synchronous events) and host calls (e.g. semihosting) per cpu.
+
Other emulation features
------------------------
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 05/25] target/alpha: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (3 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 06/25] target/arm: " Julian Ganz
` (21 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Richard Henderson
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for Alpha targets.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/alpha/helper.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index 096eac3445..a9af52a928 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -27,6 +27,7 @@
#include "exec/helper-proto.h"
#include "qemu/qemu-print.h"
#include "system/memory.h"
+#include "qemu/plugin.h"
#define CONVERT_BIT(X, SRC, DST) \
@@ -328,6 +329,7 @@ void alpha_cpu_do_interrupt(CPUState *cs)
{
CPUAlphaState *env = cpu_env(cs);
int i = cs->exception_index;
+ uint64_t last_pc = env->pc;
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static int count;
@@ -431,6 +433,17 @@ void alpha_cpu_do_interrupt(CPUState *cs)
/* Switch to PALmode. */
env->flags |= ENV_FLAG_PAL_MODE;
+
+ switch (i) {
+ case EXCP_SMP_INTERRUPT:
+ case EXCP_CLK_INTERRUPT:
+ case EXCP_DEV_INTERRUPT:
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ break;
+ }
}
bool alpha_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 06/25] target/arm: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (4 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 05/25] target/alpha: call plugin trap callbacks Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 07/25] target/avr: " Julian Ganz
` (20 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Peter Maydell, open list:ARM TCG CPUs
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for ARM (and Aarch64) targets. We decided to
treat the (V)IRQ, (VI/VF)NMI, (V)FIQ and VSERR exceptions as interrupts
since they are, presumably, async in nature.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/arm/helper.c | 24 ++++++++++++++++++++++++
target/arm/internals.h | 1 +
target/arm/tcg/m_helper.c | 5 +++++
3 files changed, 30 insertions(+)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 19637e7301..4812b30d64 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -34,6 +34,7 @@
#endif
#include "cpregs.h"
#include "target/arm/gtimer.h"
+#include "qemu/plugin.h"
#define HELPER_H "tcg/helper.h"
#include "exec/helper-proto.h.inc"
@@ -8585,6 +8586,24 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
}
}
+void arm_do_plugin_vcpu_discon_cb(CPUState *cs, uint64_t from)
+{
+ switch (cs->exception_index) {
+ case EXCP_IRQ:
+ case EXCP_VIRQ:
+ case EXCP_NMI:
+ case EXCP_VINMI:
+ case EXCP_FIQ:
+ case EXCP_VFIQ:
+ case EXCP_VFNMI:
+ case EXCP_VSERR:
+ qemu_plugin_vcpu_interrupt_cb(cs, from);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, from);
+ }
+}
+
static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
{
/*
@@ -9251,6 +9270,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
unsigned int new_el = env->exception.target_el;
+ uint64_t last_pc = cs->cc->get_pc(cs);
assert(!arm_feature(env, ARM_FEATURE_M));
@@ -9267,6 +9287,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
if (tcg_enabled() && arm_is_psci_call(cpu, cs->exception_index)) {
arm_handle_psci_call(cpu);
qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");
+ qemu_plugin_vcpu_hostcall_cb(cs, last_pc);
return;
}
@@ -9278,6 +9299,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
#ifdef CONFIG_TCG
if (cs->exception_index == EXCP_SEMIHOST) {
tcg_handle_semihosting(cs);
+ qemu_plugin_vcpu_hostcall_cb(cs, last_pc);
return;
}
#endif
@@ -9303,6 +9325,8 @@ void arm_cpu_do_interrupt(CPUState *cs)
if (!kvm_enabled()) {
cpu_set_interrupt(cs, CPU_INTERRUPT_EXITTB);
}
+
+ arm_do_plugin_vcpu_discon_cb(cs, last_pc);
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/arm/internals.h b/target/arm/internals.h
index f5a1e75db3..369ec2912b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -373,6 +373,7 @@ static inline int r14_bank_number(int mode)
void arm_cpu_register(const ARMCPUInfo *info);
+void arm_do_plugin_vcpu_discon_cb(CPUState *cs, uint64_t from);
void register_cp_regs_for_features(ARMCPU *cpu);
void init_cpreg_list(ARMCPU *cpu);
diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
index 28307b5615..31d9a59ed6 100644
--- a/target/arm/tcg/m_helper.c
+++ b/target/arm/tcg/m_helper.c
@@ -23,6 +23,7 @@
#if !defined(CONFIG_USER_ONLY)
#include "hw/intc/armv7m_nvic.h"
#endif
+#include "qemu/plugin.h"
static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
uint32_t reg, uint32_t val)
@@ -2194,6 +2195,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
CPUARMState *env = &cpu->env;
uint32_t lr;
bool ignore_stackfaults;
+ uint64_t last_pc = env->regs[15];
arm_log_exception(cs);
@@ -2361,6 +2363,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
g_assert_not_reached();
#endif
env->regs[15] += env->thumb ? 2 : 4;
+ qemu_plugin_vcpu_hostcall_cb(cs, last_pc);
return;
case EXCP_BKPT:
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
@@ -2427,6 +2430,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
ignore_stackfaults = v7m_push_stack(cpu);
v7m_exception_taken(cpu, lr, false, ignore_stackfaults);
+
+ arm_do_plugin_vcpu_discon_cb(cs, last_pc);
}
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 07/25] target/avr: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (5 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 06/25] target/arm: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 08/25] target/hppa: " Julian Ganz
` (19 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Richard Henderson, Michael Rolnik
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places the hook for AVR targets. That architecture appears
to only know interrupts.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/avr/helper.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/target/avr/helper.c b/target/avr/helper.c
index b9cd6d5ef2..f28cc08637 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -28,6 +28,7 @@
#include "exec/target_page.h"
#include "accel/tcg/cpu-ldst.h"
#include "exec/helper-proto.h"
+#include "qemu/plugin.h"
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
@@ -102,6 +103,8 @@ void avr_cpu_do_interrupt(CPUState *cs)
env->sregI = 0; /* clear Global Interrupt Flag */
cs->exception_index = -1;
+
+ qemu_plugin_vcpu_interrupt_cb(cs, ret);
}
hwaddr avr_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 08/25] target/hppa: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (6 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 07/25] target/avr: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-22 11:38 ` Philippe Mathieu-Daudé
2025-09-04 20:46 ` [PATCH v6 09/25] target/i386: " Julian Ganz
` (18 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Richard Henderson, Helge Deller
We identified a number of exceptions as interrupts, and we assume any
unknown exception is also an interrupt. HPPA appears to not have any
form of host-call.
This change places the hook for PA-RISC targets.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/hppa/int_helper.c | 44 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 191ae19404..0742990c90 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -24,6 +24,7 @@
#include "exec/helper-proto.h"
#include "hw/core/cpu.h"
#include "hw/hppa/hppa_hardware.h"
+#include "qemu/plugin.h"
static void eval_interrupt(HPPACPU *cpu)
{
@@ -95,6 +96,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
CPUHPPAState *env = &cpu->env;
int i = cs->exception_index;
uint64_t old_psw, old_gva_offset_mask;
+ uint64_t last_pc = cs->cc->get_pc(cs);
/* As documented in pa2.0 -- interruption handling. */
/* step 1 */
@@ -212,6 +214,48 @@ void hppa_cpu_do_interrupt(CPUState *cs)
env->iasq_f = 0;
env->iasq_b = 0;
+ switch (i) {
+ case EXCP_HPMC:
+ case EXCP_POWER_FAIL:
+ case EXCP_RC:
+ case EXCP_EXT_INTERRUPT:
+ case EXCP_LPMC:
+ case EXCP_PER_INTERRUPT:
+ case EXCP_TOC:
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ break;
+ case EXCP_ITLB_MISS:
+ case EXCP_IMP:
+ case EXCP_ILL:
+ case EXCP_BREAK:
+ case EXCP_PRIV_OPR:
+ case EXCP_PRIV_REG:
+ case EXCP_OVERFLOW:
+ case EXCP_COND:
+ case EXCP_ASSIST:
+ case EXCP_DTLB_MISS:
+ case EXCP_NA_ITLB_MISS:
+ case EXCP_NA_DTLB_MISS:
+ case EXCP_DMP:
+ case EXCP_DMB:
+ case EXCP_TLB_DIRTY:
+ case EXCP_PAGE_REF:
+ case EXCP_ASSIST_EMU:
+ case EXCP_HPT:
+ case EXCP_LPT:
+ case EXCP_TB:
+ case EXCP_DMAR:
+ case EXCP_DMPI:
+ case EXCP_UNALIGN:
+ case EXCP_SYSCALL:
+ case EXCP_SYSCALL_LWS:
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ break;
+ default:
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ break;
+ }
+
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static const char * const names[] = {
[EXCP_HPMC] = "high priority machine check",
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 09/25] target/i386: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (7 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 08/25] target/hppa: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 10/25] target/loongarch: " Julian Ganz
` (17 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Paolo Bonzini, Richard Henderson, Eduardo Habkost
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places the hook for x86 targets.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/i386/tcg/excp_helper.c | 3 +++
target/i386/tcg/seg_helper.c | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c
index 6fb8036d98..32f2784e92 100644
--- a/target/i386/tcg/excp_helper.c
+++ b/target/i386/tcg/excp_helper.c
@@ -23,6 +23,7 @@
#include "system/runstate.h"
#include "exec/helper-proto.h"
#include "helper-tcg.h"
+#include "qemu/plugin.h"
G_NORETURN void helper_raise_interrupt(CPUX86State *env, int intno,
int next_eip_addend)
@@ -93,6 +94,7 @@ void raise_interrupt2(CPUX86State *env, int intno,
uintptr_t retaddr)
{
CPUState *cs = env_cpu(env);
+ uint64_t last_pc = env->eip + env->segs[R_CS].base;
if (!is_int) {
cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno,
@@ -106,6 +108,7 @@ void raise_interrupt2(CPUX86State *env, int intno,
env->error_code = error_code;
env->exception_is_int = is_int;
env->exception_next_eip = env->eip + next_eip_addend;
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
cpu_loop_exit_restore(cs, retaddr);
}
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 071f3fbd83..db635aceee 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -29,6 +29,7 @@
#include "seg_helper.h"
#include "access.h"
#include "tcg-cpu.h"
+#include "qemu/plugin.h"
#ifdef TARGET_X86_64
#define SET_ESP(val, sp_mask) \
@@ -1192,6 +1193,7 @@ void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
int error_code, target_ulong next_eip, int is_hw)
{
CPUX86State *env = &cpu->env;
+ uint64_t last_pc = env->eip + env->segs[R_CS].base;
if (qemu_loglevel_mask(CPU_LOG_INT)) {
if ((env->cr[0] & CR0_PE_MASK)) {
@@ -1263,6 +1265,8 @@ void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
event_inj & ~SVM_EVTINJ_VALID);
}
#endif
+
+ qemu_plugin_vcpu_interrupt_cb(CPU(cpu), last_pc);
}
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 10/25] target/loongarch: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (8 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 09/25] target/i386: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 11/25] target/m68k: " Julian Ganz
` (16 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Richard Henderson, Song Gao
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for loongarch targets. This architecture
has one special "exception" for interrupts and no host calls.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/loongarch/cpu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 55ee317bf2..8a8b6d8eaf 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -32,6 +32,7 @@
#include "accel/tcg/cpu-ldst.h"
#include "accel/tcg/cpu-ops.h"
#include "tcg/tcg.h"
+#include "qemu/plugin.h"
#endif
#include "tcg/tcg_loongarch.h"
@@ -172,6 +173,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
int cause = -1;
bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+ uint64_t last_pc = env->pc;
if (cs->exception_index != EXCCODE_INT) {
qemu_log_mask(CPU_LOG_INT,
@@ -282,6 +284,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
__func__, env->pc, env->CSR_ERA,
cause, env->CSR_BADV, env->CSR_DERA, vector,
env->CSR_ECFG, env->CSR_ESTAT);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
} else {
if (tlbfill) {
set_pc(env, env->CSR_TLBRENTRY);
@@ -300,6 +303,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
tlbfill ? env->CSR_TLBRBADV : env->CSR_BADV,
env->CSR_BADI, env->gpr[11], cs->cpu_index,
env->CSR_ASID);
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
}
cs->exception_index = -1;
}
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 11/25] target/m68k: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (9 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 10/25] target/loongarch: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 12/25] target/microblaze: " Julian Ganz
` (15 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Laurent Vivier
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for Motorola 68000 targets.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/m68k/op_helper.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index f29ae12af8..e9c20a8e03 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -22,6 +22,7 @@
#include "exec/helper-proto.h"
#include "accel/tcg/cpu-ldst.h"
#include "semihosting/semihost.h"
+#include "qemu/plugin.h"
#if !defined(CONFIG_USER_ONLY)
@@ -183,6 +184,21 @@ static const char *m68k_exception_name(int index)
return "Unassigned";
}
+static void do_plugin_vcpu_interrupt_cb(CPUState *cs, uint64_t from)
+{
+ switch (cs->exception_index) {
+ case EXCP_SPURIOUS ... EXCP_INT_LEVEL_7:
+ qemu_plugin_vcpu_interrupt_cb(cs, from);
+ break;
+ case EXCP_SEMIHOSTING:
+ qemu_plugin_vcpu_hostcall_cb(cs, from);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, from);
+ break;
+ }
+}
+
static void cf_interrupt_all(CPUM68KState *env, int is_hw)
{
CPUState *cs = env_cpu(env);
@@ -203,6 +219,7 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw)
return;
case EXCP_SEMIHOSTING:
do_m68k_semihosting(env, env->dregs[0]);
+ qemu_plugin_vcpu_hostcall_cb(cs, retaddr);
return;
}
}
@@ -239,6 +256,8 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw)
env->aregs[7] = sp;
/* Jump to vector. */
env->pc = cpu_ldl_mmuidx_ra(env, env->vbr + vector, MMU_KERNEL_IDX, 0);
+
+ do_plugin_vcpu_interrupt_cb(cs, retaddr);
}
static inline void do_stack_frame(CPUM68KState *env, uint32_t *sp,
@@ -277,6 +296,7 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
uint32_t sp;
uint32_t vector;
uint16_t sr, oldsr;
+ uint64_t last_pc = env->pc;
if (!is_hw) {
switch (cs->exception_index) {
@@ -417,6 +437,8 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
env->aregs[7] = sp;
/* Jump to vector. */
env->pc = cpu_ldl_mmuidx_ra(env, env->vbr + vector, MMU_KERNEL_IDX, 0);
+
+ do_plugin_vcpu_interrupt_cb(cs, last_pc);
}
static void do_interrupt_all(CPUM68KState *env, int is_hw)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 12/25] target/microblaze: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (10 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 11/25] target/m68k: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 13/25] target/mips: " Julian Ganz
` (14 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Edgar E. Iglesias
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places the hook for MicroBlaze targets. This architecture
has one special "exception" for interrupts and no host calls.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/microblaze/helper.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
index ef0e2f973f..d66eab6e4b 100644
--- a/target/microblaze/helper.c
+++ b/target/microblaze/helper.c
@@ -27,6 +27,7 @@
#include "qemu/host-utils.h"
#include "exec/log.h"
#include "exec/helper-proto.h"
+#include "qemu/plugin.h"
G_NORETURN
@@ -35,6 +36,7 @@ static void mb_unaligned_access_internal(CPUState *cs, uint64_t addr,
{
CPUMBState *env = cpu_env(cs);
uint32_t esr, iflags;
+ uint64_t last_pc = env->pc;
/* Recover the pc and iflags from the corresponding insn_start. */
cpu_restore_state(cs, retaddr);
@@ -54,6 +56,7 @@ static void mb_unaligned_access_internal(CPUState *cs, uint64_t addr,
env->ear = addr;
env->esr = esr;
cs->exception_index = EXCP_HW_EXCP;
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
cpu_loop_exit(cs);
}
@@ -152,6 +155,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
CPUMBState *env = &cpu->env;
uint32_t t, msr = mb_cpu_read_msr(env);
bool set_esr;
+ uint64_t last_pc = env->pc;
/* IMM flag cannot propagate across a branch and into the dslot. */
assert((env->iflags & (D_FLAG | IMM_FLAG)) != (D_FLAG | IMM_FLAG));
@@ -256,6 +260,12 @@ void mb_cpu_do_interrupt(CPUState *cs)
env->res_addr = RES_ADDR_NONE;
env->iflags = 0;
+ if (cs->exception_index == EXCP_IRQ) {
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ } else {
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ }
+
if (!set_esr) {
qemu_log_mask(CPU_LOG_INT,
" to pc=%08x msr=%08x\n", env->pc, msr);
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 13/25] target/mips: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (11 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 12/25] target/microblaze: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-22 11:45 ` Philippe Mathieu-Daudé
2025-09-04 20:46 ` [PATCH v6 14/25] target/openrisc: " Julian Ganz
` (13 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Richard Henderson, Philippe Mathieu-Daudé,
Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for MIPS targets. We consider the exceptions
NMI and EXT_INTERRUPT to be asynchronous interrupts rather than
exceptions.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/mips/tcg/system/tlb_helper.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/target/mips/tcg/system/tlb_helper.c b/target/mips/tcg/system/tlb_helper.c
index 1e8901556d..566924b079 100644
--- a/target/mips/tcg/system/tlb_helper.c
+++ b/target/mips/tcg/system/tlb_helper.c
@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
+#include "qemu/plugin.h"
#include "cpu.h"
#include "internal.h"
@@ -1034,6 +1035,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
bool update_badinstr = 0;
target_ulong offset;
int cause = -1;
+ uint64_t last_pc = env->active_tc.PC;
if (qemu_loglevel_mask(CPU_LOG_INT)
&& cs->exception_index != EXCP_EXT_INTERRUPT) {
@@ -1052,6 +1054,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
cs->exception_index = EXCP_NONE;
mips_semihosting(env);
env->active_tc.PC += env->error_code;
+ qemu_plugin_vcpu_hostcall_cb(cs, last_pc);
return;
case EXCP_DSS:
env->CP0_Debug |= 1 << CP0DB_DSS;
@@ -1336,6 +1339,14 @@ void mips_cpu_do_interrupt(CPUState *cs)
env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
env->CP0_DEPC);
}
+ switch (cs->exception_index) {
+ case EXCP_NMI:
+ case EXCP_EXT_INTERRUPT:
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ }
cs->exception_index = EXCP_NONE;
}
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 14/25] target/openrisc: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (12 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 13/25] target/mips: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 15/25] target/ppc: " Julian Ganz
` (12 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Stafford Horne
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for OpenRISC targets. We treat anything other
than resets, timer and device interrupts as exceptions.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/openrisc/interrupt.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 486823094c..d357aaa7da 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -25,11 +25,13 @@
#ifndef CONFIG_USER_ONLY
#include "hw/loader.h"
#endif
+#include "qemu/plugin.h"
void openrisc_cpu_do_interrupt(CPUState *cs)
{
CPUOpenRISCState *env = cpu_env(cs);
int exception = cs->exception_index;
+ uint64_t last_pc = env->pc;
env->epcr = env->pc;
@@ -98,6 +100,19 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
}
+ switch (exception) {
+ case EXCP_RESET:
+ /* Resets are already exposed to plugins through a dedicated callback */
+ break;
+ case EXCP_TICK:
+ case EXCP_INT:
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ break;
+ }
+
cs->exception_index = -1;
}
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 15/25] target/ppc: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (13 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 14/25] target/openrisc: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 16/25] target/riscv: " Julian Ganz
` (11 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Nicholas Piggin, Chinmay Rath,
open list:PowerPC TCG CPUs
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for Power PC targets.
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/ppc/excp_helper.c | 41 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 1efdc4066e..be0596e41b 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -27,6 +27,7 @@
#include "internal.h"
#include "helper_regs.h"
#include "hw/ppc/ppc.h"
+#include "qemu/plugin.h"
#include "trace.h"
@@ -404,11 +405,31 @@ static void powerpc_mcheck_checkstop(CPUPPCState *env)
powerpc_checkstop(env, "machine check with MSR[ME]=0");
}
+static void powerpc_do_plugin_vcpu_interrupt_cb(CPUState *cs, int excp,
+ uint64_t from)
+{
+ switch (excp) {
+ case POWERPC_EXCP_NONE:
+ break;
+ case POWERPC_EXCP_FIT:
+ case POWERPC_EXCP_WDT:
+ case POWERPC_EXCP_PIT:
+ case POWERPC_EXCP_SMI:
+ case POWERPC_EXCP_PERFM:
+ case POWERPC_EXCP_THERM:
+ qemu_plugin_vcpu_interrupt_cb(cs, from);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, from);
+ }
+}
+
static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
int srr0 = SPR_SRR0, srr1 = SPR_SRR1;
+ uint64_t last_pc = env->nip;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -456,6 +477,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
trace_ppc_excp_fp_ignore();
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_exception_cb(env_cpu(env), last_pc);
return;
}
env->spr[SPR_40x_ESR] = ESR_FP;
@@ -510,12 +532,14 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
env->spr[srr0] = env->nip;
env->spr[srr1] = msr;
powerpc_set_excp_state(cpu, vector, new_msr);
+ powerpc_do_plugin_vcpu_interrupt_cb(env_cpu(env), excp, last_pc);
}
static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
+ uint64_t last_pc = env->nip;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -567,6 +591,7 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
trace_ppc_excp_fp_ignore();
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_exception_cb(env_cpu(env), last_pc);
return;
}
/*
@@ -653,12 +678,14 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
env->spr[SPR_SRR0] = env->nip;
env->spr[SPR_SRR1] = msr;
powerpc_set_excp_state(cpu, vector, new_msr);
+ powerpc_do_plugin_vcpu_interrupt_cb(env_cpu(env), excp, last_pc);
}
static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
+ uint64_t last_pc = env->nip;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -708,6 +735,7 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
trace_ppc_excp_fp_ignore();
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_exception_cb(env_cpu(env), last_pc);
return;
}
/*
@@ -758,6 +786,7 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
if (lev == 1 && cpu->vhyp) {
cpu->vhyp_class->hypercall(cpu->vhyp, cpu);
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_hostcall_cb(env_cpu(env), last_pc);
return;
}
@@ -803,12 +832,14 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
env->spr[SPR_SRR0] = env->nip;
env->spr[SPR_SRR1] = msr;
powerpc_set_excp_state(cpu, vector, new_msr);
+ powerpc_do_plugin_vcpu_interrupt_cb(env_cpu(env), excp, last_pc);
}
static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
+ uint64_t last_pc = env->nip;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -858,6 +889,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
trace_ppc_excp_fp_ignore();
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_exception_cb(env_cpu(env), last_pc);
return;
}
/*
@@ -908,6 +940,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
if (lev == 1 && cpu->vhyp) {
cpu->vhyp_class->hypercall(cpu->vhyp, cpu);
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_hostcall_cb(env_cpu(env), last_pc);
return;
}
@@ -947,6 +980,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
env->spr[SPR_SRR0] = env->nip;
env->spr[SPR_SRR1] = msr;
powerpc_set_excp_state(cpu, vector, new_msr);
+ powerpc_do_plugin_vcpu_interrupt_cb(env_cpu(env), excp, last_pc);
}
static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
@@ -954,6 +988,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
int srr0 = SPR_SRR0, srr1 = SPR_SRR1;
+ uint64_t last_pc = env->nip;
/*
* Book E does not play games with certain bits of xSRR1 being MSR save
@@ -1025,6 +1060,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
trace_ppc_excp_fp_ignore();
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_exception_cb(env_cpu(env), last_pc);
return;
}
/*
@@ -1133,6 +1169,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
env->spr[srr0] = env->nip;
env->spr[srr1] = msr;
powerpc_set_excp_state(cpu, vector, new_msr);
+ powerpc_do_plugin_vcpu_interrupt_cb(env_cpu(env), excp, last_pc);
}
/*
@@ -1254,6 +1291,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
int srr0 = SPR_SRR0, srr1 = SPR_SRR1, lev = -1;
+ uint64_t last_pc = env->nip;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -1353,6 +1391,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
trace_ppc_excp_fp_ignore();
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_exception_cb(env_cpu(env), last_pc);
return;
}
/*
@@ -1397,6 +1436,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
if (lev == 1 && books_vhyp_handles_hcall(cpu)) {
cpu->vhyp_class->hypercall(cpu->vhyp, cpu);
powerpc_reset_excp_state(cpu);
+ qemu_plugin_vcpu_hostcall_cb(env_cpu(env), last_pc);
return;
}
if (env->insns_flags2 & PPC2_ISA310) {
@@ -1543,6 +1583,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
powerpc_set_excp_state(cpu, vector, new_msr);
}
+ powerpc_do_plugin_vcpu_interrupt_cb(env_cpu(env), excp, last_pc);
}
#else
static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 16/25] target/riscv: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (14 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 15/25] target/ppc: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 17/25] target/rx: " Julian Ganz
` (10 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Daniel Henrique Barboza, Alistair Francis,
Palmer Dabbelt, Weiwei Li, Liu Zhiwei, open list:RISC-V TCG CPUs
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for RISC-V targets.
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/riscv/cpu_helper.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 3479a62cc7..10a10dcd90 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -36,6 +36,7 @@
#include "cpu_bits.h"
#include "debug.h"
#include "pmp.h"
+#include "qemu/plugin.h"
int riscv_env_mmu_index(CPURISCVState *env, bool ifetch)
{
@@ -2176,6 +2177,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
const bool prev_virt = env->virt_enabled;
const target_ulong prev_priv = env->priv;
+ uint64_t last_pc = env->pc;
target_ulong tval = 0;
target_ulong tinst = 0;
target_ulong htval = 0;
@@ -2198,6 +2200,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
case RISCV_EXCP_SEMIHOST:
do_common_semihosting(cs);
env->pc += 4;
+ qemu_plugin_vcpu_hostcall_cb(cs, last_pc);
return;
#endif
case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
@@ -2467,6 +2470,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
prev_priv, prev_virt);
}
+ if (async) {
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ } else {
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ }
+
/*
* Interrupt/exception/trap delivery is asynchronous event and as per
* zicfilp spec CPU should clear up the ELP state. No harm in clearing
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 17/25] target/rx: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (15 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 16/25] target/riscv: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-07 14:20 ` yoshinori.sato
2025-09-04 20:46 ` [PATCH v6 18/25] target/s390x: " Julian Ganz
` (9 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Richard Henderson, Yoshinori Sato
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for Renesas Xtreme targets.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/rx/helper.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/target/rx/helper.c b/target/rx/helper.c
index ce003af421..054bfdff57 100644
--- a/target/rx/helper.c
+++ b/target/rx/helper.c
@@ -22,6 +22,7 @@
#include "exec/log.h"
#include "accel/tcg/cpu-ldst.h"
#include "hw/irq.h"
+#include "qemu/plugin.h"
void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte)
{
@@ -46,6 +47,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
CPURXState *env = cpu_env(cs);
int do_irq = cpu_test_interrupt(cs, INT_FLAGS);
uint32_t save_psw;
+ uint64_t last_pc = env->pc;
env->in_sleep = 0;
@@ -65,6 +67,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
env->psw_ipl = 15;
cs->interrupt_request &= ~CPU_INTERRUPT_FIR;
qemu_set_irq(env->ack, env->ack_irq);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n");
} else if (do_irq & CPU_INTERRUPT_HARD) {
env->isp -= 4;
@@ -75,6 +78,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
env->psw_ipl = env->ack_ipl;
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
qemu_set_irq(env->ack, env->ack_irq);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
qemu_log_mask(CPU_LOG_INT,
"interrupt 0x%02x raised\n", env->ack_irq);
}
@@ -92,6 +96,14 @@ void rx_cpu_do_interrupt(CPUState *cs)
} else {
env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
}
+
+ if (vec == 30) {
+ /* Non-maskable interrupt */
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
+ } else {
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
+ }
+
switch (vec) {
case 20:
expname = "privilege violation";
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 18/25] target/s390x: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (16 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 17/25] target/rx: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 19/25] target/sh4: " Julian Ganz
` (8 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, David Hildenbrand, Richard Henderson,
Ilya Leoshkevich, Thomas Huth, open list:S390 TCG CPUs
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for IBM System/390 targets. We treat "program
interrupts" and service calls as exceptions. We treat external and io
"exceptions" as well as resets as interrupts.
Acked-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/s390x/tcg/excp_helper.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
index e4c75d0ce0..b7e7a4deff 100644
--- a/target/s390x/tcg/excp_helper.c
+++ b/target/s390x/tcg/excp_helper.c
@@ -34,6 +34,7 @@
#include "hw/s390x/s390_flic.h"
#include "hw/boards.h"
#endif
+#include "qemu/plugin.h"
G_NORETURN void tcg_s390_program_interrupt(CPUS390XState *env,
uint32_t code, uintptr_t ra)
@@ -499,6 +500,7 @@ void s390_cpu_do_interrupt(CPUState *cs)
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
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);
@@ -528,21 +530,27 @@ try_deliver:
switch (cs->exception_index) {
case EXCP_PGM:
do_program_interrupt(env);
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
break;
case EXCP_SVC:
do_svc_interrupt(env);
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
break;
case EXCP_EXT:
do_ext_interrupt(env);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
break;
case EXCP_IO:
do_io_interrupt(env);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
break;
case EXCP_MCHK:
do_mchk_interrupt(env);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
break;
case EXCP_RESTART:
do_restart_interrupt(env);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
break;
case EXCP_STOP:
do_stop_interrupt(env);
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 19/25] target/sh4: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (17 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 18/25] target/s390x: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-07 14:20 ` yoshinori.sato
2025-09-04 20:46 ` [PATCH v6 20/25] target/sparc: " Julian Ganz
` (7 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Richard Henderson, Yoshinori Sato
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for SuperH targets.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/sh4/helper.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 1744ef0e6d..fb26d5c35d 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -24,6 +24,7 @@
#include "exec/page-protection.h"
#include "exec/target_page.h"
#include "exec/log.h"
+#include "qemu/plugin.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/sh4/sh_intc.h"
@@ -60,6 +61,7 @@ void superh_cpu_do_interrupt(CPUState *cs)
CPUSH4State *env = cpu_env(cs);
int do_irq = cpu_test_interrupt(cs, CPU_INTERRUPT_HARD);
int do_exp, irq_vector = cs->exception_index;
+ uint64_t last_pc = env->pc;
/* prioritize exceptions over interrupts */
@@ -176,12 +178,14 @@ void superh_cpu_do_interrupt(CPUState *cs)
env->pc = env->vbr + 0x100;
break;
}
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
return;
}
if (do_irq) {
env->intevt = irq_vector;
env->pc = env->vbr + 0x600;
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
return;
}
}
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 20/25] target/sparc: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (18 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 19/25] target/sh4: " Julian Ganz
@ 2025-09-04 20:46 ` Julian Ganz
2025-09-04 20:48 ` Julian Ganz
2025-09-04 20:48 ` [PATCH v6 21/25] target/tricore: " Julian Ganz
` (6 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:46 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Richard Henderson, Mark Cave-Ayland,
Artyom Tarasenko
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for SPARC (32bit and 64bit) targets. We treat
any interrupt other than EXTINT and IVEC as exceptions as they appear to
be synchroneous events.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/sparc/int32_helper.c | 7 +++++++
target/sparc/int64_helper.c | 10 ++++++++++
2 files changed, 17 insertions(+)
diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
index 39db4ffa70..634439ab2a 100644
--- a/target/sparc/int32_helper.c
+++ b/target/sparc/int32_helper.c
@@ -24,6 +24,7 @@
#include "accel/tcg/cpu-ldst.h"
#include "exec/log.h"
#include "system/runstate.h"
+#include "qemu/plugin.h"
static const char * const excp_names[0x80] = {
[TT_TFAULT] = "Instruction Access Fault",
@@ -172,4 +173,10 @@ void sparc_cpu_do_interrupt(CPUState *cs)
env->qemu_irq_ack(env, intno);
}
#endif
+
+ if (intno == TT_EXTINT) {
+ qemu_plugin_vcpu_interrupt_cb(cs, env->regwptr[9]);
+ } else {
+ qemu_plugin_vcpu_exception_cb(cs, env->regwptr[9]);
+ }
}
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index 49e4e51c6d..1de9de0961 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -23,6 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/log.h"
#include "trace.h"
+#include "qemu/plugin.h"
#define DEBUG_PCALL
@@ -253,6 +254,15 @@ void sparc_cpu_do_interrupt(CPUState *cs)
}
env->npc = env->pc + 4;
cs->exception_index = -1;
+
+ switch (intno) {
+ case TT_EXTINT:
+ case TT_IVEC:
+ qemu_plugin_vcpu_interrupt_cb(cs, tsptr->tpc);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, tsptr->tpc);
+ }
}
trap_state *cpu_tsptr(CPUSPARCState* env)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 20/25] target/sparc: call plugin trap callbacks
2025-09-04 20:46 ` [PATCH v6 20/25] target/sparc: " Julian Ganz
@ 2025-09-04 20:48 ` Julian Ganz
0 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:48 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Richard Henderson, Mark Cave-Ayland,
Artyom Tarasenko
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for SPARC (32bit and 64bit) targets. We treat
any interrupt other than EXTINT and IVEC as exceptions as they appear to
be synchroneous events.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/sparc/int32_helper.c | 7 +++++++
target/sparc/int64_helper.c | 10 ++++++++++
2 files changed, 17 insertions(+)
diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
index 39db4ffa70..634439ab2a 100644
--- a/target/sparc/int32_helper.c
+++ b/target/sparc/int32_helper.c
@@ -24,6 +24,7 @@
#include "accel/tcg/cpu-ldst.h"
#include "exec/log.h"
#include "system/runstate.h"
+#include "qemu/plugin.h"
static const char * const excp_names[0x80] = {
[TT_TFAULT] = "Instruction Access Fault",
@@ -172,4 +173,10 @@ void sparc_cpu_do_interrupt(CPUState *cs)
env->qemu_irq_ack(env, intno);
}
#endif
+
+ if (intno == TT_EXTINT) {
+ qemu_plugin_vcpu_interrupt_cb(cs, env->regwptr[9]);
+ } else {
+ qemu_plugin_vcpu_exception_cb(cs, env->regwptr[9]);
+ }
}
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index 49e4e51c6d..1de9de0961 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -23,6 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/log.h"
#include "trace.h"
+#include "qemu/plugin.h"
#define DEBUG_PCALL
@@ -253,6 +254,15 @@ void sparc_cpu_do_interrupt(CPUState *cs)
}
env->npc = env->pc + 4;
cs->exception_index = -1;
+
+ switch (intno) {
+ case TT_EXTINT:
+ case TT_IVEC:
+ qemu_plugin_vcpu_interrupt_cb(cs, tsptr->tpc);
+ break;
+ default:
+ qemu_plugin_vcpu_exception_cb(cs, tsptr->tpc);
+ }
}
trap_state *cpu_tsptr(CPUSPARCState* env)
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 21/25] target/tricore: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (19 preceding siblings ...)
2025-09-04 20:46 ` [PATCH v6 20/25] target/sparc: " Julian Ganz
@ 2025-09-04 20:48 ` Julian Ganz
2025-09-04 20:48 ` [PATCH v6 22/25] target/xtensa: " Julian Ganz
` (5 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Bastian Koppelmann, Richard Henderson
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places an exception hook for TriCore targets. Interrupts are
not implemented for this target and it has no host calls.
Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/tricore/op_helper.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index 9910c13f4b..9bd6ce55d1 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -19,6 +19,7 @@
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
#include "accel/tcg/cpu-ldst.h"
+#include "qemu/plugin.h"
#include <zlib.h> /* for crc32 */
@@ -29,8 +30,11 @@ void raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin
uintptr_t pc, uint32_t fcd_pc)
{
CPUState *cs = env_cpu(env);
+ uint64_t last_pc;
+
/* in case we come from a helper-call we need to restore the PC */
cpu_restore_state(cs, pc);
+ last_pc = env->PC;
/* Tin is loaded into d[15] */
env->gpr_d[15] = tin;
@@ -90,6 +94,7 @@ void raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin
/* Update PC using the trap vector table */
env->PC = env->BTV | (class << 5);
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
cpu_loop_exit(cs);
}
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 22/25] target/xtensa: call plugin trap callbacks
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (20 preceding siblings ...)
2025-09-04 20:48 ` [PATCH v6 21/25] target/tricore: " Julian Ganz
@ 2025-09-04 20:48 ` Julian Ganz
2025-09-22 11:47 ` Philippe Mathieu-Daudé
2025-09-04 20:48 ` [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
` (4 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Julian Ganz, Max Filippov
We recently introduced API for registering callbacks for trap related
events as well as the corresponding hook functions. Due to differences
between architectures, the latter need to be called from target specific
code.
This change places hooks for xtensa targets.
Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Julian Ganz <neither@nut.email>
---
target/xtensa/exc_helper.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/target/xtensa/exc_helper.c b/target/xtensa/exc_helper.c
index b611c9bf97..fdc522698d 100644
--- a/target/xtensa/exc_helper.c
+++ b/target/xtensa/exc_helper.c
@@ -32,6 +32,7 @@
#include "exec/helper-proto.h"
#include "qemu/host-utils.h"
#include "qemu/atomic.h"
+#include "qemu/plugin.h"
void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
{
@@ -207,6 +208,8 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
CPUXtensaState *env = cpu_env(cs);
if (cs->exception_index == EXC_IRQ) {
+ uint64_t last_pc = env->pc;
+
qemu_log_mask(CPU_LOG_INT,
"%s(EXC_IRQ) level = %d, cintlevel = %d, "
"pc = %08x, a0 = %08x, ps = %08x, "
@@ -218,6 +221,7 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
env->sregs[INTSET], env->sregs[INTENABLE],
env->sregs[CCOUNT]);
handle_interrupt(env);
+ qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
}
switch (cs->exception_index) {
@@ -238,9 +242,11 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
env->sregs[CCOUNT]);
if (env->config->exception_vector[cs->exception_index]) {
uint32_t vector;
+ uint64_t last_pc = env->pc;
vector = env->config->exception_vector[cs->exception_index];
env->pc = relocated_vector(env, vector);
+ qemu_plugin_vcpu_exception_cb(cs, last_pc);
} else {
qemu_log_mask(CPU_LOG_INT,
"%s(pc = %08x) bad exception_index: %d\n",
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (21 preceding siblings ...)
2025-09-04 20:48 ` [PATCH v6 22/25] target/xtensa: " Julian Ganz
@ 2025-09-04 20:48 ` Julian Ganz
2025-09-21 16:46 ` Alex Bennée
2025-09-04 20:48 ` [PATCH v6 24/25] tests: add test for double-traps on rv64 Julian Ganz
` (3 subsequent siblings)
26 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:48 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Pierrick Bouvier, Alex Bennée, Alexandre Iooss,
Mahmoud Mandour
We recently introduced plugin API for the registration of callbacks for
discontinuity events, specifically for interrupts, exceptions and host
call events. The callback receives various bits of information,
including the VCPU index and PCs.
This change introduces a test plugin asserting the correctness of that
behaviour in cases where this is possible with reasonable effort.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
tests/tcg/plugins/discons.c | 210 ++++++++++++++++++++++++++++++++++
tests/tcg/plugins/meson.build | 2 +-
2 files changed, 211 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/plugins/discons.c
diff --git a/tests/tcg/plugins/discons.c b/tests/tcg/plugins/discons.c
new file mode 100644
index 0000000000..f185e3948b
--- /dev/null
+++ b/tests/tcg/plugins/discons.c
@@ -0,0 +1,210 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2025, Julian Ganz <neither@nut.email>
+ *
+ * This plugin exercises the discontinuity plugin API and asserts some
+ * of its behaviour regarding reported program counters.
+ */
+#include <stdio.h>
+
+#include <qemu-plugin.h>
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+struct cpu_state {
+ uint64_t last_pc;
+ uint64_t from_pc;
+ uint64_t next_pc;
+ uint64_t has_from;
+ bool has_next;
+ enum qemu_plugin_discon_type next_type;
+};
+
+struct insn_data {
+ uint64_t addr;
+ uint64_t next_pc;
+ bool next_valid;
+};
+
+static struct qemu_plugin_scoreboard *states;
+
+static qemu_plugin_u64 last_pc;
+static qemu_plugin_u64 from_pc;
+static qemu_plugin_u64 has_from;
+
+static bool abort_on_mismatch;
+static bool trace_all_insns;
+
+static bool addr_eq(uint64_t a, uint64_t b)
+{
+ if (a == b) {
+ return true;
+ }
+
+ uint64_t a_hw;
+ uint64_t b_hw;
+ if (!qemu_plugin_translate_vaddr(a, &a_hw) ||
+ !qemu_plugin_translate_vaddr(b, &b_hw))
+ {
+ return false;
+ }
+
+ return a_hw == b_hw;
+}
+
+static void report_mismatch(const char *pc_name, unsigned int vcpu_index,
+ enum qemu_plugin_discon_type type, uint64_t last,
+ uint64_t expected, uint64_t encountered)
+{
+ GString *report;
+ const char *discon_type_name = "unknown";
+
+ if (addr_eq(expected, encountered)) {
+ return;
+ }
+
+ switch (type) {
+ case QEMU_PLUGIN_DISCON_INTERRUPT:
+ discon_type_name = "interrupt";
+ break;
+ case QEMU_PLUGIN_DISCON_EXCEPTION:
+ discon_type_name = "exception";
+ break;
+ case QEMU_PLUGIN_DISCON_HOSTCALL:
+ discon_type_name = "hostcall";
+ break;
+ default:
+ break;
+ }
+
+ report = g_string_new(NULL);
+ g_string_append_printf(report,
+ "Discon %s PC mismatch on VCPU %d\nExpected: %"
+ PRIx64"\nEncountered: %"PRIx64"\nExecuted Last: %"
+ PRIx64"\nEvent type: %s\n",
+ pc_name, vcpu_index, expected, encountered, last,
+ discon_type_name);
+ qemu_plugin_outs(report->str);
+ if (abort_on_mismatch) {
+ g_abort();
+ }
+ g_string_free(report, true);
+}
+
+static void vcpu_discon(qemu_plugin_id_t id, unsigned int vcpu_index,
+ enum qemu_plugin_discon_type type, uint64_t from_pc,
+ uint64_t to_pc)
+{
+ struct cpu_state *state = qemu_plugin_scoreboard_find(states, vcpu_index);
+
+ if (type == QEMU_PLUGIN_DISCON_EXCEPTION &&
+ addr_eq(state->last_pc, from_pc))
+ {
+ /*
+ * For some types of exceptions, insn_exec will be called for the
+ * instruction that caused the exception. This is valid behaviour and
+ * does not need to be reported.
+ */
+ } else if (state->has_next) {
+ /*
+ * We may encounter discontinuity chains without any instructions
+ * being executed in between.
+ */
+ report_mismatch("source", vcpu_index, type, state->last_pc,
+ state->next_pc, from_pc);
+ } else if (state->has_from) {
+ report_mismatch("source", vcpu_index, type, state->last_pc,
+ state->from_pc, from_pc);
+ }
+
+ state->has_from = false;
+
+ state->next_pc = to_pc;
+ state->next_type = type;
+ state->has_next = true;
+}
+
+static void insn_exec(unsigned int vcpu_index, void *userdata)
+{
+ struct cpu_state *state = qemu_plugin_scoreboard_find(states, vcpu_index);
+
+ if (state->has_next) {
+ report_mismatch("target", vcpu_index, state->next_type, state->last_pc,
+ state->next_pc, state->last_pc);
+ state->has_next = false;
+ }
+
+ if (trace_all_insns) {
+ g_autoptr(GString) report = g_string_new(NULL);
+ g_string_append_printf(report, "Exec insn at %"PRIx64" on VCPU %d\n",
+ state->last_pc, vcpu_index);
+ qemu_plugin_outs(report->str);
+ }
+}
+
+static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
+{
+ size_t n_insns = qemu_plugin_tb_n_insns(tb);
+ for (size_t i = 0; i < n_insns; i++) {
+ struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
+ uint64_t pc = qemu_plugin_insn_vaddr(insn);
+ uint64_t next_pc = pc + qemu_plugin_insn_size(insn);
+ uint64_t has_next = (i + 1) < n_insns;
+
+ qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
+ QEMU_PLUGIN_INLINE_STORE_U64,
+ last_pc, pc);
+ qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
+ QEMU_PLUGIN_INLINE_STORE_U64,
+ from_pc, next_pc);
+ qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
+ QEMU_PLUGIN_INLINE_STORE_U64,
+ has_from, has_next);
+ qemu_plugin_register_vcpu_insn_exec_cb(insn, insn_exec,
+ QEMU_PLUGIN_CB_NO_REGS, NULL);
+ }
+}
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
+ const qemu_info_t *info,
+ int argc, char **argv)
+{
+ /* Set defaults */
+ abort_on_mismatch = true;
+ trace_all_insns = false;
+
+ for (int i = 0; i < argc; i++) {
+ char *opt = argv[i];
+ g_auto(GStrv) tokens = g_strsplit(opt, "=", 2);
+ if (g_strcmp0(tokens[0], "abort") == 0) {
+ if (!qemu_plugin_bool_parse(tokens[0], tokens[1],
+ &abort_on_mismatch)) {
+ fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
+ return -1;
+ }
+ } else if (g_strcmp0(tokens[0], "trace-all") == 0) {
+ if (!qemu_plugin_bool_parse(tokens[0], tokens[1],
+ &trace_all_insns)) {
+ fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "option parsing failed: %s\n", opt);
+ return -1;
+ }
+ }
+
+ states = qemu_plugin_scoreboard_new(sizeof(struct cpu_state));
+ last_pc = qemu_plugin_scoreboard_u64_in_struct(states, struct cpu_state,
+ last_pc);
+ from_pc = qemu_plugin_scoreboard_u64_in_struct(states, struct cpu_state,
+ from_pc);
+ has_from = qemu_plugin_scoreboard_u64_in_struct(states, struct cpu_state,
+ has_from);
+
+ qemu_plugin_register_vcpu_discon_cb(id, QEMU_PLUGIN_DISCON_ALL,
+ vcpu_discon);
+ qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
+
+ return 0;
+}
diff --git a/tests/tcg/plugins/meson.build b/tests/tcg/plugins/meson.build
index 61a007d9e7..561584159e 100644
--- a/tests/tcg/plugins/meson.build
+++ b/tests/tcg/plugins/meson.build
@@ -1,6 +1,6 @@
t = []
if get_option('plugins')
- foreach i : ['bb', 'empty', 'inline', 'insn', 'mem', 'reset', 'syscall', 'patch']
+ foreach i : ['bb', 'discons', 'empty', 'inline', 'insn', 'mem', 'reset', 'syscall', 'patch']
if host_os == 'windows'
t += shared_module(i, files(i + '.c') + '../../../contrib/plugins/win32_linker.c',
include_directories: '../../../include/qemu',
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 24/25] tests: add test for double-traps on rv64
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (22 preceding siblings ...)
2025-09-04 20:48 ` [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
@ 2025-09-04 20:48 ` Julian Ganz
2025-09-04 20:49 ` [PATCH v6 25/25] tests: add test with interrupted memory accesses " Julian Ganz
` (2 subsequent siblings)
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:48 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Daniel Henrique Barboza, Palmer Dabbelt,
Alistair Francis, Weiwei Li, Liu Zhiwei,
open list:RISC-V TCG CPUs
We do have a number of test-case for various architectures exercising
their interrupt/exception logic. However, for the recently introduced
trap API we also want to exercise the logic for double traps on at least
one architecture.
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Julian Ganz <neither@nut.email>
---
tests/tcg/riscv64/Makefile.softmmu-target | 6 ++
tests/tcg/riscv64/doubletrap.S | 73 +++++++++++++++++++++++
2 files changed, 79 insertions(+)
create mode 100644 tests/tcg/riscv64/doubletrap.S
diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target
index 3ca595335d..1a71a78653 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -24,5 +24,11 @@ EXTRA_RUNS += run-test-mepc-masking
run-test-mepc-masking: test-mepc-masking
$(call run-test, $<, $(QEMU) $(QEMU_OPTS)$<)
+EXTRA_RUNS += run-plugin-doubletrap
+run-plugin-doubletrap: doubletrap
+ $(call run-test, $<, \
+ $(QEMU) -plugin ../plugins/libdiscons.so -d plugin -D $*.pout \
+ $(QEMU_OPTS)$<)
+
# We don't currently support the multiarch system tests
undefine MULTIARCH_TESTS
diff --git a/tests/tcg/riscv64/doubletrap.S b/tests/tcg/riscv64/doubletrap.S
new file mode 100644
index 0000000000..b61089c9c1
--- /dev/null
+++ b/tests/tcg/riscv64/doubletrap.S
@@ -0,0 +1,73 @@
+ .option norvc
+
+ .text
+ .global _start
+_start:
+ # Set up vectored interrupts
+ lla t0, trap
+ add t0, t0, 1
+ csrw mtvec, t0
+
+ # Enable sw interrupts
+ csrrsi zero, mie, 0x8
+ csrrsi zero, mstatus, 0x8
+
+ # Engage the double trap: we trigger an machine-level software
+ # interrupt, which will trap to an illegal instruction
+ lui t1, 0x02000
+ li t0, 1
+ sw t0, 0(t1)
+
+ # If we still not went out via the software interrupt route after a
+ # short while, we failed the test.
+ lui t0, 0x1
+0:
+ addi t0, t0, -1
+ bnez t0, 0b
+ j fail
+
+trap:
+ j illegal_insn # Exceptions
+ j fail # Supervisor software interrupt
+ j fail
+ .insn i CUSTOM_0, 0, x0, x0, 0 # Machine software interrupt
+ j fail
+ j fail # Supervisor timer interrupt
+ j fail
+ j fail # Machine timer interrupt
+ j fail
+ j fail # Supervisor external interrupt
+ j fail
+ j fail # Machine external interrupt
+ j fail
+ j fail # Counter overflow interrupt
+ j fail
+ j fail
+
+illegal_insn:
+ # Check whether we really got an illegal instruction
+ csrr t0, mcause
+ li t1, 2
+ bne t0, t1, fail
+ li a0, 0
+ j _exit
+fail:
+ li a0, 1
+_exit:
+ lla a1, semiargs
+ li t0, 0x20026 # ADP_Stopped_ApplicationExit
+ sd t0, 0(a1)
+ sd a0, 8(a1)
+ li a0, 0x20 # TARGET_SYS_EXIT_EXTENDED
+
+ # Semihosting call sequence
+ .balign 16
+ slli zero, zero, 0x1f
+ ebreak
+ srai zero, zero, 0x7
+ j .
+
+ .data
+ .balign 16
+semiargs:
+ .space 16
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v6 25/25] tests: add test with interrupted memory accesses on rv64
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (23 preceding siblings ...)
2025-09-04 20:48 ` [PATCH v6 24/25] tests: add test for double-traps on rv64 Julian Ganz
@ 2025-09-04 20:49 ` Julian Ganz
2025-09-05 11:38 ` [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities BALATON Zoltan
2025-09-22 11:31 ` Philippe Mathieu-Daudé
26 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-04 20:49 UTC (permalink / raw)
To: qemu-devel
Cc: Julian Ganz, Daniel Henrique Barboza, Palmer Dabbelt,
Alistair Francis, Weiwei Li, Liu Zhiwei,
open list:RISC-V TCG CPUs
This test aims at catching API misbehaviour w.r.t. the interaction
between interrupts and memory accesses, such as the bug fixed in
27f347e6a1d269c533633c812321cabb249eada8
Because the condition for triggering misbehaviour may not be
deterministic and the cross-section between memory accesses and
interrupt handlers may be small, we have to place our trust in large
numbers. Instead of guessing/trying an arbitrary, fixed loop-bound, we
decided to loop for a fixed amount of real-time. This avoids the test
running into a time-out on slower machines while enabling a high number
of possible interactions on faster machines.
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Julian Ganz <neither@nut.email>
---
tests/tcg/riscv64/Makefile.softmmu-target | 6 ++
tests/tcg/riscv64/interruptedmemory.S | 67 +++++++++++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 tests/tcg/riscv64/interruptedmemory.S
diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target
index 1a71a78653..d8f92b8e61 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -30,5 +30,11 @@ run-plugin-doubletrap: doubletrap
$(QEMU) -plugin ../plugins/libdiscons.so -d plugin -D $*.pout \
$(QEMU_OPTS)$<)
+EXTRA_RUNS += run-plugin-interruptedmemory
+run-plugin-interruptedmemory: interruptedmemory
+ $(call run-test, $<, \
+ $(QEMU) -plugin ../plugins/libdiscons.so -d plugin -D $*.pout \
+ $(QEMU_OPTS)$<)
+
# We don't currently support the multiarch system tests
undefine MULTIARCH_TESTS
diff --git a/tests/tcg/riscv64/interruptedmemory.S b/tests/tcg/riscv64/interruptedmemory.S
new file mode 100644
index 0000000000..a32d672849
--- /dev/null
+++ b/tests/tcg/riscv64/interruptedmemory.S
@@ -0,0 +1,67 @@
+ .option norvc
+
+ .text
+ .global _start
+_start:
+ # Set up trap vector
+ lla t0, trap
+ csrw mtvec, t0
+
+ # Set up timer
+ lui t1, 0x02004
+ sd zero, 0(t1) # MTIMECMP0
+
+ # Enable timer interrupts
+ li t0, 0x80
+ csrrs zero, mie, t0
+ csrrsi zero, mstatus, 0x8
+
+ # Find out when to stop
+ call rtc_get
+ li t0, 60
+ slli t0, t0, 30 # Approx. 10e9 ns
+ add t0, t0, a0
+
+ # Loop with memory accesses
+ la t1, semiargs
+0:
+ ld t2, 0(t1)
+ sd t2, 0(t1)
+ call rtc_get
+ bltu a0, t0, 0b
+
+ li a0, 0
+ lla a1, semiargs
+ li t0, 0x20026 # ADP_Stopped_ApplicationExit
+ sd t0, 0(a1)
+ sd a0, 8(a1)
+ li a0, 0x20 # TARGET_SYS_EXIT_EXTENDED
+
+ # Semihosting call sequence
+ .balign 16
+ slli zero, zero, 0x1f
+ ebreak
+ srai zero, zero, 0x7
+ j .
+
+rtc_get:
+ # Get current time from the goldfish RTC
+ lui t3, 0x0101
+ lw a0, 0(t3)
+ lw t3, 4(t3)
+ slli t3, t3, 32
+ add a0, a0, t3
+ ret
+
+trap:
+ lui t5, 0x0200c
+ ld t6, -0x8(t5) # MTIME
+ addi t6, t6, 100
+ lui t5, 0x02004
+ sd t6, 0(t5) # MTIMECMP
+ mret
+
+ .data
+ .balign 16
+semiargs:
+ .space 16
--
2.49.1
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (24 preceding siblings ...)
2025-09-04 20:49 ` [PATCH v6 25/25] tests: add test with interrupted memory accesses " Julian Ganz
@ 2025-09-05 11:38 ` BALATON Zoltan
2025-09-05 12:20 ` Alex Bennée
2025-09-05 13:43 ` Julian Ganz
2025-09-22 11:31 ` Philippe Mathieu-Daudé
26 siblings, 2 replies; 57+ messages in thread
From: BALATON Zoltan @ 2025-09-05 11:38 UTC (permalink / raw)
To: Julian Ganz; +Cc: qemu-devel
On Thu, 4 Sep 2025, Julian Ganz wrote:
> Some analysis greatly benefits, or depends on, information about
> certain types of dicontinuities such as interrupts. For example, we may
> need to handle the execution of a new translation block differently if
> it is not the result of normal program flow but of an interrupt.
>
> Even with the existing interfaces, it is more or less possible to
> discern these situations, e.g. as done by the cflow plugin. However,
> this process poses a considerable overhead to the core analysis one may
> intend to perform.
I'd rather have overhead in the plugin than in interrupt and exception
handling on every target unless this can be completely disabled somehow
when not needed to not pose any overhead on interrupt handling in the
guest. Have you done any testing on how much overhead this adds to
interrupt heavy guest workloads? At least for PPC these are already much
slower than real CPU so I'd like it to get faster not slower.
Regards,
BALATON Zoltan
> These changes introduce a generic and easy-to-use interface for plugin
> authors in the form of a callback for discontinuities. Patch 1 defines
> an enumeration of some trap-related discontinuities including somewhat
> narrow definitions of the discontinuity evetns and a callback type.
> Patch 2 defines the callback registration function. Patch 3 adds some
> hooks for triggering the callbacks. Patch 4 adds an example plugin
> showcasing the new API.
>
> Patches 5 through 22 call the hooks for all architectures but hexagon,
> mapping architecture specific events to the three categories defined in
> patch 1. We don't plan to add hooks for hexagon since despite having
> exceptions apparently doesn't have any discontinuities associated with
> them.
>
> Patch 23 supplies a test plugin asserting some behavior of the plugin
> API w.r.t. the PCs reported by the new API. Finally, patches 24 and 25
> add new tests for riscv which serve as test-cases for the test plugin.
>
> Sidenote: I'm likely doing something wrong for one architecture or
> the other. These patches are untested for most of them.
>
> Richard Henderson proposed streamlining interrupts and exceptions for
> all targets and calling the hooks from a higher level rather than in
> each target code. However, there are a few obstacled and I decided to
> not do this as part of this series.
>
> Since v5:
> - The internal function plugin_vcpu_cb__discon now takes the
> qemu_plugin_event as a parameter instead of determining the event
> from the discon type.
> - Fixed computation of the last PC for ARM platforms.
> - Code mapping ARM exception index to discon type is now shared
> between m- and a-profile.
> - Fixed mapping of interrupt number to discon type for HPPA platforms.
> - Removed exception hook for some internal events for Motorola 68000.
> - Call hook for unaligned access exceptions on MicroBlaze platforms.
> - Prevented calling of exception hooks for resets on OpenRISC.
> - Made the discon test plugin compare hardware addesses transpated
> with qemu_plugin_translate_vaddr when comparing addresses. Before
> we'd use a crude bitmask.
>
> Since v4:
> - Fixed a typo in the documentation of the
> qemu_plugin_vcpu_discon_cb_t function type (pointed out by Pierrick
> Bouvier)
> - Fixed a reference in the documentation of the
> qemu_plugin_vcpu_discon_cb_t function type
> - Added hooks for SuperH and TriCore targets
> - Fixed typos in commit messages (pointed out by Daniel Henrique
> Barboza)
>
> Since v3 (RFC):
> - Switched to shifting 1 notation for qemu_plugin_discon_type values
> (as requested by Pierrick Bouvier)
> - Added missing documentation of function parameters of function
> pointer type qemu_plugin_vcpu_discon_cb_t
> - Added missing documentation of function parameters of
> qemu_plugin_register_vcpu_discon_cb
> - Eliminated "to" argument from hooks called from target specific
> code, i.e. qemu_plugin_vcpu_interrupt_cb and friends, determine "to"
> address using CPUClass::get_pc
> - Replaced comment declaring switch-case unreachable with
> g_assert_not_reached()
> - Call qemu_plugin_register_vcpu_discon_cb with QEMU_PLUGIN_DISCON_ALL
> rather than QEMU_PLUGIN_DISCON_TRAPS in "traps" example plugin
> - Take max_vcpus from qemu_info_t in "traps" example plugin, don't
> determine it based on VCPU activation
> - Added a description of the "traps" example plugin (as requested by
> Pierrick Bouvier)
> - Added section for the "traps" example plugin in documentation's
> "Emulation" chapter
> - Fixed messed-up switch-case in alpha_cpu_do_interrupt
> - Added hooks for PA-RISC, x86, loongarch, Motorola 68000, MicroBlaze,
> OpenRISC, Power PC, Renesas Xtreme, IBM System/390 and xtensa
> targets.
> - Made "discon" test plugin check PCs in vcpu_discon callback (as
> requested by Pierrick Bouvier)
> - Added parameter to "discon" test plugin for controlling which
> address bits are compared to cope with TBs being used under
> different virtual addresses
> - Added parameter to "discon" test plugin for printing a full
> instruction trace for debugging purposes
> - Made "discon" test plugin abort by default on address mismatches
> - Added test-cases for RISC-V
>
> Since v2 (tcg-plugins: add hooks for interrupts, exceptions and traps):
> - Switched from traps as core concept to more generic discontinuities
> - Switched from semihosting to hostcall as term for emulated traps
> - Added enumeration of events and dedicated callback type
> - Make callback receive event type as well as origin and target PC
> (as requested by Pierrick Bouvier)
> - Combined registration functions for different traps into a single
> one for all types of discontinuities (as requested by Pierrick
> Bouvier)
> - Migrated records in example plugin from fully pre-allocated to a
> scoreboard (as suggested by Pierrick Bouvier)
> - Handle PSCI calls as hostcall (as pointed out by Peter Maydell)
> - Added hooks for ARM Cortex M arches (as pointed out by Peter
> Maydell)
> - Added hooks for Alpha targets
> - Added hooks for MIPS targets
> - Added a plugin for testing some of the interface behaviour
>
> Since v1:
> - Split the one callback into multiple callbacks
> - Added a target-agnostic definition of the relevant event(s)
> - Call hooks from architecture-code rather than accel/tcg/cpu-exec.c
> - Added a plugin showcasing API usage
>
> Julian Ganz (25):
> plugins: add types for callbacks related to certain discontinuities
> plugins: add API for registering discontinuity callbacks
> plugins: add hooks for new discontinuity related callbacks
> contrib/plugins: add plugin showcasing new dicontinuity related API
> target/alpha: call plugin trap callbacks
> target/arm: call plugin trap callbacks
> target/avr: call plugin trap callbacks
> target/hppa: call plugin trap callbacks
> target/i386: call plugin trap callbacks
> target/loongarch: call plugin trap callbacks
> target/m68k: call plugin trap callbacks
> target/microblaze: call plugin trap callbacks
> target/mips: call plugin trap callbacks
> target/openrisc: call plugin trap callbacks
> target/ppc: call plugin trap callbacks
> target/riscv: call plugin trap callbacks
> target/rx: call plugin trap callbacks
> target/s390x: call plugin trap callbacks
> target/sh4: call plugin trap callbacks
> target/sparc: call plugin trap callbacks
> target/tricore: call plugin trap callbacks
> target/xtensa: call plugin trap callbacks
> tests: add plugin asserting correctness of discon event's to_pc
> tests: add test for double-traps on rv64
> tests: add test with interrupted memory accesses on rv64
>
> contrib/plugins/meson.build | 3 +-
> contrib/plugins/traps.c | 84 +++++++++
> docs/about/emulation.rst | 8 +
> include/qemu/plugin-event.h | 3 +
> include/qemu/plugin.h | 13 ++
> include/qemu/qemu-plugin.h | 60 +++++++
> plugins/core.c | 57 ++++++
> target/alpha/helper.c | 13 ++
> target/arm/helper.c | 24 +++
> target/arm/internals.h | 1 +
> target/arm/tcg/m_helper.c | 5 +
> target/avr/helper.c | 3 +
> target/hppa/int_helper.c | 44 +++++
> target/i386/tcg/excp_helper.c | 3 +
> target/i386/tcg/seg_helper.c | 4 +
> target/loongarch/cpu.c | 4 +
> target/m68k/op_helper.c | 22 +++
> target/microblaze/helper.c | 10 ++
> target/mips/tcg/system/tlb_helper.c | 11 ++
> target/openrisc/interrupt.c | 15 ++
> target/ppc/excp_helper.c | 41 +++++
> target/riscv/cpu_helper.c | 9 +
> target/rx/helper.c | 12 ++
> target/s390x/tcg/excp_helper.c | 8 +
> target/sh4/helper.c | 4 +
> target/sparc/int32_helper.c | 7 +
> target/sparc/int64_helper.c | 10 ++
> target/tricore/op_helper.c | 5 +
> target/xtensa/exc_helper.c | 6 +
> tests/tcg/plugins/discons.c | 210 ++++++++++++++++++++++
> tests/tcg/plugins/meson.build | 2 +-
> tests/tcg/riscv64/Makefile.softmmu-target | 12 ++
> tests/tcg/riscv64/doubletrap.S | 73 ++++++++
> tests/tcg/riscv64/interruptedmemory.S | 67 +++++++
> 34 files changed, 851 insertions(+), 2 deletions(-)
> create mode 100644 contrib/plugins/traps.c
> create mode 100644 tests/tcg/plugins/discons.c
> create mode 100644 tests/tcg/riscv64/doubletrap.S
> create mode 100644 tests/tcg/riscv64/interruptedmemory.S
>
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-05 11:38 ` [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities BALATON Zoltan
@ 2025-09-05 12:20 ` Alex Bennée
2025-09-05 13:43 ` Julian Ganz
1 sibling, 0 replies; 57+ messages in thread
From: Alex Bennée @ 2025-09-05 12:20 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: Julian Ganz, qemu-devel
BALATON Zoltan <balaton@eik.bme.hu> writes:
> On Thu, 4 Sep 2025, Julian Ganz wrote:
>> Some analysis greatly benefits, or depends on, information about
>> certain types of dicontinuities such as interrupts. For example, we may
>> need to handle the execution of a new translation block differently if
>> it is not the result of normal program flow but of an interrupt.
>>
>> Even with the existing interfaces, it is more or less possible to
>> discern these situations, e.g. as done by the cflow plugin. However,
>> this process poses a considerable overhead to the core analysis one may
>> intend to perform.
>
> I'd rather have overhead in the plugin than in interrupt and exception
> handling on every target unless this can be completely disabled
> somehow when not needed to not pose any overhead on interrupt handling
> in the guest.
If you build with --disable-plugins the compiler should dead code away
all the plugin hooks. But in general the overhead from unused plugins is
in the noise.
> Have you done any testing on how much overhead this adds
> to interrupt heavy guest workloads? At least for PPC these are already
> much slower than real CPU so I'd like it to get faster not slower.
I have a vague memory that this is due to ppc running the interrupt
handling code more often than it should. But I forget the details.
Are there any functional tests that exhibit this slow IRQ handling
behaviour?
>
> Regards,
> BALATON Zoltan
>
>> These changes introduce a generic and easy-to-use interface for plugin
>> authors in the form of a callback for discontinuities. Patch 1 defines
>> an enumeration of some trap-related discontinuities including somewhat
>> narrow definitions of the discontinuity evetns and a callback type.
>> Patch 2 defines the callback registration function. Patch 3 adds some
>> hooks for triggering the callbacks. Patch 4 adds an example plugin
>> showcasing the new API.
>>
>> Patches 5 through 22 call the hooks for all architectures but hexagon,
>> mapping architecture specific events to the three categories defined in
>> patch 1. We don't plan to add hooks for hexagon since despite having
>> exceptions apparently doesn't have any discontinuities associated with
>> them.
>>
>> Patch 23 supplies a test plugin asserting some behavior of the plugin
>> API w.r.t. the PCs reported by the new API. Finally, patches 24 and 25
>> add new tests for riscv which serve as test-cases for the test plugin.
>>
>> Sidenote: I'm likely doing something wrong for one architecture or
>> the other. These patches are untested for most of them.
>>
>> Richard Henderson proposed streamlining interrupts and exceptions for
>> all targets and calling the hooks from a higher level rather than in
>> each target code. However, there are a few obstacled and I decided to
>> not do this as part of this series.
>>
>> Since v5:
>> - The internal function plugin_vcpu_cb__discon now takes the
>> qemu_plugin_event as a parameter instead of determining the event
>> from the discon type.
>> - Fixed computation of the last PC for ARM platforms.
>> - Code mapping ARM exception index to discon type is now shared
>> between m- and a-profile.
>> - Fixed mapping of interrupt number to discon type for HPPA platforms.
>> - Removed exception hook for some internal events for Motorola 68000.
>> - Call hook for unaligned access exceptions on MicroBlaze platforms.
>> - Prevented calling of exception hooks for resets on OpenRISC.
>> - Made the discon test plugin compare hardware addesses transpated
>> with qemu_plugin_translate_vaddr when comparing addresses. Before
>> we'd use a crude bitmask.
>>
>> Since v4:
>> - Fixed a typo in the documentation of the
>> qemu_plugin_vcpu_discon_cb_t function type (pointed out by Pierrick
>> Bouvier)
>> - Fixed a reference in the documentation of the
>> qemu_plugin_vcpu_discon_cb_t function type
>> - Added hooks for SuperH and TriCore targets
>> - Fixed typos in commit messages (pointed out by Daniel Henrique
>> Barboza)
>>
>> Since v3 (RFC):
>> - Switched to shifting 1 notation for qemu_plugin_discon_type values
>> (as requested by Pierrick Bouvier)
>> - Added missing documentation of function parameters of function
>> pointer type qemu_plugin_vcpu_discon_cb_t
>> - Added missing documentation of function parameters of
>> qemu_plugin_register_vcpu_discon_cb
>> - Eliminated "to" argument from hooks called from target specific
>> code, i.e. qemu_plugin_vcpu_interrupt_cb and friends, determine "to"
>> address using CPUClass::get_pc
>> - Replaced comment declaring switch-case unreachable with
>> g_assert_not_reached()
>> - Call qemu_plugin_register_vcpu_discon_cb with QEMU_PLUGIN_DISCON_ALL
>> rather than QEMU_PLUGIN_DISCON_TRAPS in "traps" example plugin
>> - Take max_vcpus from qemu_info_t in "traps" example plugin, don't
>> determine it based on VCPU activation
>> - Added a description of the "traps" example plugin (as requested by
>> Pierrick Bouvier)
>> - Added section for the "traps" example plugin in documentation's
>> "Emulation" chapter
>> - Fixed messed-up switch-case in alpha_cpu_do_interrupt
>> - Added hooks for PA-RISC, x86, loongarch, Motorola 68000, MicroBlaze,
>> OpenRISC, Power PC, Renesas Xtreme, IBM System/390 and xtensa
>> targets.
>> - Made "discon" test plugin check PCs in vcpu_discon callback (as
>> requested by Pierrick Bouvier)
>> - Added parameter to "discon" test plugin for controlling which
>> address bits are compared to cope with TBs being used under
>> different virtual addresses
>> - Added parameter to "discon" test plugin for printing a full
>> instruction trace for debugging purposes
>> - Made "discon" test plugin abort by default on address mismatches
>> - Added test-cases for RISC-V
>>
>> Since v2 (tcg-plugins: add hooks for interrupts, exceptions and traps):
>> - Switched from traps as core concept to more generic discontinuities
>> - Switched from semihosting to hostcall as term for emulated traps
>> - Added enumeration of events and dedicated callback type
>> - Make callback receive event type as well as origin and target PC
>> (as requested by Pierrick Bouvier)
>> - Combined registration functions for different traps into a single
>> one for all types of discontinuities (as requested by Pierrick
>> Bouvier)
>> - Migrated records in example plugin from fully pre-allocated to a
>> scoreboard (as suggested by Pierrick Bouvier)
>> - Handle PSCI calls as hostcall (as pointed out by Peter Maydell)
>> - Added hooks for ARM Cortex M arches (as pointed out by Peter
>> Maydell)
>> - Added hooks for Alpha targets
>> - Added hooks for MIPS targets
>> - Added a plugin for testing some of the interface behaviour
>>
>> Since v1:
>> - Split the one callback into multiple callbacks
>> - Added a target-agnostic definition of the relevant event(s)
>> - Call hooks from architecture-code rather than accel/tcg/cpu-exec.c
>> - Added a plugin showcasing API usage
>>
>> Julian Ganz (25):
>> plugins: add types for callbacks related to certain discontinuities
>> plugins: add API for registering discontinuity callbacks
>> plugins: add hooks for new discontinuity related callbacks
>> contrib/plugins: add plugin showcasing new dicontinuity related API
>> target/alpha: call plugin trap callbacks
>> target/arm: call plugin trap callbacks
>> target/avr: call plugin trap callbacks
>> target/hppa: call plugin trap callbacks
>> target/i386: call plugin trap callbacks
>> target/loongarch: call plugin trap callbacks
>> target/m68k: call plugin trap callbacks
>> target/microblaze: call plugin trap callbacks
>> target/mips: call plugin trap callbacks
>> target/openrisc: call plugin trap callbacks
>> target/ppc: call plugin trap callbacks
>> target/riscv: call plugin trap callbacks
>> target/rx: call plugin trap callbacks
>> target/s390x: call plugin trap callbacks
>> target/sh4: call plugin trap callbacks
>> target/sparc: call plugin trap callbacks
>> target/tricore: call plugin trap callbacks
>> target/xtensa: call plugin trap callbacks
>> tests: add plugin asserting correctness of discon event's to_pc
>> tests: add test for double-traps on rv64
>> tests: add test with interrupted memory accesses on rv64
>>
>> contrib/plugins/meson.build | 3 +-
>> contrib/plugins/traps.c | 84 +++++++++
>> docs/about/emulation.rst | 8 +
>> include/qemu/plugin-event.h | 3 +
>> include/qemu/plugin.h | 13 ++
>> include/qemu/qemu-plugin.h | 60 +++++++
>> plugins/core.c | 57 ++++++
>> target/alpha/helper.c | 13 ++
>> target/arm/helper.c | 24 +++
>> target/arm/internals.h | 1 +
>> target/arm/tcg/m_helper.c | 5 +
>> target/avr/helper.c | 3 +
>> target/hppa/int_helper.c | 44 +++++
>> target/i386/tcg/excp_helper.c | 3 +
>> target/i386/tcg/seg_helper.c | 4 +
>> target/loongarch/cpu.c | 4 +
>> target/m68k/op_helper.c | 22 +++
>> target/microblaze/helper.c | 10 ++
>> target/mips/tcg/system/tlb_helper.c | 11 ++
>> target/openrisc/interrupt.c | 15 ++
>> target/ppc/excp_helper.c | 41 +++++
>> target/riscv/cpu_helper.c | 9 +
>> target/rx/helper.c | 12 ++
>> target/s390x/tcg/excp_helper.c | 8 +
>> target/sh4/helper.c | 4 +
>> target/sparc/int32_helper.c | 7 +
>> target/sparc/int64_helper.c | 10 ++
>> target/tricore/op_helper.c | 5 +
>> target/xtensa/exc_helper.c | 6 +
>> tests/tcg/plugins/discons.c | 210 ++++++++++++++++++++++
>> tests/tcg/plugins/meson.build | 2 +-
>> tests/tcg/riscv64/Makefile.softmmu-target | 12 ++
>> tests/tcg/riscv64/doubletrap.S | 73 ++++++++
>> tests/tcg/riscv64/interruptedmemory.S | 67 +++++++
>> 34 files changed, 851 insertions(+), 2 deletions(-)
>> create mode 100644 contrib/plugins/traps.c
>> create mode 100644 tests/tcg/plugins/discons.c
>> create mode 100644 tests/tcg/riscv64/doubletrap.S
>> create mode 100644 tests/tcg/riscv64/interruptedmemory.S
>>
>>
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-05 11:38 ` [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities BALATON Zoltan
2025-09-05 12:20 ` Alex Bennée
@ 2025-09-05 13:43 ` Julian Ganz
2025-09-05 19:25 ` BALATON Zoltan
1 sibling, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-05 13:43 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: qemu-devel
September 5, 2025 at 1:38 PM, "BALATON Zoltan" wrote:
> On Thu, 4 Sep 2025, Julian Ganz wrote:
> > Even with the existing interfaces, it is more or less possible to
> > discern these situations, e.g. as done by the cflow plugin. However,
> > this process poses a considerable overhead to the core analysis one may
> > intend to perform.
> >
> I'd rather have overhead in the plugin than in interrupt and exception
> handling on every target unless this can be completely disabled
> somehow when not needed to not pose any overhead on interrupt handling
> in the guest.
The "more or less" is rather heavy here: with the current API there is
no way to distinguish between interrupts and exceptions. Double-traps
can probably only be detected if you don't rely on weird, very error
prone heuristics around TB translations.
And as Alex Benée pointed out, qemu can be easily built with plugins
disabled.
> Have you done any testing on how much overhead this adds
> to interrupt heavy guest workloads? At least for PPC these are already
> much slower than real CPU so I'd like it to get faster not slower.
No, I have not made any performance measurements. However, given that
for every single TB execution a similar hook is called already, the
impact related to other existing plugin infrastructure _should_ be
neglectible.
That is, if your workload actually runs any code and is not constantly
bombarded with interrupts that _do_ result in a trap (which _may_ happen
during some tests).
So if you are performance sensitive enough to care, you will very likely
want to disable plugins anyway.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-05 13:43 ` Julian Ganz
@ 2025-09-05 19:25 ` BALATON Zoltan
2025-09-05 23:28 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: BALATON Zoltan @ 2025-09-05 19:25 UTC (permalink / raw)
To: Julian Ganz; +Cc: qemu-devel, Alex Bennée
[-- Attachment #1: Type: text/plain, Size: 3087 bytes --]
On Fri, 5 Sep 2025, Julian Ganz wrote:
> September 5, 2025 at 1:38 PM, "BALATON Zoltan" wrote:
>> On Thu, 4 Sep 2025, Julian Ganz wrote:
>>> Even with the existing interfaces, it is more or less possible to
>>> discern these situations, e.g. as done by the cflow plugin. However,
>>> this process poses a considerable overhead to the core analysis one may
>>> intend to perform.
>>>
>> I'd rather have overhead in the plugin than in interrupt and exception
>> handling on every target unless this can be completely disabled
>> somehow when not needed to not pose any overhead on interrupt handling
>> in the guest.
>
> The "more or less" is rather heavy here: with the current API there is
> no way to distinguish between interrupts and exceptions. Double-traps
> can probably only be detected if you don't rely on weird, very error
> prone heuristics around TB translations.
>
> And as Alex Benée pointed out, qemu can be easily built with plugins
> disabled.
>
>> Have you done any testing on how much overhead this adds
>> to interrupt heavy guest workloads? At least for PPC these are already
>> much slower than real CPU so I'd like it to get faster not slower.
>
> No, I have not made any performance measurements. However, given that
> for every single TB execution a similar hook is called already, the
> impact related to other existing plugin infrastructure _should_ be
> neglectible.
>
> That is, if your workload actually runs any code and is not constantly
> bombarded with interrupts that _do_ result in a trap (which _may_ happen
> during some tests).
>
> So if you are performance sensitive enough to care, you will very likely
> want to disable plugins anyway.
I can disable plugins and do that normally but that does not help those
who get QEMU from their distro (i.e. most users). If this infrastructure
was disabled in default builds and needed an explicit option to enable
then those who need it could enable it and not imposed it on everyone else
who just get a default build from a distro and never use plugins. Having
an option which needs rebuild is like not having the option for most
people. I guess the question is which is the larger group? Those who just
run guests or those who use this instrumentation with plugins. The default
may better be what the larger group needs. Even then distros may still
change the default so it would be best if the overhead can be minimised
even if enabled. I think the log infrastructure does that, would a similar
solution work here?
For testing I've found that because embedded PPC CPUs have a software
controlled MMU (and in addition to that QEMU may flush TLB entries too
often) running something that does a lot of memory access like runnung the
STREAM benchmark on sam460ex is hit by this IIRC but anything else causing
a lot of interrupts like reading from emulated disk or sound is probably
affected as well. I've tried to optimise PPC exception handling a bit
before but whenever I optimise something it is later undone by other
changes not caring about performance.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-05 19:25 ` BALATON Zoltan
@ 2025-09-05 23:28 ` Julian Ganz
2025-09-07 20:21 ` BALATON Zoltan
0 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-05 23:28 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: qemu-devel, Alex Bennée
September 5, 2025 at 9:25 PM, "BALATON Zoltan" wrote:
> On Fri, 5 Sep 2025, Julian Ganz wrote:
> > September 5, 2025 at 1:38 PM, "BALATON Zoltan" wrote:
> > > Have you done any testing on how much overhead this adds
> > > to interrupt heavy guest workloads? At least for PPC these are already
> > > much slower than real CPU so I'd like it to get faster not slower.
> > >
> > No, I have not made any performance measurements. However, given that
> > for every single TB execution a similar hook is called already, the
> > impact related to other existing plugin infrastructure _should_ be
> > neglectible.
> >
> > That is, if your workload actually runs any code and is not constantly
> > bombarded with interrupts that _do_ result in a trap (which _may_ happen
> > during some tests).
> >
> > So if you are performance sensitive enough to care, you will very likely
> > want to disable plugins anyway.
> >
> I can disable plugins and do that normally but that does not help those who get QEMU from their distro (i.e. most users). If this infrastructure was disabled in default builds and needed an explicit option to enable then those who need it could enable it and not imposed it on everyone else who just get a default build from a distro and never use plugins. Having an option which needs rebuild is like not having the option for most people. I guess the question is which is the larger group? Those who just run guests or those who use this instrumentation with plugins.
Hard to say.
> The default may better be what the larger group needs. Even then distros may still change the default so it would be best if the overhead can be minimised even if enabled. I think the log infrastructure does that, would a similar solution work here?
>
> For testing I've found that because embedded PPC CPUs have a software controlled MMU (and in addition to that QEMU may flush TLB entries too often) running something that does a lot of memory access like runnung the STREAM benchmark on sam460ex is hit by this IIRC but anything else causing a lot of interrupts like reading from emulated disk or sound is probably affected as well. I've tried to optimise PPC exception handling a bit before but whenever I optimise something it is later undone by other changes not caring about performance.
I could try running the benchmark on multiple versions:
* qemu with plugins disabled,
* with plugins enabled but without these patches and
* with plugins enabled and with these patches.
However, I'll likely only report back with results next week, though.
Do you happen to have an image you can point me to? Either something
that has the benchmark already or some unixoid running on the platform?
I'm currently not motivated enough to cook up some bare-metal testbed
for a platform I'm not familiar with.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 17/25] target/rx: call plugin trap callbacks
2025-09-04 20:46 ` [PATCH v6 17/25] target/rx: " Julian Ganz
@ 2025-09-07 14:20 ` yoshinori.sato
0 siblings, 0 replies; 57+ messages in thread
From: yoshinori.sato @ 2025-09-07 14:20 UTC (permalink / raw)
To: Julian Ganz; +Cc: qemu-devel, Richard Henderson, Yoshinori Sato
On Fri, 05 Sep 2025 05:46:54 +0900,
Julian Ganz wrote:
>
> We recently introduced API for registering callbacks for trap related
> events as well as the corresponding hook functions. Due to differences
> between architectures, the latter need to be called from target specific
> code.
>
> This change places hooks for Renesas Xtreme targets.
>
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> target/rx/helper.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/target/rx/helper.c b/target/rx/helper.c
> index ce003af421..054bfdff57 100644
> --- a/target/rx/helper.c
> +++ b/target/rx/helper.c
> @@ -22,6 +22,7 @@
> #include "exec/log.h"
> #include "accel/tcg/cpu-ldst.h"
> #include "hw/irq.h"
> +#include "qemu/plugin.h"
>
> void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte)
> {
> @@ -46,6 +47,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
> CPURXState *env = cpu_env(cs);
> int do_irq = cpu_test_interrupt(cs, INT_FLAGS);
> uint32_t save_psw;
> + uint64_t last_pc = env->pc;
>
> env->in_sleep = 0;
>
> @@ -65,6 +67,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
> env->psw_ipl = 15;
> cs->interrupt_request &= ~CPU_INTERRUPT_FIR;
> qemu_set_irq(env->ack, env->ack_irq);
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n");
> } else if (do_irq & CPU_INTERRUPT_HARD) {
> env->isp -= 4;
> @@ -75,6 +78,7 @@ void rx_cpu_do_interrupt(CPUState *cs)
> env->psw_ipl = env->ack_ipl;
> cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
> qemu_set_irq(env->ack, env->ack_irq);
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> qemu_log_mask(CPU_LOG_INT,
> "interrupt 0x%02x raised\n", env->ack_irq);
> }
> @@ -92,6 +96,14 @@ void rx_cpu_do_interrupt(CPUState *cs)
> } else {
> env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
> }
> +
> + if (vec == 30) {
> + /* Non-maskable interrupt */
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> + } else {
> + qemu_plugin_vcpu_exception_cb(cs, last_pc);
> + }
> +
> switch (vec) {
> case 20:
> expname = "privilege violation";
> --
> 2.49.1
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 19/25] target/sh4: call plugin trap callbacks
2025-09-04 20:46 ` [PATCH v6 19/25] target/sh4: " Julian Ganz
@ 2025-09-07 14:20 ` yoshinori.sato
0 siblings, 0 replies; 57+ messages in thread
From: yoshinori.sato @ 2025-09-07 14:20 UTC (permalink / raw)
To: Julian Ganz; +Cc: qemu-devel, Richard Henderson, Yoshinori Sato
On Fri, 05 Sep 2025 05:46:56 +0900,
Julian Ganz wrote:
>
> We recently introduced API for registering callbacks for trap related
> events as well as the corresponding hook functions. Due to differences
> between architectures, the latter need to be called from target specific
> code.
>
> This change places hooks for SuperH targets.
>
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> target/sh4/helper.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/target/sh4/helper.c b/target/sh4/helper.c
> index 1744ef0e6d..fb26d5c35d 100644
> --- a/target/sh4/helper.c
> +++ b/target/sh4/helper.c
> @@ -24,6 +24,7 @@
> #include "exec/page-protection.h"
> #include "exec/target_page.h"
> #include "exec/log.h"
> +#include "qemu/plugin.h"
>
> #if !defined(CONFIG_USER_ONLY)
> #include "hw/sh4/sh_intc.h"
> @@ -60,6 +61,7 @@ void superh_cpu_do_interrupt(CPUState *cs)
> CPUSH4State *env = cpu_env(cs);
> int do_irq = cpu_test_interrupt(cs, CPU_INTERRUPT_HARD);
> int do_exp, irq_vector = cs->exception_index;
> + uint64_t last_pc = env->pc;
>
> /* prioritize exceptions over interrupts */
>
> @@ -176,12 +178,14 @@ void superh_cpu_do_interrupt(CPUState *cs)
> env->pc = env->vbr + 0x100;
> break;
> }
> + qemu_plugin_vcpu_exception_cb(cs, last_pc);
> return;
> }
>
> if (do_irq) {
> env->intevt = irq_vector;
> env->pc = env->vbr + 0x600;
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> return;
> }
> }
> --
> 2.49.1
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-05 23:28 ` Julian Ganz
@ 2025-09-07 20:21 ` BALATON Zoltan
2025-09-08 20:51 ` Julian Ganz
2025-09-09 19:48 ` Julian Ganz
0 siblings, 2 replies; 57+ messages in thread
From: BALATON Zoltan @ 2025-09-07 20:21 UTC (permalink / raw)
To: Julian Ganz; +Cc: qemu-devel, Alex Bennée
On Fri, 5 Sep 2025, Julian Ganz wrote:
> September 5, 2025 at 9:25 PM, "BALATON Zoltan" wrote:
>> On Fri, 5 Sep 2025, Julian Ganz wrote:
>>> September 5, 2025 at 1:38 PM, "BALATON Zoltan" wrote:
>>>> Have you done any testing on how much overhead this adds
>>>> to interrupt heavy guest workloads? At least for PPC these are already
>>>> much slower than real CPU so I'd like it to get faster not slower.
>>>>
>>> No, I have not made any performance measurements. However, given that
>>> for every single TB execution a similar hook is called already, the
>>> impact related to other existing plugin infrastructure _should_ be
>>> neglectible.
>>>
>>> That is, if your workload actually runs any code and is not constantly
>>> bombarded with interrupts that _do_ result in a trap (which _may_ happen
>>> during some tests).
>>>
>>> So if you are performance sensitive enough to care, you will very likely
>>> want to disable plugins anyway.
>>>
>> I can disable plugins and do that normally but that does not help those who get QEMU from their distro (i.e. most users). If this infrastructure was disabled in default builds and needed an explicit option to enable then those who need it could enable it and not imposed it on everyone else who just get a default build from a distro and never use plugins. Having an option which needs rebuild is like not having the option for most people. I guess the question is which is the larger group? Those who just run guests or those who use this instrumentation with plugins.
>
> Hard to say.
>
>> The default may better be what the larger group needs. Even then distros may still change the default so it would be best if the overhead can be minimised even if enabled. I think the log infrastructure does that, would a similar solution work here?
>>
>> For testing I've found that because embedded PPC CPUs have a software controlled MMU (and in addition to that QEMU may flush TLB entries too often) running something that does a lot of memory access like runnung the STREAM benchmark on sam460ex is hit by this IIRC but anything else causing a lot of interrupts like reading from emulated disk or sound is probably affected as well. I've tried to optimise PPC exception handling a bit before but whenever I optimise something it is later undone by other changes not caring about performance.
>
> I could try running the benchmark on multiple versions:
>
> * qemu with plugins disabled,
> * with plugins enabled but without these patches and
> * with plugins enabled and with these patches.
>
> However, I'll likely only report back with results next week, though.
> Do you happen to have an image you can point me to? Either something
> that has the benchmark already or some unixoid running on the platform?
> I'm currently not motivated enough to cook up some bare-metal testbed
> for a platform I'm not familiar with.
I don't have ready images to test embedded PPC MMU exceptions which I
think this may affect most. I had an image for pegasos2 for a general test
used here:
https://lists.nongnu.org/archive/html/qemu-discuss/2023-12/msg00008.html
but that machine has a G4 CPU which has hardware MMU so is likely not
affected.
I have uploaded some PPC binaries for the STREAM benchmark that I tested
with before here:
http://zero.eik.bme.hu/~balaton/qemu/stream-test.zip
which may excercise this if run on sam460ex or ppce500 machines but I
don't have a scripted test case for that. There is some docs on how to run
Linux on these machines here:
https://www.qemu.org/docs/master/system/target-ppc.html
Alternatively maybe running a disk IO benchmark on an emulated IDE
controller using PIO mode or some other device that generates a lots of
interrupts may test this. I think you can use the "info irq" command in
QEMU Monitor to check how many interrupts you get.
Regards,
BALATON Zoltan
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-07 20:21 ` BALATON Zoltan
@ 2025-09-08 20:51 ` Julian Ganz
2025-09-09 19:48 ` Julian Ganz
1 sibling, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-08 20:51 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: qemu-devel, Alex Bennée
September 7, 2025 at 10:21 PM, "BALATON Zoltan" wrote:
> On Fri, 5 Sep 2025, Julian Ganz wrote:
>
> >
> > September 5, 2025 at 9:25 PM, "BALATON Zoltan" wrote:
> > > The default may better be what the larger group needs. Even then distros may still change the default so it would be best if the overhead can be minimised even if enabled. I think the log infrastructure does that, would a similar solution work here?
> > >
> > > For testing I've found that because embedded PPC CPUs have a software controlled MMU (and in addition to that QEMU may flush TLB entries too often) running something that does a lot of memory access like runnung the STREAM benchmark on sam460ex is hit by this IIRC but anything else causing a lot of interrupts like reading from emulated disk or sound is probably affected as well. I've tried to optimise PPC exception handling a bit before but whenever I optimise something it is later undone by other changes not caring about performance.
> > >
> > I could try running the benchmark on multiple versions:
> >
> > * qemu with plugins disabled,
> > * with plugins enabled but without these patches and
> > * with plugins enabled and with these patches.
> >
> > However, I'll likely only report back with results next week, though.
> > Do you happen to have an image you can point me to? Either something
> > that has the benchmark already or some unixoid running on the platform?
> > I'm currently not motivated enough to cook up some bare-metal testbed
> > for a platform I'm not familiar with.
> >
> I don't have ready images to test embedded PPC MMU exceptions which I think this may affect most. I had an image for pegasos2 for a general test used here:
> https://lists.nongnu.org/archive/html/qemu-discuss/2023-12/msg00008.html
> but that machine has a G4 CPU which has hardware MMU so is likely not affected.
I ran this test anyway, because it was easy enough to run. Tweaked the
script to do 10 runs, each with one of the aforementioned variants.
Isolating the time stats printed gives you the following:
Qemu with patches and plugins enabled:
Frame | CPU time/estim | REAL time/estim | play/CPU | ETA
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2557x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2621x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2536x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2394x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2529x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2565x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2456x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2450x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2526x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2528x| 0:00
Qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these patches,
but plugins enabled:
Frame | CPU time/estim | REAL time/estim | play/CPU | ETA
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2309x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2399x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2547x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2511x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2265x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2156x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2401x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2460x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2472x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2370x| 0:00
Qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these patches,
with plugins disabled:
Frame | CPU time/estim | REAL time/estim | play/CPU | ETA
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2478x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2509x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2500x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2019x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2439x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2453x| 0:00
1149/1149 (100%)| 0:25/ 0:25| 0:25/ 0:25| 1.1945x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2331x| 0:00
1149/1149 (100%)| 0:23/ 0:23| 0:23/ 0:23| 1.2510x| 0:00
1149/1149 (100%)| 0:24/ 0:24| 0:24/ 0:24| 1.2467x| 0:00
So nothing to see here. If anything, we see a slight reduction in
runtime with these patches, which doesn't makes any sense. I did not do
a fresh clean build for those, and the order I ran the tests may have
had some influence on the results.
> I have uploaded some PPC binaries for the STREAM benchmark that I tested with before here:
> http://zero.eik.bme.hu/~balaton/qemu/stream-test.zip
> which may excercise this if run on sam460ex or ppce500 machines but I don't have a scripted test case for that. There is some docs on how to run Linux on these machines here:
> https://www.qemu.org/docs/master/system/target-ppc.html
Thanks, I'll have alook at how to run those over the course of this
week.
> Alternatively maybe running a disk IO benchmark on an emulated IDE controller using PIO mode or some other device that generates a lots of interrupts may test this. I think you can use the "info irq" command in QEMU Monitor to check how many interrupts you get.
I started writing a small exception/interrupt torture test for the
PPC440 with the help of robots. If and when I'm finishing it I'll do
some measurements with that.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-07 20:21 ` BALATON Zoltan
2025-09-08 20:51 ` Julian Ganz
@ 2025-09-09 19:48 ` Julian Ganz
2025-09-10 10:06 ` BALATON Zoltan
1 sibling, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-09 19:48 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: qemu-devel, Alex Bennée
September 7, 2025 at 10:21 PM, "BALATON Zoltan" wrote:
> I have uploaded some PPC binaries for the STREAM benchmark that I tested with before here:
> http://zero.eik.bme.hu/~balaton/qemu/stream-test.zip
> which may excercise this if run on sam460ex or ppce500 machines but I don't have a scripted test case for that. There is some docs on how to run Linux on these machines here:
> https://www.qemu.org/docs/master/system/target-ppc.html
After spending too much time looking for usable root-images (and then
giving up and just stuffing the executables in an ext2), I got to run
these beanchmarks on Linux 4.4.5 configured for the Sam460ex from [1].
I ran streamPPCpowerpcO3 on qemu with these patches:
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 2867.6 0.056828 0.055795 0.061792
Scale: 1057.5 0.153282 0.151305 0.158115
Add: 1308.8 0.187095 0.183380 0.193672
Triad: 1111.6 0.220863 0.215902 0.230440
-------------------------------------------------------------
After doing a clean build, with the fans still audible:
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 2932.9 0.055131 0.054554 0.055667
Scale: 1067.9 0.151520 0.149832 0.155000
Add: 1324.9 0.184807 0.181150 0.191386
Triad: 1122.0 0.220080 0.213896 0.229302
-------------------------------------------------------------
On qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
patches, but plugins enabled:
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 2972.1 0.054407 0.053834 0.054675
Scale: 1068.6 0.151503 0.149726 0.154594
Add: 1327.6 0.185160 0.180784 0.193181
Triad: 1127.2 0.219249 0.212915 0.229230
-------------------------------------------------------------
And on qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
patches, with plugins disabled:
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 2983.4 0.055141 0.053630 0.060013
Scale: 1058.3 0.152353 0.151186 0.155072
Add: 1323.9 0.184707 0.181279 0.188868
Triad: 1128.2 0.218674 0.212734 0.230314
-------------------------------------------------------------
I fail to see any significant indication that these patches, or
plugins in general, would result in a degredation of performance.
Regards,
Julian
[1]: http://www.supertuxkart-amiga.de/amiga/sam.html#downloads
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-09 19:48 ` Julian Ganz
@ 2025-09-10 10:06 ` BALATON Zoltan
2025-09-10 11:41 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: BALATON Zoltan @ 2025-09-10 10:06 UTC (permalink / raw)
To: Julian Ganz; +Cc: qemu-devel, Alex Bennée
On Tue, 9 Sep 2025, Julian Ganz wrote:
> September 7, 2025 at 10:21 PM, "BALATON Zoltan" wrote:
>> I have uploaded some PPC binaries for the STREAM benchmark that I tested with before here:
>> http://zero.eik.bme.hu/~balaton/qemu/stream-test.zip
>> which may excercise this if run on sam460ex or ppce500 machines but I don't have a scripted test case for that. There is some docs on how to run Linux on these machines here:
>> https://www.qemu.org/docs/master/system/target-ppc.html
>
> After spending too much time looking for usable root-images (and then
> giving up and just stuffing the executables in an ext2), I got to run
> these beanchmarks on Linux 4.4.5 configured for the Sam460ex from [1].
Thank you for testing this.
> I ran streamPPCpowerpcO3 on qemu with these patches:
>
> -------------------------------------------------------------
> Function Best Rate MB/s Avg time Min time Max time
> Copy: 2867.6 0.056828 0.055795 0.061792
> Scale: 1057.5 0.153282 0.151305 0.158115
> Add: 1308.8 0.187095 0.183380 0.193672
> Triad: 1111.6 0.220863 0.215902 0.230440
> -------------------------------------------------------------
>
> After doing a clean build, with the fans still audible:
>
> -------------------------------------------------------------
> Function Best Rate MB/s Avg time Min time Max time
> Copy: 2932.9 0.055131 0.054554 0.055667
> Scale: 1067.9 0.151520 0.149832 0.155000
> Add: 1324.9 0.184807 0.181150 0.191386
> Triad: 1122.0 0.220080 0.213896 0.229302
> -------------------------------------------------------------
What was different between the above two runs? I guess maybe one is with
plugins disabled but it's not clear from the description.
> On qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
> patches, but plugins enabled:
>
> -------------------------------------------------------------
> Function Best Rate MB/s Avg time Min time Max time
> Copy: 2972.1 0.054407 0.053834 0.054675
> Scale: 1068.6 0.151503 0.149726 0.154594
> Add: 1327.6 0.185160 0.180784 0.193181
> Triad: 1127.2 0.219249 0.212915 0.229230
> -------------------------------------------------------------
>
> And on qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
> patches, with plugins disabled:
>
> -------------------------------------------------------------
> Function Best Rate MB/s Avg time Min time Max time
> Copy: 2983.4 0.055141 0.053630 0.060013
> Scale: 1058.3 0.152353 0.151186 0.155072
> Add: 1323.9 0.184707 0.181279 0.188868
> Triad: 1128.2 0.218674 0.212734 0.230314
> -------------------------------------------------------------
>
> I fail to see any significant indication that these patches, or
> plugins in general, would result in a degredation of performance.
With worst case Copy test it seems to be about 3.5% (and about 1.7% with
plugins disabled?) and should be less than that normally so it does not
add much more overhead to plugins than there is already so this should be
acceptable. It may still be interesting to see if the overhead with
plugins disabled can be avoided with a similar way as logging does it.
Regards,
BALATON Zoltan
> Regards,
> Julian
>
> [1]: http://www.supertuxkart-amiga.de/amiga/sam.html#downloads
>
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-10 10:06 ` BALATON Zoltan
@ 2025-09-10 11:41 ` Julian Ganz
2025-09-10 12:09 ` Alex Bennée
0 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-10 11:41 UTC (permalink / raw)
To: BALATON Zoltan; +Cc: qemu-devel, Alex Bennée
September 10, 2025 at 12:06 PM, "BALATON Zoltan" wrote:
> On Tue, 9 Sep 2025, Julian Ganz wrote:
> > I ran streamPPCpowerpcO3 on qemu with these patches:
> >
> > -------------------------------------------------------------
> > Function Best Rate MB/s Avg time Min time Max time
> > Copy: 2867.6 0.056828 0.055795 0.061792
> > Scale: 1057.5 0.153282 0.151305 0.158115
> > Add: 1308.8 0.187095 0.183380 0.193672
> > Triad: 1111.6 0.220863 0.215902 0.230440
> > -------------------------------------------------------------
> >
> > After doing a clean build, with the fans still audible:
> >
> > -------------------------------------------------------------
> > Function Best Rate MB/s Avg time Min time Max time
> > Copy: 2932.9 0.055131 0.054554 0.055667
> > Scale: 1067.9 0.151520 0.149832 0.155000
> > Add: 1324.9 0.184807 0.181150 0.191386
> > Triad: 1122.0 0.220080 0.213896 0.229302
> > -------------------------------------------------------------
> >
> What was different between the above two runs? I guess maybe one is with plugins disabled but it's not clear from the description.
The difference is nothing but a a clean rebuild of qemu. As you see
there are fluctuations already. Plugins are enabled for both cases.
> > On qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
> > patches, but plugins enabled:
> >
> > -------------------------------------------------------------
> > Function Best Rate MB/s Avg time Min time Max time
> > Copy: 2972.1 0.054407 0.053834 0.054675
> > Scale: 1068.6 0.151503 0.149726 0.154594
> > Add: 1327.6 0.185160 0.180784 0.193181
> > Triad: 1127.2 0.219249 0.212915 0.229230
> > -------------------------------------------------------------
> >
> > And on qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
> > patches, with plugins disabled:
> >
> > -------------------------------------------------------------
> > Function Best Rate MB/s Avg time Min time Max time
> > Copy: 2983.4 0.055141 0.053630 0.060013
> > Scale: 1058.3 0.152353 0.151186 0.155072
> > Add: 1323.9 0.184707 0.181279 0.188868
> > Triad: 1128.2 0.218674 0.212734 0.230314
> > -------------------------------------------------------------
> >
> > I fail to see any significant indication that these patches, or
> > plugins in general, would result in a degredation of performance.
> >
> With worst case Copy test it seems to be about 3.5% (and about 1.7% with plugins disabled?) and should be less than that normally so it does not add much more overhead to plugins than there is already so this should be acceptable. It may still be interesting to see if the overhead with plugins disabled can be avoided with a similar way as logging does it.
The thing is: that's probably just usual fluctuations. As you have seen
with the first two measurements the values fluctuate quite a bit between
runs of the test on the very same qemu (assuming that a clean build did
not incur any _other_ relevant change). For example, the best rate for
scale shown with plugins enabled is one percent faster than with plugins
disabled. Is this significant? Probably not. Or at least it doesn't make
much sense.
TL:RD: run the very same test multiple times without any changes and
you get "vastly" different results.
And just from these coarse statistics it's hard to judge whether
especially min/max have any significance anyway. That's why you usually
also include deviation/variance when writing performance tests, and some
percentiles if you have enough individual measurements and the means
to store those. What you _can_ tell from these numbers is that the
spread for a single function and run is in the percents.
I may do some more tests this week, with runtimes longer than a few
seconds if I can find the motivation to set up everything I'd need to
compile your benchmark. In the mean-time, you are welcome to make your
own measurements if you want to. The patches are also availible at [1]
if you don't want to apply them to your local tree yourself.
Regards,
Julian
[1]: https://github.com/patchew-project/qemu/tree/patchew/cover.1757018626.git.neither@nut.email
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-10 11:41 ` Julian Ganz
@ 2025-09-10 12:09 ` Alex Bennée
2025-09-10 15:04 ` BALATON Zoltan
0 siblings, 1 reply; 57+ messages in thread
From: Alex Bennée @ 2025-09-10 12:09 UTC (permalink / raw)
To: Julian Ganz; +Cc: BALATON Zoltan, qemu-devel
"Julian Ganz" <neither@nut.email> writes:
> September 10, 2025 at 12:06 PM, "BALATON Zoltan" wrote:
>> On Tue, 9 Sep 2025, Julian Ganz wrote:
>> > I ran streamPPCpowerpcO3 on qemu with these patches:
>> >
>> > -------------------------------------------------------------
>> > Function Best Rate MB/s Avg time Min time Max time
>> > Copy: 2867.6 0.056828 0.055795 0.061792
>> > Scale: 1057.5 0.153282 0.151305 0.158115
>> > Add: 1308.8 0.187095 0.183380 0.193672
>> > Triad: 1111.6 0.220863 0.215902 0.230440
>> > -------------------------------------------------------------
>> >
>> > After doing a clean build, with the fans still audible:
>> >
>> > -------------------------------------------------------------
>> > Function Best Rate MB/s Avg time Min time Max time
>> > Copy: 2932.9 0.055131 0.054554 0.055667
>> > Scale: 1067.9 0.151520 0.149832 0.155000
>> > Add: 1324.9 0.184807 0.181150 0.191386
>> > Triad: 1122.0 0.220080 0.213896 0.229302
>> > -------------------------------------------------------------
>> >
>> What was different between the above two runs? I guess maybe one is with plugins disabled but it's not clear from the description.
>
> The difference is nothing but a a clean rebuild of qemu. As you see
> there are fluctuations already. Plugins are enabled for both cases.
>
>> > On qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
>> > patches, but plugins enabled:
>> >
>> > -------------------------------------------------------------
>> > Function Best Rate MB/s Avg time Min time Max time
>> > Copy: 2972.1 0.054407 0.053834 0.054675
>> > Scale: 1068.6 0.151503 0.149726 0.154594
>> > Add: 1327.6 0.185160 0.180784 0.193181
>> > Triad: 1127.2 0.219249 0.212915 0.229230
>> > -------------------------------------------------------------
>> >
>> > And on qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
>> > patches, with plugins disabled:
>> >
>> > -------------------------------------------------------------
>> > Function Best Rate MB/s Avg time Min time Max time
>> > Copy: 2983.4 0.055141 0.053630 0.060013
>> > Scale: 1058.3 0.152353 0.151186 0.155072
>> > Add: 1323.9 0.184707 0.181279 0.188868
>> > Triad: 1128.2 0.218674 0.212734 0.230314
>> > -------------------------------------------------------------
>> >
>> > I fail to see any significant indication that these patches, or
>> > plugins in general, would result in a degredation of performance.
>> >
>> With worst case Copy test it seems to be about 3.5% (and about 1.7%
>> with plugins disabled?) and should be less than that normally so it
>> does not add much more overhead to plugins than there is already so
>> this should be acceptable. It may still be interesting to see if the
>> overhead with plugins disabled can be avoided with a similar way as
>> logging does it.
>
> The thing is: that's probably just usual fluctuations. As you have seen
> with the first two measurements the values fluctuate quite a bit between
> runs of the test on the very same qemu (assuming that a clean build did
> not incur any _other_ relevant change). For example, the best rate for
> scale shown with plugins enabled is one percent faster than with plugins
> disabled. Is this significant? Probably not. Or at least it doesn't make
> much sense.
I wouldn't spend too much time chasing this down. As you say this
fluctuation is well within the noise range.
I can recommend hyperfine as a runner:
https://github.com/sharkdp/hyperfine
as it does some work on how many times you need to run a test before the
results are statistically relevant.
> I may do some more tests this week, with runtimes longer than a few
> seconds if I can find the motivation to set up everything I'd need to
> compile your benchmark. In the mean-time, you are welcome to make your
> own measurements if you want to. The patches are also availible at [1]
> if you don't want to apply them to your local tree yourself.
Balton,
I don't think worries about performance impact are justified and Julian
has certainly done enough due diligence here. If you can come up with a
repeatable test that shows a measurable impact then please do so.
>
> Regards,
> Julian
>
> [1]: https://github.com/patchew-project/qemu/tree/patchew/cover.1757018626.git.neither@nut.email
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-10 12:09 ` Alex Bennée
@ 2025-09-10 15:04 ` BALATON Zoltan
0 siblings, 0 replies; 57+ messages in thread
From: BALATON Zoltan @ 2025-09-10 15:04 UTC (permalink / raw)
To: Alex Bennée; +Cc: Julian Ganz, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 4920 bytes --]
On Wed, 10 Sep 2025, Alex Bennée wrote:
> "Julian Ganz" <neither@nut.email> writes:
>> September 10, 2025 at 12:06 PM, "BALATON Zoltan" wrote:
>>> On Tue, 9 Sep 2025, Julian Ganz wrote:
>>>> I ran streamPPCpowerpcO3 on qemu with these patches:
>>>>
>>>> -------------------------------------------------------------
>>>> Function Best Rate MB/s Avg time Min time Max time
>>>> Copy: 2867.6 0.056828 0.055795 0.061792
>>>> Scale: 1057.5 0.153282 0.151305 0.158115
>>>> Add: 1308.8 0.187095 0.183380 0.193672
>>>> Triad: 1111.6 0.220863 0.215902 0.230440
>>>> -------------------------------------------------------------
>>>>
>>>> After doing a clean build, with the fans still audible:
>>>>
>>>> -------------------------------------------------------------
>>>> Function Best Rate MB/s Avg time Min time Max time
>>>> Copy: 2932.9 0.055131 0.054554 0.055667
>>>> Scale: 1067.9 0.151520 0.149832 0.155000
>>>> Add: 1324.9 0.184807 0.181150 0.191386
>>>> Triad: 1122.0 0.220080 0.213896 0.229302
>>>> -------------------------------------------------------------
>>>>
>>> What was different between the above two runs? I guess maybe one is with plugins disabled but it's not clear from the description.
>>
>> The difference is nothing but a a clean rebuild of qemu. As you see
>> there are fluctuations already. Plugins are enabled for both cases.
>>
>>>> On qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
>>>> patches, but plugins enabled:
>>>>
>>>> -------------------------------------------------------------
>>>> Function Best Rate MB/s Avg time Min time Max time
>>>> Copy: 2972.1 0.054407 0.053834 0.054675
>>>> Scale: 1068.6 0.151503 0.149726 0.154594
>>>> Add: 1327.6 0.185160 0.180784 0.193181
>>>> Triad: 1127.2 0.219249 0.212915 0.229230
>>>> -------------------------------------------------------------
>>>>
>>>> And on qemu (6a9fa5ef3230a7d51e0d953a59ee9ef10af705b8) without these
>>>> patches, with plugins disabled:
>>>>
>>>> -------------------------------------------------------------
>>>> Function Best Rate MB/s Avg time Min time Max time
>>>> Copy: 2983.4 0.055141 0.053630 0.060013
>>>> Scale: 1058.3 0.152353 0.151186 0.155072
>>>> Add: 1323.9 0.184707 0.181279 0.188868
>>>> Triad: 1128.2 0.218674 0.212734 0.230314
>>>> -------------------------------------------------------------
>>>>
>>>> I fail to see any significant indication that these patches, or
>>>> plugins in general, would result in a degredation of performance.
>>>>
>>> With worst case Copy test it seems to be about 3.5% (and about 1.7%
>>> with plugins disabled?) and should be less than that normally so it
>>> does not add much more overhead to plugins than there is already so
>>> this should be acceptable. It may still be interesting to see if the
>>> overhead with plugins disabled can be avoided with a similar way as
>>> logging does it.
>>
>> The thing is: that's probably just usual fluctuations. As you have seen
>> with the first two measurements the values fluctuate quite a bit between
>> runs of the test on the very same qemu (assuming that a clean build did
>> not incur any _other_ relevant change). For example, the best rate for
>> scale shown with plugins enabled is one percent faster than with plugins
>> disabled. Is this significant? Probably not. Or at least it doesn't make
>> much sense.
>
> I wouldn't spend too much time chasing this down. As you say this
> fluctuation is well within the noise range.
>
> I can recommend hyperfine as a runner:
>
> https://github.com/sharkdp/hyperfine
>
> as it does some work on how many times you need to run a test before the
> results are statistically relevant.
>
>> I may do some more tests this week, with runtimes longer than a few
>> seconds if I can find the motivation to set up everything I'd need to
>> compile your benchmark. In the mean-time, you are welcome to make your
>> own measurements if you want to. The patches are also availible at [1]
>> if you don't want to apply them to your local tree yourself.
>
> Balton,
>
> I don't think worries about performance impact are justified and Julian
> has certainly done enough due diligence here. If you can come up with a
> repeatable test that shows a measurable impact then please do so.
I agree this testing is enough to ensure there is no big impact. I just
wanted to make sure there is some testing and not just adding stuff
without worrying about performance. I'd like to keep QEMU quick and only
add unavoidable overhead where possible but I don't demand to spend too
much time on that. If Julian got interested and does more testing that may
give some interesting results for possible optimisation but if no time for
that this was enough to measure the impact for this series.
Regards,
BALATON Zoltan
>> Regards,
>> Julian
>>
>> [1]: https://github.com/patchew-project/qemu/tree/patchew/cover.1757018626.git.neither@nut.email
>
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-04 20:48 ` [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
@ 2025-09-21 16:46 ` Alex Bennée
2025-09-22 10:11 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: Alex Bennée @ 2025-09-21 16:46 UTC (permalink / raw)
To: Julian Ganz
Cc: qemu-devel, Pierrick Bouvier, Alexandre Iooss, Mahmoud Mandour
Julian Ganz <neither@nut.email> writes:
> We recently introduced plugin API for the registration of callbacks for
> discontinuity events, specifically for interrupts, exceptions and host
> call events. The callback receives various bits of information,
> including the VCPU index and PCs.
>
> This change introduces a test plugin asserting the correctness of that
> behaviour in cases where this is possible with reasonable effort.
>
> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> tests/tcg/plugins/discons.c | 210 ++++++++++++++++++++++++++++++++++
> tests/tcg/plugins/meson.build | 2 +-
> 2 files changed, 211 insertions(+), 1 deletion(-)
> create mode 100644 tests/tcg/plugins/discons.c
>
> diff --git a/tests/tcg/plugins/discons.c b/tests/tcg/plugins/discons.c
> new file mode 100644
> index 0000000000..f185e3948b
> --- /dev/null
> +++ b/tests/tcg/plugins/discons.c
> @@ -0,0 +1,210 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2025, Julian Ganz <neither@nut.email>
> + *
> + * This plugin exercises the discontinuity plugin API and asserts some
> + * of its behaviour regarding reported program counters.
> + */
> +#include <stdio.h>
> +
> +#include <qemu-plugin.h>
> +
> +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +
> +struct cpu_state {
> + uint64_t last_pc;
> + uint64_t from_pc;
> + uint64_t next_pc;
> + uint64_t has_from;
> + bool has_next;
> + enum qemu_plugin_discon_type next_type;
> +};
> +
> +struct insn_data {
> + uint64_t addr;
> + uint64_t next_pc;
> + bool next_valid;
> +};
> +
> +static struct qemu_plugin_scoreboard *states;
> +
> +static qemu_plugin_u64 last_pc;
> +static qemu_plugin_u64 from_pc;
> +static qemu_plugin_u64 has_from;
> +
> +static bool abort_on_mismatch;
> +static bool trace_all_insns;
> +
> +static bool addr_eq(uint64_t a, uint64_t b)
> +{
> + if (a == b) {
> + return true;
> + }
> +
> + uint64_t a_hw;
> + uint64_t b_hw;
> + if (!qemu_plugin_translate_vaddr(a, &a_hw) ||
> + !qemu_plugin_translate_vaddr(b, &b_hw))
> + {
> + return false;
> + }
> +
> + return a_hw == b_hw;
> +}
> +
> +static void report_mismatch(const char *pc_name, unsigned int vcpu_index,
> + enum qemu_plugin_discon_type type, uint64_t last,
> + uint64_t expected, uint64_t encountered)
> +{
> + GString *report;
This could be:
g_autoptr(GString) buf = g_string_new(NULL);
> + const char *discon_type_name = "unknown";
> +
> + if (addr_eq(expected, encountered)) {
> + return;
> + }
> +
> + switch (type) {
> + case QEMU_PLUGIN_DISCON_INTERRUPT:
> + discon_type_name = "interrupt";
> + break;
> + case QEMU_PLUGIN_DISCON_EXCEPTION:
> + discon_type_name = "exception";
> + break;
> + case QEMU_PLUGIN_DISCON_HOSTCALL:
> + discon_type_name = "hostcall";
> + break;
> + default:
> + break;
> + }
> +
> + report = g_string_new(NULL);
> + g_string_append_printf(report,
> + "Discon %s PC mismatch on VCPU %d\nExpected: %"
> + PRIx64"\nEncountered: %"PRIx64"\nExecuted Last: %"
> + PRIx64"\nEvent type: %s\n",
> + pc_name, vcpu_index, expected, encountered, last,
> + discon_type_name);
> + qemu_plugin_outs(report->str);
I think we might want to flush here because
> + if (abort_on_mismatch) {
> + g_abort();
> + }
This is firing on:
🕙17:35:50 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?]
➜ make run-plugin-catch-syscalls-with-libdiscons.so V=1
timeout -s KILL --foreground 120 env QEMU=/home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 -plugin ../plugins/libdiscons.so -d plugin -D catch-syscalls-with-libdiscons.so.pout catch-syscalls > run-plugin-catch-syscalls-with-libdiscons.so.out
Aborted
make: *** [Makefile:226: run-plugin-catch-syscalls-with-libdiscons.so] Error 134
🕙17:35:52 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?] [🔴 USAGE]
✗
although it never gets to the point of reporting what failed:
Thread 1 "qemu-i386" hit Breakpoint 1, __GI_abort () at ./stdlib/abort.c:72
warning: 72 ./stdlib/abort.c: No such file or directory
(gdb) bt
#0 __GI_abort () at ./stdlib/abort.c:72
#1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
#2 0x00007ffff6308c0d in insn_exec (vcpu_index=0, userdata=0x0) at ../../tests/tcg/plugins/discons.c:132
#3 0x00007fffea431114 in code_gen_buffer ()
#4 0x000055555577b0a6 in cpu_tb_exec (cpu=0x529000005200, itb=0x7fffea431000 <code_gen_buffer+200659>, tb_exit=0x7ffff49c9530) at ../../accel/tcg/cpu-exec.c:438
#5 0x000055555577c92f in cpu_loop_exec_tb (cpu=0x529000005200, tb=0x7fffea431000 <code_gen_buffer+200659>, pc=134574955, last_tb=0x7ffff49c9540, tb_exit=0x7ffff49c9530)
at ../../accel/tcg/cpu-exec.c:871
#6 0x000055555577d151 in cpu_exec_loop (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:981
#7 0x000055555577d2fe in cpu_exec_setjmp (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:998
#8 0x000055555577d4c8 in cpu_exec (cpu=0x529000005200) at ../../accel/tcg/cpu-exec.c:1024
#9 0x00005555557bfc83 in cpu_loop (env=0x529000007dd0) at ../../linux-user/i386/cpu_loop.c:215
#10 0x00005555558ee3e1 in main (argc=4, argv=0x7fffffffe688, envp=0x7fffffffe6b0) at ../../linux-user/main.c:1038
(gdb) f 1
#1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
89 g_abort();
(gdb) p report
$1 = (GString *) 0x50300002bf00
(gdb) p report->Str
There is no member named Str.
(gdb) p report->str
$2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
(gdb)
I think this is where it is going wrong:
IN: _dl_early_allocate
0x0805736b: 89 c2 movl %eax, %edx
0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
0x08057370: 89 c8 movl %ecx, %eax
0x08057372: cd 80 int $0x80
> + g_string_free(report, true);
so we could drop this... or..
> +}
> +
> +static void vcpu_discon(qemu_plugin_id_t id, unsigned int vcpu_index,
> + enum qemu_plugin_discon_type type, uint64_t from_pc,
> + uint64_t to_pc)
> +{
> + struct cpu_state *state = qemu_plugin_scoreboard_find(states, vcpu_index);
> +
> + if (type == QEMU_PLUGIN_DISCON_EXCEPTION &&
> + addr_eq(state->last_pc, from_pc))
> + {
> + /*
> + * For some types of exceptions, insn_exec will be called for the
> + * instruction that caused the exception. This is valid behaviour and
> + * does not need to be reported.
> + */
> + } else if (state->has_next) {
> + /*
> + * We may encounter discontinuity chains without any instructions
> + * being executed in between.
> + */
> + report_mismatch("source", vcpu_index, type, state->last_pc,
> + state->next_pc, from_pc);
> + } else if (state->has_from) {
> + report_mismatch("source", vcpu_index, type, state->last_pc,
> + state->from_pc, from_pc);
> + }
> +
> + state->has_from = false;
> +
> + state->next_pc = to_pc;
> + state->next_type = type;
> + state->has_next = true;
> +}
> +
> +static void insn_exec(unsigned int vcpu_index, void *userdata)
> +{
> + struct cpu_state *state = qemu_plugin_scoreboard_find(states, vcpu_index);
> +
> + if (state->has_next) {
> + report_mismatch("target", vcpu_index, state->next_type, state->last_pc,
> + state->next_pc, state->last_pc);
> + state->has_next = false;
> + }
> +
> + if (trace_all_insns) {
> + g_autoptr(GString) report = g_string_new(NULL);
> + g_string_append_printf(report, "Exec insn at %"PRIx64" on VCPU %d\n",
> + state->last_pc, vcpu_index);
> + qemu_plugin_outs(report->str);
> + }
> +}
> +
> +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
> +{
> + size_t n_insns = qemu_plugin_tb_n_insns(tb);
> + for (size_t i = 0; i < n_insns; i++) {
> + struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
> + uint64_t pc = qemu_plugin_insn_vaddr(insn);
> + uint64_t next_pc = pc + qemu_plugin_insn_size(insn);
> + uint64_t has_next = (i + 1) < n_insns;
> +
> + qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
> + QEMU_PLUGIN_INLINE_STORE_U64,
> + last_pc, pc);
> + qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
> + QEMU_PLUGIN_INLINE_STORE_U64,
> + from_pc, next_pc);
> + qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
> + QEMU_PLUGIN_INLINE_STORE_U64,
> + has_from, has_next);
> + qemu_plugin_register_vcpu_insn_exec_cb(insn, insn_exec,
> + QEMU_PLUGIN_CB_NO_REGS, NULL);
> + }
> +}
> +
> +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
> + const qemu_info_t *info,
> + int argc, char **argv)
> +{
> + /* Set defaults */
> + abort_on_mismatch = true;
> + trace_all_insns = false;
> +
> + for (int i = 0; i < argc; i++) {
> + char *opt = argv[i];
> + g_auto(GStrv) tokens = g_strsplit(opt, "=", 2);
> + if (g_strcmp0(tokens[0], "abort") == 0) {
> + if (!qemu_plugin_bool_parse(tokens[0], tokens[1],
> + &abort_on_mismatch)) {
> + fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
> + return -1;
> + }
> + } else if (g_strcmp0(tokens[0], "trace-all") == 0) {
> + if (!qemu_plugin_bool_parse(tokens[0], tokens[1],
> + &trace_all_insns)) {
> + fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
> + return -1;
> + }
> + } else {
> + fprintf(stderr, "option parsing failed: %s\n", opt);
> + return -1;
> + }
> + }
> +
> + states = qemu_plugin_scoreboard_new(sizeof(struct cpu_state));
> + last_pc = qemu_plugin_scoreboard_u64_in_struct(states, struct cpu_state,
> + last_pc);
> + from_pc = qemu_plugin_scoreboard_u64_in_struct(states, struct cpu_state,
> + from_pc);
> + has_from = qemu_plugin_scoreboard_u64_in_struct(states, struct cpu_state,
> + has_from);
> +
> + qemu_plugin_register_vcpu_discon_cb(id, QEMU_PLUGIN_DISCON_ALL,
> + vcpu_discon);
> + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
> +
> + return 0;
> +}
> diff --git a/tests/tcg/plugins/meson.build b/tests/tcg/plugins/meson.build
> index 61a007d9e7..561584159e 100644
> --- a/tests/tcg/plugins/meson.build
> +++ b/tests/tcg/plugins/meson.build
> @@ -1,6 +1,6 @@
> t = []
> if get_option('plugins')
> - foreach i : ['bb', 'empty', 'inline', 'insn', 'mem', 'reset', 'syscall', 'patch']
> + foreach i : ['bb', 'discons', 'empty', 'inline', 'insn', 'mem', 'reset', 'syscall', 'patch']
> if host_os == 'windows'
> t += shared_module(i, files(i + '.c') + '../../../contrib/plugins/win32_linker.c',
> include_directories: '../../../include/qemu',
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-21 16:46 ` Alex Bennée
@ 2025-09-22 10:11 ` Julian Ganz
2025-09-22 10:15 ` Daniel P. Berrangé
2025-09-23 20:29 ` Julian Ganz
0 siblings, 2 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-22 10:11 UTC (permalink / raw)
To: Alex Bennée
Cc: qemu-devel, Pierrick Bouvier, Alexandre Iooss, Mahmoud Mandour
Hi Alex,
September 21, 2025 at 6:46 PM, "Alex Bennée" <alex.bennee@linaro.org mailto:alex.bennee@linaro.org?to=%22Alex%20Benn%C3%A9e%22%20%3Calex.bennee%40linaro.org%3E > wrote:
> Julian Ganz <neither@nut.email> writes:
> > +static void report_mismatch(const char *pc_name, unsigned int vcpu_index,
> > + enum qemu_plugin_discon_type type, uint64_t last,
> > + uint64_t expected, uint64_t encountered)
> > +{
> > + GString *report;
> >
> This could be:
>
> g_autoptr(GString) buf = g_string_new(NULL);
I wanted to avoid doing an allocation regardless of whether we do have
anything to report or not. But I guess a performance plugin isn't
performance critical enough to worry? Anyway, I will have another look
at g_autoptr.
> > + const char *discon_type_name = "unknown";
> > +
> > + if (addr_eq(expected, encountered)) {
> > + return;
> > + }
> > +
> > + switch (type) {
> > + case QEMU_PLUGIN_DISCON_INTERRUPT:
> > + discon_type_name = "interrupt";
> > + break;
> > + case QEMU_PLUGIN_DISCON_EXCEPTION:
> > + discon_type_name = "exception";
> > + break;
> > + case QEMU_PLUGIN_DISCON_HOSTCALL:
> > + discon_type_name = "hostcall";
> > + break;
> > + default:
> > + break;
> > + }
> > +
> > + report = g_string_new(NULL);
> > + g_string_append_printf(report,
> > + "Discon %s PC mismatch on VCPU %d\nExpected: %"
> > + PRIx64"\nEncountered: %"PRIx64"\nExecuted Last: %"
> > + PRIx64"\nEvent type: %s\n",
> > + pc_name, vcpu_index, expected, encountered, last,
> > + discon_type_name);
> > + qemu_plugin_outs(report->str);
> >
> I think we might want to flush here because
Yes we do. I probably (incorrectly) assumed `qemu_plugin_outs` already
did that.
>
> >
> > + if (abort_on_mismatch) {
> > + g_abort();
> > + }
> >
> This is firing on:
>
> 🕙17:35:50 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?]
> ➜ make run-plugin-catch-syscalls-with-libdiscons.so V=1
> timeout -s KILL --foreground 120 env QEMU=/home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 -plugin ../plugins/libdiscons.so -d plugin -D catch-syscalls-with-libdiscons.so.pout catch-syscalls > run-plugin-catch-syscalls-with-libdiscons.so.out
> Aborted
> make: *** [Makefile:226: run-plugin-catch-syscalls-with-libdiscons.so] Error 134
> 🕙17:35:52 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?] [🔴 USAGE]
> ✗
>
> although it never gets to the point of reporting what failed:
>
> Thread 1 "qemu-i386" hit Breakpoint 1, __GI_abort () at ./stdlib/abort.c:72
> warning: 72 ./stdlib/abort.c: No such file or directory
> (gdb) bt
> #0 __GI_abort () at ./stdlib/abort.c:72
> #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> #2 0x00007ffff6308c0d in insn_exec (vcpu_index=0, userdata=0x0) at ../../tests/tcg/plugins/discons.c:132
> #3 0x00007fffea431114 in code_gen_buffer ()
> #4 0x000055555577b0a6 in cpu_tb_exec (cpu=0x529000005200, itb=0x7fffea431000 <code_gen_buffer+200659>, tb_exit=0x7ffff49c9530) at ../../accel/tcg/cpu-exec.c:438
> #5 0x000055555577c92f in cpu_loop_exec_tb (cpu=0x529000005200, tb=0x7fffea431000 <code_gen_buffer+200659>, pc=134574955, last_tb=0x7ffff49c9540, tb_exit=0x7ffff49c9530)
> at ../../accel/tcg/cpu-exec.c:871
> #6 0x000055555577d151 in cpu_exec_loop (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:981
> #7 0x000055555577d2fe in cpu_exec_setjmp (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:998
> #8 0x000055555577d4c8 in cpu_exec (cpu=0x529000005200) at ../../accel/tcg/cpu-exec.c:1024
> #9 0x00005555557bfc83 in cpu_loop (env=0x529000007dd0) at ../../linux-user/i386/cpu_loop.c:215
> #10 0x00005555558ee3e1 in main (argc=4, argv=0x7fffffffe688, envp=0x7fffffffe6b0) at ../../linux-user/main.c:1038
> (gdb) f 1
> #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> 89 g_abort();
> (gdb) p report
> $1 = (GString *) 0x50300002bf00
> (gdb) p report->Str
> There is no member named Str.
> (gdb) p report->str
> $2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
> (gdb)
>
> I think this is where it is going wrong:
>
> IN: _dl_early_allocate
> 0x0805736b: 89 c2 movl %eax, %edx
> 0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
> 0x08057370: 89 c8 movl %ecx, %eax
> 0x08057372: cd 80 int $0x80
Thanks! I'll have a closer look.
> >
> > + g_string_free(report, true);
> >
> so we could drop this... or..
As aborting is optional, we should free.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-22 10:11 ` Julian Ganz
@ 2025-09-22 10:15 ` Daniel P. Berrangé
2025-09-23 20:29 ` Julian Ganz
1 sibling, 0 replies; 57+ messages in thread
From: Daniel P. Berrangé @ 2025-09-22 10:15 UTC (permalink / raw)
To: Julian Ganz
Cc: Alex Bennée, qemu-devel, Pierrick Bouvier, Alexandre Iooss,
Mahmoud Mandour
On Mon, Sep 22, 2025 at 10:11:23AM +0000, Julian Ganz wrote:
> Hi Alex,
>
> September 21, 2025 at 6:46 PM, "Alex Bennée" <alex.bennee@linaro.org mailto:alex.bennee@linaro.org?to=%22Alex%20Benn%C3%A9e%22%20%3Calex.bennee%40linaro.org%3E > wrote:
> > Julian Ganz <neither@nut.email> writes:
> > > +static void report_mismatch(const char *pc_name, unsigned int vcpu_index,
> > > + enum qemu_plugin_discon_type type, uint64_t last,
> > > + uint64_t expected, uint64_t encountered)
> > > +{
> > > + GString *report;
> > >
> > This could be:
> >
> > g_autoptr(GString) buf = g_string_new(NULL);
>
> I wanted to avoid doing an allocation regardless of whether we do have
> anything to report or not. But I guess a performance plugin isn't
> performance critical enough to worry? Anyway, I will have another look
> at g_autoptr.
IMHO the use of GString is pointless, there is only a single
g_string_append_printf call. GString is only useful when
incrementally constructing a string from many pieces. This
code could have just used 'g_strdup_printf' AFAICT.
>
> > > + const char *discon_type_name = "unknown";
> > > +
> > > + if (addr_eq(expected, encountered)) {
> > > + return;
> > > + }
> > > +
> > > + switch (type) {
> > > + case QEMU_PLUGIN_DISCON_INTERRUPT:
> > > + discon_type_name = "interrupt";
> > > + break;
> > > + case QEMU_PLUGIN_DISCON_EXCEPTION:
> > > + discon_type_name = "exception";
> > > + break;
> > > + case QEMU_PLUGIN_DISCON_HOSTCALL:
> > > + discon_type_name = "hostcall";
> > > + break;
> > > + default:
> > > + break;
> > > + }
> > > +
> > > + report = g_string_new(NULL);
> > > + g_string_append_printf(report,
> > > + "Discon %s PC mismatch on VCPU %d\nExpected: %"
> > > + PRIx64"\nEncountered: %"PRIx64"\nExecuted Last: %"
> > > + PRIx64"\nEvent type: %s\n",
> > > + pc_name, vcpu_index, expected, encountered, last,
> > > + discon_type_name);
> > > + qemu_plugin_outs(report->str);
> > >
> > I think we might want to flush here because
>
> Yes we do. I probably (incorrectly) assumed `qemu_plugin_outs` already
> did that.
>
> >
> > >
> > > + if (abort_on_mismatch) {
> > > + g_abort();
> > > + }
> > >
> > This is firing on:
> >
> > 🕙17:35:50 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?]
> > ➜ make run-plugin-catch-syscalls-with-libdiscons.so V=1
> > timeout -s KILL --foreground 120 env QEMU=/home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 -plugin ../plugins/libdiscons.so -d plugin -D catch-syscalls-with-libdiscons.so.pout catch-syscalls > run-plugin-catch-syscalls-with-libdiscons.so.out
> > Aborted
> > make: *** [Makefile:226: run-plugin-catch-syscalls-with-libdiscons.so] Error 134
> > 🕙17:35:52 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?] [🔴 USAGE]
> > ✗
> >
> > although it never gets to the point of reporting what failed:
> >
> > Thread 1 "qemu-i386" hit Breakpoint 1, __GI_abort () at ./stdlib/abort.c:72
> > warning: 72 ./stdlib/abort.c: No such file or directory
> > (gdb) bt
> > #0 __GI_abort () at ./stdlib/abort.c:72
> > #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> > encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> > #2 0x00007ffff6308c0d in insn_exec (vcpu_index=0, userdata=0x0) at ../../tests/tcg/plugins/discons.c:132
> > #3 0x00007fffea431114 in code_gen_buffer ()
> > #4 0x000055555577b0a6 in cpu_tb_exec (cpu=0x529000005200, itb=0x7fffea431000 <code_gen_buffer+200659>, tb_exit=0x7ffff49c9530) at ../../accel/tcg/cpu-exec.c:438
> > #5 0x000055555577c92f in cpu_loop_exec_tb (cpu=0x529000005200, tb=0x7fffea431000 <code_gen_buffer+200659>, pc=134574955, last_tb=0x7ffff49c9540, tb_exit=0x7ffff49c9530)
> > at ../../accel/tcg/cpu-exec.c:871
> > #6 0x000055555577d151 in cpu_exec_loop (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:981
> > #7 0x000055555577d2fe in cpu_exec_setjmp (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:998
> > #8 0x000055555577d4c8 in cpu_exec (cpu=0x529000005200) at ../../accel/tcg/cpu-exec.c:1024
> > #9 0x00005555557bfc83 in cpu_loop (env=0x529000007dd0) at ../../linux-user/i386/cpu_loop.c:215
> > #10 0x00005555558ee3e1 in main (argc=4, argv=0x7fffffffe688, envp=0x7fffffffe6b0) at ../../linux-user/main.c:1038
> > (gdb) f 1
> > #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> > encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> > 89 g_abort();
> > (gdb) p report
> > $1 = (GString *) 0x50300002bf00
> > (gdb) p report->Str
> > There is no member named Str.
> > (gdb) p report->str
> > $2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
> > (gdb)
> >
> > I think this is where it is going wrong:
> >
> > IN: _dl_early_allocate
> > 0x0805736b: 89 c2 movl %eax, %edx
> > 0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
> > 0x08057370: 89 c8 movl %ecx, %eax
> > 0x08057372: cd 80 int $0x80
>
> Thanks! I'll have a closer look.
>
> > >
> > > + g_string_free(report, true);
> > >
> > so we could drop this... or..
>
> As aborting is optional, we should free.
>
> Regards,
> Julian
>
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
` (25 preceding siblings ...)
2025-09-05 11:38 ` [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities BALATON Zoltan
@ 2025-09-22 11:31 ` Philippe Mathieu-Daudé
2025-09-22 20:54 ` Julian Ganz
26 siblings, 1 reply; 57+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-22 11:31 UTC (permalink / raw)
To: Julian Ganz, qemu-devel
Hi Julian,
On 4/9/25 22:46, Julian Ganz wrote:
> Some analysis greatly benefits, or depends on, information about
> certain types of dicontinuities such as interrupts. For example, we may
> need to handle the execution of a new translation block differently if
> it is not the result of normal program flow but of an interrupt.
>
> Even with the existing interfaces, it is more or less possible to
> discern these situations, e.g. as done by the cflow plugin. However,
> this process poses a considerable overhead to the core analysis one may
> intend to perform.
>
> These changes introduce a generic and easy-to-use interface for plugin
> authors in the form of a callback for discontinuities. Patch 1 defines
> an enumeration of some trap-related discontinuities including somewhat
> narrow definitions of the discontinuity evetns and a callback type.
> Patch 2 defines the callback registration function. Patch 3 adds some
> hooks for triggering the callbacks. Patch 4 adds an example plugin
> showcasing the new API.
>
> Patches 5 through 22 call the hooks for all architectures but hexagon,
> mapping architecture specific events to the three categories defined in
> patch 1. We don't plan to add hooks for hexagon since despite having
> exceptions apparently doesn't have any discontinuities associated with
> them.
> Richard Henderson proposed streamlining interrupts and exceptions for
> all targets and calling the hooks from a higher level rather than in
> each target code. However, there are a few obstacled and I decided to
> not do this as part of this series.
Does that mean another part is planned, and when it lands then these
patches will be reverted?
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks
2025-09-04 20:46 ` [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
@ 2025-09-22 11:34 ` Philippe Mathieu-Daudé
2025-09-22 20:57 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-22 11:34 UTC (permalink / raw)
To: Julian Ganz, qemu-devel
Cc: Alex Bennée, Alexandre Iooss, Mahmoud Mandour,
Pierrick Bouvier
On 4/9/25 22:46, Julian Ganz wrote:
> The plugin API allows registration of callbacks for a variety of VCPU
> related events, such as VCPU reset, idle and resume. In addition, we
> recently introduced API for registering callbacks for discontinuity
> events, specifically for interrupts, exceptions and host calls.
>
> This change introduces the corresponding hooks called from target
> specific code inside qemu.
>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> include/qemu/plugin.h | 12 ++++++++++++
> plugins/core.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 54 insertions(+)
>
> diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
> index 8cf20cd96f..cea0a68858 100644
> --- a/include/qemu/plugin.h
> +++ b/include/qemu/plugin.h
> @@ -161,6 +161,9 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu);
> void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb);
> void qemu_plugin_vcpu_idle_cb(CPUState *cpu);
> void qemu_plugin_vcpu_resume_cb(CPUState *cpu);
> +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from);
> +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from);
> +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from);
> void
> qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1,
> uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5,
> @@ -258,6 +261,15 @@ static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
> static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
> { }
>
> +static inline void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
> +{ }
> +
> +static inline void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
> +{ }
> +
> +static inline void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
> +{ }
> +
> static inline void
> qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
> uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6,
> diff --git a/plugins/core.c b/plugins/core.c
> index a04cb2392d..1f0ddebcbf 100644
> --- a/plugins/core.c
> +++ b/plugins/core.c
> @@ -105,6 +105,30 @@ static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev)
> }
> }
>
> +/*
> + * Disable CFI checks.
> + * The callback function has been loaded from an external library so we do not
> + * have type information
> + */
> +QEMU_DISABLE_CFI
> +static void plugin_vcpu_cb__discon(CPUState *cpu,
> + enum qemu_plugin_event ev,
> + enum qemu_plugin_discon_type type,
> + uint64_t from)
> +{
> + struct qemu_plugin_cb *cb, *next;
> + uint64_t to = cpu->cc->get_pc(cpu);
> +
> + if (cpu->cpu_index < plugin.num_vcpus) {
> + /* iterate safely; plugins might uninstall themselves at any time */
> + QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
> + qemu_plugin_vcpu_discon_cb_t func = cb->f.vcpu_discon;
> +
> + func(cb->ctx->id, cpu->cpu_index, type, from, to);
> + }
> + }
> +}
> +
> /*
> * Disable CFI checks.
> * The callback function has been loaded from an external library so we do not
> @@ -557,6 +581,24 @@ void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
> }
> }
>
> +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
> +{
> + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_INTERRUPT,
> + QEMU_PLUGIN_DISCON_INTERRUPT, from);
> +}
> +
> +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
> +{
> + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_EXCEPTION,
> + QEMU_PLUGIN_DISCON_EXCEPTION, from);
> +}
> +
> +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
> +{
> + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_HOSTCALL,
> + QEMU_PLUGIN_DISCON_HOSTCALL, from);
> +}
No blocking question; do we really need one callback for each discon
type? (can't we just pass the type by argument?).
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 08/25] target/hppa: call plugin trap callbacks
2025-09-04 20:46 ` [PATCH v6 08/25] target/hppa: " Julian Ganz
@ 2025-09-22 11:38 ` Philippe Mathieu-Daudé
2025-09-22 21:09 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-22 11:38 UTC (permalink / raw)
To: Julian Ganz, qemu-devel; +Cc: Richard Henderson, Helge Deller
On 4/9/25 22:46, Julian Ganz wrote:
> We identified a number of exceptions as interrupts, and we assume any
> unknown exception is also an interrupt. HPPA appears to not have any
> form of host-call.
>
> This change places the hook for PA-RISC targets.
>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> target/hppa/int_helper.c | 44 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 44 insertions(+)
>
> diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
> index 191ae19404..0742990c90 100644
> --- a/target/hppa/int_helper.c
> +++ b/target/hppa/int_helper.c
> @@ -24,6 +24,7 @@
> #include "exec/helper-proto.h"
> #include "hw/core/cpu.h"
> #include "hw/hppa/hppa_hardware.h"
> +#include "qemu/plugin.h"
>
> static void eval_interrupt(HPPACPU *cpu)
> {
> @@ -95,6 +96,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
> CPUHPPAState *env = &cpu->env;
> int i = cs->exception_index;
> uint64_t old_psw, old_gva_offset_mask;
> + uint64_t last_pc = cs->cc->get_pc(cs);
>
> /* As documented in pa2.0 -- interruption handling. */
> /* step 1 */
> @@ -212,6 +214,48 @@ void hppa_cpu_do_interrupt(CPUState *cs)
> env->iasq_f = 0;
> env->iasq_b = 0;
>
> + switch (i) {
> + case EXCP_HPMC:
> + case EXCP_POWER_FAIL:
> + case EXCP_RC:
> + case EXCP_EXT_INTERRUPT:
> + case EXCP_LPMC:
> + case EXCP_PER_INTERRUPT:
> + case EXCP_TOC:
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
In the other target patches you list a set and default to
the rest, why listing here the 2 sets and then falling
back to the default? Should the default be g_assert_not_reached()?
> + break;
> + case EXCP_ITLB_MISS:
> + case EXCP_IMP:
> + case EXCP_ILL:
> + case EXCP_BREAK:
> + case EXCP_PRIV_OPR:
> + case EXCP_PRIV_REG:
> + case EXCP_OVERFLOW:
> + case EXCP_COND:
> + case EXCP_ASSIST:
> + case EXCP_DTLB_MISS:
> + case EXCP_NA_ITLB_MISS:
> + case EXCP_NA_DTLB_MISS:
> + case EXCP_DMP:
> + case EXCP_DMB:
> + case EXCP_TLB_DIRTY:
> + case EXCP_PAGE_REF:
> + case EXCP_ASSIST_EMU:
> + case EXCP_HPT:
> + case EXCP_LPT:
> + case EXCP_TB:
> + case EXCP_DMAR:
> + case EXCP_DMPI:
> + case EXCP_UNALIGN:
> + case EXCP_SYSCALL:
> + case EXCP_SYSCALL_LWS:
> + qemu_plugin_vcpu_exception_cb(cs, last_pc);
> + break;
> + default:
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> + break;
> + }
> +
> if (qemu_loglevel_mask(CPU_LOG_INT)) {
> static const char * const names[] = {
> [EXCP_HPMC] = "high priority machine check",
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 13/25] target/mips: call plugin trap callbacks
2025-09-04 20:46 ` [PATCH v6 13/25] target/mips: " Julian Ganz
@ 2025-09-22 11:45 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 57+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-22 11:45 UTC (permalink / raw)
To: Julian Ganz, qemu-devel
Cc: Richard Henderson, Aurelien Jarno, Jiaxun Yang, Aleksandar Rikalo
Hi Julian,
On 4/9/25 22:46, Julian Ganz wrote:
> We recently introduced API for registering callbacks for trap related
> events as well as the corresponding hook functions. Due to differences
> between architectures, the latter need to be called from target specific
> code.
>
> This change places hooks for MIPS targets. We consider the exceptions
> NMI and EXT_INTERRUPT to be asynchronous interrupts rather than
> exceptions.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> target/mips/tcg/system/tlb_helper.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/target/mips/tcg/system/tlb_helper.c b/target/mips/tcg/system/tlb_helper.c
> index 1e8901556d..566924b079 100644
> --- a/target/mips/tcg/system/tlb_helper.c
> +++ b/target/mips/tcg/system/tlb_helper.c
> @@ -18,6 +18,7 @@
> */
> #include "qemu/osdep.h"
> #include "qemu/bitops.h"
> +#include "qemu/plugin.h"
>
> #include "cpu.h"
> #include "internal.h"
> @@ -1034,6 +1035,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
> bool update_badinstr = 0;
> target_ulong offset;
> int cause = -1;
> + uint64_t last_pc = env->active_tc.PC;
>
> if (qemu_loglevel_mask(CPU_LOG_INT)
> && cs->exception_index != EXCP_EXT_INTERRUPT) {
> @@ -1052,6 +1054,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
> cs->exception_index = EXCP_NONE;
I wonder why this code path is different. I'd unify by removing this
line and replacing s/return/break/, then handle in the switch case
you add at the end.
Anyway,
Acked-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> mips_semihosting(env);
> env->active_tc.PC += env->error_code;
> + qemu_plugin_vcpu_hostcall_cb(cs, last_pc);
> return;
> case EXCP_DSS:
> env->CP0_Debug |= 1 << CP0DB_DSS;
> @@ -1336,6 +1339,14 @@ void mips_cpu_do_interrupt(CPUState *cs)
> env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
> env->CP0_DEPC);
> }
> + switch (cs->exception_index) {
> + case EXCP_NMI:
> + case EXCP_EXT_INTERRUPT:
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> + break;
> + default:
> + qemu_plugin_vcpu_exception_cb(cs, last_pc);
> + }
> cs->exception_index = EXCP_NONE;
> }
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 22/25] target/xtensa: call plugin trap callbacks
2025-09-04 20:48 ` [PATCH v6 22/25] target/xtensa: " Julian Ganz
@ 2025-09-22 11:47 ` Philippe Mathieu-Daudé
2025-09-22 21:12 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-22 11:47 UTC (permalink / raw)
To: Julian Ganz, qemu-devel; +Cc: Max Filippov
Hi Julian, Max,
On 4/9/25 22:48, Julian Ganz wrote:
> We recently introduced API for registering callbacks for trap related
> events as well as the corresponding hook functions. Due to differences
> between architectures, the latter need to be called from target specific
> code.
>
> This change places hooks for xtensa targets.
>
> Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> target/xtensa/exc_helper.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/target/xtensa/exc_helper.c b/target/xtensa/exc_helper.c
> index b611c9bf97..fdc522698d 100644
> --- a/target/xtensa/exc_helper.c
> +++ b/target/xtensa/exc_helper.c
> @@ -32,6 +32,7 @@
> #include "exec/helper-proto.h"
> #include "qemu/host-utils.h"
> #include "qemu/atomic.h"
> +#include "qemu/plugin.h"
>
> void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
> {
> @@ -207,6 +208,8 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
> CPUXtensaState *env = cpu_env(cs);
>
> if (cs->exception_index == EXC_IRQ) {
> + uint64_t last_pc = env->pc;
> +
> qemu_log_mask(CPU_LOG_INT,
> "%s(EXC_IRQ) level = %d, cintlevel = %d, "
> "pc = %08x, a0 = %08x, ps = %08x, "
> @@ -218,6 +221,7 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
> env->sregs[INTSET], env->sregs[INTENABLE],
> env->sregs[CCOUNT]);
> handle_interrupt(env);
> + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> }
>
> switch (cs->exception_index) {
> @@ -238,9 +242,11 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
> env->sregs[CCOUNT]);
> if (env->config->exception_vector[cs->exception_index]) {
> uint32_t vector;
> + uint64_t last_pc = env->pc;
>
> vector = env->config->exception_vector[cs->exception_index];
> env->pc = relocated_vector(env, vector);
> + qemu_plugin_vcpu_exception_cb(cs, last_pc);
> } else {
> qemu_log_mask(CPU_LOG_INT,
> "%s(pc = %08x) bad exception_index: %d\n",
Should we call qemu_plugin_vcpu_hostcall_cb() in SIMCALL opcode?
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities
2025-09-22 11:31 ` Philippe Mathieu-Daudé
@ 2025-09-22 20:54 ` Julian Ganz
0 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-22 20:54 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Hi Philippe,
September 22, 2025 at 1:31 PM, "Philippe Mathieu-Daudé" wrote:
> > Richard Henderson proposed streamlining interrupts and exceptions for
> > all targets and calling the hooks from a higher level rather than in
> > each target code. However, there are a few obstacled and I decided to
> > not do this as part of this series.
> >
> Does that mean another part is planned, and when it lands then these
> patches will be reverted?
I don't have any tangible plans for a follow-up series. If I end up
drafting one it will likely take a while.
A follow-up series will likely not straight revert these changes since
they essentially mark points where we would want to return some required
additional information to said higher level. The hooks would instead
vanish one by one as part of a migration.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks
2025-09-22 11:34 ` Philippe Mathieu-Daudé
@ 2025-09-22 20:57 ` Julian Ganz
0 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-22 20:57 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Alex Bennée, Alexandre Iooss, Mahmoud Mandour,
Pierrick Bouvier
Hi Philippe,
September 22, 2025 at 1:34 PM, "Philippe Mathieu-Daudé" wrote:
> On 4/9/25 22:46, Julian Ganz wrote:
>
> >
> > The plugin API allows registration of callbacks for a variety of VCPU
> > related events, such as VCPU reset, idle and resume. In addition, we
> > recently introduced API for registering callbacks for discontinuity
> > events, specifically for interrupts, exceptions and host calls.
> > This change introduces the corresponding hooks called from target
> > specific code inside qemu.
> > Signed-off-by: Julian Ganz <neither@nut.email>
> > ---
> > include/qemu/plugin.h | 12 ++++++++++++
> > plugins/core.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 54 insertions(+)
> > diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
> > index 8cf20cd96f..cea0a68858 100644
> > --- a/include/qemu/plugin.h
> > +++ b/include/qemu/plugin.h
> > @@ -161,6 +161,9 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu);
> > void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb);
> > void qemu_plugin_vcpu_idle_cb(CPUState *cpu);
> > void qemu_plugin_vcpu_resume_cb(CPUState *cpu);
> > +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from);
> > +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from);
> > +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from);
> > void
> > qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1,
> > uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5,
> > @@ -258,6 +261,15 @@ static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
> > static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
> > { }
> > > +static inline void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
> > +{ }
> > +
> > +static inline void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
> > +{ }
> > +
> > +static inline void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
> > +{ }
> > +
> > static inline void
> > qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
> > uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6,
> > diff --git a/plugins/core.c b/plugins/core.c
> > index a04cb2392d..1f0ddebcbf 100644
> > --- a/plugins/core.c
> > +++ b/plugins/core.c
> > @@ -105,6 +105,30 @@ static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev)
> > }
> > }
> > > +/*
> > + * Disable CFI checks.
> > + * The callback function has been loaded from an external library so we do not
> > + * have type information
> > + */
> > +QEMU_DISABLE_CFI
> > +static void plugin_vcpu_cb__discon(CPUState *cpu,
> > + enum qemu_plugin_event ev,
> > + enum qemu_plugin_discon_type type,
> > + uint64_t from)
> > +{
> > + struct qemu_plugin_cb *cb, *next;
> > + uint64_t to = cpu->cc->get_pc(cpu);
> > +
> > + if (cpu->cpu_index < plugin.num_vcpus) {
> > + /* iterate safely; plugins might uninstall themselves at any time */
> > + QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
> > + qemu_plugin_vcpu_discon_cb_t func = cb->f.vcpu_discon;
> > +
> > + func(cb->ctx->id, cpu->cpu_index, type, from, to);
> > + }
> > + }
> > +}
> > +
> > /*
> > * Disable CFI checks.
> > * The callback function has been loaded from an external library so we do not
> > @@ -557,6 +581,24 @@ void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
> > }
> > }
> > > +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
> > +{
> > + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_INTERRUPT,
> > + QEMU_PLUGIN_DISCON_INTERRUPT, from);
> > +}
> > +
> > +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
> > +{
> > + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_EXCEPTION,
> > + QEMU_PLUGIN_DISCON_EXCEPTION, from);
> > +}
> > +
> > +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
> > +{
> > + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_HOSTCALL,
> > + QEMU_PLUGIN_DISCON_HOSTCALL, from);
> > +}
> >
> No blocking question; do we really need one callback for each discon
> type? (can't we just pass the type by argument?).
Yes we could, but the enum would likely end up more noisy. And we would
need to translate discon type to (plugin API) event type again. And we
just got rid of that in the last iteration.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 08/25] target/hppa: call plugin trap callbacks
2025-09-22 11:38 ` Philippe Mathieu-Daudé
@ 2025-09-22 21:09 ` Julian Ganz
0 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-22 21:09 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel; +Cc: Richard Henderson, Helge Deller
Hi Philippe,
September 22, 2025 at 1:38 PM, "Philippe Mathieu-Daudé" wrote:
> On 4/9/25 22:46, Julian Ganz wrote:
> > diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
> > index 191ae19404..0742990c90 100644
> > --- a/target/hppa/int_helper.c
> > +++ b/target/hppa/int_helper.c
> > @@ -212,6 +214,48 @@ void hppa_cpu_do_interrupt(CPUState *cs)
> > env->iasq_f = 0;
> > env->iasq_b = 0;
> > > + switch (i) {
> > + case EXCP_HPMC:
> > + case EXCP_POWER_FAIL:
> > + case EXCP_RC:
> > + case EXCP_EXT_INTERRUPT:
> > + case EXCP_LPMC:
> > + case EXCP_PER_INTERRUPT:
> > + case EXCP_TOC:
> > + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> >
> In the other target patches you list a set and default to
> the rest, why listing here the 2 sets and then falling
> back to the default? Should the default be g_assert_not_reached()?
Most architectures have either few inerrupts (and lots of exception) or
some clear distinction (e.g. RISC-V has a bit differentiating the two).
I found HPPA a bit confusing in this regard. Or to be more precise had
the feeling I would forget some case if I did not write them all down.
This _should_ mean that I already covered anything, but the logging code
further down also makes a point of covering the case that the exception
index is not one of these constants.
My memory is hazy but I might have read somewhere that some HPPA
platforms _may_ have additional interrupts not covered in the ISA spec.
At least this would not have been unheard of for an architecture.
If I'm wrong about that I'm happy to declare the default case
unreachable.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 22/25] target/xtensa: call plugin trap callbacks
2025-09-22 11:47 ` Philippe Mathieu-Daudé
@ 2025-09-22 21:12 ` Julian Ganz
0 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-22 21:12 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel; +Cc: Max Filippov
September 22, 2025 at 1:47 PM, "Philippe Mathieu-Daudé" wrote:
> On 4/9/25 22:48, Julian Ganz wrote:
> > We recently introduced API for registering callbacks for trap related
> > events as well as the corresponding hook functions. Due to differences
> > between architectures, the latter need to be called from target specific
> > code.
> > This change places hooks for xtensa targets.
> > Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
> > Signed-off-by: Julian Ganz <neither@nut.email>
> > ---
> > target/xtensa/exc_helper.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> > diff --git a/target/xtensa/exc_helper.c b/target/xtensa/exc_helper.c
> > index b611c9bf97..fdc522698d 100644
> > --- a/target/xtensa/exc_helper.c
> > +++ b/target/xtensa/exc_helper.c
> > @@ -32,6 +32,7 @@
> > #include "exec/helper-proto.h"
> > #include "qemu/host-utils.h"
> > #include "qemu/atomic.h"
> > +#include "qemu/plugin.h"
> > > void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
> > {
> > @@ -207,6 +208,8 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
> > CPUXtensaState *env = cpu_env(cs);
> > > if (cs->exception_index == EXC_IRQ) {
> > + uint64_t last_pc = env->pc;
> > +
> > qemu_log_mask(CPU_LOG_INT,
> > "%s(EXC_IRQ) level = %d, cintlevel = %d, "
> > "pc = %08x, a0 = %08x, ps = %08x, "
> > @@ -218,6 +221,7 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
> > env->sregs[INTSET], env->sregs[INTENABLE],
> > env->sregs[CCOUNT]);
> > handle_interrupt(env);
> > + qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
> > }
> > > switch (cs->exception_index) {
> > @@ -238,9 +242,11 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
> > env->sregs[CCOUNT]);
> > if (env->config->exception_vector[cs->exception_index]) {
> > uint32_t vector;
> > + uint64_t last_pc = env->pc;
> > > vector = env->config->exception_vector[cs->exception_index];
> > env->pc = relocated_vector(env, vector);
> > + qemu_plugin_vcpu_exception_cb(cs, last_pc);
> > } else {
> > qemu_log_mask(CPU_LOG_INT,
> > "%s(pc = %08x) bad exception_index: %d\n",
> >
> Should we call qemu_plugin_vcpu_hostcall_cb() in SIMCALL opcode?
Probably yes. Thanks for catching that!
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-22 10:11 ` Julian Ganz
2025-09-22 10:15 ` Daniel P. Berrangé
@ 2025-09-23 20:29 ` Julian Ganz
2025-09-24 15:31 ` Julian Ganz
1 sibling, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-23 20:29 UTC (permalink / raw)
To: Julian Ganz, Alex Bennée
Cc: qemu-devel, Pierrick Bouvier, Alexandre Iooss, Mahmoud Mandour
Hi again,
September 22, 2025 at 12:11 PM, "Julian Ganz" wrote:
> September 21, 2025 at 6:46 PM, "Alex Bennée" wrote:
> > Julian Ganz <neither@nut.email> writes:
> > + report = g_string_new(NULL);
> > + g_string_append_printf(report,
> > + "Discon %s PC mismatch on VCPU %d\nExpected: %"
> > + PRIx64"\nEncountered: %"PRIx64"\nExecuted Last: %"
> > + PRIx64"\nEvent type: %s\n",
> > + pc_name, vcpu_index, expected, encountered, last,
> > + discon_type_name);
> > + qemu_plugin_outs(report->str);
> >
> > I think we might want to flush here because
> >
> Yes we do. I probably (incorrectly) assumed `qemu_plugin_outs` already
> did that.
Sorry to ask, but is there any way to flush the associated output stream
from an plugin? Or in general? I didn't find anything other than
`qemu_plugin_outs` regarding output. And that calls `qemu_log_mask`...
> > This is firing on:
> >
> > 🕙17:35:50 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?]
> > ➜ make run-plugin-catch-syscalls-with-libdiscons.so V=1
> > timeout -s KILL --foreground 120 env QEMU=/home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 -plugin ../plugins/libdiscons.so -d plugin -D catch-syscalls-with-libdiscons.so.pout catch-syscalls > run-plugin-catch-syscalls-with-libdiscons.so.out
> > Aborted
> > make: *** [Makefile:226: run-plugin-catch-syscalls-with-libdiscons.so] Error 134
> > 🕙17:35:52 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?] [🔴 USAGE]
> > ✗
> >
> > although it never gets to the point of reporting what failed:
> >
> > Thread 1 "qemu-i386" hit Breakpoint 1, __GI_abort () at ./stdlib/abort.c:72
> > warning: 72 ./stdlib/abort.c: No such file or directory
> > (gdb) bt
> > #0 __GI_abort () at ./stdlib/abort.c:72
> > #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> > encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> > #2 0x00007ffff6308c0d in insn_exec (vcpu_index=0, userdata=0x0) at ../../tests/tcg/plugins/discons.c:132
> > #3 0x00007fffea431114 in code_gen_buffer ()
> > #4 0x000055555577b0a6 in cpu_tb_exec (cpu=0x529000005200, itb=0x7fffea431000 <code_gen_buffer+200659>, tb_exit=0x7ffff49c9530) at ../../accel/tcg/cpu-exec.c:438
> > #5 0x000055555577c92f in cpu_loop_exec_tb (cpu=0x529000005200, tb=0x7fffea431000 <code_gen_buffer+200659>, pc=134574955, last_tb=0x7ffff49c9540, tb_exit=0x7ffff49c9530)
> > at ../../accel/tcg/cpu-exec.c:871
> > #6 0x000055555577d151 in cpu_exec_loop (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:981
> > #7 0x000055555577d2fe in cpu_exec_setjmp (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:998
> > #8 0x000055555577d4c8 in cpu_exec (cpu=0x529000005200) at ../../accel/tcg/cpu-exec.c:1024
> > #9 0x00005555557bfc83 in cpu_loop (env=0x529000007dd0) at ../../linux-user/i386/cpu_loop.c:215
> > #10 0x00005555558ee3e1 in main (argc=4, argv=0x7fffffffe688, envp=0x7fffffffe6b0) at ../../linux-user/main.c:1038
> > (gdb) f 1
> > #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> > encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> > 89 g_abort();
> > (gdb) p report
> > $1 = (GString *) 0x50300002bf00
> > (gdb) p report->Str
> > There is no member named Str.
> > (gdb) p report->str
> > $2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
> > (gdb)
> >
> > I think this is where it is going wrong:
> >
> > IN: _dl_early_allocate
> > 0x0805736b: 89 c2 movl %eax, %edx
> > 0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
> > 0x08057370: 89 c8 movl %ecx, %eax
> > 0x08057372: cd 80 int $0x80
> >
> Thanks! I'll have a closer look.
I probably didn't configure the target I need for this test on my
private machine (which uses musl, so some targets are awkward). Could it
be that this doesn't run in system emulation mode and the exception is
somehow handled natively? I did not account for that possibility and I
don't think I'll get the testing plugin to do anything meaningful
outside system emulation.
I will keep on looking into this.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-23 20:29 ` Julian Ganz
@ 2025-09-24 15:31 ` Julian Ganz
2025-09-25 10:41 ` Alex Bennée
0 siblings, 1 reply; 57+ messages in thread
From: Julian Ganz @ 2025-09-24 15:31 UTC (permalink / raw)
To: Alex Bennée
Cc: qemu-devel, Pierrick Bouvier, Alexandre Iooss, Mahmoud Mandour
September 23, 2025 at 10:29 PM, "Julian Ganz" wrote:
> September 22, 2025 at 12:11 PM, "Julian Ganz" wrote:
> > September 21, 2025 at 6:46 PM, "Alex Bennée" wrote:
> > This is firing on:
> >
> > 🕙17:35:50 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?]
> > ➜ make run-plugin-catch-syscalls-with-libdiscons.so V=1
> > timeout -s KILL --foreground 120 env QEMU=/home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 -plugin ../plugins/libdiscons.so -d plugin -D catch-syscalls-with-libdiscons.so.pout catch-syscalls > run-plugin-catch-syscalls-with-libdiscons.so.out
> > Aborted
> > make: *** [Makefile:226: run-plugin-catch-syscalls-with-libdiscons.so] Error 134
> > 🕙17:35:52 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?] [🔴 USAGE]
> > ✗
> >
> > although it never gets to the point of reporting what failed:
> >
> > Thread 1 "qemu-i386" hit Breakpoint 1, __GI_abort () at ./stdlib/abort.c:72
> > warning: 72 ./stdlib/abort.c: No such file or directory
> > (gdb) bt
> > #0 __GI_abort () at ./stdlib/abort.c:72
> > #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> > encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> > #2 0x00007ffff6308c0d in insn_exec (vcpu_index=0, userdata=0x0) at ../../tests/tcg/plugins/discons.c:132
> > #3 0x00007fffea431114 in code_gen_buffer ()
> > #4 0x000055555577b0a6 in cpu_tb_exec (cpu=0x529000005200, itb=0x7fffea431000 <code_gen_buffer+200659>, tb_exit=0x7ffff49c9530) at ../../accel/tcg/cpu-exec.c:438
> > #5 0x000055555577c92f in cpu_loop_exec_tb (cpu=0x529000005200, tb=0x7fffea431000 <code_gen_buffer+200659>, pc=134574955, last_tb=0x7ffff49c9540, tb_exit=0x7ffff49c9530)
> > at ../../accel/tcg/cpu-exec.c:871
> > #6 0x000055555577d151 in cpu_exec_loop (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:981
> > #7 0x000055555577d2fe in cpu_exec_setjmp (cpu=0x529000005200, sc=0x7ffff483a740) at ../../accel/tcg/cpu-exec.c:998
> > #8 0x000055555577d4c8 in cpu_exec (cpu=0x529000005200) at ../../accel/tcg/cpu-exec.c:1024
> > #9 0x00005555557bfc83 in cpu_loop (env=0x529000007dd0) at ../../linux-user/i386/cpu_loop.c:215
> > #10 0x00005555558ee3e1 in main (argc=4, argv=0x7fffffffe688, envp=0x7fffffffe6b0) at ../../linux-user/main.c:1038
> > (gdb) f 1
> > #1 0x00007ffff630874d in report_mismatch (pc_name=0x7ffff630a220 "target", vcpu_index=0, type=QEMU_PLUGIN_DISCON_EXCEPTION, last=134574955, expected=134574953,
> > encountered=134574955) at ../../tests/tcg/plugins/discons.c:89
> > 89 g_abort();
> > (gdb) p report
> > $1 = (GString *) 0x50300002bf00
> > (gdb) p report->Str
> > There is no member named Str.
> > (gdb) p report->str
> > $2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
> > (gdb)
> >
> > I think this is where it is going wrong:
> >
> > IN: _dl_early_allocate
> > 0x0805736b: 89 c2 movl %eax, %edx
> > 0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
> > 0x08057370: 89 c8 movl %ecx, %eax
> > 0x08057372: cd 80 int $0x80
> >
> > Thanks! I'll have a closer look.
> >
> I probably didn't configure the target I need for this test on my
> private machine (which uses musl, so some targets are awkward).
Turned out I just ran `make` in the wrong directory.
> Could it
> be that this doesn't run in system emulation mode and the exception is
> somehow handled natively? I did not account for that possibility and I
> don't think I'll get the testing plugin to do anything meaningful
> outside system emulation.
As expected the plugin ran in a qemu configuration in which the API does
not behave as expected. Which I could have figured out by the logs Alex
provided if I paid attention. Sorry for the noise.
I added a check to the plugin that bails out if qemu does not run in
system emulation mode (which I thought I did, but that was only for the
contrib plugin).
Even if we cannot test the API for user mode, it may still provide some
utility, so I suggest _just_ letting the testing plugin do nothing in
that case. In fact, I'm considering removing the check from the contrib
"traps" plugin now that I saw that the API _is_ triggered in user mode.
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-24 15:31 ` Julian Ganz
@ 2025-09-25 10:41 ` Alex Bennée
2025-09-25 12:42 ` Julian Ganz
0 siblings, 1 reply; 57+ messages in thread
From: Alex Bennée @ 2025-09-25 10:41 UTC (permalink / raw)
To: Julian Ganz
Cc: qemu-devel, Pierrick Bouvier, Alexandre Iooss, Mahmoud Mandour,
Richard Henderson
"Julian Ganz" <neither@nut.email> writes:
(add Richard to Cc)
> September 23, 2025 at 10:29 PM, "Julian Ganz" wrote:
>> September 22, 2025 at 12:11 PM, "Julian Ganz" wrote:
>> > September 21, 2025 at 6:46 PM, "Alex Bennée" wrote:
>> > This is firing on:
>> >
>> > 🕙17:35:50 alex@draig:tests/tcg/i386-linux-user on review/tcg-discon-v6 [$!?]
>> > ➜ make run-plugin-catch-syscalls-with-libdiscons.so V=1
>> > timeout -s KILL --foreground 120 env
>> > QEMU=/home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386
>> > /home/alex/lsrc/qemu.git/builds/sanitisers/qemu-i386 -plugin
>> > ../plugins/libdiscons.so -d plugin -D
>> > catch-syscalls-with-libdiscons.so.pout catch-syscalls >
>> > run-plugin-catch-syscalls-with-libdiscons.so.out
>> > Aborted
>> > make: *** [Makefile:226: run-plugin-catch-syscalls-with-libdiscons.so] Error 134
<snip>
>> > (gdb) p report->str
>> > $2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
>> > (gdb)
>> >
>> > I think this is where it is going wrong:
>> >
>> > IN: _dl_early_allocate
>> > 0x0805736b: 89 c2 movl %eax, %edx
>> > 0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
>> > 0x08057370: 89 c8 movl %ecx, %eax
>> > 0x08057372: cd 80 int $0x80
>> >
>> > Thanks! I'll have a closer look.
>> >
>> I probably didn't configure the target I need for this test on my
>> private machine (which uses musl, so some targets are awkward).
>
> Turned out I just ran `make` in the wrong directory.
>
>> Could it
>> be that this doesn't run in system emulation mode and the exception is
>> somehow handled natively? I did not account for that possibility and I
>> don't think I'll get the testing plugin to do anything meaningful
>> outside system emulation.
>
> As expected the plugin ran in a qemu configuration in which the API does
> not behave as expected. Which I could have figured out by the logs Alex
> provided if I paid attention. Sorry for the noise.
>
> I added a check to the plugin that bails out if qemu does not run in
> system emulation mode (which I thought I did, but that was only for the
> contrib plugin).
>
> Even if we cannot test the API for user mode, it may still provide some
> utility, so I suggest _just_ letting the testing plugin do nothing in
> that case. In fact, I'm considering removing the check from the contrib
> "traps" plugin now that I saw that the API _is_ triggered in user
> mode.
Is this just because we are missing the hooks into the linux-user
run-loop? I assume int $0x80 is a syscall so we should report an
exception type at that point?
In fact I think you could probably generate the event at
qemu_plugin_vcpu_syscall()?
force_sig_fault() and force_sig() might be the other places that should
be hooked. Or possibly handle_pending_signal() where all the other
signals affect the code flow.
I think that can avoid patching every arches run loop.
Richard, WDYT?
>
> Regards,
> Julian
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc
2025-09-25 10:41 ` Alex Bennée
@ 2025-09-25 12:42 ` Julian Ganz
0 siblings, 0 replies; 57+ messages in thread
From: Julian Ganz @ 2025-09-25 12:42 UTC (permalink / raw)
To: Alex Bennée
Cc: qemu-devel, Pierrick Bouvier, Alexandre Iooss, Mahmoud Mandour,
Richard Henderson
Hi Alex,
September 25, 2025 at 12:41 PM, "Alex Bennée" wrote:
> "Julian Ganz" <neither@nut.email> writes:
> > September 23, 2025 at 10:29 PM, "Julian Ganz" wrote:
> > > September 22, 2025 at 12:11 PM, "Julian Ganz" wrote:
> > > > (gdb) p report->str
> > > > $2 = (gchar *) 0x51100001fbc0 "Discon target PC mismatch on VCPU 0\nExpected: 8057369\nEncountered: 805736b\nExecuted Last: 805736b\nEvent type: exception\n"
> > > > (gdb)
> > > >
> > > > I think this is where it is going wrong:
> > > >
> > > > IN: _dl_early_allocate
> > > > 0x0805736b: 89 c2 movl %eax, %edx
> > > > 0x0805736d: 8d 1c 28 leal (%eax, %ebp), %ebx
> > > > 0x08057370: 89 c8 movl %ecx, %eax
> > > > 0x08057372: cd 80 int $0x80
> > > >
> > > > Thanks! I'll have a closer look.
> > > >
> > > I probably didn't configure the target I need for this test on my
> > > private machine (which uses musl, so some targets are awkward).
> > >
> > Turned out I just ran `make` in the wrong directory.
> >
> > >
> > > Could it
> > > be that this doesn't run in system emulation mode and the exception is
> > > somehow handled natively? I did not account for that possibility and I
> > > don't think I'll get the testing plugin to do anything meaningful
> > > outside system emulation.
> > >
> > As expected the plugin ran in a qemu configuration in which the API does
> > not behave as expected. Which I could have figured out by the logs Alex
> > provided if I paid attention. Sorry for the noise.
> >
> > I added a check to the plugin that bails out if qemu does not run in
> > system emulation mode (which I thought I did, but that was only for the
> > contrib plugin).
> >
> > Even if we cannot test the API for user mode, it may still provide some
> > utility, so I suggest _just_ letting the testing plugin do nothing in
> > that case. In fact, I'm considering removing the check from the contrib
> > "traps" plugin now that I saw that the API _is_ triggered in user
> > mode.
> >
> Is this just because we are missing the hooks into the linux-user
> run-loop? I assume int $0x80 is a syscall so we should report an
> exception type at that point?
We _do_ observe the exception occuring, we just don't observe it being
handled. Instead we observe the result after the trap handler returned.
And that's probably what we want for user-mode emulation where we don't
have any introspection into the trap handler's execution.
What trips the testing plugin is that it expects observing the trap
handler, and there's currently nothing we can do here instead of just
giving up when running user-mode emulation. We can introduce actual tests
for user-mode emulation again in the future, should we introduce a
discontinuity type for trap handler return (e.g. for RISC-V's `mret`).
> In fact I think you could probably generate the event at
> qemu_plugin_vcpu_syscall()?
I could, but that would be somewhat separate from the trap related
stuff. Syscalls would likely qualify as a separate, new discontinuity
type similar to host calls.
> force_sig_fault() and force_sig() might be the other places that should
> be hooked. Or possibly handle_pending_signal() where all the other
> signals affect the code flow.
>
> I think that can avoid patching every arches run loop.
I still need to distinguish between discontinuity types, and that does
(currently) require target specific knowledge. Or maybe I misunderstood
what you were trying to say?
Regards,
Julian
^ permalink raw reply [flat|nested] 57+ messages in thread
end of thread, other threads:[~2025-09-25 12:44 UTC | newest]
Thread overview: 57+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-04 20:46 [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
2025-09-04 20:46 ` [PATCH v6 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
2025-09-04 20:46 ` [PATCH v6 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
2025-09-04 20:46 ` [PATCH v6 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
2025-09-22 11:34 ` Philippe Mathieu-Daudé
2025-09-22 20:57 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API Julian Ganz
2025-09-04 20:46 ` [PATCH v6 05/25] target/alpha: call plugin trap callbacks Julian Ganz
2025-09-04 20:46 ` [PATCH v6 06/25] target/arm: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 07/25] target/avr: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 08/25] target/hppa: " Julian Ganz
2025-09-22 11:38 ` Philippe Mathieu-Daudé
2025-09-22 21:09 ` Julian Ganz
2025-09-04 20:46 ` [PATCH v6 09/25] target/i386: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 10/25] target/loongarch: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 11/25] target/m68k: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 12/25] target/microblaze: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 13/25] target/mips: " Julian Ganz
2025-09-22 11:45 ` Philippe Mathieu-Daudé
2025-09-04 20:46 ` [PATCH v6 14/25] target/openrisc: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 15/25] target/ppc: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 16/25] target/riscv: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 17/25] target/rx: " Julian Ganz
2025-09-07 14:20 ` yoshinori.sato
2025-09-04 20:46 ` [PATCH v6 18/25] target/s390x: " Julian Ganz
2025-09-04 20:46 ` [PATCH v6 19/25] target/sh4: " Julian Ganz
2025-09-07 14:20 ` yoshinori.sato
2025-09-04 20:46 ` [PATCH v6 20/25] target/sparc: " Julian Ganz
2025-09-04 20:48 ` Julian Ganz
2025-09-04 20:48 ` [PATCH v6 21/25] target/tricore: " Julian Ganz
2025-09-04 20:48 ` [PATCH v6 22/25] target/xtensa: " Julian Ganz
2025-09-22 11:47 ` Philippe Mathieu-Daudé
2025-09-22 21:12 ` Julian Ganz
2025-09-04 20:48 ` [PATCH v6 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
2025-09-21 16:46 ` Alex Bennée
2025-09-22 10:11 ` Julian Ganz
2025-09-22 10:15 ` Daniel P. Berrangé
2025-09-23 20:29 ` Julian Ganz
2025-09-24 15:31 ` Julian Ganz
2025-09-25 10:41 ` Alex Bennée
2025-09-25 12:42 ` Julian Ganz
2025-09-04 20:48 ` [PATCH v6 24/25] tests: add test for double-traps on rv64 Julian Ganz
2025-09-04 20:49 ` [PATCH v6 25/25] tests: add test with interrupted memory accesses " Julian Ganz
2025-09-05 11:38 ` [PATCH v6 00/25] tcg-plugins: add hooks for discontinuities BALATON Zoltan
2025-09-05 12:20 ` Alex Bennée
2025-09-05 13:43 ` Julian Ganz
2025-09-05 19:25 ` BALATON Zoltan
2025-09-05 23:28 ` Julian Ganz
2025-09-07 20:21 ` BALATON Zoltan
2025-09-08 20:51 ` Julian Ganz
2025-09-09 19:48 ` Julian Ganz
2025-09-10 10:06 ` BALATON Zoltan
2025-09-10 11:41 ` Julian Ganz
2025-09-10 12:09 ` Alex Bennée
2025-09-10 15:04 ` BALATON Zoltan
2025-09-22 11:31 ` Philippe Mathieu-Daudé
2025-09-22 20:54 ` Julian Ganz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).