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

* spice/spice.v66:
  docs: add spice-port-fqdn.txt
  spice-qemu-char: register spicevmc ports during qemu_spice_init()
  spice-qemu-char: keep a list of spice chardev
  spice-qemu-char: add spiceport chardev
  spice-qemu-char: factor out CharDriverState creation
  spice-qemu-char: write to chardev whatever amount it can read
  qxl+vnc: register a vm state change handler for dummy spice_server
  qxl: save qemu_create_displaysurface_from result

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2012-12-18 15:41:21 -06:00
commit 510981a097
8 changed files with 141 additions and 23 deletions

19
docs/spice-port-fqdn.txt Normal file
View file

@ -0,0 +1,19 @@
A Spice port channel is an arbitrary communication between the Spice
server host side and the client side.
Thanks to the associated reverse fully qualified domain name (fqdn),
a Spice client can handle the various ports appropriately.
The following fqdn names are reserved by the QEMU project:
org.qemu.monitor.hmp.0
QEMU human monitor
org.qemu.monitor.qmp.0:
QEMU control monitor
org.qemu.console.serial.0
QEMU virtual serial port
org.qemu.console.debug.0
QEMU debug console

View file

@ -113,11 +113,12 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.bits_pp);
if (qxl->guest_primary.qxl_stride > 0) {
qemu_free_displaysurface(vga->ds);
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.bits_pp,
qxl->guest_primary.abs_stride,
qxl->guest_primary.data);
vga->ds->surface = qemu_create_displaysurface_from
(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.bits_pp,
qxl->guest_primary.abs_stride,
qxl->guest_primary.data);
} else {
qemu_resize_displaysurface(vga->ds,
qxl->guest_primary.surface.width,

View file

@ -2762,6 +2762,9 @@ static const struct {
#endif
#ifdef CONFIG_SPICE
{ .name = "spicevmc", .open = qemu_chr_open_spice },
#if SPICE_SERVER_VERSION >= 0x000c02
{ .name = "spiceport", .open = qemu_chr_open_spice_port },
#endif
#endif
};

View file

@ -1749,6 +1749,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
#endif
#if defined(CONFIG_SPICE)
"-chardev spicevmc,id=id,name=name[,debug=debug]\n"
"-chardev spiceport,id=id,name=name[,debug=debug]\n"
#endif
, QEMU_ARCH_ALL
)
@ -1776,6 +1777,7 @@ Backend is one of:
@option{tty},
@option{parport},
@option{spicevmc}.
@option{spiceport}.
The specific backend will determine the applicable options.
All devices must have an id, which can be any string up to 127 characters long.
@ -1961,6 +1963,17 @@ required.
Connect to a spice virtual machine channel, such as vdiport.
@item -chardev spiceport ,id=@var{id} ,debug=@var{debug}, name=@var{name}
@option{spiceport} is only available when spice support is built in.
@option{debug} debug level for spicevmc
@option{name} name of spice port to connect to
Connect to a spice port, allowing a Spice client to handle the traffic
identified by a name (preferably a fqdn).
@end table
ETEXI

View file

@ -3,6 +3,7 @@
#include "ui/qemu-spice.h"
#include <spice.h>
#include <spice-experimental.h>
#include <spice/protocol.h>
#include "osdep.h"
@ -14,8 +15,6 @@
} \
} while (0)
#define VMC_MAX_HOST_WRITE 2048
typedef struct SpiceCharDriver {
CharDriverState* chr;
SpiceCharDeviceInstance sin;
@ -25,8 +24,12 @@ typedef struct SpiceCharDriver {
uint8_t *datapos;
ssize_t bufsize, datalen;
uint32_t debug;
QLIST_ENTRY(SpiceCharDriver) next;
} SpiceCharDriver;
static QLIST_HEAD(, SpiceCharDriver) spice_chars =
QLIST_HEAD_INITIALIZER(spice_chars);
static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
{
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
@ -35,8 +38,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
uint8_t* p = (uint8_t*)buf;
while (len > 0) {
last_out = MIN(len, VMC_MAX_HOST_WRITE);
if (qemu_chr_be_can_write(scd->chr) < last_out) {
last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
if (last_out <= 0) {
break;
}
qemu_chr_be_write(scd->chr, p, last_out);
@ -69,6 +72,27 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
return bytes;
}
#if SPICE_SERVER_VERSION >= 0x000c02
static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
{
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
int chr_event;
switch (event) {
case SPICE_PORT_EVENT_BREAK:
chr_event = CHR_EVENT_BREAK;
break;
default:
dprintf(scd, 2, "%s: unknown %d\n", __func__, event);
return;
}
dprintf(scd, 2, "%s: %d\n", __func__, event);
trace_spice_vmc_event(chr_event);
qemu_chr_be_event(scd->chr, chr_event);
}
#endif
static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
{
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
@ -105,6 +129,9 @@ static SpiceCharDeviceInterface vmc_interface = {
.state = vmc_state,
.write = vmc_write,
.read = vmc_read,
#if SPICE_SERVER_VERSION >= 0x000c02
.event = vmc_event,
#endif
};
@ -156,6 +183,7 @@ static void spice_chr_close(struct CharDriverState *chr)
printf("%s\n", __func__);
vmc_unregister_interface(s);
QLIST_REMOVE(s, next);
g_free(s);
}
@ -188,13 +216,34 @@ static void print_allowed_subtypes(void)
fprintf(stderr, "\n");
}
CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
{
CharDriverState *chr;
SpiceCharDriver *s;
const char* name = qemu_opt_get(opts, "name");
uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
const char** psubtype = spice_server_char_device_recognized_subtypes();
chr = g_malloc0(sizeof(CharDriverState));
s = g_malloc0(sizeof(SpiceCharDriver));
s->chr = chr;
s->debug = debug;
s->active = false;
s->sin.subtype = subtype;
chr->opaque = s;
chr->chr_write = spice_chr_write;
chr->chr_close = spice_chr_close;
chr->chr_guest_open = spice_chr_guest_open;
chr->chr_guest_close = spice_chr_guest_close;
QLIST_INSERT_HEAD(&spice_chars, s, next);
return chr;
}
CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
{
CharDriverState *chr;
const char *name = qemu_opt_get(opts, "name");
const char **psubtype = spice_server_char_device_recognized_subtypes();
const char *subtype = NULL;
if (name == NULL) {
@ -214,17 +263,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
return NULL;
}
chr = g_malloc0(sizeof(CharDriverState));
s = g_malloc0(sizeof(SpiceCharDriver));
s->chr = chr;
s->debug = debug;
s->active = false;
s->sin.subtype = subtype;
chr->opaque = s;
chr->chr_write = spice_chr_write;
chr->chr_close = spice_chr_close;
chr->chr_guest_open = spice_chr_guest_open;
chr->chr_guest_close = spice_chr_guest_close;
chr = chr_open(opts, subtype);
#if SPICE_SERVER_VERSION < 0x000901
/* See comment in vmc_state() */
@ -235,3 +274,35 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
return chr;
}
#if SPICE_SERVER_VERSION >= 0x000c02
CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts)
{
CharDriverState *chr;
SpiceCharDriver *s;
const char *name = qemu_opt_get(opts, "name");
if (name == NULL) {
fprintf(stderr, "spice-qemu-char: missing name parameter\n");
return NULL;
}
chr = chr_open(opts, "port");
s = chr->opaque;
s->sin.portname = name;
return chr;
}
void qemu_spice_register_ports(void)
{
SpiceCharDriver *s;
QLIST_FOREACH(s, &spice_chars, next) {
if (s->sin.portname == NULL) {
continue;
}
vmc_register_interface(s);
}
}
#endif

View file

@ -535,6 +535,7 @@ spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d"
spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
spice_vmc_event(int event) "spice vmc event %d"
# hw/lm32_pic.c
lm32_pic_raise_irq(void) "Raise CPU interrupt"

View file

@ -46,6 +46,10 @@ void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
#if SPICE_SERVER_VERSION >= 0x000c02
CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts);
void qemu_spice_register_ports(void);
#endif
#else /* CONFIG_SPICE */
#include "monitor.h"

View file

@ -714,6 +714,10 @@ void qemu_spice_init(void)
g_free(x509_key_file);
g_free(x509_cert_file);
g_free(x509_cacert_file);
#if SPICE_SERVER_VERSION >= 0x000c02
qemu_spice_register_ports();
#endif
}
int qemu_spice_add_interface(SpiceBaseInstance *sin)
@ -732,6 +736,8 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
*/
spice_server = spice_server_new();
spice_server_init(spice_server, &core_interface);
qemu_add_vm_change_state_handler(vm_change_state_handler,
&spice_server);
}
return spice_server_add_interface(spice_server, sin);