aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/spiceaudio.c4
-rw-r--r--chardev/spice.c2
-rw-r--r--include/ui/qemu-spice-module.h44
-rw-r--r--include/ui/qemu-spice.h42
-rw-r--r--monitor/misc.c2
-rw-r--r--monitor/qmp-cmds.c6
-rw-r--r--softmmu/vl.c10
-rw-r--r--ui/meson.build28
-rw-r--r--ui/spice-core.c31
-rw-r--r--ui/spice-input.c6
-rw-r--r--ui/spice-module.c85
-rw-r--r--util/module.c44
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 */