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 2/8] plugins: version 2, require unique plugin names
Date: Thu, 09 Mar 2023 14:17:54 +0000	[thread overview]
Message-ID: <87v8jam1tb.fsf@linaro.org> (raw)
In-Reply-To: <20221213213757.4123265-3-fasano@mit.edu>


Andrew Fasano <fasano@mit.edu> writes:

> From: Elysia Witham <elysia.witham@ll.mit.edu>
>
> In order for the QPP API to resolve interactions between plugins,
> plugins must export their own names which cannot match any other
> loaded plugins.
>
> Signed-off-by: Elysia Witham <elysia.witham@ll.mit.edu>
> Signed-off-by: Andrew Fasano <fasano@mit.edu>
> ---
>  include/qemu/qemu-plugin.h |  2 +-
>  plugins/core.c             | 12 +++++++++
>  plugins/loader.c           | 50 +++++++++++++++++++++++++++++++++-----
>  plugins/plugin.h           |  7 ++++++
>  tests/plugin/bb.c          |  1 +
>  tests/plugin/empty.c       |  1 +
>  tests/plugin/insn.c        |  1 +
>  tests/plugin/mem.c         |  1 +
>  tests/plugin/syscall.c     |  1 +
>  9 files changed, 69 insertions(+), 7 deletions(-)
>
> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
> index d0e9d03adf..5326f33ce8 100644
> --- a/include/qemu/qemu-plugin.h
> +++ b/include/qemu/qemu-plugin.h
> @@ -51,7 +51,7 @@ typedef uint64_t qemu_plugin_id_t;
>  
>  extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
>  
> -#define QEMU_PLUGIN_VERSION 1
> +#define QEMU_PLUGIN_VERSION 2
>  
>  /**
>   * struct qemu_info_t - system information for plugins
> diff --git a/plugins/core.c b/plugins/core.c
> index ccb770a485..5fbdcb5768 100644
> --- a/plugins/core.c
> +++ b/plugins/core.c
> @@ -236,6 +236,18 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu)
>      qemu_rec_mutex_unlock(&plugin.lock);
>  }
>  
> +int name_to_plugin_version(const char *name)
> +{
> +    struct qemu_plugin_ctx *ctx;
> +    QTAILQ_FOREACH(ctx, &plugin.ctxs, entry) {
> +        if (strcmp(ctx->name, name) == 0) {
> +            return ctx->version;
> +        }
> +    }
> +    warn_report("Could not find any plugin named %s.", name);
> +    return -1;
> +}
> +

This function seems to be unused.

>  struct plugin_for_each_args {
>      struct qemu_plugin_ctx *ctx;
>      qemu_plugin_vcpu_simple_cb_t cb;
> diff --git a/plugins/loader.c b/plugins/loader.c
> index 88c30bde2d..12c0680e03 100644
> --- a/plugins/loader.c
> +++ b/plugins/loader.c
> @@ -177,7 +177,7 @@ QEMU_DISABLE_CFI
>  static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info, Error **errp)
>  {
>      qemu_plugin_install_func_t install;
> -    struct qemu_plugin_ctx *ctx;
> +    struct qemu_plugin_ctx *ctx, *ctx2;
>      gpointer sym;
>      int rc;
>  
> @@ -208,17 +208,55 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info, E
>                     desc->path, g_module_error());
>          goto err_symbol;
>      } else {
> -        int version = *(int *)sym;
> -        if (version < QEMU_PLUGIN_MIN_VERSION) {
> +        ctx->version = *(int *)sym;
> +        if (ctx->version < QEMU_PLUGIN_MIN_VERSION) {
>              error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but "
>                         "this QEMU supports only a minimum version of %d",
> -                       desc->path, version, QEMU_PLUGIN_MIN_VERSION);
> +                       desc->path, ctx->version, QEMU_PLUGIN_MIN_VERSION);
>              goto err_symbol;
> -        } else if (version > QEMU_PLUGIN_VERSION) {
> +        } else if (ctx->version > QEMU_PLUGIN_VERSION) {
>              error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but "
>                         "this QEMU supports only up to version %d",
> -                       desc->path, version, QEMU_PLUGIN_VERSION);
> +                       desc->path, ctx->version, QEMU_PLUGIN_VERSION);
>              goto err_symbol;
> +        } else if (ctx->version < QPP_MINIMUM_VERSION) {
> +            ctx->name = NULL;

A comment wouldn't go amiss here. Something like:

  "Older plugins will not be available for QPP calls".

> +        } else {
> +            if (!g_module_symbol(ctx->handle, "qemu_plugin_name", &sym)) {
> +                error_setg(errp, "Could not load plugin %s: plugin does not "
> +                           "declare plugin name %s",
> +                           desc->path, g_module_error());
> +                goto err_symbol;
> +            }
> +            ctx->name = (const char *)strdup(*(const char **)sym);
> +            QTAILQ_FOREACH(ctx2, &plugin.ctxs, entry) {
> +                if (strcmp(ctx2->name, ctx->name) == 0) {
> +                    error_setg(errp, "Could not load plugin %s as the name %s "
> +                               "is already in use by plugin at %s",
> +                               desc->path, ctx->name, ctx2->desc->path);
> +                    goto err_symbol;
> +                }
> +            }
> +            if (g_module_symbol(ctx->handle, "qemu_plugin_uses", &sym)) {
> +                const char **dependencies = &(*(const char **)sym);
> +                bool found = false;
> +                while (*dependencies) {
> +                    found = false;
> +                    QTAILQ_FOREACH(ctx2, &plugin.ctxs, entry) {
> +                        if (strcmp(ctx2->name, *dependencies) == 0) {

Lets use glib where we can, in this case g_strcmp0().

> +                            dependencies++;
> +                            found = true;
> +                            break;
> +                        }
> +                    }
> +                    if (!found) {
> +                        error_setg(errp, "Could not load plugin %s as it is "
> +                                   "dependent on %s which is not loaded",
> +                                   ctx->name, *dependencies);
> +                        goto err_symbol;
> +                    }

We are implying a load order here which we should document. Ideally we
could avoid it but I suspect that requires too much hoop jumping.

> +                }
> +            }
>          }
>      }
>  
> diff --git a/plugins/plugin.h b/plugins/plugin.h
> index 5eb2fdbc85..ce885bfa98 100644
> --- a/plugins/plugin.h
> +++ b/plugins/plugin.h
> @@ -16,6 +16,7 @@
>  #include "qemu/qht.h"
>  
>  #define QEMU_PLUGIN_MIN_VERSION 0
> +#define QPP_MINIMUM_VERSION 2
>  
>  /* global state */
>  struct qemu_plugin_state {
> @@ -50,6 +51,8 @@ struct qemu_plugin_state {
>  struct qemu_plugin_ctx {
>      GModule *handle;
>      qemu_plugin_id_t id;
> +    const char *name;
> +    int version;
>      struct qemu_plugin_cb *callbacks[QEMU_PLUGIN_EV_MAX];
>      QTAILQ_ENTRY(qemu_plugin_ctx) entry;
>      /*
> @@ -64,6 +67,8 @@ struct qemu_plugin_ctx {
>  
>  struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id);
>  
> +struct qemu_plugin_ctx *plugin_name_to_ctx_locked(const char* name);
> +
>  void plugin_register_inline_op(GArray **arr,
>                                 enum qemu_plugin_mem_rw rw,
>                                 enum qemu_plugin_op op, void *ptr,
> @@ -97,4 +102,6 @@ void plugin_register_vcpu_mem_cb(GArray **arr,
>  
>  void exec_inline_op(struct qemu_plugin_dyn_cb *cb);
>  
> +int name_to_plugin_version(const char *name);
> +
>  #endif /* PLUGIN_H */
> diff --git a/tests/plugin/bb.c b/tests/plugin/bb.c
> index 7d470a1011..c04e5aaf90 100644
> --- a/tests/plugin/bb.c
> +++ b/tests/plugin/bb.c
> @@ -15,6 +15,7 @@
>  #include <qemu-plugin.h>
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "bb";
>  
>  typedef struct {
>      GMutex lock;
> diff --git a/tests/plugin/empty.c b/tests/plugin/empty.c
> index 8fa6bacd93..0f3d2b92b9 100644
> --- a/tests/plugin/empty.c
> +++ b/tests/plugin/empty.c
> @@ -14,6 +14,7 @@
>  #include <qemu-plugin.h>
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "empty";
>  
>  /*
>   * Empty TB translation callback.
> diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c
> index cd5ea5d4ae..3f71138139 100644
> --- a/tests/plugin/insn.c
> +++ b/tests/plugin/insn.c
> @@ -15,6 +15,7 @@
>  #include <qemu-plugin.h>
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "insn";
>  
>  #define MAX_CPUS 8 /* lets not go nuts */
>  
> diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c
> index 4570f7d815..35e5d7fe2a 100644
> --- a/tests/plugin/mem.c
> +++ b/tests/plugin/mem.c
> @@ -15,6 +15,7 @@
>  #include <qemu-plugin.h>
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "mem";
>  
>  static uint64_t inline_mem_count;
>  static uint64_t cb_mem_count;
> diff --git a/tests/plugin/syscall.c b/tests/plugin/syscall.c
> index 96040c578f..922bdbd2e6 100644
> --- a/tests/plugin/syscall.c
> +++ b/tests/plugin/syscall.c
> @@ -15,6 +15,7 @@
>  #include <qemu-plugin.h>
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "syscall";
>  
>  typedef struct {
>      int64_t num;

You should update the plugins in contrib/plugins as well.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


  reply	other threads:[~2023-03-09 14:34 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 [this message]
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
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=87v8jam1tb.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.