qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities
@ 2025-05-19 15:19 Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
                   ` (25 more replies)
  0 siblings, 26 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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.

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                   |  86 +++++++++
 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                            |  68 +++++++
 target/alpha/helper.c                     |  13 ++
 target/arm/helper.c                       |  24 +++
 target/arm/tcg/m_helper.c                 |  18 ++
 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                   |  24 +++
 target/microblaze/helper.c                |   8 +
 target/mips/tcg/system/tlb_helper.c       |  11 ++
 target/openrisc/interrupt.c               |  13 ++
 target/ppc/excp_helper.c                  |  42 +++++
 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               | 216 ++++++++++++++++++++++
 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 +++++++
 33 files changed, 881 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.0



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

* [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 16:43   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, Pierrick Bouvier

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>
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 9726a9ebf3..27a176b631 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 3a850aa216..2e849bff0b 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -154,6 +154,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.0



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

* [PATCH v5 02/25] plugins: add API for registering discontinuity callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 16:48   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
                   ` (23 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel
  Cc: Julian Ganz, Pierrick Bouvier, 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>
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 2e849bff0b..6d46d15e27 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -274,6 +274,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 eb9281fe54..dc1f5cb4d8 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -551,6 +551,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.0



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

* [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 16:55   ` Richard Henderson
  2025-05-24 17:27   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API Julian Ganz
                   ` (22 subsequent siblings)
  25 siblings, 2 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel
  Cc: Julian Ganz, Pierrick Bouvier, 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, 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.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Julian Ganz <neither@nut.email>
---
 include/qemu/plugin.h | 12 ++++++++++
 plugins/core.c        | 53 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index 27a176b631..3494325039 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,
@@ -243,6 +246,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 dc1f5cb4d8..f07813d588 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -104,6 +104,44 @@ 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_discon_type type,
+                                   uint64_t from)
+{
+    struct qemu_plugin_cb *cb, *next;
+    enum qemu_plugin_event ev;
+    uint64_t to = cpu->cc->get_pc(cpu);
+
+    if (cpu->cpu_index < plugin.num_vcpus) {
+        switch (type) {
+        case QEMU_PLUGIN_DISCON_INTERRUPT:
+            ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT;
+            break;
+        case QEMU_PLUGIN_DISCON_EXCEPTION:
+            ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION;
+            break;
+        case QEMU_PLUGIN_DISCON_HOSTCALL:
+            ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+
+        /* 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
@@ -539,6 +577,21 @@ 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_DISCON_INTERRUPT, from);
+}
+
+void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
+{
+    plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_EXCEPTION, from);
+}
+
+void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
+{
+    plugin_vcpu_cb__discon(cpu, 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.0



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

* [PATCH v5 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (2 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 05/25] target/alpha: call plugin trap callbacks Julian Ganz
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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     | 86 +++++++++++++++++++++++++++++++++++++
 docs/about/emulation.rst    |  8 ++++
 3 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 contrib/plugins/traps.c

diff --git a/contrib/plugins/meson.build b/contrib/plugins/meson.build
index fa8a426c8b..327b48c888 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..aa943fb55c
--- /dev/null
+++ b/contrib/plugins/traps.c
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ */
+
+#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 a72591ee4d..f985fce8ec 100644
--- a/docs/about/emulation.rst
+++ b/docs/about/emulation.rst
@@ -812,6 +812,14 @@ This plugin can limit the number of Instructions Per Second that are executed::
     - Maximum number of instructions per cpu that can be executed in one second.
       The plugin will sleep when the given number of instructions is reached.
 
+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.0



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

* [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (3 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 16:56   ` Richard Henderson
  2025-05-25 12:14   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 06/25] target/arm: " Julian Ganz
                   ` (20 subsequent siblings)
  25 siblings, 2 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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.

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.0



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

* [PATCH v5 06/25] target/arm: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (4 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 05/25] target/alpha: call plugin trap callbacks Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:05   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 07/25] target/avr: " Julian Ganz
                   ` (19 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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/tcg/m_helper.c | 18 ++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7631210287..06070441a6 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"
@@ -10214,6 +10215,24 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
     }
 }
 
+static void arm_do_plugin_vcpu_interrupt_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)
 {
     /*
@@ -10880,6 +10899,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 = env->pc;
 
     assert(!arm_feature(env, ARM_FEATURE_M));
 
@@ -10896,6 +10916,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;
     }
 
@@ -10907,6 +10928,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
@@ -10932,6 +10954,8 @@ void arm_cpu_do_interrupt(CPUState *cs)
     if (!kvm_enabled()) {
         cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
     }
+
+    arm_do_plugin_vcpu_interrupt_cb(cs, last_pc);
 }
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
index 6614719832..bcb4aae0d5 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)
@@ -2185,6 +2186,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
     CPUARMState *env = &cpu->env;
     uint32_t lr;
     bool ignore_stackfaults;
+    uint64_t last_pc = env->pc;
 
     arm_log_exception(cs);
 
@@ -2352,6 +2354,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);
@@ -2418,6 +2421,21 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
 
     ignore_stackfaults = v7m_push_stack(cpu);
     v7m_exception_taken(cpu, lr, false, ignore_stackfaults);
+
+    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, last_pc);
+        break;
+    default:
+        qemu_plugin_vcpu_exception_cb(cs, last_pc);
+    }
 }
 
 uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
-- 
2.49.0



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

* [PATCH v5 07/25] target/avr: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (5 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 06/25] target/arm: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:06   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 08/25] target/hppa: " Julian Ganz
                   ` (18 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, 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.

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.0



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

* [PATCH v5 08/25] target/hppa: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (6 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 07/25] target/avr: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:07   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 09/25] target/i386: " Julian Ganz
                   ` (17 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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 7d48643bb6..e9325319a7 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 */
@@ -208,6 +210,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_exception_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.0



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

* [PATCH v5 09/25] target/i386: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (7 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 08/25] target/hppa: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 10/25] target/loongarch: " Julian Ganz
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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.0



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

* [PATCH v5 10/25] target/loongarch: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (8 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 09/25] target/i386: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:10   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 11/25] target/m68k: " Julian Ganz
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, 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.

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 f7535d1be7..d1ed56d15e 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -31,6 +31,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"
 
@@ -171,6 +172,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,
@@ -281,6 +283,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);
@@ -299,6 +302,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.0



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

* [PATCH v5 11/25] target/m68k: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (9 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 10/25] target/loongarch: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:19   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 12/25] target/microblaze: " Julian Ganz
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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 | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index f29ae12af8..ca15af5765 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);
@@ -200,9 +216,11 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw)
         case EXCP_RTE:
             /* Return from an exception.  */
             cf_rte(env);
+            qemu_plugin_vcpu_exception_cb(cs, retaddr);
             return;
         case EXCP_SEMIHOSTING:
             do_m68k_semihosting(env, env->dregs[0]);
+            qemu_plugin_vcpu_hostcall_cb(cs, retaddr);
             return;
         }
     }
@@ -239,6 +257,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,12 +297,14 @@ 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) {
         case EXCP_RTE:
             /* Return from an exception.  */
             m68k_rte(env);
+            qemu_plugin_vcpu_exception_cb(cs, last_pc);
             return;
         }
     }
@@ -417,6 +439,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.0



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

* [PATCH v5 12/25] target/microblaze: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (10 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 11/25] target/m68k: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:21   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 13/25] target/mips: " Julian Ganz
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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 | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
index 9203192483..27283c5dc4 100644
--- a/target/microblaze/helper.c
+++ b/target/microblaze/helper.c
@@ -26,6 +26,7 @@
 #include "exec/target_page.h"
 #include "qemu/host-utils.h"
 #include "exec/log.h"
+#include "qemu/plugin.h"
 
 #ifndef CONFIG_USER_ONLY
 static bool mb_cpu_access_is_secure(MicroBlazeCPU *cpu,
@@ -109,6 +110,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));
@@ -213,6 +215,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.0



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

* [PATCH v5 13/25] target/mips: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (11 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 12/25] target/microblaze: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:23   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 14/25] target/openrisc: " Julian Ganz
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel
  Cc: Julian Ganz, 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.

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 eccaf3624c..abc4d9fef0 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.0



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

* [PATCH v5 14/25] target/openrisc: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (12 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 13/25] target/mips: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:25   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 15/25] target/ppc: " Julian Ganz
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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 | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 486823094c..08f0ed9b89 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,17 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
         cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
     }
 
+    switch (exception) {
+    case EXCP_RESET:
+    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.0



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

* [PATCH v5 15/25] target/ppc: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (13 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 14/25] target/openrisc: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:30   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 16/25] target/riscv: " Julian Ganz
                   ` (10 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel
  Cc: Julian Ganz, Nicholas Piggin, Daniel Henrique Barboza,
	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 | 42 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 1efdc4066e..24740a000b 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,32 @@ 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_DEBUG:
+    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 +478,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 +533,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 +592,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 +679,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 +736,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 +787,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 +833,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 +890,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 +941,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 +981,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 +989,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 +1061,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 +1170,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 +1292,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 +1392,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 +1437,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 +1584,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.0



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

* [PATCH v5 16/25] target/riscv: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (14 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 15/25] target/ppc: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-19 15:19 ` [PATCH v5 17/25] target/rx: " Julian Ganz
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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 d5039f69a9..dce7e34cba 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)
 {
@@ -2173,6 +2174,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;
@@ -2195,6 +2197,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:
@@ -2464,6 +2467,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.0



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

* [PATCH v5 17/25] target/rx: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (15 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 16/25] target/riscv: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:34   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 18/25] target/s390x: " Julian Ganz
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, 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.

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 0640ab322b..09f1c25be2 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 = cs->interrupt_request & 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.0



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

* [PATCH v5 18/25] target/s390x: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (16 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 17/25] target/rx: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:36   ` Richard Henderson
  2025-05-19 15:19 ` [PATCH v5 19/25] target/sh4: " Julian Ganz
                   ` (7 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 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>
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.0



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

* [PATCH v5 19/25] target/sh4: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (17 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 18/25] target/s390x: " Julian Ganz
@ 2025-05-19 15:19 ` Julian Ganz
  2025-05-24 17:38   ` Richard Henderson
  2025-05-19 15:20 ` [PATCH v5 20/25] target/sparc: " Julian Ganz
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, 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.

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 fb7642bda1..ef8760111d 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 = cs->interrupt_request & 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.0



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

* [PATCH v5 20/25] target/sparc: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (18 preceding siblings ...)
  2025-05-19 15:19 ` [PATCH v5 19/25] target/sh4: " Julian Ganz
@ 2025-05-19 15:20 ` Julian Ganz
  2025-05-24 17:41   ` Richard Henderson
  2025-05-19 15:20 ` [PATCH v5 21/25] target/tricore: " Julian Ganz
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, 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.

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 bd14c7a0db..9868a80669 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.0



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

* [PATCH v5 21/25] target/tricore: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (19 preceding siblings ...)
  2025-05-19 15:20 ` [PATCH v5 20/25] target/sparc: " Julian Ganz
@ 2025-05-19 15:20 ` Julian Ganz
  2025-05-20 14:25   ` Bastian Koppelmann
  2025-05-24 17:44   ` Richard Henderson
  2025-05-19 15:20 ` [PATCH v5 22/25] target/xtensa: " Julian Ganz
                   ` (4 subsequent siblings)
  25 siblings, 2 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: Julian Ganz, Bastian Koppelmann

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.

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.0



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

* [PATCH v5 22/25] target/xtensa: call plugin trap callbacks
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (20 preceding siblings ...)
  2025-05-19 15:20 ` [PATCH v5 21/25] target/tricore: " Julian Ganz
@ 2025-05-19 15:20 ` Julian Ganz
  2025-05-19 15:24 ` [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:20 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.0



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

* [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (21 preceding siblings ...)
  2025-05-19 15:20 ` [PATCH v5 22/25] target/xtensa: " Julian Ganz
@ 2025-05-19 15:24 ` Julian Ganz
  2025-05-20 20:01   ` Pierrick Bouvier
  2025-05-19 15:24 ` [PATCH v5 24/25] tests: add test for double-traps on rv64 Julian Ganz
                   ` (2 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Julian Ganz, Alex Bennée, Alexandre Iooss, Mahmoud Mandour,
	Pierrick Bouvier

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. Since
instruction PCs are recorded at translation blocks translation time and
a TB may be used in multiple processes running in distinct virtual
memory, the plugin allows comparing not full addresses but a subset of
address bits via the `compare-addr-bits` option.

Signed-off-by: Julian Ganz <neither@nut.email>
---

Pierrick: I did implement the changes you requested, but I did not add
your Reviewed-By because I felt the changes were not trivial enough to
not require a new, coarse review.

 tests/tcg/plugins/discons.c   | 216 ++++++++++++++++++++++++++++++++++
 tests/tcg/plugins/meson.build |   2 +-
 2 files changed, 217 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..afbd1b400d
--- /dev/null
+++ b/tests/tcg/plugins/discons.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2025, Julian Ganz <neither@nut.email>
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ *
+ * 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 uint64_t compare_addr_mask;
+
+static bool addr_eq(uint64_t a, uint64_t b)
+{
+    return ((a ^ b) & compare_addr_mask) == 0;
+}
+
+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;
+    compare_addr_mask = -1;
+
+    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 if (g_strcmp0(tokens[0], "compare-addr-bits") == 0) {
+            if (g_strcmp0(tokens[1], "full") == 0) {
+                compare_addr_mask = -1;
+            } else {
+                char *end = tokens[1];
+                guint64 bits = g_ascii_strtoull(tokens[1], &end, 10);
+                if (bits == 0 || bits > 64 || *end) {
+                    fprintf(stderr,
+                            "integer parsing failed or out of range: %s\n",
+                            opt);
+                    return -1;
+                }
+                compare_addr_mask = ~(((uint64_t) -1) << bits);
+            }
+        } 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 41f02f2c7f..1b13d6e614 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']
+  foreach i : ['bb', 'discons', 'empty', 'inline', 'insn', 'mem', 'reset', 'syscall']
     if host_os == 'windows'
       t += shared_module(i, files(i + '.c') + '../../../contrib/plugins/win32_linker.c',
                         include_directories: '../../../include/qemu',
-- 
2.49.0



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

* [PATCH v5 24/25] tests: add test for double-traps on rv64
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (22 preceding siblings ...)
  2025-05-19 15:24 ` [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
@ 2025-05-19 15:24 ` Julian Ganz
  2025-05-19 15:24 ` [PATCH v5 25/25] tests: add test with interrupted memory accesses " Julian Ganz
  2025-09-02 10:20 ` [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Alex Bennée
  25 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:24 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 7c1d44d3f4..5fba973e18 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -20,5 +20,11 @@ EXTRA_RUNS += run-issue1060
 run-issue1060: issue1060
 	$(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.0



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

* [PATCH v5 25/25] tests: add test with interrupted memory accesses on rv64
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (23 preceding siblings ...)
  2025-05-19 15:24 ` [PATCH v5 24/25] tests: add test for double-traps on rv64 Julian Ganz
@ 2025-05-19 15:24 ` Julian Ganz
  2025-09-02 10:20 ` [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Alex Bennée
  25 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-19 15:24 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 5fba973e18..5d07755964 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -26,5 +26,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.0



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

* Re: [PATCH v5 21/25] target/tricore: call plugin trap callbacks
  2025-05-19 15:20 ` [PATCH v5 21/25] target/tricore: " Julian Ganz
@ 2025-05-20 14:25   ` Bastian Koppelmann
  2025-05-24 17:44   ` Richard Henderson
  1 sibling, 0 replies; 64+ messages in thread
From: Bastian Koppelmann @ 2025-05-20 14:25 UTC (permalink / raw)
  To: Julian Ganz; +Cc: qemu-devel

On Mon, May 19, 2025 at 05:20:01PM +0200, 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 an exception hook for TriCore targets. Interrupts are
> not implemented for this target and it has no host calls.
> 
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
>  target/tricore/op_helper.c | 5 +++++
>  1 file changed, 5 insertions(+)

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>

Cheers,
Bastian


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

* Re: [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc
  2025-05-19 15:24 ` [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
@ 2025-05-20 20:01   ` Pierrick Bouvier
  2025-05-20 20:44     ` Julian Ganz
  0 siblings, 1 reply; 64+ messages in thread
From: Pierrick Bouvier @ 2025-05-20 20:01 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel
  Cc: Alex Bennée, Alexandre Iooss, Mahmoud Mandour

On 5/19/25 8:24 AM, Julian Ganz wrote:
> 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. Since
> instruction PCs are recorded at translation blocks translation time and
> a TB may be used in multiple processes running in distinct virtual
> memory, the plugin allows comparing not full addresses but a subset of
> address bits via the `compare-addr-bits` option.
> 
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
> 
> Pierrick: I did implement the changes you requested, but I did not add
> your Reviewed-By because I felt the changes were not trivial enough to
> not require a new, coarse review.
>

Looks good to me, thanks.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>

Regarding the issue with the same tb being mapped at different virtual 
addresses, I'm ok with the current solution of comparing only page bits.

That said, a better solution could be to compare physical addresses when 
a discon is detected (on plugin side), and confirm it's really a 
discontinuity or just a different mapping. With this approach, it's not 
even needed to have a dedicated option, and there would be no false 
positive in the plugin. It's just a suggestion though.

Regards,
Pierrick


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

* Re: [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc
  2025-05-20 20:01   ` Pierrick Bouvier
@ 2025-05-20 20:44     ` Julian Ganz
  2025-05-20 21:09       ` Pierrick Bouvier
  0 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-20 20:44 UTC (permalink / raw)
  To: Pierrick Bouvier, qemu-devel
  Cc: Alex Bennée, Alexandre Iooss, Mahmoud Mandour

Hi Pierrick,

May 20, 2025 at 10:01 PM, Pierrick Bouvier wrote:
> Regarding the issue with the same tb being mapped at different virtual addresses, I'm ok with the current solution of comparing only page bits.
> 
> That said, a better solution could be to compare physical addresses when a discon is detected (on plugin side), and confirm it's really a discontinuity or just a different mapping. With this approach, it's not even needed to have a dedicated option, and there would be no false positive in the plugin. It's just a suggestion though.

I actually tried to do this before resorting to the current appraoch.
However, there is only API for querying an instruction's or TB's
hardware address and none that would let me translate the virtual
addresses we receive in the discon callback, which we need to compare
against.

I considered also passing the hardware address to the callback (do the
translation in the `plugin_vcpu_cb__discon` hook), but that turned out
to be not straight forward and not something we'd want to do in the
hook, either.

Regards,
Julian


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

* Re: [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc
  2025-05-20 20:44     ` Julian Ganz
@ 2025-05-20 21:09       ` Pierrick Bouvier
  2025-05-21 19:03         ` Pierrick Bouvier
  0 siblings, 1 reply; 64+ messages in thread
From: Pierrick Bouvier @ 2025-05-20 21:09 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel
  Cc: Alex Bennée, Alexandre Iooss, Mahmoud Mandour

On 5/20/25 1:44 PM, Julian Ganz wrote:
> Hi Pierrick,
> 
> May 20, 2025 at 10:01 PM, Pierrick Bouvier wrote:
>> Regarding the issue with the same tb being mapped at different virtual addresses, I'm ok with the current solution of comparing only page bits.
>>
>> That said, a better solution could be to compare physical addresses when a discon is detected (on plugin side), and confirm it's really a discontinuity or just a different mapping. With this approach, it's not even needed to have a dedicated option, and there would be no false positive in the plugin. It's just a suggestion though.
> 
> I actually tried to do this before resorting to the current appraoch.
> However, there is only API for querying an instruction's or TB's
> hardware address and none that would let me translate the virtual
> addresses we receive in the discon callback, which we need to compare
> against.
>

It would be acceptable to add such a function allowing to query physical 
address for a virtual address (using cpu_get_phys_page_debug behind the 
hoods), as it's not leaking any QEMU implementation detail.

We can implement this later if you don't want to extend your series with 
this.

> I considered also passing the hardware address to the callback (do the
> translation in the `plugin_vcpu_cb__discon` hook), but that turned out
> to be not straight forward and not something we'd want to do in the
> hook, either.
>

Yes, in some cases, people will want virtual addresses, and sometimes 
physical ones. So passing physical ones only is too restrictive.

This plugin is a bit specific, as it's explicitely tracking all 
transitions between instructions, where a "normal" plugin will just work 
with discontinuities. That said, the use case to get physical address 
from a virtual one is a real need.

> Regards,
> Julian

Regards,
Pierrick


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

* Re: [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc
  2025-05-20 21:09       ` Pierrick Bouvier
@ 2025-05-21 19:03         ` Pierrick Bouvier
  0 siblings, 0 replies; 64+ messages in thread
From: Pierrick Bouvier @ 2025-05-21 19:03 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel
  Cc: Alex Bennée, Alexandre Iooss, Mahmoud Mandour

On 5/20/25 2:09 PM, Pierrick Bouvier wrote:
> On 5/20/25 1:44 PM, Julian Ganz wrote:
>> Hi Pierrick,
>>
>> May 20, 2025 at 10:01 PM, Pierrick Bouvier wrote:
>>> Regarding the issue with the same tb being mapped at different virtual addresses, I'm ok with the current solution of comparing only page bits.
>>>
>>> That said, a better solution could be to compare physical addresses when a discon is detected (on plugin side), and confirm it's really a discontinuity or just a different mapping. With this approach, it's not even needed to have a dedicated option, and there would be no false positive in the plugin. It's just a suggestion though.
>>
>> I actually tried to do this before resorting to the current appraoch.
>> However, there is only API for querying an instruction's or TB's
>> hardware address and none that would let me translate the virtual
>> addresses we receive in the discon callback, which we need to compare
>> against.
>>
> 
> It would be acceptable to add such a function allowing to query physical
> address for a virtual address (using cpu_get_phys_page_debug behind the
> hoods), as it's not leaking any QEMU implementation detail.
> 
> We can implement this later if you don't want to extend your series with
> this.
>

An happy coincidence, this was just posted:
https://lore.kernel.org/qemu-devel/20250521094333.4075796-6-rowanbhart@gmail.com/

>> I considered also passing the hardware address to the callback (do the
>> translation in the `plugin_vcpu_cb__discon` hook), but that turned out
>> to be not straight forward and not something we'd want to do in the
>> hook, either.
>>
> 
> Yes, in some cases, people will want virtual addresses, and sometimes
> physical ones. So passing physical ones only is too restrictive.
> 
> This plugin is a bit specific, as it's explicitely tracking all
> transitions between instructions, where a "normal" plugin will just work
> with discontinuities. That said, the use case to get physical address
> from a virtual one is a real need.
> 
>> Regards,
>> Julian
> 
> Regards,
> Pierrick



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

* Re: [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities
  2025-05-19 15:19 ` [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
@ 2025-05-24 16:43   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 16:43 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, Julian Ganz wrote:
> 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>
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   include/qemu/plugin.h      |  1 +
>   include/qemu/qemu-plugin.h | 44 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 45 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 02/25] plugins: add API for registering discontinuity callbacks
  2025-05-19 15:19 ` [PATCH v5 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
@ 2025-05-24 16:48   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 16:48 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 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>
> 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(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-19 15:19 ` [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
@ 2025-05-24 16:55   ` Richard Henderson
  2025-05-25 20:56     ` Julian Ganz
  2025-05-24 17:27   ` Richard Henderson
  1 sibling, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 16:55 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, Julian Ganz wrote:
> +QEMU_DISABLE_CFI
> +static void plugin_vcpu_cb__discon(CPUState *cpu,
> +                                   enum qemu_plugin_discon_type type,
> +                                   uint64_t from)
> +{
> +    struct qemu_plugin_cb *cb, *next;
> +    enum qemu_plugin_event ev;
> +    uint64_t to = cpu->cc->get_pc(cpu);
> +
> +    if (cpu->cpu_index < plugin.num_vcpus) {
> +        switch (type) {
> +        case QEMU_PLUGIN_DISCON_INTERRUPT:
> +            ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT;
> +            break;
> +        case QEMU_PLUGIN_DISCON_EXCEPTION:
> +            ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION;
> +            break;
> +        case QEMU_PLUGIN_DISCON_HOSTCALL:
> +            ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL;
> +            break;

No point passing in QEMU_PLUGIN_DISCON_* only to covert it to QEMU_PLUGIN_EV_*.

> +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from)
> +{
> +    plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_INTERRUPT, from);
> +}
> +
> +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
> +{
> +    plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_EXCEPTION, from);
> +}
> +
> +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
> +{
> +    plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_HOSTCALL, from);
> +}

Better to pass in the value we really want here.


r~


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

* Re: [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 05/25] target/alpha: call plugin trap callbacks Julian Ganz
@ 2025-05-24 16:56   ` Richard Henderson
  2025-05-25 12:14   ` Richard Henderson
  1 sibling, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 16:56 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel

On 5/19/25 16:19, 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 Alpha targets.
> 
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   target/alpha/helper.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 06/25] target/arm: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 06/25] target/arm: " Julian Ganz
@ 2025-05-24 17:05   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:05 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, Julian Ganz wrote:
> @@ -10880,6 +10899,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 = env->pc;

Incorrect.

env->pc is for aarch64 only.
env->regs[15] is for aarch32.

You probably want to use cpu->cc->tcg_ops->get_pc here.
Or export arm_cpu_get_pc from cpu.c so that you can call it directly.

> diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
> index 6614719832..bcb4aae0d5 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)
> @@ -2185,6 +2186,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
>       CPUARMState *env = &cpu->env;
>       uint32_t lr;
>       bool ignore_stackfaults;
> +    uint64_t last_pc = env->pc;

m-profile is always aarch32.

> +    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, last_pc);
> +        break;
> +    default:
> +        qemu_plugin_vcpu_exception_cb(cs, last_pc);
> +    }

Share code with a-profile?  Perhaps place the function in internals.h.


r~


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

* Re: [PATCH v5 07/25] target/avr: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 07/25] target/avr: " Julian Ganz
@ 2025-05-24 17:06   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:06 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 the hook for AVR targets. That architecture appears
> to only know interrupts.
> 
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   target/avr/helper.c | 3 +++
>   1 file changed, 3 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 08/25] target/hppa: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 08/25] target/hppa: " Julian Ganz
@ 2025-05-24 17:07   ` Richard Henderson
  2025-05-24 23:19     ` Julian Ganz
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:07 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel; +Cc: Helge Deller

On 5/19/25 16:19, 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 7d48643bb6..e9325319a7 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 */
> @@ -208,6 +210,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_exception_cb(cs, last_pc);

Interrupts.  Why are these separate from default:?

r~

> +        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] 64+ messages in thread

* Re: [PATCH v5 10/25] target/loongarch: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 10/25] target/loongarch: " Julian Ganz
@ 2025-05-24 17:10   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:10 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 loongarch targets. This architecture
> has one special "exception" for interrupts and no host calls.
> 
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
>   target/loongarch/cpu.c | 4 ++++
>   1 file changed, 4 insertions(+)


Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH v5 11/25] target/m68k: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 11/25] target/m68k: " Julian Ganz
@ 2025-05-24 17:19   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:19 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 Motorola 68000 targets.
> 
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
>   target/m68k/op_helper.c | 24 ++++++++++++++++++++++++
>   1 file changed, 24 insertions(+)
> 
> diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
> index f29ae12af8..ca15af5765 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);
> @@ -200,9 +216,11 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw)
>           case EXCP_RTE:
>               /* Return from an exception.  */
>               cf_rte(env);
> +            qemu_plugin_vcpu_exception_cb(cs, retaddr);
>               return;

EXCP_RTE is not an architectural exception, it's qemu implementation detail.  Think 
"subroutine return, and also pop cpu state".  I don't think you should expose this. 
Certainly you're not instrumenting "return from exception" for other targets.

> @@ -277,12 +297,14 @@ 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) {
>           case EXCP_RTE:
>               /* Return from an exception.  */
>               m68k_rte(env);
> +            qemu_plugin_vcpu_exception_cb(cs, last_pc);
>               return;
>           }
>       }

Likewise.


r~


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

* Re: [PATCH v5 12/25] target/microblaze: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 12/25] target/microblaze: " Julian Ganz
@ 2025-05-24 17:21   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:21 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 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 | 8 ++++++++
>   1 file changed, 8 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 13/25] target/mips: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 13/25] target/mips: " Julian Ganz
@ 2025-05-24 17:23   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:23 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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.
> 
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   target/mips/tcg/system/tlb_helper.c | 11 +++++++++++
>   1 file changed, 11 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 14/25] target/openrisc: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 14/25] target/openrisc: " Julian Ganz
@ 2025-05-24 17:25   ` Richard Henderson
  2025-05-25 20:56     ` Julian Ganz
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:25 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 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 | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
> 
> diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
> index 486823094c..08f0ed9b89 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,17 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>           cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
>       }
>   
> +    switch (exception) {
> +    case EXCP_RESET:

There are plenty of other EXCP_RESET uses that aren't marked as interrupt.
Bug?

Anyway, for this patch,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~

> +    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;
>   }
>   



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

* Re: [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-19 15:19 ` [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
  2025-05-24 16:55   ` Richard Henderson
@ 2025-05-24 17:27   ` Richard Henderson
  2025-05-25 20:56     ` Julian Ganz
  1 sibling, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:27 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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.
> 
> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
>   include/qemu/plugin.h | 12 ++++++++++
>   plugins/core.c        | 53 +++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 65 insertions(+)
> 
> diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
> index 27a176b631..3494325039 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,
> @@ -243,6 +246,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 dc1f5cb4d8..f07813d588 100644
> --- a/plugins/core.c
> +++ b/plugins/core.c
> @@ -104,6 +104,44 @@ 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_discon_type type,
> +                                   uint64_t from)
> +{
> +    struct qemu_plugin_cb *cb, *next;
> +    enum qemu_plugin_event ev;
> +    uint64_t to = cpu->cc->get_pc(cpu);

Maybe cleaner to pass in @to.  It's readily available in the callers.


r~

> +
> +    if (cpu->cpu_index < plugin.num_vcpus) {
> +        switch (type) {
> +        case QEMU_PLUGIN_DISCON_INTERRUPT:
> +            ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT;
> +            break;
> +        case QEMU_PLUGIN_DISCON_EXCEPTION:
> +            ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION;
> +            break;
> +        case QEMU_PLUGIN_DISCON_HOSTCALL:
> +            ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL;
> +            break;
> +        default:
> +            g_assert_not_reached();
> +        }
> +
> +        /* 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
> @@ -539,6 +577,21 @@ 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_DISCON_INTERRUPT, from);
> +}
> +
> +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from)
> +{
> +    plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_EXCEPTION, from);
> +}
> +
> +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from)
> +{
> +    plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_HOSTCALL, from);
> +}
> +
>   void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id,
>                                          qemu_plugin_vcpu_simple_cb_t cb)
>   {



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

* Re: [PATCH v5 15/25] target/ppc: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 15/25] target/ppc: " Julian Ganz
@ 2025-05-24 17:30   ` Richard Henderson
  2025-05-26 10:04     ` Julian Ganz
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:30 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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 Power PC targets.
> 
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
>   target/ppc/excp_helper.c | 42 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 42 insertions(+)
> 
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 1efdc4066e..24740a000b 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,32 @@ 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_DEBUG:

I think DEBUG is an exception.  It's synchronous.

> @@ -758,6 +787,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);

Err... I think you need to be more specific about what you mean by "hostcall".  Certainly 
this isn't the same thing as semihosting.


r~


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

* Re: [PATCH v5 17/25] target/rx: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 17/25] target/rx: " Julian Ganz
@ 2025-05-24 17:34   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:34 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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.
> 
> Signed-off-by: Julian Ganz <neither@nut.email>
> ---
>   target/rx/helper.c | 12 ++++++++++++
>   1 file changed, 12 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 18/25] target/s390x: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 18/25] target/s390x: " Julian Ganz
@ 2025-05-24 17:36   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:36 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel
  Cc: David Hildenbrand, Ilya Leoshkevich, Thomas Huth,
	open list:S390 TCG CPUs

On 5/19/25 16:19, 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 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>
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   target/s390x/tcg/excp_helper.c | 8 ++++++++
>   1 file changed, 8 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 19/25] target/sh4: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 19/25] target/sh4: " Julian Ganz
@ 2025-05-24 17:38   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:38 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:19, 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.
> 
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   target/sh4/helper.c | 4 ++++
>   1 file changed, 4 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 20/25] target/sparc: call plugin trap callbacks
  2025-05-19 15:20 ` [PATCH v5 20/25] target/sparc: " Julian Ganz
@ 2025-05-24 17:41   ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:41 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:20, 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 SPARC (32bit and 64bit) targets. We treat
> any interrupt other than EXTINT and IVEC as exceptions as they appear to
> be synchroneous events.
> 
> 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(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 21/25] target/tricore: call plugin trap callbacks
  2025-05-19 15:20 ` [PATCH v5 21/25] target/tricore: " Julian Ganz
  2025-05-20 14:25   ` Bastian Koppelmann
@ 2025-05-24 17:44   ` Richard Henderson
  1 sibling, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-24 17:44 UTC (permalink / raw)
  To: qemu-devel

On 5/19/25 16:20, 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 an exception hook for TriCore targets. Interrupts are
> not implemented for this target and it has no host calls.
> 
> Signed-off-by: Julian Ganz<neither@nut.email>
> ---
>   target/tricore/op_helper.c | 5 +++++
>   1 file changed, 5 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH v5 08/25] target/hppa: call plugin trap callbacks
  2025-05-24 17:07   ` Richard Henderson
@ 2025-05-24 23:19     ` Julian Ganz
  0 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-24 23:19 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: Helge Deller

Hi Richard,

thanks for the feedback. For some reason only three of your replies made
it to my inbox, but I've seen them (on lore.kernel.org) and I will
incorporate it.

May 24, 2025 at 7:07 PM, Richard Henderson wrote:
> On 5/19/25 16:19, Julian Ganz wrote:
> >  diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
> >  index 7d48643bb6..e9325319a7 100644
> >  --- a/target/hppa/int_helper.c
> >  +++ b/target/hppa/int_helper.c
> > <snip>
> >  @@ -208,6 +210,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_exception_cb(cs, last_pc);
> > 
> Interrupts. Why are these separate from default:?

Oh, right. That should have been interrupts. Thanks for catching that.

It's a crude attempt to make sure I covered all exception types
correctly. The default case handles unknown exceptions, which I _assume_
are interrupts triggered by some periphery (but i might be wrong about
that). I was afraid that the simple absence of a name from the list
below would be too error-prone in terms of long-term maintenance. I'm
not against removing this, though.

Regards,
Julian


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

* Re: [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-19 15:19 ` [PATCH v5 05/25] target/alpha: call plugin trap callbacks Julian Ganz
  2025-05-24 16:56   ` Richard Henderson
@ 2025-05-25 12:14   ` Richard Henderson
  2025-05-25 20:16     ` Julian Ganz
  1 sibling, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-25 12:14 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel

On 5/19/25 16:19, 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 Alpha targets.
> 
> 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;
> +    }

Having read the whole series now, I think it would be better to change the 
TCGCPUOps.do_interrupt interface.

Instead of having each target call qemu_plugin_*, instead have each do_interrupt return 
the discontinuity type, or 0 if the interrupt is blocked so no state change.

Change to cpu_handle_exception would be of the form:

     if (qemu_plugin_discon_enabled(cpu)) {
         vaddr from = tcg_ops->get_pc(cpu);
         unsigned ev = tcg_ops->do_interrupt(cpu);
         if (ev) {
             qemu_plugin_vcpu_discon_cb(cpu, ev, from);
         }
     } else {
         tcg_ops->do_interrupt(cpu);
     }


r~


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

* Re: [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-25 12:14   ` Richard Henderson
@ 2025-05-25 20:16     ` Julian Ganz
  2025-05-26  9:01       ` Richard Henderson
  0 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-25 20:16 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Hi Richard,

May 25, 2025 at 2:14 PM, Richard Henderson wrote:
> Having read the whole series now, I think it would be better to change the TCGCPUOps.do_interrupt interface.
> 
> Instead of having each target call qemu_plugin_*, instead have each do_interrupt return the discontinuity type, or 0 if the interrupt is blocked so no state change.
> 
> Change to cpu_handle_exception would be of the form:
> 
>  if (qemu_plugin_discon_enabled(cpu)) {
>  vaddr from = tcg_ops->get_pc(cpu);
>  unsigned ev = tcg_ops->do_interrupt(cpu);
>  if (ev) {
>  qemu_plugin_vcpu_discon_cb(cpu, ev, from);
>  }
>  } else {
>  tcg_ops->do_interrupt(cpu);
>  }

Personally, I'd be in favour of that. However, I do see some obstacles
to that.

Quite a few targets to call their do_interrupt function internally,
usually from their exec_interrupt. We would then handle that function's
return value at the call site?

Also, some targets such as tricore only have a dummy/stub do_interrupt
and handle exceptions differently inside non-returning functions. For
those, we would call the hooks directly from there as we do now?

And then we have some targets that deviate in some other way. For
example, s390x_cpu_do_interrupt effectively contains a loop, and we
potentially need to call one of the hooks for each iteration.

Regards,
Julian


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

* Re: [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-24 16:55   ` Richard Henderson
@ 2025-05-25 20:56     ` Julian Ganz
  2025-05-26  8:08       ` Julian Ganz
  0 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-25 20:56 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Julian Ganz, Pierrick Bouvier, Alex Bennée, Alexandre Iooss,
	Mahmoud Mandour, qemu-devel

Hi Richard,

CC-ing all the maintainers again.

Richard Henderson wrote:
> On 5/19/25 16:19, Julian Ganz wrote:
> > +QEMU_DISABLE_CFI
> > +static void plugin_vcpu_cb__discon(CPUState *cpu,
> > +                                   enum qemu_plugin_discon_type type,
> > +                                   uint64_t from)
> > +{
> > +    struct qemu_plugin_cb *cb, *next;
> > +    enum qemu_plugin_event ev;
> > +    uint64_t to = cpu->cc->get_pc(cpu);
> > +
> > +    if (cpu->cpu_index < plugin.num_vcpus) {
> > +        switch (type) {
> > +        case QEMU_PLUGIN_DISCON_INTERRUPT:
> > +            ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT;
> > +            break;
> > +        case QEMU_PLUGIN_DISCON_EXCEPTION:
> > +            ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION;
> > +            break;
> > +        case QEMU_PLUGIN_DISCON_HOSTCALL:
> > +            ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL;
> > +            break;
> 
> No point passing in QEMU_PLUGIN_DISCON_* only to covert it to QEMU_PLUGIN_EV_*.

It easily looks that way, and I myself stubled upon this at least one or two
times, but `type` is the enum we pass to the callback a few lines down and part
of the public plugin API. `ev` on the other hand is the offset in the `cb_list`.
So some translation is neccessary, unfortunately.

Regards,
Julian


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

* Re: [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-24 17:27   ` Richard Henderson
@ 2025-05-25 20:56     ` Julian Ganz
  0 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-25 20:56 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Julian Ganz, Pierrick Bouvier, Alex Bennée, Alexandre Iooss,
	Mahmoud Mandour, qemu-devel

Hi Richard,

Richard Henderson wrote:
> On 5/19/25 16:19, Julian Ganz wrote:
> > diff --git a/plugins/core.c b/plugins/core.c
> > index dc1f5cb4d8..f07813d588 100644
> > --- a/plugins/core.c
> > +++ b/plugins/core.c
> > @@ -104,6 +104,44 @@ 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_discon_type type,
> > +                                   uint64_t from)
> > +{
> > +    struct qemu_plugin_cb *cb, *next;
> > +    enum qemu_plugin_event ev;
> > +    uint64_t to = cpu->cc->get_pc(cpu);
> 
> Maybe cleaner to pass in @to.  It's readily available in the callers.

We originally did do that. However, we tried to reduce the noise we have at the
hook calling site to a minimum. And for some targets we would need to consult
get_pc anyway because the PC computation... takes more than one line.

I can still add the parameter. But especially given your latest sugestion of
altering the do_interrupt interface this may not be worth it.

Regards,
Julian


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

* Re: [PATCH v5 14/25] target/openrisc: call plugin trap callbacks
  2025-05-24 17:25   ` Richard Henderson
@ 2025-05-25 20:56     ` Julian Ganz
  0 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-25 20:56 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Julian Ganz, Stafford Horne, qemu-devel

Hi Richard,

> On 5/19/25 16:19, Julian Ganz wrote:
> > diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
> > index 486823094c..08f0ed9b89 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,17 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
> >           cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
> >       }
> >   
> > +    switch (exception) {
> > +    case EXCP_RESET:
> 
> There are plenty of other EXCP_RESET uses that aren't marked as interrupt.
> Bug?

Mh... I might not have been perfectly consistent with resets. We do expect
plugins to be notified of resets already, so we probably don't want to trigger
exception or interrupt callbacks.

I'll check and adjust for the next series.

Regards,
Julian


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

* Re: [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-25 20:56     ` Julian Ganz
@ 2025-05-26  8:08       ` Julian Ganz
  2025-05-26  9:02         ` Richard Henderson
  0 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-26  8:08 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Pierrick Bouvier, Alex Bennée, Alexandre Iooss,
	Mahmoud Mandour, qemu-devel

May 25, 2025 at 10:56 PM, "Julian Ganz" wrote:
> Richard Henderson wrote:
> > On 5/19/25 16:19, Julian Ganz wrote:
> >  +QEMU_DISABLE_CFI
> >  +static void plugin_vcpu_cb__discon(CPUState *cpu,
> >  + enum qemu_plugin_discon_type type,
> >  + uint64_t from)
> >  +{
> >  + struct qemu_plugin_cb *cb, *next;
> >  + enum qemu_plugin_event ev;
> >  + uint64_t to = cpu->cc->get_pc(cpu);
> >  +
> >  + if (cpu->cpu_index < plugin.num_vcpus) {
> >  + switch (type) {
> >  + case QEMU_PLUGIN_DISCON_INTERRUPT:
> >  + ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT;
> >  + break;
> >  + case QEMU_PLUGIN_DISCON_EXCEPTION:
> >  + ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION;
> >  + break;
> >  + case QEMU_PLUGIN_DISCON_HOSTCALL:
> >  + ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL;
> >  + break;
> >  
> >  No point passing in QEMU_PLUGIN_DISCON_* only to covert it to QEMU_PLUGIN_EV_*.
> > 
> It easily looks that way, and I myself stubled upon this at least one or two
> times, but `type` is the enum we pass to the callback a few lines down and part
> of the public plugin API. `ev` on the other hand is the offset in the `cb_list`.
> So some translation is neccessary, unfortunately.

I just realized that you probably meant that we should pass ev as a
parameter to plugin_vcpu_cb__discon. This we can obviously do.

Regards,
Julian


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

* Re: [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-25 20:16     ` Julian Ganz
@ 2025-05-26  9:01       ` Richard Henderson
  2025-05-26  9:54         ` Julian Ganz
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Henderson @ 2025-05-26  9:01 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel, David Hildenbrand

On 5/25/25 21:16, Julian Ganz wrote:
> Hi Richard,
> 
> May 25, 2025 at 2:14 PM, Richard Henderson wrote:
>> Having read the whole series now, I think it would be better to change the TCGCPUOps.do_interrupt interface.
>>
>> Instead of having each target call qemu_plugin_*, instead have each do_interrupt return the discontinuity type, or 0 if the interrupt is blocked so no state change.
>>
>> Change to cpu_handle_exception would be of the form:
>>
>>   if (qemu_plugin_discon_enabled(cpu)) {
>>   vaddr from = tcg_ops->get_pc(cpu);
>>   unsigned ev = tcg_ops->do_interrupt(cpu);
>>   if (ev) {
>>   qemu_plugin_vcpu_discon_cb(cpu, ev, from);
>>   }
>>   } else {
>>   tcg_ops->do_interrupt(cpu);
>>   }
> 
> Personally, I'd be in favour of that. However, I do see some obstacles
> to that.
> 
> Quite a few targets to call their do_interrupt function internally,
> usually from their exec_interrupt. We would then handle that function's
> return value at the call site?

Yes, I think we'd alter the return value of exec_interrupt to match do_interrupt.
There's a comment about exec_interrupt may longjmp away, but that *appears* to be 
historical.  I couldn't identify an existing target that does that.

> Also, some targets such as tricore only have a dummy/stub do_interrupt
> and handle exceptions differently inside non-returning functions. For
> those, we would call the hooks directly from there as we do now?

It may be only tricore.  And you're right, it would be a non-trivial reorg to make tricore 
fall in line with other implementations.  So retaining the separate 
qemu_plugin_vcpu_exception_cb will be required in the short term.


> And then we have some targets that deviate in some other way. For
> example, s390x_cpu_do_interrupt effectively contains a loop, and we
> potentially need to call one of the hooks for each iteration.

That is distinctly odd.  I don't understand what's going on there.

David, can you elucidate re ce204cba74b?  Is this intending to stack all outstanding 
interrupts all at once, leaving the highest priority, then return-from-interrupt processes 
the lower priorities?  It's definitely unusual, but most things about s390x are...  :-)


r~


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

* Re: [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks
  2025-05-26  8:08       ` Julian Ganz
@ 2025-05-26  9:02         ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-26  9:02 UTC (permalink / raw)
  To: Julian Ganz
  Cc: Pierrick Bouvier, Alex Bennée, Alexandre Iooss,
	Mahmoud Mandour, qemu-devel

On 5/26/25 09:08, Julian Ganz wrote:
> May 25, 2025 at 10:56 PM, "Julian Ganz" wrote:
>> Richard Henderson wrote:
>>> On 5/19/25 16:19, Julian Ganz wrote:
>>>   +QEMU_DISABLE_CFI
>>>   +static void plugin_vcpu_cb__discon(CPUState *cpu,
>>>   + enum qemu_plugin_discon_type type,
>>>   + uint64_t from)
>>>   +{
>>>   + struct qemu_plugin_cb *cb, *next;
>>>   + enum qemu_plugin_event ev;
>>>   + uint64_t to = cpu->cc->get_pc(cpu);
>>>   +
>>>   + if (cpu->cpu_index < plugin.num_vcpus) {
>>>   + switch (type) {
>>>   + case QEMU_PLUGIN_DISCON_INTERRUPT:
>>>   + ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT;
>>>   + break;
>>>   + case QEMU_PLUGIN_DISCON_EXCEPTION:
>>>   + ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION;
>>>   + break;
>>>   + case QEMU_PLUGIN_DISCON_HOSTCALL:
>>>   + ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL;
>>>   + break;
>>>   
>>>   No point passing in QEMU_PLUGIN_DISCON_* only to covert it to QEMU_PLUGIN_EV_*.
>>>
>> It easily looks that way, and I myself stubled upon this at least one or two
>> times, but `type` is the enum we pass to the callback a few lines down and part
>> of the public plugin API. `ev` on the other hand is the offset in the `cb_list`.
>> So some translation is neccessary, unfortunately.
> 
> I just realized that you probably meant that we should pass ev as a
> parameter to plugin_vcpu_cb__discon. This we can obviously do.

Yes, that's what I meant.

r~


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

* Re: [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-26  9:01       ` Richard Henderson
@ 2025-05-26  9:54         ` Julian Ganz
  2025-05-26 16:22           ` Richard Henderson
  0 siblings, 1 reply; 64+ messages in thread
From: Julian Ganz @ 2025-05-26  9:54 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel, David Hildenbrand

Hi Richard,

May 26, 2025 at 11:01 AM, Richard Henderson wrote:
> On 5/25/25 21:16, Julian Ganz wrote:
> > Also, some targets such as tricore only have a dummy/stub do_interrupt
> >  and handle exceptions differently inside non-returning functions. For
> >  those, we would call the hooks directly from there as we do now?
> > 
> It may be only tricore. And you're right, it would be a non-trivial reorg to make tricore fall in line with other implementations. So retaining the separate qemu_plugin_vcpu_exception_cb will be required in the short term.

Yes, tricore (and hexagon, which I decided to not support) are the only
ones that don't have a do_interrupt at all.

Note that x86, and maybe other targets as well, may not return from its
do_interrupt but call cpu_loop_exit_restore or something similar,
arbitrarily deep in their call stack. But as far as I can tell that's
also exclusively for exceptions.

Regards,
Julian


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

* Re: [PATCH v5 15/25] target/ppc: call plugin trap callbacks
  2025-05-24 17:30   ` Richard Henderson
@ 2025-05-26 10:04     ` Julian Ganz
  0 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-05-26 10:04 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Julian Ganz, Nicholas Piggin, Daniel Henrique Barboza, qemu-ppc,
	qemu-devel

Hi Richard,

sorry for the late reply to this mail in particular. I needed my memory to be
refreshed.

On 5/19/25 16:19, Julian Ganz wrote:
> > @@ -758,6 +787,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);
> 
> Err... I think you need to be more specific about what you mean by "hostcall".  Certainly 
> this isn't the same thing as semihosting.

We count as a hostcall anything that is handled by code which execution is not
visible to plugins through the exec_insn callbacks. I believe that this is the
case hee, but I might be wrong.

Regards,
Julian


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

* Re: [PATCH v5 05/25] target/alpha: call plugin trap callbacks
  2025-05-26  9:54         ` Julian Ganz
@ 2025-05-26 16:22           ` Richard Henderson
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Henderson @ 2025-05-26 16:22 UTC (permalink / raw)
  To: Julian Ganz, qemu-devel, David Hildenbrand

On 5/26/25 10:54, Julian Ganz wrote:
> Hi Richard,
> 
> May 26, 2025 at 11:01 AM, Richard Henderson wrote:
>> On 5/25/25 21:16, Julian Ganz wrote:
>>> Also, some targets such as tricore only have a dummy/stub do_interrupt
>>>   and handle exceptions differently inside non-returning functions. For
>>>   those, we would call the hooks directly from there as we do now?
>>>
>> It may be only tricore. And you're right, it would be a non-trivial reorg to make tricore fall in line with other implementations. So retaining the separate qemu_plugin_vcpu_exception_cb will be required in the short term.
> 
> Yes, tricore (and hexagon, which I decided to not support) are the only
> ones that don't have a do_interrupt at all.

Hexagon does not yet support system mode, and so is out-of-scope.


r~


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

* Re: [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities
  2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
                   ` (24 preceding siblings ...)
  2025-05-19 15:24 ` [PATCH v5 25/25] tests: add test with interrupted memory accesses " Julian Ganz
@ 2025-09-02 10:20 ` Alex Bennée
  2025-09-02 11:49   ` Julian Ganz
  25 siblings, 1 reply; 64+ messages in thread
From: Alex Bennée @ 2025-09-02 10:20 UTC (permalink / raw)
  To: Julian Ganz; +Cc: qemu-devel

Julian Ganz <neither@nut.email> writes:

> 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.
>
> 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)

Hi Julian,

Just checking what the status of these patches are. It looks like you
have a number of comments to address but the number of reviewed patches
is going up each revision.

Do you think you will be able to spin a new revision and look to get
this merged in the 10.2 cycle?

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


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

* Re: [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities
  2025-09-02 10:20 ` [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Alex Bennée
@ 2025-09-02 11:49   ` Julian Ganz
  0 siblings, 0 replies; 64+ messages in thread
From: Julian Ganz @ 2025-09-02 11:49 UTC (permalink / raw)
  To: Alex Bennée; +Cc: qemu-devel

Hi Alex,

September 2, 2025 at 12:20 PM, "Alex Bennée" wrote:
> Julian Ganz <neither@nut.email> writes:
> 
> > 
> > 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.
> > 
> >  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)
> > 
> Hi Julian,
> 
> Just checking what the status of these patches are. It looks like you
> have a number of comments to address but the number of reviewed patches
> is going up each revision.
> 
> Do you think you will be able to spin a new revision and look to get
> this merged in the 10.2 cycle?

I did plan to send the next revision, but got swept up by other work.
I'll try to get the series ready over the next few days and stay
engaged until the patches are accepted. I am aiming at the 10.2 cycle.

Regards,
Julian


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

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

Thread overview: 64+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-19 15:19 [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Julian Ganz
2025-05-19 15:19 ` [PATCH v5 01/25] plugins: add types for callbacks related to certain discontinuities Julian Ganz
2025-05-24 16:43   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 02/25] plugins: add API for registering discontinuity callbacks Julian Ganz
2025-05-24 16:48   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 03/25] plugins: add hooks for new discontinuity related callbacks Julian Ganz
2025-05-24 16:55   ` Richard Henderson
2025-05-25 20:56     ` Julian Ganz
2025-05-26  8:08       ` Julian Ganz
2025-05-26  9:02         ` Richard Henderson
2025-05-24 17:27   ` Richard Henderson
2025-05-25 20:56     ` Julian Ganz
2025-05-19 15:19 ` [PATCH v5 04/25] contrib/plugins: add plugin showcasing new dicontinuity related API Julian Ganz
2025-05-19 15:19 ` [PATCH v5 05/25] target/alpha: call plugin trap callbacks Julian Ganz
2025-05-24 16:56   ` Richard Henderson
2025-05-25 12:14   ` Richard Henderson
2025-05-25 20:16     ` Julian Ganz
2025-05-26  9:01       ` Richard Henderson
2025-05-26  9:54         ` Julian Ganz
2025-05-26 16:22           ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 06/25] target/arm: " Julian Ganz
2025-05-24 17:05   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 07/25] target/avr: " Julian Ganz
2025-05-24 17:06   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 08/25] target/hppa: " Julian Ganz
2025-05-24 17:07   ` Richard Henderson
2025-05-24 23:19     ` Julian Ganz
2025-05-19 15:19 ` [PATCH v5 09/25] target/i386: " Julian Ganz
2025-05-19 15:19 ` [PATCH v5 10/25] target/loongarch: " Julian Ganz
2025-05-24 17:10   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 11/25] target/m68k: " Julian Ganz
2025-05-24 17:19   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 12/25] target/microblaze: " Julian Ganz
2025-05-24 17:21   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 13/25] target/mips: " Julian Ganz
2025-05-24 17:23   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 14/25] target/openrisc: " Julian Ganz
2025-05-24 17:25   ` Richard Henderson
2025-05-25 20:56     ` Julian Ganz
2025-05-19 15:19 ` [PATCH v5 15/25] target/ppc: " Julian Ganz
2025-05-24 17:30   ` Richard Henderson
2025-05-26 10:04     ` Julian Ganz
2025-05-19 15:19 ` [PATCH v5 16/25] target/riscv: " Julian Ganz
2025-05-19 15:19 ` [PATCH v5 17/25] target/rx: " Julian Ganz
2025-05-24 17:34   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 18/25] target/s390x: " Julian Ganz
2025-05-24 17:36   ` Richard Henderson
2025-05-19 15:19 ` [PATCH v5 19/25] target/sh4: " Julian Ganz
2025-05-24 17:38   ` Richard Henderson
2025-05-19 15:20 ` [PATCH v5 20/25] target/sparc: " Julian Ganz
2025-05-24 17:41   ` Richard Henderson
2025-05-19 15:20 ` [PATCH v5 21/25] target/tricore: " Julian Ganz
2025-05-20 14:25   ` Bastian Koppelmann
2025-05-24 17:44   ` Richard Henderson
2025-05-19 15:20 ` [PATCH v5 22/25] target/xtensa: " Julian Ganz
2025-05-19 15:24 ` [PATCH v5 23/25] tests: add plugin asserting correctness of discon event's to_pc Julian Ganz
2025-05-20 20:01   ` Pierrick Bouvier
2025-05-20 20:44     ` Julian Ganz
2025-05-20 21:09       ` Pierrick Bouvier
2025-05-21 19:03         ` Pierrick Bouvier
2025-05-19 15:24 ` [PATCH v5 24/25] tests: add test for double-traps on rv64 Julian Ganz
2025-05-19 15:24 ` [PATCH v5 25/25] tests: add test with interrupted memory accesses " Julian Ganz
2025-09-02 10:20 ` [PATCH v5 00/25] tcg-plugins: add hooks for discontinuities Alex Bennée
2025-09-02 11:49   ` 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).