On 3/11/26 2:59 AM, Alex Bennée wrote:
Pierrick Bouvier <[email protected]> writes:

On 3/9/26 9:21 AM, Florian Hofhammer wrote:
This patch adds docstrings for typedefs and function declarations in
include/plugins/qemu-plugin.h that were previously missing. This
resolves inconsistencies in the docs, e.g., the description for
qemu_plugin_read_register() referring to qemu_plugin_register_flush_cb()
but code cache flush callbacks not being documented themselves.
Signed-off-by: Florian Hofhammer <[email protected]>
---
Hi,
While working on a QEMU plugin and browsing the online docs at
https://www.qemu.org/docs/master/devel/tcg-plugins.html, I noticed that
some of the API functions were not actually documented.
I went through the include/plugins/qemu-plugin.h header file and
added
docstrings where they were missing, hoping of course that I documented
the correct functionality based on my understanding of the plugin
internals.
I hope that's useful and I didn't miss anything!


Thanks for the effort, that's always welcome to add documentation on a
public API like this!

Best regards,
Florian
--
Florian Hofhammer
---
   include/plugins/qemu-plugin.h | 98 
++++++++++++++++++++++++++++++++++++++-----
   1 file changed, 88 insertions(+), 10 deletions(-)
diff --git a/include/plugins/qemu-plugin.h
b/include/plugins/qemu-plugin.h
index 827e8e1787..fcf5af52ed 100644
--- a/include/plugins/qemu-plugin.h
+++ b/include/plugins/qemu-plugin.h
@@ -339,12 +339,28 @@ enum qemu_plugin_cb_flags {
       QEMU_PLUGIN_CB_RW_REGS_PC,
   };
   +/**
+ * enum qemu_plugin_mem_rw - type of memory access
+ *
+ * @QEMU_PLUGIN_MEM_R: memory read access only
+ * @QEMU_PLUGIN_MEM_W: memory write access only
+ * @QEMU_PLUGIN_MEM_RW: memory read and write access
+ */
   enum qemu_plugin_mem_rw {
       QEMU_PLUGIN_MEM_R = 1,
       QEMU_PLUGIN_MEM_W,
       QEMU_PLUGIN_MEM_RW,
   };
   +/**
+ * enum qemu_plugin_mem_value_type - size of memory value
+ *
+ * @QEMU_PLUGIN_MEM_VALUE_U8: unsigned 8-bit value
+ * @QEMU_PLUGIN_MEM_VALUE_U16: unsigned 16-bit value
+ * @QEMU_PLUGIN_MEM_VALUE_U32: unsigned 32-bit value
+ * @QEMU_PLUGIN_MEM_VALUE_U64: unsigned 64-bit value
+ * @QEMU_PLUGIN_MEM_VALUE_U128: unsigned 128-bit value
+ */
   enum qemu_plugin_mem_value_type {
       QEMU_PLUGIN_MEM_VALUE_U8,
       QEMU_PLUGIN_MEM_VALUE_U16,
@@ -353,7 +369,13 @@ enum qemu_plugin_mem_value_type {
       QEMU_PLUGIN_MEM_VALUE_U128,
   };
   -/* typedef qemu_plugin_mem_value - value accessed during a
load/store */
+/**
+ * typedef qemu_plugin_mem_value - value accessed during a load/store
+ *
+ * @type: the memory access size
+ * @data: the value accessed during the memory operation (value after
+ *        read/write)
+ */
   typedef struct {
       enum qemu_plugin_mem_value_type type;
       union {
@@ -462,7 +484,6 @@ void qemu_plugin_register_vcpu_tb_exec_cond_cb(struct 
qemu_plugin_tb *tb,
    * @QEMU_PLUGIN_INLINE_ADD_U64: add an immediate value uint64_t
    * @QEMU_PLUGIN_INLINE_STORE_U64: store an immediate value uint64_t
    */
-
   enum qemu_plugin_op {
       QEMU_PLUGIN_INLINE_ADD_U64,
       QEMU_PLUGIN_INLINE_STORE_U64,
@@ -803,6 +824,20 @@ const void *qemu_plugin_request_time_control(void);
   QEMU_PLUGIN_API
   void qemu_plugin_update_ns(const void *handle, int64_t time);
   +/**
+ * typedef qemu_plugin_vcpu_syscall_cb_t - vCPU syscall callback function type
+ * @id: plugin id
+ * @vcpu_index: the executing vCPU
+ * @num: the syscall number
+ * @a1: the 1st syscall argument
+ * @a2: the 2nd syscall argument
+ * @a3: the 3rd syscall argument
+ * @a4: the 4th syscall argument
+ * @a5: the 5th syscall argument
+ * @a6: the 6th syscall argument
+ * @a7: the 7th syscall argument
+ * @a8: the 8th syscall argument
+ */
   typedef void
   (*qemu_plugin_vcpu_syscall_cb_t)(qemu_plugin_id_t id, unsigned int 
vcpu_index,
                                    int64_t num, uint64_t a1, uint64_t a2,
@@ -836,24 +871,61 @@ typedef bool
                                           uint64_t a6, uint64_t a7, uint64_t 
a8,
                                           uint64_t *sysret);
   -QEMU_PLUGIN_API
-void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id,
-                                          qemu_plugin_vcpu_syscall_cb_t cb);
-
+/**
+ * typedef qemu_plugin_vcpu_syscall_ret_cb_t - vCPU syscall return callback
+ * function type
+ * @id: plugin id
+ * @vcpu_index: the executing vCPU
+ * @num: the syscall number
+ * @ret: the syscall return value
+ */
   typedef void
   (*qemu_plugin_vcpu_syscall_ret_cb_t)(qemu_plugin_id_t id, unsigned int 
vcpu_idx,
                                        int64_t num, int64_t ret);
   +/**
+ * qemu_plugin_register_vcpu_syscall_cb() - register a syscall entry callback
+ * @id: plugin id
+ * @cb: callback of type qemu_plugin_vcpu_syscall_cb_t
+ *
+ * This registers a callback for every syscall executed by the guest. The @cb
+ * function is executed before a syscall is handled by the host.
+ */
   QEMU_PLUGIN_API
-void
-qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id,
-                                         qemu_plugin_vcpu_syscall_ret_cb_t cb);
+void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id,
+                                          qemu_plugin_vcpu_syscall_cb_t cb);
   +/**
+ * qemu_plugin_register_vcpu_syscall_filter_cb() - register a syscall filter
+ * callback
+ * @id: plugin id
+ * @cb: callback of type qemu_plugin_vcpu_syscall_filter_cb_t
+ *
+ * This registers a callback for every syscall executed by the guest. The @cb
+ * function is executed before a syscall is handled by the host. If the
+ * callback returns true, the syscall is filtered and will not be executed by
+ * the host. The callback must then set the syscall return value via the
+ * corresponding pointer passed to it.
+ */
   QEMU_PLUGIN_API
   void
   qemu_plugin_register_vcpu_syscall_filter_cb(qemu_plugin_id_t id,
                                               
qemu_plugin_vcpu_syscall_filter_cb_t cb);
   +/**
+ * qemu_plugin_register_vcpu_syscall_ret_cb() - register a syscall entry
+ * callback
+ * @id: plugin id
+ * @cb: callback of type qemu_plugin_vcpu_syscall_ret_cb_t
+ *
+ * This registers a callback for every syscall executed by the guest. The @cb
+ * function is executed upon return from the host syscall before execution is
+ * handed back to the guest.
+ */
+QEMU_PLUGIN_API
+void
+qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id,
+                                         qemu_plugin_vcpu_syscall_ret_cb_t cb);
     /**
    * qemu_plugin_insn_disas() - return disassembly string for instruction
@@ -861,7 +933,6 @@ 
qemu_plugin_register_vcpu_syscall_filter_cb(qemu_plugin_id_t id,
    *
    * Returns an allocated string containing the disassembly
    */
-
   QEMU_PLUGIN_API
   char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn);
   @@ -888,6 +959,13 @@ QEMU_PLUGIN_API
   void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id,
                                  qemu_plugin_vcpu_simple_cb_t cb);
   +/**
+ * qemu_plugin_register_flush_cb() - register code cache flush callback
+ * @id: plugin ID
+ * @cb: callback
+ *
+ * The @cb function is called every time the code cache is flushed.
+ */

Thanks, I was thinking to document this since someone asked a question
on IRC a few weeks ago.

May you add here:
"This callback can be used to free resources associated with existing
translated blocks in a plugin. @cb is guaranteed to run with all cpus
being stopped, thus no lock is required within it."

This does make me wonder what the use case for this callback is? In
theory the state of the code cache should be an internal implementation
detail that plugins shouldn't need to concern themselves with.


It can be useful for plugins who want a callback to cleanup resources they allocated for each tb (like a hashtable associating a pc to some data). At the moment, that's the only way to be notified that a TB won't be used anymore. Even though it's an implementation detail when we do such an operation, it's one thing that is mandatory for plugins allocating a lot of data per tb, which quickly adds up. In all cases, when a tb won't be used anymore will always be an implementation detail, since we need to do flush them in case we fill the jump cache for instance.

All that said, there is no usage of this callback in any existing plugins, and the documentation I asked to Florian was inspired by someone coming on IRC a few weeks ago with the question "How can I know when a tb won't be used anymore so I can free data associated?".

Regards,
Pierrick

Reply via email to