diff options
-rw-r--r-- | audio/spiceaudio.c | 4 | ||||
-rw-r--r-- | chardev/spice.c | 2 | ||||
-rw-r--r-- | include/ui/qemu-spice-module.h | 44 | ||||
-rw-r--r-- | include/ui/qemu-spice.h | 42 | ||||
-rw-r--r-- | monitor/misc.c | 2 | ||||
-rw-r--r-- | monitor/qmp-cmds.c | 6 | ||||
-rw-r--r-- | softmmu/vl.c | 10 | ||||
-rw-r--r-- | ui/meson.build | 28 | ||||
-rw-r--r-- | ui/spice-core.c | 31 | ||||
-rw-r--r-- | ui/spice-input.c | 6 | ||||
-rw-r--r-- | ui/spice-module.c | 85 | ||||
-rw-r--r-- | util/module.c | 44 |
12 files changed, 232 insertions, 72 deletions
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index ed6dff1dcc..8967cca129 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -106,7 +106,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as, out->active = 0; out->sin.base.sif = &playback_sif.base; - qemu_spice_add_interface (&out->sin.base); + qemu_spice.add_interface(&out->sin.base); #if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 spice_server_set_playback_rate(&out->sin, settings.freq); #endif @@ -215,7 +215,7 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) in->active = 0; in->sin.base.sif = &record_sif.base; - qemu_spice_add_interface (&in->sin.base); + qemu_spice.add_interface(&in->sin.base); #if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 spice_server_set_record_rate(&in->sin, settings.freq); #endif diff --git a/chardev/spice.c b/chardev/spice.c index 7d1fb17718..1104426e3a 100644 --- a/chardev/spice.c +++ b/chardev/spice.c @@ -110,7 +110,7 @@ static void vmc_register_interface(SpiceChardev *scd) return; } scd->sin.base.sif = &vmc_interface.base; - qemu_spice_add_interface(&scd->sin.base); + qemu_spice.add_interface(&scd->sin.base); scd->active = true; trace_spice_vmc_register_interface(scd); } diff --git a/include/ui/qemu-spice-module.h b/include/ui/qemu-spice-module.h new file mode 100644 index 0000000000..1f22d557ea --- /dev/null +++ b/include/ui/qemu-spice-module.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_SPICE_MODULE_H +#define QEMU_SPICE_MODULE_H + +#ifdef CONFIG_SPICE +#include <spice.h> +#endif + +typedef struct SpiceInfo SpiceInfo; + +struct QemuSpiceOps { + void (*init)(void); + void (*display_init)(void); + int (*migrate_info)(const char *h, int p, int t, const char *s); + int (*set_passwd)(const char *passwd, + bool fail_if_connected, bool disconnect_if_connected); + int (*set_pw_expire)(time_t expires); + int (*display_add_client)(int csock, int skipauth, int tls); +#ifdef CONFIG_SPICE + int (*add_interface)(SpiceBaseInstance *sin); + SpiceInfo* (*qmp_query)(Error **errp); +#endif +}; + +extern int using_spice; +extern struct QemuSpiceOps qemu_spice; + +#endif diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index 0e8ec3f0d7..2beb792972 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -19,24 +19,17 @@ #define QEMU_SPICE_H #include "qapi/error.h" +#include "ui/qemu-spice-module.h" #ifdef CONFIG_SPICE #include <spice.h> #include "qemu/config-file.h" -extern int using_spice; - -void qemu_spice_init(void); void qemu_spice_input_init(void); void qemu_spice_display_init(void); -int qemu_spice_display_add_client(int csock, int skipauth, int tls); -int qemu_spice_add_interface(SpiceBaseInstance *sin); bool qemu_spice_have_display_interface(QemuConsole *con); int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con); -int qemu_spice_set_passwd(const char *passwd, - bool fail_if_connected, bool disconnect_if_connected); -int qemu_spice_set_pw_expire(time_t expires); int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, const char *subject); @@ -50,40 +43,7 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, #include "qemu/error-report.h" -#define using_spice 0 #define spice_displays 0 -static inline int qemu_spice_set_passwd(const char *passwd, - bool fail_if_connected, - bool disconnect_if_connected) -{ - return -1; -} -static inline int qemu_spice_set_pw_expire(time_t expires) -{ - return -1; -} -static inline int qemu_spice_migrate_info(const char *h, int p, int t, - const char *s) -{ - return -1; -} - -static inline int qemu_spice_display_add_client(int csock, int skipauth, - int tls) -{ - return -1; -} - -static inline void qemu_spice_display_init(void) -{ - /* This must never be called if CONFIG_SPICE is disabled */ - error_report("spice support is disabled"); - abort(); -} - -static inline void qemu_spice_init(void) -{ -} #endif /* CONFIG_SPICE */ diff --git a/monitor/misc.c b/monitor/misc.c index 4a859fb24a..32e6a8c13d 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -437,7 +437,7 @@ void qmp_client_migrate_info(const char *protocol, const char *hostname, return; } - if (qemu_spice_migrate_info(hostname, + if (qemu_spice.migrate_info(hostname, has_port ? port : -1, has_tls_port ? tls_port : -1, cert_subject)) { diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 1abef70a89..a08143b323 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -197,7 +197,7 @@ void qmp_set_password(const char *protocol, const char *password, if (!qemu_using_spice(errp)) { return; } - rc = qemu_spice_set_passwd(password, fail_if_connected, + rc = qemu_spice.set_passwd(password, fail_if_connected, disconnect_if_connected); if (rc != 0) { error_setg(errp, QERR_SET_PASSWD_FAILED); @@ -243,7 +243,7 @@ void qmp_expire_password(const char *protocol, const char *whenstr, if (!qemu_using_spice(errp)) { return; } - rc = qemu_spice_set_pw_expire(when); + rc = qemu_spice.set_pw_expire(when); if (rc != 0) { error_setg(errp, QERR_SET_PASSWD_FAILED); } @@ -340,7 +340,7 @@ void qmp_add_client(const char *protocol, const char *fdname, } skipauth = has_skipauth ? skipauth : false; tls = has_tls ? tls : false; - if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { + if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) { error_setg(errp, "spice failed to add client"); close(fd); } diff --git a/softmmu/vl.c b/softmmu/vl.c index cb476aa70b..14fc527fc6 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3705,7 +3705,11 @@ void qemu_init(int argc, char **argv, char **envp) break; } case QEMU_OPTION_spice: - olist = qemu_find_opts("spice"); + olist = qemu_find_opts_err("spice", NULL); + if (!olist) { + ui_module_load_one("spice-core"); + olist = qemu_find_opts("spice"); + } if (!olist) { error_report("spice support is disabled"); exit(1); @@ -4151,7 +4155,7 @@ void qemu_init(int argc, char **argv, char **envp) /* spice needs the timers to be initialized by this point */ /* spice must initialize before audio as it changes the default auiodev */ /* spice must initialize before chardevs (for spicevmc and spiceport) */ - qemu_spice_init(); + qemu_spice.init(); qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, &error_fatal); @@ -4447,7 +4451,7 @@ void qemu_init(int argc, char **argv, char **envp) #endif if (using_spice) { - qemu_spice_display_init(); + qemu_spice.display_init(); } if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { diff --git a/ui/meson.build b/ui/meson.build index ab4de98b38..5d4906c023 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -12,9 +12,9 @@ softmmu_ss.add(files( 'keymaps.c', 'qemu-pixman.c', )) +softmmu_ss.add([spice_headers, files('spice-module.c')]) softmmu_ss.add(when: 'CONFIG_LINUX', if_true: files('input-linux.c')) -softmmu_ss.add(when: [spice, 'CONFIG_SPICE'], if_true: files('spice-core.c', 'spice-input.c', 'spice-display.c')) softmmu_ss.add(when: cocoa, if_true: files('cocoa.m')) vnc_ss = ss.source_set() @@ -33,8 +33,6 @@ vnc_ss.add(zlib, png, jpeg) vnc_ss.add(when: sasl, if_true: files('vnc-auth-sasl.c')) softmmu_ss.add_all(when: vnc, if_true: vnc_ss) softmmu_ss.add(when: vnc, if_false: files('vnc-stubs.c')) -softmmu_ss.add(when: [opengl, 'CONFIG_OPENGL'], if_true: files('shader.c', 'console-gl.c', 'egl-helpers.c', 'egl-context.c')) -softmmu_ss.add(when: [opengl, 'CONFIG_OPENGL_DMABUF'], if_true: files('egl-headless.c')) specific_ss.add(when: ['CONFIG_SOFTMMU'], if_true: opengl) ui_modules = {} @@ -45,6 +43,20 @@ if curses.found() ui_modules += {'curses' : curses_ss} endif +if config_host.has_key('CONFIG_OPENGL') + opengl_ss = ss.source_set() + opengl_ss.add(when: [opengl, pixman, 'CONFIG_OPENGL'], + if_true: files('shader.c', 'console-gl.c', 'egl-helpers.c', 'egl-context.c')) + ui_modules += {'opengl' : opengl_ss} +endif + +if config_host.has_key('CONFIG_OPENGL_DMABUF') + egl_headless_ss = ss.source_set() + egl_headless_ss.add(when: [opengl, pixman, 'CONFIG_OPENGL_DMABUF'], + if_true: files('egl-headless.c')) + ui_modules += {'egl-headless' : egl_headless_ss} +endif + if config_host.has_key('CONFIG_GTK') softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c')) @@ -70,6 +82,16 @@ if sdl.found() ui_modules += {'sdl' : sdl_ss} endif +if config_host.has_key('CONFIG_SPICE') + spice_core_ss = ss.source_set() + spice_core_ss.add(spice, pixman, files( + 'spice-core.c', + 'spice-input.c', + 'spice-display.c' + )) + ui_modules += {'spice-core' : spice_core_ss} +endif + if config_host.has_key('CONFIG_SPICE') and config_host.has_key('CONFIG_GIO') spice_ss = ss.source_set() spice_ss.add(spice, gio, pixman, files('spice-app.c')) diff --git a/ui/spice-core.c b/ui/spice-core.c index 47700b2200..eea52f5389 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -48,7 +48,6 @@ static time_t auth_expires = TIME_MAX; static int spice_migration_completed; static int spice_display_is_running; static int spice_have_target_host; -int using_spice = 0; static QemuThread me; @@ -503,7 +502,7 @@ static QemuOptsList qemu_spice_opts = { }, }; -SpiceInfo *qmp_query_spice(Error **errp) +static SpiceInfo *qmp_query_spice_real(Error **errp) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); int port, tls_port; @@ -634,7 +633,7 @@ static void vm_change_state_handler(void *opaque, int running, } } -void qemu_spice_init(void) +static void qemu_spice_init(void) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); const char *password, *str, *x509_dir, *addr, @@ -728,7 +727,7 @@ void qemu_spice_init(void) tls_ciphers); } if (password) { - qemu_spice_set_passwd(password, false, false); + qemu_spice.set_passwd(password, false, false); } if (qemu_opt_get_bool(opts, "sasl", 0)) { if (spice_server_set_sasl(spice_server, 1) == -1) { @@ -801,7 +800,7 @@ void qemu_spice_init(void) migration_state.notify = migration_state_notifier; add_migration_state_change_notifier(&migration_state); spice_migrate.base.sif = &migrate_interface.base; - qemu_spice_add_interface(&spice_migrate.base); + qemu_spice.add_interface(&spice_migrate.base); qemu_spice_input_init(); @@ -830,7 +829,7 @@ void qemu_spice_init(void) #endif } -int qemu_spice_add_interface(SpiceBaseInstance *sin) +static int qemu_spice_add_interface(SpiceBaseInstance *sin) { if (!spice_server) { if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) { @@ -942,8 +941,8 @@ static int qemu_spice_set_ticket(bool fail_if_conn, bool disconnect_if_conn) fail_if_conn, disconnect_if_conn); } -int qemu_spice_set_passwd(const char *passwd, - bool fail_if_conn, bool disconnect_if_conn) +static int qemu_spice_set_passwd(const char *passwd, + bool fail_if_conn, bool disconnect_if_conn) { if (strcmp(auth, "spice") != 0) { return -1; @@ -954,13 +953,13 @@ int qemu_spice_set_passwd(const char *passwd, return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn); } -int qemu_spice_set_pw_expire(time_t expires) +static int qemu_spice_set_pw_expire(time_t expires) { auth_expires = expires; return qemu_spice_set_ticket(false, false); } -int qemu_spice_display_add_client(int csock, int skipauth, int tls) +static int qemu_spice_display_add_client(int csock, int skipauth, int tls) { if (tls) { return spice_server_add_ssl_client(spice_server, csock, skipauth); @@ -994,8 +993,20 @@ int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd) return spice_display_is_running; } +static struct QemuSpiceOps real_spice_ops = { + .init = qemu_spice_init, + .display_init = qemu_spice_display_init, + .migrate_info = qemu_spice_migrate_info, + .set_passwd = qemu_spice_set_passwd, + .set_pw_expire = qemu_spice_set_pw_expire, + .display_add_client = qemu_spice_display_add_client, + .add_interface = qemu_spice_add_interface, + .qmp_query = qmp_query_spice_real, +}; + static void spice_register_config(void) { + qemu_spice = real_spice_ops; qemu_add_opts(&qemu_spice_opts); } opts_init(spice_register_config); diff --git a/ui/spice-input.c b/ui/spice-input.c index 21990fa996..bbd502564e 100644 --- a/ui/spice-input.c +++ b/ui/spice-input.c @@ -231,7 +231,7 @@ static void mouse_mode_notifier(Notifier *notifier, void *data) } if (is_absolute) { - qemu_spice_add_interface(&pointer->tablet.base); + qemu_spice.add_interface(&pointer->tablet.base); } else { spice_server_remove_interface(&pointer->tablet.base); } @@ -245,13 +245,13 @@ void qemu_spice_input_init(void) kbd = g_malloc0(sizeof(*kbd)); kbd->sin.base.sif = &kbd_interface.base; - qemu_spice_add_interface(&kbd->sin.base); + qemu_spice.add_interface(&kbd->sin.base); qemu_add_led_event_handler(kbd_leds, kbd); pointer = g_malloc0(sizeof(*pointer)); pointer->mouse.base.sif = &mouse_interface.base; pointer->tablet.base.sif = &tablet_interface.base; - qemu_spice_add_interface(&pointer->mouse.base); + qemu_spice.add_interface(&pointer->mouse.base); pointer->absolute = false; pointer->mouse_mode.notify = mouse_mode_notifier; diff --git a/ui/spice-module.c b/ui/spice-module.c new file mode 100644 index 0000000000..3222335872 --- /dev/null +++ b/ui/spice-module.c @@ -0,0 +1,85 @@ +/* + * spice module support, also spice stubs. + * + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/qapi-types-ui.h" +#include "qapi/qapi-commands-ui.h" +#include "ui/qemu-spice-module.h" + +int using_spice; + +static void qemu_spice_init_stub(void) +{ +} + +static void qemu_spice_display_init_stub(void) +{ + /* This must never be called if CONFIG_SPICE is disabled */ + error_report("spice support is disabled"); + abort(); +} + +static int qemu_spice_migrate_info_stub(const char *h, int p, int t, + const char *s) +{ + return -1; +} + +static int qemu_spice_set_passwd_stub(const char *passwd, + bool fail_if_connected, + bool disconnect_if_connected) +{ + return -1; +} + +static int qemu_spice_set_pw_expire_stub(time_t expires) +{ + return -1; +} + +static int qemu_spice_display_add_client_stub(int csock, int skipauth, + int tls) +{ + return -1; +} + +struct QemuSpiceOps qemu_spice = { + .init = qemu_spice_init_stub, + .display_init = qemu_spice_display_init_stub, + .migrate_info = qemu_spice_migrate_info_stub, + .set_passwd = qemu_spice_set_passwd_stub, + .set_pw_expire = qemu_spice_set_pw_expire_stub, + .display_add_client = qemu_spice_display_add_client_stub, +}; + +#ifdef CONFIG_SPICE + +SpiceInfo *qmp_query_spice(Error **errp) +{ + if (!qemu_spice.qmp_query) { + SpiceInfo *info = g_new0(SpiceInfo, 1); + info->enabled = false; + return info; + } + return qemu_spice.qmp_query(errp); +} + +#endif diff --git a/util/module.c b/util/module.c index f0ed05fbd0..fe3b82dd4d 100644 --- a/util/module.c +++ b/util/module.c @@ -110,7 +110,7 @@ void module_call_init(module_init_type type) } #ifdef CONFIG_MODULES -static int module_load_file(const char *fname, bool mayfail) +static int module_load_file(const char *fname, bool mayfail, bool export_symbols) { GModule *g_module; void (*sym)(void); @@ -118,7 +118,7 @@ static int module_load_file(const char *fname, bool mayfail) int len = strlen(fname); int suf_len = strlen(dsosuf); ModuleEntry *e, *next; - int ret; + int ret, flags; if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) { /* wrong suffix */ @@ -132,7 +132,11 @@ static int module_load_file(const char *fname, bool mayfail) assert(QTAILQ_EMPTY(&dso_init_list)); - g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + flags = G_MODULE_BIND_LAZY; + if (!export_symbols) { + flags |= G_MODULE_BIND_LOCAL; + } + g_module = g_module_open(fname, flags); if (!g_module) { if (!mayfail) { fprintf(stderr, "Failed to open module: %s\n", @@ -167,6 +171,24 @@ static int module_load_file(const char *fname, bool mayfail) out: return ret; } + +static const struct { + const char *name; + const char *dep; +} module_deps[] = { + { "audio-spice", "ui-spice-core" }, + { "chardev-spice", "ui-spice-core" }, + { "hw-display-qxl", "ui-spice-core" }, + { "ui-spice-app", "ui-spice-core" }, + { "ui-spice-app", "chardev-spice" }, + +#ifdef CONFIG_OPENGL + { "ui-egl-headless", "ui-opengl" }, + { "ui-gtk", "ui-opengl" }, + { "ui-sdl", "ui-opengl" }, + { "ui-spice-core", "ui-opengl" }, +#endif +}; #endif bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) @@ -182,7 +204,8 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) char *dirs[5]; char *module_name; int i = 0, n_dirs = 0; - int ret; + int ret, dep; + bool export_symbols = false; static GHashTable *loaded_modules; if (!g_module_supported()) { @@ -196,6 +219,17 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) module_name = g_strdup_printf("%s%s", prefix, lib_name); + for (dep = 0; dep < ARRAY_SIZE(module_deps); dep++) { + if (strcmp(module_name, module_deps[dep].name) == 0) { + /* we depend on another module */ + module_load_one("", module_deps[dep].dep, false); + } + if (strcmp(module_name, module_deps[dep].dep) == 0) { + /* another module depends on us */ + export_symbols = true; + } + } + if (!g_hash_table_add(loaded_modules, module_name)) { g_free(module_name); return true; @@ -220,7 +254,7 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) for (i = 0; i < n_dirs; i++) { fname = g_strdup_printf("%s/%s%s", dirs[i], module_name, CONFIG_HOST_DSOSUF); - ret = module_load_file(fname, mayfail); + ret = module_load_file(fname, mayfail, export_symbols); g_free(fname); fname = NULL; /* Try loading until loaded a module file */ |