diff mbox series

[v3,07/50] plugin: add user-facing API

Message ID 20190614171200.21078-8-alex.bennee@linaro.org
State New
Headers show
Series tcg plugin support | expand

Commit Message

Alex Bennée June 14, 2019, 5:11 p.m. UTC
From: "Emilio G. Cota" <cota@braap.org>


Add the API first to ease review.

Signed-off-by: Emilio G. Cota <cota@braap.org>

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>


---
v3
  - merge in changes to plugin install/reset/uninstall
  - split api file
---
 include/qemu/qemu-plugin.h | 339 +++++++++++++++++++++++++++++++++++++
 1 file changed, 339 insertions(+)
 create mode 100644 include/qemu/qemu-plugin.h

-- 
2.20.1

Comments

Pranith Kumar June 19, 2019, 3:34 a.m. UTC | #1
On Fri, Jun 14, 2019 at 10:24 AM Alex Bennée <alex.bennee@linaro.org> wrote:
>

> From: "Emilio G. Cota" <cota@braap.org>

>

> Add the API first to ease review.

>

> Signed-off-by: Emilio G. Cota <cota@braap.org>

> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

>

> ---

> v3

>   - merge in changes to plugin install/reset/uninstall

>   - split api file

> ---

>  include/qemu/qemu-plugin.h | 339 +++++++++++++++++++++++++++++++++++++

>  1 file changed, 339 insertions(+)

>  create mode 100644 include/qemu/qemu-plugin.h

>

> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h

> new file mode 100644

> index 0000000000..0db1ef9714

> --- /dev/null

> +++ b/include/qemu/qemu-plugin.h

> @@ -0,0 +1,339 @@

> +/*

> + * Copyright (C) 2017, Emilio G. Cota <cota@braap.org>

> + * Copyright (C) 2019, Linaro

> + *

> + * License: GNU GPL, version 2 or later.

> + *   See the COPYING file in the top-level directory.

> + *

> + * SPDX-License-Identifier: GPL-2.0-or-later

> + */

> +#ifndef QEMU_PLUGIN_API_H

> +#define QEMU_PLUGIN_API_H

> +

> +#include <inttypes.h>

> +#include <stdbool.h>

> +

> +/*

> + * For best performance, build the plugin with -fvisibility=hidden so that

> + * QEMU_PLUGIN_LOCAL is implicit. Then, just mark qemu_plugin_install with

> + * QEMU_PLUGIN_EXPORT. For more info, see

> + *   https://gcc.gnu.org/wiki/Visibility

> + */

> +#if defined _WIN32 || defined __CYGWIN__

> +  #ifdef BUILDING_DLL

> +    #define QEMU_PLUGIN_EXPORT __declspec(dllexport)

> +  #else

> +    #define QEMU_PLUGIN_EXPORT __declspec(dllimport)

> +  #endif

> +  #define QEMU_PLUGIN_LOCAL

> +#else

> +  #if __GNUC__ >= 4

> +    #define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))

> +    #define QEMU_PLUGIN_LOCAL  __attribute__((visibility("hidden")))

> +  #else

> +    #define QEMU_PLUGIN_EXPORT

> +    #define QEMU_PLUGIN_LOCAL

> +  #endif

> +#endif

> +

> +typedef uint64_t qemu_plugin_id_t;

> +

> +/**

> + * qemu_plugin_install() - Install a plugin

> + * @id: this plugin's opaque ID

> + * @argc: number of arguments

> + * @argv: array of arguments (@argc elements)

> + *

> + * All plugins must export this symbol.

> + *

> + * Note: Calling qemu_plugin_uninstall() from this function is a bug. To raise

> + * an error during install, return !0.

> + *

> + * Note: @argv remains valid throughout the lifetime of the loaded plugin.

> + */

> +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, int argc,

> +                                           char **argv);

> +

> +/*

> + * Prototypes for the various callback styles we will be registering

> + * in the following functions.

> + */

> +typedef void (*qemu_plugin_simple_cb_t)(qemu_plugin_id_t id);

> +

> +typedef void (*qemu_plugin_udata_cb_t)(qemu_plugin_id_t id, void *userdata);

> +

> +typedef void (*qemu_plugin_vcpu_simple_cb_t)(qemu_plugin_id_t id,

> +                                             unsigned int vcpu_index);

> +

> +typedef void (*qemu_plugin_vcpu_udata_cb_t)(unsigned int vcpu_index,

> +                                            void *userdata);

> +

> +/**

> + * qemu_plugin_uninstall() - Uninstall a plugin

> + * @id: this plugin's opaque ID

> + * @cb: callback to be called once the plugin has been removed

> + *

> + * Do NOT assume that the plugin has been uninstalled once this function

> + * returns. Plugins are uninstalled asynchronously, and therefore the given

> + * plugin receives callbacks until @cb is called.

> + *

> + * Note: Calling this function from qemu_plugin_install() is a bug.

> + */

> +void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb);

> +

> +/**

> + * qemu_plugin_reset() - Reset a plugin

> + * @id: this plugin's opaque ID

> + * @cb: callback to be called once the plugin has been reset

> + *

> + * Unregisters all callbacks for the plugin given by @id.

> + *

> + * Do NOT assume that the plugin has been reset once this function returns.

> + * Plugins are reset asynchronously, and therefore the given plugin receives

> + * callbacks until @cb is called.

> + */

> +void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb);

> +

> +/**

> + * qemu_plugin_register_vcpu_init_cb() - register a vCPU initialization callback

> + * @id: plugin ID

> + * @cb: callback function

> + *

> + * The @cb function is called every time a vCPU is initialized.

> + *

> + * See also: qemu_plugin_register_vcpu_exit_cb()

> + */

> +void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id,

> +                                       qemu_plugin_vcpu_simple_cb_t cb);

> +

> +/**

> + * qemu_plugin_register_vcpu_exit_cb() - register a vCPU exit callback

> + * @id: plugin ID

> + * @cb: callback function

> + *

> + * The @cb function is called every time a vCPU exits.

> + *

> + * See also: qemu_plugin_register_vcpu_init_cb()

> + */

> +void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id,

> +                                       qemu_plugin_vcpu_simple_cb_t cb);

> +

> +/**

> + * qemu_plugin_register_vcpu_idle_cb() - register a vCPU idle callback

> + * @id: plugin ID

> + * @cb: callback function

> + *

> + * The @cb function is called every time a vCPU idles.

> + */

> +void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id,

> +                                       qemu_plugin_vcpu_simple_cb_t cb);

> +

> +/**

> + * qemu_plugin_register_vcpu_resume_cb() - register a vCPU resume callback

> + * @id: plugin ID

> + * @cb: callback function

> + *

> + * The @cb function is called every time a vCPU resumes execution.

> + */

> +void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id,

> +                                         qemu_plugin_vcpu_simple_cb_t cb);

> +

> +/*

> + * Opaque types that the plugin is given during the translation and

> + * instrumentation phase.

> + */

> +struct qemu_plugin_tb;

> +struct qemu_plugin_insn;

> +

> +enum qemu_plugin_cb_flags {

> +    QEMU_PLUGIN_CB_NO_REGS, /* callback does not access the CPU's regs */

> +    QEMU_PLUGIN_CB_R_REGS,  /* callback reads the CPU's regs */

> +    QEMU_PLUGIN_CB_RW_REGS, /* callback reads and writes the CPU's regs */

> +};

> +

> +enum qemu_plugin_mem_rw {

> +    QEMU_PLUGIN_MEM_R = 1,

> +    QEMU_PLUGIN_MEM_W,

> +    QEMU_PLUGIN_MEM_RW,

> +};


Why is this structure different from qemu_plugin_cb_flags? I think
both of them could use a similar structure. Both of them can have
(_NO, _R, _W, _RW) I think.

> +

> +/**

> + * qemu_plugin_register_vcpu_tb_trans_cb() - register a translate cb

> + * @id: plugin ID

> + * @cb: callback function

> + *

> + * The @cb function is called every time a translation occurs. The @cb

> + * function is passed an opaque qemu_plugin_type which is can query


s/is/it/


> + * for additional information including the list of translated

> + * instructions. At this point the plugin can register further

> + * callbacks to be triggered when the block or individual instruction

> + * executes.

> + */

> +typedef void (*qemu_plugin_vcpu_tb_trans_cb_t)(qemu_plugin_id_t id,

> +                                               unsigned int vcpu_index,

> +                                               struct qemu_plugin_tb *tb);

> +

> +void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id,

> +                                           qemu_plugin_vcpu_tb_trans_cb_t cb);

> +

> +/**

> + * qemu_plugin_register_vcpu_tb_trans_exec_cb() - register execution callback

> + * @tb: the opaque qemu_plugin_tb handle for the translation

> + * @cb: callback function

> + * @flags: does the plugin read or write the CPU's registers?

> + * @userdata: any plugin data to pass to the @cb?

> + *

> + * The @cb function is called every time a translated unit executes.

> + */

> +void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,

> +                                          qemu_plugin_vcpu_udata_cb_t cb,

> +                                          enum qemu_plugin_cb_flags flags,

> +                                          void *userdata);

> +

> +enum qemu_plugin_op {

> +    QEMU_PLUGIN_INLINE_ADD_U64,

> +};

> +

> +/**

> + * qemu_plugin_register_vcpu_tb_trans_exec_inline() - execution inline op

> + * @tb: the opaque qemu_plugin_tb handle for the translation

> + * @op: the type of qemu_plugin_op (e.g. ADD_U64)

> + * @ptr: the target memory location for the op

> + * @imm: the op data (e.g. 1)

> + *

> + * Insert an inline op to every time a translated unit executes.

> + * Useful if you just want to increment a single counter somewhere in

> + * memory.

> + */

> +void qemu_plugin_register_vcpu_tb_exec_inline(struct qemu_plugin_tb *tb,

> +                                              enum qemu_plugin_op op,

> +                                              void *ptr, uint64_t imm);

> +

> +/**

> + * qemu_plugin_register_vcpu_insn_exec_cb() - register insn execution cb

> + * @insn: the opaque qemu_plugin_insn handle for an instruction

> + * @cb: callback function

> + * @flags: does the plugin read or write the CPU's registers?

> + * @userdata: any plugin data to pass to the @cb?

> + *

> + * The @cb function is called every time an instruction is executed

> + */

> +void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,

> +                                            qemu_plugin_vcpu_udata_cb_t cb,

> +                                            enum qemu_plugin_cb_flags flags,

> +                                            void *userdata);

> +

> +/**

> + * qemu_plugin_register_vcpu_insn_exec_inline() - insn execution inline op

> + * @insn: the opaque qemu_plugin_insn handle for an instruction

> + * @cb: callback function

> + * @op: the type of qemu_plugin_op (e.g. ADD_U64)

> + * @ptr: the target memory location for the op

> + * @imm: the op data (e.g. 1)

> + *

> + * Insert an inline op to every time an instruction executes. Useful

> + * if you just want to increment a single counter somewhere in memory.

> + */

> +void qemu_plugin_register_vcpu_insn_exec_inline(struct qemu_plugin_insn *insn,

> +                                                enum qemu_plugin_op op,

> +                                                void *ptr, uint64_t imm);

> +

> +/*

> + * Helpers to query information about the instructions in a block

> + */

> +size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb);

> +

> +uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb);

> +

> +struct qemu_plugin_insn *

> +qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx);

> +

> +const void *qemu_plugin_insn_data(const struct qemu_plugin_insn *insn);

> +

> +size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn);

> +

> +uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn);

> +void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn);

> +

> +/*

> + * Memory Instrumentation

> + */

> +typedef uint32_t qemu_plugin_meminfo_t;

> +

> +unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info);

> +bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info);

> +bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info);

> +bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info);

> +

> +typedef void

> +(*qemu_plugin_vcpu_mem_cb_t)(unsigned int vcpu_index,

> +                             qemu_plugin_meminfo_t info, uint64_t vaddr,

> +                             void *userdata);

> +

> +typedef void

> +(*qemu_plugin_vcpu_mem_haddr_cb_t)(unsigned int vcpu_index,

> +                                   qemu_plugin_meminfo_t info, uint64_t vaddr,

> +                                   void *haddr, void *userdata);

> +

> +void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,

> +                                      qemu_plugin_vcpu_mem_cb_t cb,

> +                                      enum qemu_plugin_cb_flags flags,

> +                                      enum qemu_plugin_mem_rw rw,

> +                                      void *userdata);

> +

> +void qemu_plugin_register_vcpu_mem_haddr_cb(struct qemu_plugin_insn *insn,

> +                                            qemu_plugin_vcpu_mem_haddr_cb_t cb,

> +                                            enum qemu_plugin_cb_flags flags,

> +                                            enum qemu_plugin_mem_rw rw,

> +                                            void *userdata);

> +

> +void qemu_plugin_register_vcpu_mem_inline(struct qemu_plugin_insn *insn,

> +                                          enum qemu_plugin_mem_rw rw,

> +                                          enum qemu_plugin_op op, void *ptr,

> +                                          uint64_t imm);

> +

> +uint64_t qemu_plugin_ram_addr_from_host(void *haddr);

> +

> +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,

> +                                 uint64_t a3, uint64_t a4, uint64_t a5,

> +                                 uint64_t a6, uint64_t a7, uint64_t a8);

> +

> +void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id,

> +                                          qemu_plugin_vcpu_syscall_cb_t cb);

> +

> +typedef void

> +(*qemu_plugin_vcpu_syscall_ret_cb_t)(qemu_plugin_id_t id, unsigned int vcpu_idx,

> +                                     int64_t num, int64_t ret);

> +

> +void

> +qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id,

> +                                         qemu_plugin_vcpu_syscall_ret_cb_t cb);

> +

> +

> +/**

> + * qemu_plugin_vcpu_for_each() - iterate over the existing vCPU

> + * @id: plugin ID

> + * @cb: callback function

> + *

> + * The @cb function is called once for each existing vCPU.

> + *

> + * See also: qemu_plugin_register_vcpu_init_cb()

> + */

> +void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id,

> +                               qemu_plugin_vcpu_simple_cb_t cb);

> +

> +void qemu_plugin_register_flush_cb(qemu_plugin_id_t id,

> +                                   qemu_plugin_simple_cb_t cb);

> +

> +void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id,

> +                                    qemu_plugin_udata_cb_t cb, void *userdata);

> +

> +/* returns -1 in user-mode */

> +int qemu_plugin_n_vcpus(void);

> +

> +/* returns -1 in user-mode */

> +int qemu_plugin_n_max_vcpus(void);

> +

> +#endif /* QEMU_PLUGIN_API_H */

> --

> 2.20.1

>

>



--
Pranith
Alex Bennée June 19, 2019, 11:32 a.m. UTC | #2
Pranith Kumar <pranith.foss@gmail.com> writes:

> On Fri, Jun 14, 2019 at 10:24 AM Alex Bennée <alex.bennee@linaro.org> wrote:

>>

>> From: "Emilio G. Cota" <cota@braap.org>

>>

>> Add the API first to ease review.

>>

>> Signed-off-by: Emilio G. Cota <cota@braap.org>

>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

>>

>> ---

>> v3

>>   - merge in changes to plugin install/reset/uninstall

>>   - split api file

>> ---

>>  include/qemu/qemu-plugin.h | 339 +++++++++++++++++++++++++++++++++++++

>>  1 file changed, 339 insertions(+)

>>  create mode 100644 include/qemu/qemu-plugin.h

>>

>> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h

>> new file mode 100644

>> index 0000000000..0db1ef9714

>> --- /dev/null

>> +++ b/include/qemu/qemu-plugin.h

>> @@ -0,0 +1,339 @@

>> +/*

>> + * Copyright (C) 2017, Emilio G. Cota <cota@braap.org>

>> + * Copyright (C) 2019, Linaro

>> + *

>> + * License: GNU GPL, version 2 or later.

>> + *   See the COPYING file in the top-level directory.

>> + *

>> + * SPDX-License-Identifier: GPL-2.0-or-later

>> + */

>> +#ifndef QEMU_PLUGIN_API_H

>> +#define QEMU_PLUGIN_API_H

>> +

>> +#include <inttypes.h>

>> +#include <stdbool.h>

>> +

>> +/*

>> + * For best performance, build the plugin with -fvisibility=hidden so that

>> + * QEMU_PLUGIN_LOCAL is implicit. Then, just mark qemu_plugin_install with

>> + * QEMU_PLUGIN_EXPORT. For more info, see

>> + *   https://gcc.gnu.org/wiki/Visibility

>> + */

>> +#if defined _WIN32 || defined __CYGWIN__

>> +  #ifdef BUILDING_DLL

>> +    #define QEMU_PLUGIN_EXPORT __declspec(dllexport)

>> +  #else

>> +    #define QEMU_PLUGIN_EXPORT __declspec(dllimport)

>> +  #endif

>> +  #define QEMU_PLUGIN_LOCAL

>> +#else

>> +  #if __GNUC__ >= 4

>> +    #define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))

>> +    #define QEMU_PLUGIN_LOCAL  __attribute__((visibility("hidden")))

>> +  #else

>> +    #define QEMU_PLUGIN_EXPORT

>> +    #define QEMU_PLUGIN_LOCAL

>> +  #endif

>> +#endif

>> +

>> +typedef uint64_t qemu_plugin_id_t;

>> +

>> +/**

>> + * qemu_plugin_install() - Install a plugin

>> + * @id: this plugin's opaque ID

>> + * @argc: number of arguments

>> + * @argv: array of arguments (@argc elements)

>> + *

>> + * All plugins must export this symbol.

>> + *

>> + * Note: Calling qemu_plugin_uninstall() from this function is a bug. To raise

>> + * an error during install, return !0.

>> + *

>> + * Note: @argv remains valid throughout the lifetime of the loaded plugin.

>> + */

>> +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, int argc,

>> +                                           char **argv);

>> +

>> +/*

>> + * Prototypes for the various callback styles we will be registering

>> + * in the following functions.

>> + */

>> +typedef void (*qemu_plugin_simple_cb_t)(qemu_plugin_id_t id);

>> +

>> +typedef void (*qemu_plugin_udata_cb_t)(qemu_plugin_id_t id, void *userdata);

>> +

>> +typedef void (*qemu_plugin_vcpu_simple_cb_t)(qemu_plugin_id_t id,

>> +                                             unsigned int vcpu_index);

>> +

>> +typedef void (*qemu_plugin_vcpu_udata_cb_t)(unsigned int vcpu_index,

>> +                                            void *userdata);

>> +

>> +/**

>> + * qemu_plugin_uninstall() - Uninstall a plugin

>> + * @id: this plugin's opaque ID

>> + * @cb: callback to be called once the plugin has been removed

>> + *

>> + * Do NOT assume that the plugin has been uninstalled once this function

>> + * returns. Plugins are uninstalled asynchronously, and therefore the given

>> + * plugin receives callbacks until @cb is called.

>> + *

>> + * Note: Calling this function from qemu_plugin_install() is a bug.

>> + */

>> +void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb);

>> +

>> +/**

>> + * qemu_plugin_reset() - Reset a plugin

>> + * @id: this plugin's opaque ID

>> + * @cb: callback to be called once the plugin has been reset

>> + *

>> + * Unregisters all callbacks for the plugin given by @id.

>> + *

>> + * Do NOT assume that the plugin has been reset once this function returns.

>> + * Plugins are reset asynchronously, and therefore the given plugin receives

>> + * callbacks until @cb is called.

>> + */

>> +void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb);

>> +

>> +/**

>> + * qemu_plugin_register_vcpu_init_cb() - register a vCPU initialization callback

>> + * @id: plugin ID

>> + * @cb: callback function

>> + *

>> + * The @cb function is called every time a vCPU is initialized.

>> + *

>> + * See also: qemu_plugin_register_vcpu_exit_cb()

>> + */

>> +void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id,

>> +                                       qemu_plugin_vcpu_simple_cb_t cb);

>> +

>> +/**

>> + * qemu_plugin_register_vcpu_exit_cb() - register a vCPU exit callback

>> + * @id: plugin ID

>> + * @cb: callback function

>> + *

>> + * The @cb function is called every time a vCPU exits.

>> + *

>> + * See also: qemu_plugin_register_vcpu_init_cb()

>> + */

>> +void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id,

>> +                                       qemu_plugin_vcpu_simple_cb_t cb);

>> +

>> +/**

>> + * qemu_plugin_register_vcpu_idle_cb() - register a vCPU idle callback

>> + * @id: plugin ID

>> + * @cb: callback function

>> + *

>> + * The @cb function is called every time a vCPU idles.

>> + */

>> +void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id,

>> +                                       qemu_plugin_vcpu_simple_cb_t cb);

>> +

>> +/**

>> + * qemu_plugin_register_vcpu_resume_cb() - register a vCPU resume callback

>> + * @id: plugin ID

>> + * @cb: callback function

>> + *

>> + * The @cb function is called every time a vCPU resumes execution.

>> + */

>> +void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id,

>> +                                         qemu_plugin_vcpu_simple_cb_t cb);

>> +

>> +/*

>> + * Opaque types that the plugin is given during the translation and

>> + * instrumentation phase.

>> + */

>> +struct qemu_plugin_tb;

>> +struct qemu_plugin_insn;

>> +

>> +enum qemu_plugin_cb_flags {

>> +    QEMU_PLUGIN_CB_NO_REGS, /* callback does not access the CPU's regs */

>> +    QEMU_PLUGIN_CB_R_REGS,  /* callback reads the CPU's regs */

>> +    QEMU_PLUGIN_CB_RW_REGS, /* callback reads and writes the CPU's regs */

>> +};

>> +

>> +enum qemu_plugin_mem_rw {

>> +    QEMU_PLUGIN_MEM_R = 1,

>> +    QEMU_PLUGIN_MEM_W,

>> +    QEMU_PLUGIN_MEM_RW,

>> +};

>

> Why is this structure different from qemu_plugin_cb_flags? I think

> both of them could use a similar structure. Both of them can have

> (_NO, _R, _W, _RW) I think.


They do refer to semantically different things. The plugin CB flags are
important for ensuring registers are synced or not before the callback.
The memory callbacks flags control where the callbacks are placed with
respect to the access.

>

>> +

>> +/**

>> + * qemu_plugin_register_vcpu_tb_trans_cb() - register a translate cb

>> + * @id: plugin ID

>> + * @cb: callback function

>> + *

>> + * The @cb function is called every time a translation occurs. The @cb

>> + * function is passed an opaque qemu_plugin_type which is can query

>

> s/is/it/


Fixed.

--
Alex Bennée
diff mbox series

Patch

diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
new file mode 100644
index 0000000000..0db1ef9714
--- /dev/null
+++ b/include/qemu/qemu-plugin.h
@@ -0,0 +1,339 @@ 
+/*
+ * Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
+ * Copyright (C) 2019, Linaro
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_PLUGIN_API_H
+#define QEMU_PLUGIN_API_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+/*
+ * For best performance, build the plugin with -fvisibility=hidden so that
+ * QEMU_PLUGIN_LOCAL is implicit. Then, just mark qemu_plugin_install with
+ * QEMU_PLUGIN_EXPORT. For more info, see
+ *   https://gcc.gnu.org/wiki/Visibility
+ */
+#if defined _WIN32 || defined __CYGWIN__
+  #ifdef BUILDING_DLL
+    #define QEMU_PLUGIN_EXPORT __declspec(dllexport)
+  #else
+    #define QEMU_PLUGIN_EXPORT __declspec(dllimport)
+  #endif
+  #define QEMU_PLUGIN_LOCAL
+#else
+  #if __GNUC__ >= 4
+    #define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))
+    #define QEMU_PLUGIN_LOCAL  __attribute__((visibility("hidden")))
+  #else
+    #define QEMU_PLUGIN_EXPORT
+    #define QEMU_PLUGIN_LOCAL
+  #endif
+#endif
+
+typedef uint64_t qemu_plugin_id_t;
+
+/**
+ * qemu_plugin_install() - Install a plugin
+ * @id: this plugin's opaque ID
+ * @argc: number of arguments
+ * @argv: array of arguments (@argc elements)
+ *
+ * All plugins must export this symbol.
+ *
+ * Note: Calling qemu_plugin_uninstall() from this function is a bug. To raise
+ * an error during install, return !0.
+ *
+ * Note: @argv remains valid throughout the lifetime of the loaded plugin.
+ */
+QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, int argc,
+                                           char **argv);
+
+/*
+ * Prototypes for the various callback styles we will be registering
+ * in the following functions.
+ */
+typedef void (*qemu_plugin_simple_cb_t)(qemu_plugin_id_t id);
+
+typedef void (*qemu_plugin_udata_cb_t)(qemu_plugin_id_t id, void *userdata);
+
+typedef void (*qemu_plugin_vcpu_simple_cb_t)(qemu_plugin_id_t id,
+                                             unsigned int vcpu_index);
+
+typedef void (*qemu_plugin_vcpu_udata_cb_t)(unsigned int vcpu_index,
+                                            void *userdata);
+
+/**
+ * qemu_plugin_uninstall() - Uninstall a plugin
+ * @id: this plugin's opaque ID
+ * @cb: callback to be called once the plugin has been removed
+ *
+ * Do NOT assume that the plugin has been uninstalled once this function
+ * returns. Plugins are uninstalled asynchronously, and therefore the given
+ * plugin receives callbacks until @cb is called.
+ *
+ * Note: Calling this function from qemu_plugin_install() is a bug.
+ */
+void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb);
+
+/**
+ * qemu_plugin_reset() - Reset a plugin
+ * @id: this plugin's opaque ID
+ * @cb: callback to be called once the plugin has been reset
+ *
+ * Unregisters all callbacks for the plugin given by @id.
+ *
+ * Do NOT assume that the plugin has been reset once this function returns.
+ * Plugins are reset asynchronously, and therefore the given plugin receives
+ * callbacks until @cb is called.
+ */
+void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_init_cb() - register a vCPU initialization callback
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU is initialized.
+ *
+ * See also: qemu_plugin_register_vcpu_exit_cb()
+ */
+void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id,
+                                       qemu_plugin_vcpu_simple_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_exit_cb() - register a vCPU exit callback
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU exits.
+ *
+ * See also: qemu_plugin_register_vcpu_init_cb()
+ */
+void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id,
+                                       qemu_plugin_vcpu_simple_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_idle_cb() - register a vCPU idle callback
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU idles.
+ */
+void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id,
+                                       qemu_plugin_vcpu_simple_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_resume_cb() - register a vCPU resume callback
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a vCPU resumes execution.
+ */
+void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id,
+                                         qemu_plugin_vcpu_simple_cb_t cb);
+
+/*
+ * Opaque types that the plugin is given during the translation and
+ * instrumentation phase.
+ */
+struct qemu_plugin_tb;
+struct qemu_plugin_insn;
+
+enum qemu_plugin_cb_flags {
+    QEMU_PLUGIN_CB_NO_REGS, /* callback does not access the CPU's regs */
+    QEMU_PLUGIN_CB_R_REGS,  /* callback reads the CPU's regs */
+    QEMU_PLUGIN_CB_RW_REGS, /* callback reads and writes the CPU's regs */
+};
+
+enum qemu_plugin_mem_rw {
+    QEMU_PLUGIN_MEM_R = 1,
+    QEMU_PLUGIN_MEM_W,
+    QEMU_PLUGIN_MEM_RW,
+};
+
+/**
+ * qemu_plugin_register_vcpu_tb_trans_cb() - register a translate cb
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called every time a translation occurs. The @cb
+ * function is passed an opaque qemu_plugin_type which is can query
+ * for additional information including the list of translated
+ * instructions. At this point the plugin can register further
+ * callbacks to be triggered when the block or individual instruction
+ * executes.
+ */
+typedef void (*qemu_plugin_vcpu_tb_trans_cb_t)(qemu_plugin_id_t id,
+                                               unsigned int vcpu_index,
+                                               struct qemu_plugin_tb *tb);
+
+void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id,
+                                           qemu_plugin_vcpu_tb_trans_cb_t cb);
+
+/**
+ * qemu_plugin_register_vcpu_tb_trans_exec_cb() - register execution callback
+ * @tb: the opaque qemu_plugin_tb handle for the translation
+ * @cb: callback function
+ * @flags: does the plugin read or write the CPU's registers?
+ * @userdata: any plugin data to pass to the @cb?
+ *
+ * The @cb function is called every time a translated unit executes.
+ */
+void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
+                                          qemu_plugin_vcpu_udata_cb_t cb,
+                                          enum qemu_plugin_cb_flags flags,
+                                          void *userdata);
+
+enum qemu_plugin_op {
+    QEMU_PLUGIN_INLINE_ADD_U64,
+};
+
+/**
+ * qemu_plugin_register_vcpu_tb_trans_exec_inline() - execution inline op
+ * @tb: the opaque qemu_plugin_tb handle for the translation
+ * @op: the type of qemu_plugin_op (e.g. ADD_U64)
+ * @ptr: the target memory location for the op
+ * @imm: the op data (e.g. 1)
+ *
+ * Insert an inline op to every time a translated unit executes.
+ * Useful if you just want to increment a single counter somewhere in
+ * memory.
+ */
+void qemu_plugin_register_vcpu_tb_exec_inline(struct qemu_plugin_tb *tb,
+                                              enum qemu_plugin_op op,
+                                              void *ptr, uint64_t imm);
+
+/**
+ * qemu_plugin_register_vcpu_insn_exec_cb() - register insn execution cb
+ * @insn: the opaque qemu_plugin_insn handle for an instruction
+ * @cb: callback function
+ * @flags: does the plugin read or write the CPU's registers?
+ * @userdata: any plugin data to pass to the @cb?
+ *
+ * The @cb function is called every time an instruction is executed
+ */
+void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
+                                            qemu_plugin_vcpu_udata_cb_t cb,
+                                            enum qemu_plugin_cb_flags flags,
+                                            void *userdata);
+
+/**
+ * qemu_plugin_register_vcpu_insn_exec_inline() - insn execution inline op
+ * @insn: the opaque qemu_plugin_insn handle for an instruction
+ * @cb: callback function
+ * @op: the type of qemu_plugin_op (e.g. ADD_U64)
+ * @ptr: the target memory location for the op
+ * @imm: the op data (e.g. 1)
+ *
+ * Insert an inline op to every time an instruction executes. Useful
+ * if you just want to increment a single counter somewhere in memory.
+ */
+void qemu_plugin_register_vcpu_insn_exec_inline(struct qemu_plugin_insn *insn,
+                                                enum qemu_plugin_op op,
+                                                void *ptr, uint64_t imm);
+
+/*
+ * Helpers to query information about the instructions in a block
+ */
+size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb);
+
+uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb);
+
+struct qemu_plugin_insn *
+qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx);
+
+const void *qemu_plugin_insn_data(const struct qemu_plugin_insn *insn);
+
+size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn);
+
+uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn);
+void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn);
+
+/*
+ * Memory Instrumentation
+ */
+typedef uint32_t qemu_plugin_meminfo_t;
+
+unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info);
+bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info);
+bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info);
+bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info);
+
+typedef void
+(*qemu_plugin_vcpu_mem_cb_t)(unsigned int vcpu_index,
+                             qemu_plugin_meminfo_t info, uint64_t vaddr,
+                             void *userdata);
+
+typedef void
+(*qemu_plugin_vcpu_mem_haddr_cb_t)(unsigned int vcpu_index,
+                                   qemu_plugin_meminfo_t info, uint64_t vaddr,
+                                   void *haddr, void *userdata);
+
+void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,
+                                      qemu_plugin_vcpu_mem_cb_t cb,
+                                      enum qemu_plugin_cb_flags flags,
+                                      enum qemu_plugin_mem_rw rw,
+                                      void *userdata);
+
+void qemu_plugin_register_vcpu_mem_haddr_cb(struct qemu_plugin_insn *insn,
+                                            qemu_plugin_vcpu_mem_haddr_cb_t cb,
+                                            enum qemu_plugin_cb_flags flags,
+                                            enum qemu_plugin_mem_rw rw,
+                                            void *userdata);
+
+void qemu_plugin_register_vcpu_mem_inline(struct qemu_plugin_insn *insn,
+                                          enum qemu_plugin_mem_rw rw,
+                                          enum qemu_plugin_op op, void *ptr,
+                                          uint64_t imm);
+
+uint64_t qemu_plugin_ram_addr_from_host(void *haddr);
+
+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,
+                                 uint64_t a3, uint64_t a4, uint64_t a5,
+                                 uint64_t a6, uint64_t a7, uint64_t a8);
+
+void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id,
+                                          qemu_plugin_vcpu_syscall_cb_t cb);
+
+typedef void
+(*qemu_plugin_vcpu_syscall_ret_cb_t)(qemu_plugin_id_t id, unsigned int vcpu_idx,
+                                     int64_t num, int64_t ret);
+
+void
+qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id,
+                                         qemu_plugin_vcpu_syscall_ret_cb_t cb);
+
+
+/**
+ * qemu_plugin_vcpu_for_each() - iterate over the existing vCPU
+ * @id: plugin ID
+ * @cb: callback function
+ *
+ * The @cb function is called once for each existing vCPU.
+ *
+ * See also: qemu_plugin_register_vcpu_init_cb()
+ */
+void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id,
+                               qemu_plugin_vcpu_simple_cb_t cb);
+
+void qemu_plugin_register_flush_cb(qemu_plugin_id_t id,
+                                   qemu_plugin_simple_cb_t cb);
+
+void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id,
+                                    qemu_plugin_udata_cb_t cb, void *userdata);
+
+/* returns -1 in user-mode */
+int qemu_plugin_n_vcpus(void);
+
+/* returns -1 in user-mode */
+int qemu_plugin_n_max_vcpus(void);
+
+#endif /* QEMU_PLUGIN_API_H */