Commit 510981a0 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

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: default avatarAnthony Liguori <aliguori@us.ibm.com>
parents c3a1ecd0 700f6b6a
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
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
+6 −5
Original line number Diff line number Diff line
@@ -113,7 +113,8 @@ 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,
            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,
+3 −0
Original line number Diff line number Diff line
@@ -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
};

+13 −0
Original line number Diff line number Diff line
@@ -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

+89 −18
Original line number Diff line number Diff line
@@ -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,12 +216,33 @@ 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);

    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;

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