|
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
|
|
Justin M. Forbes |
a81953 |
index 4da33b5..90544c5 100644
|
|
Justin M. Forbes |
a81953 |
|
|
Justin M. Forbes |
a81953 |
|
|
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
|
|
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 |
|
|
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 |
|