[RFC PATCH v2 1/7] plugins: add API for registering trap related callbacks

Julian Ganz posted 7 patches 3 days, 6 hours ago
[RFC PATCH v2 1/7] plugins: add API for registering trap related callbacks
Posted by Julian Ganz 3 days, 6 hours ago
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 and, on most platforms, 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 an interface for the registration of trap related
callbacks. Specifically we (loosely) define interrupts, exceptions and
semihosting events across all platforms and introduce one callback for
each type of event. Because possible modes and concepts for enumeration
of traps vary greatly between different architectures the callbacks are
`qemu_plugin_vcpu_simple_cb_t`. That is, they only receive the VCPU id
and may need to call other API functions for retrieving additional
information.

Signed-off-by: Julian Ganz <neither@nut.email>
---
 include/qemu/plugin-event.h  |  3 +++
 include/qemu/qemu-plugin.h   | 45 ++++++++++++++++++++++++++++++++++++
 plugins/core.c               | 18 +++++++++++++++
 plugins/qemu-plugins.symbols |  3 +++
 4 files changed, 69 insertions(+)

diff --git a/include/qemu/plugin-event.h b/include/qemu/plugin-event.h
index 7056d8427b..2b69a3821b 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_SEMIHOSTING,
     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 622c9a0232..94c3ccd496 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -230,6 +230,51 @@ 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_interrupt_cb() - register a vCPU interrupt callback
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU receives an interrupt, after the
+ * vCPU was prepared to handle the interrupt. An interrupt, in this context and
+ * across all architectures, is defined as an asynchronous event, usually
+ * originating from outside the CPU. Preparation usually entails updating the PC
+ * to some interrupt handler or trap vector entry.
+ */
+QEMU_PLUGIN_API
+void qemu_plugin_register_vcpu_interrupt_cb(qemu_plugin_id_t id,
+                                            qemu_plugin_vcpu_simple_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_exception_cb() - register a vCPU exception callback
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU receives an exception (excluding
+ * semihosting events), after the vCPU was prepared to handle the expection. An
+ * exception, in this context and across all architectures, is defined as a
+ * synchronous event in response to a specific instruction being executed.
+ * Preparation usually entails updating the PC to some exception handler or trap
+ * vector entry.
+ */
+QEMU_PLUGIN_API
+void qemu_plugin_register_vcpu_exception_cb(qemu_plugin_id_t id,
+                                            qemu_plugin_vcpu_simple_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_semihosting_cb() - register a vCPU semihosting cb
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU encounters a semihosting event,
+ * after the event was handled. A semihosting event can be thought of as a
+ * special kind of exception that is not handled by code run by the vCPU but
+ * machinery outside the vCPU.
+ */
+QEMU_PLUGIN_API
+void qemu_plugin_register_vcpu_semihosting_cb(qemu_plugin_id_t id,
+                                              qemu_plugin_vcpu_simple_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 bb105e8e68..9de997069c 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -559,6 +559,24 @@ 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_interrupt_cb(qemu_plugin_id_t id,
+                                            qemu_plugin_vcpu_simple_cb_t cb)
+{
+    plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INTERRUPT, cb);
+}
+
+void qemu_plugin_register_vcpu_exception_cb(qemu_plugin_id_t id,
+                                            qemu_plugin_vcpu_simple_cb_t cb)
+{
+    plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXCEPTION, cb);
+}
+
+void qemu_plugin_register_vcpu_semihosting_cb(qemu_plugin_id_t id,
+                                              qemu_plugin_vcpu_simple_cb_t cb)
+{
+    plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SEMIHOSTING, cb);
+}
+
 void qemu_plugin_register_flush_cb(qemu_plugin_id_t id,
                                    qemu_plugin_simple_cb_t cb)
 {
diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols
index 032661f9ea..449a47af22 100644
--- a/plugins/qemu-plugins.symbols
+++ b/plugins/qemu-plugins.symbols
@@ -34,6 +34,9 @@
   qemu_plugin_register_vcpu_mem_cb;
   qemu_plugin_register_vcpu_mem_inline_per_vcpu;
   qemu_plugin_register_vcpu_resume_cb;
+  qemu_plugin_register_vcpu_interrupt_cb;
+  qemu_plugin_register_vcpu_exception_cb;
+  qemu_plugin_register_vcpu_semihosting_cb;
   qemu_plugin_register_vcpu_syscall_cb;
   qemu_plugin_register_vcpu_syscall_ret_cb;
   qemu_plugin_register_vcpu_tb_exec_cb;
-- 
2.45.2