Merge remote-tracking branch 'spice/spice.v45' into staging

This commit is contained in:
Anthony Liguori 2011-10-31 10:12:14 -05:00
commit eca968d0d4
9 changed files with 132 additions and 54 deletions

View file

@ -824,7 +824,8 @@ ETEXI
.params = "protocol hostname port tls-port cert-subject",
.help = "send migration info to spice/vnc client",
.user_print = monitor_user_noop,
.mhandler.cmd_new = client_migrate_info,
.mhandler.cmd_async = client_migrate_info,
.flags = MONITOR_CMD_ASYNC,
},
STEXI

View file

@ -18,8 +18,6 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include "qemu-common.h"
#include "qemu-timer.h"
#include "qemu-queue.h"
@ -238,6 +236,9 @@ void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
{
qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
qemu_mutex_lock(&qxl->track_lock);
qxl->guest_cursor = 0;
qemu_mutex_unlock(&qxl->track_lock);
}
@ -330,6 +331,7 @@ static void init_qxl_ram(PCIQXLDevice *d)
d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC);
d->ram->int_pending = cpu_to_le32(0);
d->ram->int_mask = cpu_to_le32(0);
d->ram->update_surface = 0;
SPICE_RING_INIT(&d->ram->cmd_ring);
SPICE_RING_INIT(&d->ram->cursor_ring);
SPICE_RING_INIT(&d->ram->release_ring);
@ -402,7 +404,9 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
{
QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
if (cmd->type == QXL_CURSOR_SET) {
qemu_mutex_lock(&qxl->track_lock);
qxl->guest_cursor = ext->cmd.data;
qemu_mutex_unlock(&qxl->track_lock);
}
break;
}
@ -1067,6 +1071,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
d->mode = QXL_MODE_UNDEFINED;
qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
qxl_spice_reset_cursor(d);
return 1;
}
@ -1212,10 +1217,6 @@ async_common:
qxl_update_irq(d);
break;
case QXL_IO_NOTIFY_OOM:
if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
break;
}
pthread_yield();
if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
break;
}
@ -1372,7 +1373,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
if ((old_pending & le_events) == le_events) {
return;
}
if (pthread_self() == d->main) {
if (qemu_thread_is_self(&d->main)) {
qxl_update_irq(d);
} else {
if (write(d->pipe[1], d, 1) != 1) {
@ -1391,7 +1392,7 @@ static void init_pipe_signaling(PCIQXLDevice *d)
fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
fcntl(d->pipe[0], F_SETOWN, getpid());
d->main = pthread_self();
qemu_thread_get_self(&d->main);
qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
}
@ -1710,10 +1711,12 @@ static int qxl_post_load(void *opaque, int version)
cmds[out].group_id = MEMSLOT_GROUP_GUEST;
out++;
}
cmds[out].cmd.data = d->guest_cursor;
cmds[out].cmd.type = QXL_CMD_CURSOR;
cmds[out].group_id = MEMSLOT_GROUP_GUEST;
out++;
if (d->guest_cursor) {
cmds[out].cmd.data = d->guest_cursor;
cmds[out].cmd.type = QXL_CMD_CURSOR;
cmds[out].group_id = MEMSLOT_GROUP_GUEST;
out++;
}
qxl_spice_loadvm_commands(d, cmds, out);
g_free(cmds);
@ -1787,6 +1790,19 @@ static VMStateDescription qxl_vmstate = {
},
};
static Property qxl_properties[] = {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
QXL_DEFAULT_REVISION),
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
DEFINE_PROP_END_OF_LIST(),
};
static PCIDeviceInfo qxl_info_primary = {
.qdev.name = "qxl-vga",
.qdev.desc = "Spice QXL GPU (primary, vga compatible)",
@ -1799,18 +1815,7 @@ static PCIDeviceInfo qxl_info_primary = {
.vendor_id = REDHAT_PCI_VENDOR_ID,
.device_id = QXL_DEVICE_ID_STABLE,
.class_id = PCI_CLASS_DISPLAY_VGA,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
QXL_DEFAULT_REVISION),
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
DEFINE_PROP_END_OF_LIST(),
}
.qdev.props = qxl_properties,
};
static PCIDeviceInfo qxl_info_secondary = {
@ -1823,18 +1828,7 @@ static PCIDeviceInfo qxl_info_secondary = {
.vendor_id = REDHAT_PCI_VENDOR_ID,
.device_id = QXL_DEVICE_ID_STABLE,
.class_id = PCI_CLASS_DISPLAY_OTHER,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
QXL_DEFAULT_REVISION),
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
DEFINE_PROP_END_OF_LIST(),
}
.qdev.props = qxl_properties,
};
static void qxl_register(void)

View file

@ -4,6 +4,7 @@
#include "hw.h"
#include "pci.h"
#include "vga_int.h"
#include "qemu-thread.h"
#include "ui/qemu-spice.h"
#include "ui/spice-display.h"
@ -63,7 +64,7 @@ typedef struct PCIQXLDevice {
QemuMutex track_lock;
/* thread signaling */
pthread_t main;
QemuThread main;
int pipe[2];
/* ram pci bar */

View file

@ -372,11 +372,22 @@ void remove_migration_state_change_notifier(Notifier *notify)
notifier_list_remove(&migration_state_notifiers, notify);
}
bool migration_is_active(MigrationState *s)
{
return s->state == MIG_STATE_ACTIVE;
}
bool migration_has_finished(MigrationState *s)
{
return s->state == MIG_STATE_COMPLETED;
}
bool migration_has_failed(MigrationState *s)
{
return (s->state == MIG_STATE_CANCELLED ||
s->state == MIG_STATE_ERROR);
}
void migrate_fd_connect(MigrationState *s)
{
int ret;

View file

@ -76,7 +76,9 @@ void migrate_fd_connect(MigrationState *s);
void add_migration_state_change_notifier(Notifier *notify);
void remove_migration_state_change_notifier(Notifier *notify);
bool migration_is_active(MigrationState *);
bool migration_has_finished(MigrationState *);
bool migration_has_failed(MigrationState *);
uint64_t ram_bytes_remaining(void);
uint64_t ram_bytes_transferred(void);

View file

@ -1153,7 +1153,8 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
return -1;
}
static int client_migrate_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
static int client_migrate_info(Monitor *mon, const QDict *qdict,
MonitorCompletion cb, void *opaque)
{
const char *protocol = qdict_get_str(qdict, "protocol");
const char *hostname = qdict_get_str(qdict, "hostname");
@ -1168,7 +1169,8 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict, QObject **ret_d
return -1;
}
ret = qemu_spice_migrate_info(hostname, port, tls_port, subject);
ret = qemu_spice_migrate_info(hostname, port, tls_port, subject,
cb, opaque);
if (ret != 0) {
qerror_report(QERR_UNDEFINED_ERROR);
return -1;

View file

@ -569,7 +569,8 @@ EQMP
.params = "protocol hostname port tls-port cert-subject",
.help = "send migration info to spice/vnc client",
.user_print = monitor_user_noop,
.mhandler.cmd_new = client_migrate_info,
.mhandler.cmd_async = client_migrate_info,
.flags = MONITOR_CMD_ASYNC,
},
SQMP

View file

@ -25,6 +25,7 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "qemu-char.h"
#include "monitor.h"
extern int using_spice;
@ -37,7 +38,8 @@ 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);
const char *subject,
MonitorCompletion cb, void *opaque);
void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
@ -45,6 +47,7 @@ void do_info_spice(Monitor *mon, QObject **ret_data);
int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr);
#else /* CONFIG_SPICE */
#include "monitor.h"
#define using_spice 0
static inline int qemu_spice_set_passwd(const char *passwd,
@ -57,8 +60,13 @@ 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_migrate_info(const char *h, int p, int t,
const char *s,
MonitorCompletion cb, void *opaque)
{
cb(opaque, NULL);
return -1;
}
#endif /* CONFIG_SPICE */

View file

@ -19,10 +19,10 @@
#include <spice-experimental.h>
#include <netdb.h>
#include <pthread.h>
#include "qemu-common.h"
#include "qemu-spice.h"
#include "qemu-thread.h"
#include "qemu-timer.h"
#include "qemu-queue.h"
#include "qemu-x509.h"
@ -45,7 +45,7 @@ static char *auth_passwd;
static time_t auth_expires = TIME_MAX;
int using_spice = 0;
static pthread_t me;
static QemuThread me;
struct SpiceTimer {
QEMUTimer *timer;
@ -133,7 +133,7 @@ static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *
static void watch_remove(SpiceWatch *watch)
{
watch_update_mask(watch, 0);
qemu_set_fd_handler(watch->fd, NULL, NULL, NULL);
QTAILQ_REMOVE(&watches, watch, next);
g_free(watch);
}
@ -229,7 +229,7 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
* thread and grab the iothread lock if so before calling qemu
* functions.
*/
bool need_lock = !pthread_equal(me, pthread_self());
bool need_lock = !qemu_thread_is_self(&me);
if (need_lock) {
qemu_mutex_lock_iothread();
}
@ -288,6 +288,38 @@ static SpiceCoreInterface core_interface = {
#endif
};
#ifdef SPICE_INTERFACE_MIGRATION
typedef struct SpiceMigration {
SpiceMigrateInstance sin;
struct {
MonitorCompletion *cb;
void *opaque;
} connect_complete;
} SpiceMigration;
static void migrate_connect_complete_cb(SpiceMigrateInstance *sin);
static const SpiceMigrateInterface migrate_interface = {
.base.type = SPICE_INTERFACE_MIGRATION,
.base.description = "migration",
.base.major_version = SPICE_INTERFACE_MIGRATION_MAJOR,
.base.minor_version = SPICE_INTERFACE_MIGRATION_MINOR,
.migrate_connect_complete = migrate_connect_complete_cb,
.migrate_end_complete = NULL,
};
static SpiceMigration spice_migrate;
static void migrate_connect_complete_cb(SpiceMigrateInstance *sin)
{
SpiceMigration *sm = container_of(sin, SpiceMigration, sin);
if (sm->connect_complete.cb) {
sm->connect_complete.cb(sm->connect_complete.opaque, NULL);
}
sm->connect_complete.cb = NULL;
}
#endif
/* config string parsing */
static int name2enum(const char *string, const char *table[], int entries)
@ -413,7 +445,7 @@ void do_info_spice(Monitor *mon, QObject **ret_data)
int port, tls_port;
char version_string[20]; /* 12 = |255.255.255\0| is the max */
if (!spice_server) {
if (!spice_server || !opts) {
*ret_data = qobject_from_jsonf("{ 'enabled': false }");
return;
}
@ -449,18 +481,39 @@ static void migration_state_notifier(Notifier *notifier, void *data)
{
MigrationState *s = data;
if (migration_has_finished(s)) {
if (migration_is_active(s)) {
#ifdef SPICE_INTERFACE_MIGRATION
spice_server_migrate_start(spice_server);
#endif
} else if (migration_has_finished(s)) {
#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
#ifndef SPICE_INTERFACE_MIGRATION
spice_server_migrate_switch(spice_server);
#else
spice_server_migrate_end(spice_server, true);
} else if (migration_has_failed(s)) {
spice_server_migrate_end(spice_server, false);
#endif
#endif
}
}
int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
const char *subject)
const char *subject,
MonitorCompletion *cb, void *opaque)
{
return spice_server_migrate_info(spice_server, hostname,
port, tls_port, subject);
int ret;
#ifdef SPICE_INTERFACE_MIGRATION
spice_migrate.connect_complete.cb = cb;
spice_migrate.connect_complete.opaque = opaque;
ret = spice_server_migrate_connect(spice_server, hostname,
port, tls_port, subject);
#else
ret = spice_server_migrate_info(spice_server, hostname,
port, tls_port, subject);
cb(opaque, NULL);
#endif
return ret;
}
static int add_channel(const char *name, const char *value, void *opaque)
@ -503,7 +556,7 @@ void qemu_spice_init(void)
spice_image_compression_t compression;
spice_wan_compression_t wan_compr;
me = pthread_self();
qemu_thread_get_self(&me);
if (!opts) {
return;
@ -650,6 +703,11 @@ void qemu_spice_init(void)
migration_state.notify = migration_state_notifier;
add_migration_state_change_notifier(&migration_state);
#ifdef SPICE_INTERFACE_MIGRATION
spice_migrate.sin.base.sif = &migrate_interface.base;
spice_migrate.connect_complete.cb = NULL;
qemu_spice_add_interface(&spice_migrate.sin.base);
#endif
qemu_spice_input_init();
qemu_spice_audio_init();