All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Andrew Fasano <fasano@mit.edu>
Cc: qemu-devel@nongnu.org, elysia.witham@ll.mit.edu,
	erdnaxe@crans.org, ma.mandourr@gmail.com
Subject: Re: [PATCH 5/8] plugins: implement QPP callbacks
Date: Thu, 09 Mar 2023 16:17:05 +0000	[thread overview]
Message-ID: <87ilf9nba0.fsf@linaro.org> (raw)
In-Reply-To: <20221213213757.4123265-6-fasano@mit.edu>


Andrew Fasano <fasano@mit.edu> writes:

> From: Elysia Witham <elysia.witham@ll.mit.edu>
>
> Plugins are able to use API functions which are explained in
> <qemu-plugin.h> to create and run their own callbacks and register
> functions on another plugin's callbacks.
>
> Signed-off-by: Elysia Witham <elysia.witham@ll.mit.edu>
> Signed-off-by: Andrew Fasano <fasano@mit.edu>
> ---
>  include/qemu/qemu-plugin.h   |  46 +++++++++++++++
>  plugins/api.c                | 111 +++++++++++++++++++++++++++++++++++
>  plugins/loader.c             |   1 +
>  plugins/qemu-plugins.symbols |   4 ++
>  4 files changed, 162 insertions(+)
>
> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
> index 3ec82ce97f..4221545015 100644
> --- a/include/qemu/qemu-plugin.h
> +++ b/include/qemu/qemu-plugin.h
> @@ -354,6 +354,52 @@ 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);
>  
> +/**
> + * qemu_plugin_create_callback() - create a new cb with given name
> + * @id: unique plugin id
> + * @name: name of cb
> + *
> + * Returns: true on success, false otherwise
> + */
> +bool qemu_plugin_create_callback(qemu_plugin_id_t id, const char *name);
> +
> +/**
> + * qemu_plugin_run_callback() - run all functions registered to cb with given
> + * name using given args
> + * @id: unique plugin id
> + * @name: name of cb
> + * @evdata: pointer to evdata struct
> + * @udata: pointer to udata struct
> + *
> + * Returns: true if any registerd functions were run, false otherwise
> + */
> +bool qemu_plugin_run_callback(qemu_plugin_id_t id, const char *name,
> +                              gpointer evdata, gpointer udata);
> +
> +/**
> + * qemu_plugin_reg_callback() - register a function to be called on cb with
> + * given name
> + * @target_plugin: name of plugin that provides the callback
> + * @cb_name: name of the callback
> + * @function_pointer: pointer to function being registered
> + *
> + * Returns: true if function was registered successfully, false otherwise
> + */
> +bool qemu_plugin_reg_callback(const char *target_plugin, const char *cb_name,
> +                              cb_func_t function_pointer);
> +
> +/**
> + * qemu_plugin_unreg_callback() - unregister a function to be called on cb
> + * with given name
> + * @target_plugin: name of plugin that provides the callback
> + * @cb_name: name of the callback
> + * @function_pointer: pointer to function being unregistered
> + *
> + * Returns: true if function was unregistered successfully, false otherwise
> + */
> +bool qemu_plugin_unreg_callback(const char *target_plugin, const char *cb_name,
> +                                cb_func_t function_pointer);
> +
>  /**
>   * qemu_plugin_tb_get_insn() - retrieve handle for instruction
>   * @tb: opaque handle to TB passed to callback
> diff --git a/plugins/api.c b/plugins/api.c
> index 2078b16edb..1f7ea718dc 100644
> --- a/plugins/api.c
> +++ b/plugins/api.c
> @@ -400,6 +400,117 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
>      return name && value && qapi_bool_parse(name, value, ret, NULL);
>  }
>  
> +bool qemu_plugin_create_callback(qemu_plugin_id_t id, const char *cb_name)
> +{
> +    struct qemu_plugin_ctx *ctx = plugin_id_to_ctx_locked(id);

c.f. last patch. I see no locking going on here.

> +    if (ctx == NULL) {
> +        error_report("Cannot create callback with invalid plugin ID");
> +        return false;
> +    }
> +
> +    if (ctx->version < QPP_MINIMUM_VERSION) {
> +        error_report("Plugin %s cannot create callbacks as its PLUGIN_VERSION"
> +                     " %d is below QPP_MINIMUM_VERSION (%d).",
> +                     ctx->name, ctx->version, QPP_MINIMUM_VERSION);
> +        return false;
> +    }
> +
> +    if (plugin_find_qpp_cb(ctx, cb_name)) {
> +        error_report("Plugin %s already created callback %s", ctx->name,
> +                     cb_name);
> +        return false;
> +    }
> +
> +    plugin_add_qpp_cb(ctx, cb_name);
> +    return true;
> +}
> +
> +bool qemu_plugin_run_callback(qemu_plugin_id_t id, const char *cb_name,
> +                              gpointer evdata, gpointer udata) {
> +    struct qemu_plugin_ctx *ctx = plugin_id_to_ctx_locked(id);

Or here.

> +    if (ctx == NULL) {
> +        error_report("Cannot run callback with invalid plugin ID");
> +        return false;
> +    }
> +
> +    struct qemu_plugin_qpp_cb *cb = plugin_find_qpp_cb(ctx, cb_name);
> +    if (!cb) {
> +        error_report("Can not run previously-unregistered callback %s in "
> +                     "plugin %s", cb_name, ctx->name);
> +        return false;
> +    }
> +
> +    for (int i = 0; i < cb->counter; i++) {
> +        cb_func_t qpp_cb_func = cb->registered_cb_funcs[i];
> +        qpp_cb_func(evdata, udata);
> +    }
> +
> +    return (cb->registered_cb_funcs[0] != NULL);
> +}
> +
> +bool qemu_plugin_reg_callback(const char *target_plugin, const char *cb_name,
> +                              cb_func_t function_pointer) {
> +    struct qemu_plugin_ctx *ctx = plugin_name_to_ctx_locked(target_plugin);
> +    if (ctx == NULL) {
> +        error_report("Cannot register callback with unknown plugin %s",
> +                     target_plugin);
> +      return false;
> +    }
> +
> +    struct qemu_plugin_qpp_cb *cb = plugin_find_qpp_cb(ctx, cb_name);
> +    if (!cb) {
> +        error_report("Cannot register a function to run on callback %s in "
> +                     "plugin %s as that callback does not exist",
> +                     cb_name, target_plugin);
> +        return false;
> +    }
> +
> +    if (cb->counter == QEMU_PLUGIN_EV_MAX) {

I'm a little confused why there is a relation to the number of callbacks
QPP can support and the list of qemu callback events.

> +        error_report("The maximum number of allowed callbacks are already "
> +                     "registered for callback %s in plugin %s",
> +                     cb_name, target_plugin);
> +        return false;
> +    }
> +
> +    cb->registered_cb_funcs[cb->counter] = function_pointer;
> +    cb->counter++;
> +    return true;
> +}
> +
> +bool qemu_plugin_unreg_callback(const char *target_plugin, const char *cb_name,
> +                              cb_func_t function_pointer) {
> +    struct qemu_plugin_ctx *ctx =
> plugin_name_to_ctx_locked(target_plugin);

Locking.

> +    if (ctx == NULL) {
> +        error_report("Cannot remove callback function from unknown plugin %s",
> +                     target_plugin);
> +        return false;
> +    }
> +
> +    struct qemu_plugin_qpp_cb *cb = plugin_find_qpp_cb(ctx, cb_name);
> +    if (!cb) {
> +        error_report("Cannot remove a function to run on callback %s in "
> +                     "plugin %s as that callback does not exist",
> +                     cb_name, target_plugin);
> +        return false;
> +    }
> +
> +    for (int i = 0; i < cb->counter; i++) {
> +        if (cb->registered_cb_funcs[i] == function_pointer) {
> +            for (int j = i + 1; j < cb->counter; j++) {
> +                cb->registered_cb_funcs[i] = cb->registered_cb_funcs[j];
> +                i++;
> +            }
> +            cb->registered_cb_funcs[i] = NULL;
> +            cb->counter--;
> +            return true;
> +        }
> +    }
> +    error_report("Function to remove not found in registered functions "
> +                 "for callback %s in plugin %s",
> +                 cb_name, target_plugin);
> +    return false;
> +}
> +
>  /*
>   * Binary path, start and end locations
>   */
> diff --git a/plugins/loader.c b/plugins/loader.c
> index ab01d0753c..7f047ebc99 100644
> --- a/plugins/loader.c
> +++ b/plugins/loader.c
> @@ -310,6 +310,7 @@ void plugin_add_qpp_cb(struct qemu_plugin_ctx *ctx, const char *name)
>      new_cb = qemu_memalign(qemu_dcache_linesize, sizeof(*new_cb));
>      memset(new_cb, 0, sizeof(*new_cb));
>      new_cb->name = name;
> +    new_cb->counter = 0;
>      QTAILQ_INSERT_TAIL(&ctx->qpp_cbs, new_cb, entry);
>  }
>  
> diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols
> index 71f6c90549..b7013980cf 100644
> --- a/plugins/qemu-plugins.symbols
> +++ b/plugins/qemu-plugins.symbols
> @@ -3,6 +3,10 @@
>    qemu_plugin_end_code;
>    qemu_plugin_entry_code;
>    qemu_plugin_get_hwaddr;
> +  qemu_plugin_create_callback;
> +  qemu_plugin_run_callback;
> +  qemu_plugin_reg_callback;
> +  qemu_plugin_unreg_callback;
>    qemu_plugin_hwaddr_device_name;
>    qemu_plugin_hwaddr_is_io;
>    qemu_plugin_hwaddr_phys_addr;


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


  reply	other threads:[~2023-03-09 16:24 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-13 21:37 [PATCH 0/8] Inter-plugin interactions with QPP Andrew Fasano
2022-12-13 21:37 ` [PATCH 1/8] docs/devel: describe QPP API Andrew Fasano
2023-03-09 14:15   ` Alex Bennée
2022-12-13 21:37 ` [PATCH 2/8] plugins: version 2, require unique plugin names Andrew Fasano
2023-03-09 14:17   ` Alex Bennée
2022-12-13 21:37 ` [PATCH 3/8] plugins: add id_to_plugin_name Andrew Fasano
2023-03-09 14:45   ` Alex Bennée
2022-12-13 21:37 ` [PATCH 4/8] plugins: add core API functions for QPP callbacks Andrew Fasano
2023-03-09 16:09   ` Alex Bennée
2022-12-13 21:37 ` [PATCH 5/8] plugins: implement " Andrew Fasano
2023-03-09 16:17   ` Alex Bennée [this message]
2022-12-13 21:37 ` [PATCH 6/8] plugins: implement QPP import function Andrew Fasano
2023-03-09 16:26   ` Alex Bennée
2022-12-13 21:37 ` [PATCH 7/8] include/qemu: added macro for " Andrew Fasano
2022-12-13 21:37 ` [PATCH 8/8] tests: build and run QPP tests Andrew Fasano
2023-03-09 16:37   ` Alex Bennée

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ilf9nba0.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=elysia.witham@ll.mit.edu \
    --cc=erdnaxe@crans.org \
    --cc=fasano@mit.edu \
    --cc=ma.mandourr@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.