modules: build spice and opengl as module.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCgAGBQJfkRSjAAoJEEy22O7T6HE4w4UP/RHNNgRzPWB7kJaiCDGrqGVK
 FSMqUKTkzieIEvW7baVaY19KY2z5HB9Mtna6Ogl6BXdMbmwwaxdMtzHc9RySlLyP
 iUA9iFqDjYbbFtanFEQjv/181Dr/Ib3AgW4muQi/BysvAu9GmFQuRlK07w3KR+QR
 0HXYmrKqpnQxrM0s3h9XwT2VKRYEk8X3fcsQypTyiuqqFXFveIwoFl0XtcU8kq8K
 D+BI/nRZRr+wQG2fW0JjRPRxiUPSAUJgMRqJhPdZ+55enfaxCUTThpw9UVRa8vsr
 g7SY6vadGbqyxq45kyc56p7oc5gxeUbTXklrJqz4blBhl/AnAZyjVMOhBqz3+Sgl
 DORyjrz+M4Wyb/nzlh0HsuZYJmHH3tNgFEruPbyPT4LTpFZ8yUuThNUTl8r6r5aE
 mJkRW9U1xeSrsdiw7vJv+gfxC4J37EMry0OdcL6fcixZSEXaDT/9E+MMhz9UOAC1
 cGTg7fBN4sc/6oifqURz3vMJF1NcSocqPg0rvbkOCAzlf5TzRD07A6lgzLclemyi
 XpKp0qbfE9esLAj5/FPZHkOSGKApo3WzdtExrc8aGIRqE3y1FNUG0hY9RTHEi2po
 vWUEmneTo08Ly+t/COBikOUCGwZAZDIr9v7dxZBBmcmvqRrhbzHAr+JM1y0Unfy1
 /3dNMlA2qsjbezkDzO1U
 =5tJo
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/modules-20201022-pull-request' into staging

modules: build spice and opengl as module.

# gpg: Signature made Thu 22 Oct 2020 06:12:03 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/modules-20201022-pull-request:
  opengl: build opengl helper code modular
  opengl: build egl-headless display modular
  spice: flip modules switch
  modules: add spice dependencies
  modules: dependencies infrastructure
  spice: load module when enabled on the cmdline
  spice: wire up monitor in QemuSpiceOps.
  spice: move display_add_client() to QemuSpiceOps.
  spice: move auth functions to QemuSpiceOps.
  spice: move add_interface() to QemuSpiceOps.
  spice: move display_init() to QemuSpiceOps.
  spice: move qemu_spice_init() to QemuSpiceOps.
  spice: add QemuSpiceOps, move migrate_info
  spice: add module helpers

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-10-22 12:33:20 +01:00
commit 4c5b97bfd0
12 changed files with 232 additions and 72 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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)) {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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'))

View File

@ -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);

View File

@ -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;

85
ui/spice-module.c Normal file
View File

@ -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

View File

@ -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 */