Blame 0016-spice-add-virtio-serial-based-vdi-port-backend.patch

Justin M. Forbes a81953
From ebf4cebd082442ed2bc11475fde301c18648298d Mon Sep 17 00:00:00 2001
Justin M. Forbes a81953
From: Gerd Hoffmann <kraxel@redhat.com>
Justin M. Forbes a81953
Date: Tue, 20 Apr 2010 13:33:54 +0200
Justin M. Forbes a81953
Subject: [PATCH 16/39] spice: add virtio-serial based vdi port backend.
Justin M. Forbes a81953
Justin M. Forbes a81953
Adds the spicevmc device.  This is a communication channel between the
Justin M. Forbes a81953
spice client and the guest.  It is used to send display information and
Justin M. Forbes a81953
mouse events from the spice clients to the guest.
Justin M. Forbes a81953
---
Justin M. Forbes a81953
 Makefile.target |    1 +
Justin M. Forbes a81953
 hw/spice-vmc.c  |  203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Justin M. Forbes a81953
 2 files changed, 204 insertions(+), 0 deletions(-)
Justin M. Forbes a81953
 create mode 100644 hw/spice-vmc.c
Justin M. Forbes a81953
Justin M. Forbes a81953
diff --git a/Makefile.target b/Makefile.target
Justin M. Forbes a81953
index 4da33b5..90544c5 100644
Justin M. Forbes a81953
--- a/Makefile.target
Justin M. Forbes a81953
+++ b/Makefile.target
Justin M. Forbes a81953
@@ -217,6 +217,7 @@ obj-i386-y += pc_piix.o
Justin M. Forbes a81953
 obj-i386-y += testdev.o
Justin M. Forbes a81953
 obj-i386-y += acpi.o acpi_piix4.o
Justin M. Forbes a81953
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
Justin M. Forbes a81953
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
Justin M. Forbes a81953
Justin M. Forbes a81953
 obj-i386-y += pcspk.o i8254.o
Justin M. Forbes a81953
 obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
Justin M. Forbes a81953
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
Justin M. Forbes a81953
new file mode 100644
Justin M. Forbes a81953
index 0000000..3f6a2bb
Justin M. Forbes a81953
--- /dev/null
Justin M. Forbes a81953
+++ b/hw/spice-vmc.c
Justin M. Forbes a81953
@@ -0,0 +1,203 @@
Justin M. Forbes a81953
+/*
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+ Spice Virtual Machine Channel (VMC).
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+ A virtio-serial port used for spice to guest communication, over
Justin M. Forbes a81953
+ which spice client and a daemon in the guest operating system
Justin M. Forbes a81953
+ communicate.
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+ Replaces the old vdi_port PCI device.
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+*/
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#include <stdio.h>
Justin M. Forbes a81953
+#include <stdbool.h>
Justin M. Forbes a81953
+#include <spice.h>
Justin M. Forbes a81953
+#include <spice-experimental.h>
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#include "virtio-serial.h"
Justin M. Forbes a81953
+#include "qemu-spice.h"
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
Justin M. Forbes a81953
+#define VMC_DEVICE_NAME       "spicevmc"
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#define dprintf(_svc, _level, _fmt, ...)                                \
Justin M. Forbes a81953
+    do {                                                                \
Justin M. Forbes a81953
+        if (_svc->debug >= _level) {                                    \
Justin M. Forbes a81953
+            fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__);              \
Justin M. Forbes a81953
+        }                                                               \
Justin M. Forbes a81953
+    } while (0)
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+typedef struct SpiceVirtualChannel {
Justin M. Forbes a81953
+    VirtIOSerialPort      port;
Justin M. Forbes a81953
+    VMChangeStateEntry    *vmstate;
Justin M. Forbes a81953
+    SpiceVDIPortInstance  sin;
Justin M. Forbes a81953
+    bool                  active;
Justin M. Forbes a81953
+    uint8_t               *buffer;
Justin M. Forbes a81953
+    uint8_t               *datapos;
Justin M. Forbes a81953
+    ssize_t               bufsize, datalen;
Justin M. Forbes a81953
+    uint32_t              debug;
Justin M. Forbes a81953
+} SpiceVirtualChannel;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
Justin M. Forbes a81953
+    ssize_t out;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    out = virtio_serial_write(&svc->port, buf, len);
Justin M. Forbes a81953
+    dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
Justin M. Forbes a81953
+    return out;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
Justin M. Forbes a81953
+    int bytes = MIN(len, svc->datalen);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
Justin M. Forbes a81953
+    if (bytes) {
Justin M. Forbes a81953
+        memcpy(buf, svc->datapos, bytes);
Justin M. Forbes a81953
+        svc->datapos += bytes;
Justin M. Forbes a81953
+        svc->datalen -= bytes;
Justin M. Forbes a81953
+        if (0 == svc->datalen) {
Justin M. Forbes a81953
+            virtio_serial_throttle_port(&svc->port, false);
Justin M. Forbes a81953
+        }
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    return bytes;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static SpiceVDIPortInterface vmc_interface = {
Justin M. Forbes a81953
+    .base.type          = SPICE_INTERFACE_VDI_PORT,
Justin M. Forbes a81953
+    .base.description   = "spice virtual channel vdi port",
Justin M. Forbes a81953
+    .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
Justin M. Forbes a81953
+    .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
Justin M. Forbes a81953
+    .write              = vmc_write,
Justin M. Forbes a81953
+    .read               = vmc_read,
Justin M. Forbes a81953
+};
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_register_interface(SpiceVirtualChannel *svc)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (svc->active) {
Justin M. Forbes a81953
+        return;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    svc->sin.base.sif = &vmc_interface.base;
Justin M. Forbes a81953
+    spice_server_add_interface(spice_server, &svc->sin.base);
Justin M. Forbes a81953
+    svc->active = true;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_unregister_interface(SpiceVirtualChannel *svc)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (!svc->active) {
Justin M. Forbes a81953
+        return;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    spice_server_remove_interface(&svc->sin.base);
Justin M. Forbes a81953
+    svc->active = false;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_change_state_handler(void *opaque, int running, int reason)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = opaque;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (running && svc->active) {
Justin M. Forbes a81953
+        spice_server_vdi_port_wakeup(&svc->sin);
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+/*
Justin M. Forbes a81953
+ * virtio-serial callbacks
Justin M. Forbes a81953
+ */
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_guest_open(VirtIOSerialPort *port)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    vmc_register_interface(svc);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_guest_close(VirtIOSerialPort *port)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    vmc_unregister_interface(svc);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_guest_ready(VirtIOSerialPort *port)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    if (svc->active)
Justin M. Forbes a81953
+        spice_server_vdi_port_wakeup(&svc->sin);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 2, "%s: %zd\n", __func__, len);
Justin M. Forbes a81953
+    assert(svc->datapos == 0);
Justin M. Forbes a81953
+    if (svc->bufsize < len) {
Justin M. Forbes a81953
+        svc->bufsize = len;
Justin M. Forbes a81953
+        svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    memcpy(svc->buffer, buf, len);
Justin M. Forbes a81953
+    svc->datapos = svc->buffer;
Justin M. Forbes a81953
+    svc->datalen = len;
Justin M. Forbes a81953
+    virtio_serial_throttle_port(&svc->port, true);
Justin M. Forbes a81953
+    spice_server_vdi_port_wakeup(&svc->sin);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int vmc_initfn(VirtIOSerialDevice *dev)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (!using_spice)
Justin M. Forbes a81953
+        return -1;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
Justin M. Forbes a81953
+    svc->vmstate = qemu_add_vm_change_state_handler(
Justin M. Forbes a81953
+        vmc_change_state_handler, svc);
Justin M. Forbes a81953
+    virtio_serial_open(port);
Justin M. Forbes a81953
+    return 0;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int vmc_exitfn(VirtIOSerialDevice *dev)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
Justin M. Forbes a81953
+    SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dprintf(svc, 1, "%s\n", __func__);
Justin M. Forbes a81953
+    vmc_unregister_interface(svc);
Justin M. Forbes a81953
+    qemu_del_vm_change_state_handler(svc->vmstate);
Justin M. Forbes a81953
+    virtio_serial_close(port);
Justin M. Forbes a81953
+    return 0;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static VirtIOSerialPortInfo vmc_info = {
Justin M. Forbes a81953
+    .qdev.name     = VMC_DEVICE_NAME,
Justin M. Forbes a81953
+    .qdev.size     = sizeof(SpiceVirtualChannel),
Justin M. Forbes a81953
+    .init          = vmc_initfn,
Justin M. Forbes a81953
+    .exit          = vmc_exitfn,
Justin M. Forbes a81953
+    .guest_open    = vmc_guest_open,
Justin M. Forbes a81953
+    .guest_close   = vmc_guest_close,
Justin M. Forbes a81953
+    .guest_ready   = vmc_guest_ready,
Justin M. Forbes a81953
+    .have_data     = vmc_have_data,
Justin M. Forbes a81953
+    .qdev.props = (Property[]) {
Justin M. Forbes a81953
+        DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
Justin M. Forbes a81953
+        DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
Justin M. Forbes a81953
+        DEFINE_PROP_END_OF_LIST(),
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+};
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void vmc_register(void)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    virtio_serial_port_qdev_register(&vmc_info);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+device_init(vmc_register)
Justin M. Forbes a81953
-- 
Justin M. Forbes a81953
1.7.2.3
Justin M. Forbes a81953