[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC PATCH v2 2/7] Add plugin support
From: |
Alex Bennée |
Subject: |
Re: [Qemu-devel] [RFC PATCH v2 2/7] Add plugin support |
Date: |
Fri, 07 Sep 2018 15:14:15 +0100 |
User-agent: |
mu4e 1.1.0; emacs 26.1.50 |
Pavel Dovgalyuk <address@hidden> writes:
> This patch adds support for dynamically loaded plugins.
> Every plugin is a dynamic library with a set of optional exported
> functions that will be called from QEMU.
>
<snip>
> +
> +static QLIST_HEAD(, QemuPluginInfo) qemu_plugins
> + = QLIST_HEAD_INITIALIZER(qemu_plugins);
> +
> +static QemuOptsList qemu_plugin_opts = {
> + .name = "plugin",
> + .head = QTAILQ_HEAD_INITIALIZER(qemu_plugin_opts.head),
> + .desc = {
> + {
> + .name = "file",
> + .type = QEMU_OPT_STRING,
> + },{
> + .name = "args",
> + .type = QEMU_OPT_STRING,
> + },
> + { /* end of list */ }
> + },
> +};
> +
> +void qemu_plugin_parse_cmd_args(const char *optarg)
> +{
> + QemuOpts *opts = qemu_opts_parse_noisily(&qemu_plugin_opts, optarg,
> false);
> + qemu_plugin_load(qemu_opt_get(opts, "file"),
> + qemu_opt_get(opts, "args"));
> +}
Currently this is only available to system mode emulation. Can it be
extended to include linux-user as well?
> +
> +void qemu_plugin_load(const char *filename, const char *args)
> +{
> + GModule *g_module;
> + QemuPluginInfo *info = NULL;
> + if (!filename) {
> + error_report("plugin name was not specified");
> + return;
> + }
> + g_module = g_module_open(filename,
> + G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
> + if (!g_module) {
> + error_report("can't load plugin '%s'", filename);
> + return;
> + }
> + info = g_new0(QemuPluginInfo, 1);
> + info->filename = g_strdup(filename);
> + info->g_module = g_module;
> + if (args) {
> + info->args = g_strdup(args);
> + }
> +
> + g_module_symbol(g_module, "plugin_init", (gpointer*)&info->init);
> +
> + /* Get the instrumentation callbacks */
> + g_module_symbol(g_module, "plugin_needs_before_insn",
> + (gpointer*)&info->needs_before_insn);
> + g_module_symbol(g_module, "plugin_before_insn",
> + (gpointer*)&info->before_insn);
> +
> + QLIST_INSERT_HEAD(&qemu_plugins, info, next);
> +
> + return;
> +}
> +
> +void qemu_plugins_init(void)
> +{
> + QemuPluginInfo *info;
> + QLIST_FOREACH(info, &qemu_plugins, next) {
> + if (info->init) {
> + info->init(info->args);
> + }
> + }
> +}
> diff --git a/qemu-options.hx b/qemu-options.hx
> index c0d3951..d171544 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3950,6 +3950,16 @@ Dump json-encoded vmstate information for current
> machine type to file
> in @var{file}
> ETEXI
>
> +#ifdef CONFIG_PLUGINS
> +DEF("plugin", HAS_ARG, QEMU_OPTION_plugin, \
> + "-plugin file=<file>[,args=<args>] load <dso> plugin with
> <args>\n", QEMU_ARCH_ALL)
> +STEXI
> address@hidden -plugin address@hidden,address@hidden
> address@hidden -plugin
> +Load @var{file} plugin passing @var{args} arguments.
> +ETEXI
> +#endif
> +
> STEXI
> @end table
> ETEXI
> diff --git a/vl.c b/vl.c
> index 0603171..05420bf 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -129,6 +129,7 @@ int main(int argc, char **argv)
> #include "qapi/qapi-commands-run-state.h"
> #include "qapi/qmp/qerror.h"
> #include "sysemu/iothread.h"
> +#include "qemu/plugins.h"
>
> #define MAX_VIRTIO_CONSOLES 1
>
> @@ -3925,6 +3926,11 @@ int main(int argc, char **argv, char **envp)
> exit(1);
> }
> break;
> +#ifdef CONFIG_PLUGINS
> + case QEMU_OPTION_plugin:
> + qemu_plugin_parse_cmd_args(optarg);
> + break;
> +#endif
> case QEMU_OPTION_nodefconfig:
> case QEMU_OPTION_nouserconfig:
> /* Nothing to be parsed here. Especially, do not error out
> below. */
> @@ -4470,6 +4476,8 @@ int main(int argc, char **argv, char **envp)
> }
> parse_numa_opts(current_machine);
>
> + qemu_plugins_init();
> +
> /* do monitor/qmp handling at preconfig state if requested */
> main_loop();
>
--
Alex Bennée