Updates from upstream to support spice 0.6.0
This commit is contained in:
parent
dbbd2b2c03
commit
a81953e710
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
qemu-kvm-0.13.0-b81fe95.tar.gz
|
||||
qemu-kvm-0.13.0-25fdf4a.tar.gz
|
||||
/qemu-kvm-0.13.0-rc1.tar.gz
|
||||
|
259
0001-add-pflib-PixelFormat-conversion-library.patch
Normal file
259
0001-add-pflib-PixelFormat-conversion-library.patch
Normal file
@ -0,0 +1,259 @@
|
||||
From 09992bc6b432987ed3871dd7e4327ab6a589b865 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 09:54:27 +0200
|
||||
Subject: [PATCH 01/39] add pflib: PixelFormat conversion library.
|
||||
|
||||
---
|
||||
Makefile.objs | 1 +
|
||||
pflib.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
pflib.h | 6 ++
|
||||
3 files changed, 220 insertions(+), 0 deletions(-)
|
||||
create mode 100644 pflib.c
|
||||
create mode 100644 pflib.h
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index dbee210..147051f 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -84,6 +84,7 @@ common-obj-y += qemu-char.o savevm.o #aio.o
|
||||
common-obj-y += msmouse.o ps2.o
|
||||
common-obj-y += qdev.o qdev-properties.o
|
||||
common-obj-y += block-migration.o
|
||||
+common-obj-y += pflib.o
|
||||
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
diff --git a/pflib.c b/pflib.c
|
||||
new file mode 100644
|
||||
index 0000000..1154d0c
|
||||
--- /dev/null
|
||||
+++ b/pflib.c
|
||||
@@ -0,0 +1,213 @@
|
||||
+/*
|
||||
+ * PixelFormat conversion library.
|
||||
+ *
|
||||
+ * Author: Gerd Hoffmann <kraxel@redhat.com>
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
+ * the COPYING file in the top-level directory.
|
||||
+ *
|
||||
+ */
|
||||
+#include "qemu-common.h"
|
||||
+#include "console.h"
|
||||
+#include "pflib.h"
|
||||
+
|
||||
+typedef struct QemuPixel QemuPixel;
|
||||
+
|
||||
+typedef void (*pf_convert)(QemuPfConv *conv,
|
||||
+ void *dst, void *src, uint32_t cnt);
|
||||
+typedef void (*pf_convert_from)(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt);
|
||||
+typedef void (*pf_convert_to)(PixelFormat *pf,
|
||||
+ void *dst, QemuPixel *src, uint32_t cnt);
|
||||
+
|
||||
+struct QemuPfConv {
|
||||
+ pf_convert convert;
|
||||
+ PixelFormat src;
|
||||
+ PixelFormat dst;
|
||||
+
|
||||
+ /* for copy_generic() */
|
||||
+ pf_convert_from conv_from;
|
||||
+ pf_convert_to conv_to;
|
||||
+ QemuPixel *conv_buf;
|
||||
+ uint32_t conv_cnt;
|
||||
+};
|
||||
+
|
||||
+struct QemuPixel {
|
||||
+ uint8_t red;
|
||||
+ uint8_t green;
|
||||
+ uint8_t blue;
|
||||
+ uint8_t alpha;
|
||||
+};
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* PixelFormat -> QemuPixel conversions */
|
||||
+
|
||||
+static void conv_16_to_pixel(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint16_t *src16 = src;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ dst->red = ((*src16 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
|
||||
+ dst->green = ((*src16 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
|
||||
+ dst->blue = ((*src16 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
|
||||
+ dst->alpha = ((*src16 & pf->amask) >> pf->ashift) << (8 - pf->abits);
|
||||
+ dst++, src16++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* assumes pf->{r,g,b,a}bits == 8 */
|
||||
+static void conv_32_to_pixel_fast(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t *src32 = src;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ dst->red = (*src32 & pf->rmask) >> pf->rshift;
|
||||
+ dst->green = (*src32 & pf->gmask) >> pf->gshift;
|
||||
+ dst->blue = (*src32 & pf->bmask) >> pf->bshift;
|
||||
+ dst->alpha = (*src32 & pf->amask) >> pf->ashift;
|
||||
+ dst++, src32++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void conv_32_to_pixel_generic(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t *src32 = src;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ if (pf->rbits < 8) {
|
||||
+ dst->red = ((*src32 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
|
||||
+ } else {
|
||||
+ dst->red = ((*src32 & pf->rmask) >> pf->rshift) >> (pf->rbits - 8);
|
||||
+ }
|
||||
+ if (pf->gbits < 8) {
|
||||
+ dst->green = ((*src32 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
|
||||
+ } else {
|
||||
+ dst->green = ((*src32 & pf->gmask) >> pf->gshift) >> (pf->gbits - 8);
|
||||
+ }
|
||||
+ if (pf->bbits < 8) {
|
||||
+ dst->blue = ((*src32 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
|
||||
+ } else {
|
||||
+ dst->blue = ((*src32 & pf->bmask) >> pf->bshift) >> (pf->bbits - 8);
|
||||
+ }
|
||||
+ if (pf->abits < 8) {
|
||||
+ dst->alpha = ((*src32 & pf->amask) >> pf->ashift) << (8 - pf->abits);
|
||||
+ } else {
|
||||
+ dst->alpha = ((*src32 & pf->amask) >> pf->ashift) >> (pf->abits - 8);
|
||||
+ }
|
||||
+ dst++, src32++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* QemuPixel -> PixelFormat conversions */
|
||||
+
|
||||
+static void conv_pixel_to_16(PixelFormat *pf,
|
||||
+ void *dst, QemuPixel *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint16_t *dst16 = dst;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ *dst16 = ((uint16_t)src->red >> (8 - pf->rbits)) << pf->rshift;
|
||||
+ *dst16 |= ((uint16_t)src->green >> (8 - pf->gbits)) << pf->gshift;
|
||||
+ *dst16 |= ((uint16_t)src->blue >> (8 - pf->bbits)) << pf->bshift;
|
||||
+ *dst16 |= ((uint16_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
|
||||
+ dst16++, src++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void conv_pixel_to_32(PixelFormat *pf,
|
||||
+ void *dst, QemuPixel *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t *dst32 = dst;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ *dst32 = ((uint32_t)src->red >> (8 - pf->rbits)) << pf->rshift;
|
||||
+ *dst32 |= ((uint32_t)src->green >> (8 - pf->gbits)) << pf->gshift;
|
||||
+ *dst32 |= ((uint32_t)src->blue >> (8 - pf->bbits)) << pf->bshift;
|
||||
+ *dst32 |= ((uint32_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
|
||||
+ dst32++, src++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* PixelFormat -> PixelFormat conversions */
|
||||
+
|
||||
+static void convert_copy(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t bytes = cnt * conv->src.bytes_per_pixel;
|
||||
+ memcpy(dst, src, bytes);
|
||||
+}
|
||||
+
|
||||
+static void convert_generic(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ if (conv->conv_cnt < cnt) {
|
||||
+ conv->conv_cnt = cnt;
|
||||
+ conv->conv_buf = qemu_realloc(conv->conv_buf, sizeof(QemuPixel) * conv->conv_cnt);
|
||||
+ }
|
||||
+ conv->conv_from(&conv->src, conv->conv_buf, src, cnt);
|
||||
+ conv->conv_to(&conv->dst, dst, conv->conv_buf, cnt);
|
||||
+}
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* public interface */
|
||||
+
|
||||
+QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src)
|
||||
+{
|
||||
+ QemuPfConv *conv = qemu_mallocz(sizeof(QemuPfConv));
|
||||
+
|
||||
+ conv->src = *src;
|
||||
+ conv->dst = *dst;
|
||||
+
|
||||
+ if (memcmp(&conv->src, &conv->dst, sizeof(PixelFormat)) == 0) {
|
||||
+ /* formats identical, can simply copy */
|
||||
+ conv->convert = convert_copy;
|
||||
+ } else {
|
||||
+ /* generic two-step conversion: src -> QemuPixel -> dst */
|
||||
+ switch (conv->src.bytes_per_pixel) {
|
||||
+ case 2:
|
||||
+ conv->conv_from = conv_16_to_pixel;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ if (conv->src.rbits == 8 && conv->src.gbits == 8 && conv->src.bbits == 8) {
|
||||
+ conv->conv_from = conv_32_to_pixel_fast;
|
||||
+ } else {
|
||||
+ conv->conv_from = conv_32_to_pixel_generic;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto err;
|
||||
+ }
|
||||
+ switch (conv->dst.bytes_per_pixel) {
|
||||
+ case 2:
|
||||
+ conv->conv_to = conv_pixel_to_16;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ conv->conv_to = conv_pixel_to_32;
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto err;
|
||||
+ }
|
||||
+ conv->convert = convert_generic;
|
||||
+ }
|
||||
+ return conv;
|
||||
+
|
||||
+err:
|
||||
+ qemu_free(conv);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ conv->convert(conv, dst, src, cnt);
|
||||
+}
|
||||
+
|
||||
+void qemu_pf_conv_put(QemuPfConv *conv)
|
||||
+{
|
||||
+ if (conv) {
|
||||
+ qemu_free(conv->conv_buf);
|
||||
+ qemu_free(conv);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/pflib.h b/pflib.h
|
||||
new file mode 100644
|
||||
index 0000000..8d73fdd
|
||||
--- /dev/null
|
||||
+++ b/pflib.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+/* public */
|
||||
+typedef struct QemuPfConv QemuPfConv;
|
||||
+
|
||||
+QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src);
|
||||
+void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt);
|
||||
+void qemu_pf_conv_put(QemuPfConv *conv);
|
||||
--
|
||||
1.7.2.3
|
||||
|
39
0002-configure-add-logging.patch
Normal file
39
0002-configure-add-logging.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 89df4f8cf7ecde07e3dc5e2ea3c19cbcd02165d0 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 23 Apr 2010 13:44:10 +0200
|
||||
Subject: [PATCH 02/39] configure: add logging
|
||||
|
||||
Write compile commands and messages to config.log.
|
||||
Useful for debugging configure.
|
||||
---
|
||||
configure | 7 +++++--
|
||||
1 files changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index b85590f..e09c442 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -16,15 +16,18 @@ TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
|
||||
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
|
||||
|
||||
trap "rm -f $TMPC $TMPO $TMPE ; exit" EXIT INT QUIT TERM
|
||||
+rm -f config.log
|
||||
|
||||
compile_object() {
|
||||
- $cc $QEMU_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null
|
||||
+ echo $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log
|
||||
+ $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log 2>&1
|
||||
}
|
||||
|
||||
compile_prog() {
|
||||
local_cflags="$1"
|
||||
local_ldflags="$2"
|
||||
- $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags > /dev/null 2> /dev/null
|
||||
+ echo $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log
|
||||
+ $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log 2>&1
|
||||
}
|
||||
|
||||
# check whether a command is available to this shell (may be either an
|
||||
--
|
||||
1.7.2.3
|
||||
|
94
0003-add-spice-into-the-configure-file.patch
Normal file
94
0003-add-spice-into-the-configure-file.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From 0034da7fb15d1225e0fd725009743d48511a90b7 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 24 Mar 2010 10:26:51 +0100
|
||||
Subject: [PATCH 03/39] add spice into the configure file
|
||||
|
||||
---
|
||||
configure | 36 ++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 36 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index e09c442..2aaa6d7 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -331,6 +331,7 @@ cpu_emulation="yes"
|
||||
check_utests="no"
|
||||
user_pie="no"
|
||||
zero_malloc=""
|
||||
+spice=""
|
||||
|
||||
# OS specific
|
||||
if check_define __linux__ ; then
|
||||
@@ -647,6 +648,10 @@ for opt do
|
||||
;;
|
||||
--enable-kvm-device-assignment) kvm_cap_device_assignment="yes"
|
||||
;;
|
||||
+ --disable-spice) spice="no"
|
||||
+ ;;
|
||||
+ --enable-spice) spice="yes"
|
||||
+ ;;
|
||||
--enable-profiler) profiler="yes"
|
||||
;;
|
||||
--enable-cocoa)
|
||||
@@ -933,6 +938,8 @@ echo " --enable-docs enable documentation build"
|
||||
echo " --disable-docs disable documentation build"
|
||||
echo " --disable-vhost-net disable vhost-net acceleration support"
|
||||
echo " --enable-vhost-net enable vhost-net acceleration support"
|
||||
+echo " --disable-spice disable spice"
|
||||
+echo " --enable-spice enable spice"
|
||||
echo ""
|
||||
echo "NOTE: The object files are built at the place where configure is launched"
|
||||
exit 1
|
||||
@@ -2184,6 +2191,30 @@ if compile_prog "" ""; then
|
||||
gcc_attribute_warn_unused_result=yes
|
||||
fi
|
||||
|
||||
+# spice probe
|
||||
+if test "$spice" != "no" ; then
|
||||
+ cat > $TMPC << EOF
|
||||
+#include <spice.h>
|
||||
+int main(void) { spice_server_new(); return 0; }
|
||||
+EOF
|
||||
+ spice_proto_ver=$($pkgconfig --modversion spice-protocol 2>/dev/null)
|
||||
+ spice_server_ver=$($pkgconfig --modversion spice-server 2>/dev/null)
|
||||
+ spice_cflags=$($pkgconfig --cflags spice-protocol spice-server 2>/dev/null)
|
||||
+ spice_libs=$($pkgconfig --libs spice-protocol spice-server 2>/dev/null)
|
||||
+ if compile_prog "$spice_cflags" "$spice_libs" ; then
|
||||
+ spice="yes"
|
||||
+ libs_softmmu="$libs_softmmu $spice_libs"
|
||||
+ QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
|
||||
+ else
|
||||
+ if test "$spice" = "yes" ; then
|
||||
+ feature_not_found "spice"
|
||||
+ fi
|
||||
+ spice="no"
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+##########################################
|
||||
+
|
||||
##########################################
|
||||
# check if we have fdatasync
|
||||
|
||||
@@ -2329,6 +2360,7 @@ echo "preadv support $preadv"
|
||||
echo "fdatasync $fdatasync"
|
||||
echo "uuid support $uuid"
|
||||
echo "vhost-net support $vhost_net"
|
||||
+echo "spice support $spice"
|
||||
|
||||
if test $sdl_too_old = "yes"; then
|
||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
|
||||
@@ -2574,6 +2606,10 @@ else
|
||||
echo "CONFIG_NO_CPU_EMULATION=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
+if test "$spice" = "yes" ; then
|
||||
+ echo "CONFIG_SPICE=y" >> $config_host_mak
|
||||
+fi
|
||||
+
|
||||
# XXX: suppress that
|
||||
if [ "$bsd" = "yes" ] ; then
|
||||
echo "CONFIG_BSD=y" >> $config_host_mak
|
||||
--
|
||||
1.7.2.3
|
||||
|
333
0004-spice-core-bits.patch
Normal file
333
0004-spice-core-bits.patch
Normal file
@ -0,0 +1,333 @@
|
||||
From 67361a4ad5c99c5dfecdb9d2fc1ba794c38c44ff Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:27 -0300
|
||||
Subject: [PATCH 04/39] spice: core bits
|
||||
|
||||
Add -spice command line switch. Has support setting passwd and port for
|
||||
now. With this patch applied the spice client can successfully connect
|
||||
to qemu. You can't do anything useful yet though.
|
||||
---
|
||||
Makefile.objs | 2 +
|
||||
qemu-config.c | 23 ++++++++
|
||||
qemu-config.h | 1 +
|
||||
qemu-options.hx | 8 +++
|
||||
qemu-spice.h | 22 ++++++++
|
||||
spice.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
vl.c | 15 ++++++
|
||||
7 files changed, 222 insertions(+), 0 deletions(-)
|
||||
create mode 100644 qemu-spice.h
|
||||
create mode 100644 spice.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 147051f..569b458 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -89,6 +89,8 @@ common-obj-y += pflib.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
|
||||
+common-obj-$(CONFIG_SPICE) += spice.o
|
||||
+
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
audio-obj-$(CONFIG_OSS) += ossaudio.o
|
||||
diff --git a/qemu-config.c b/qemu-config.c
|
||||
index 08ee553..8a894cf 100644
|
||||
--- a/qemu-config.c
|
||||
+++ b/qemu-config.c
|
||||
@@ -346,6 +346,26 @@ QemuOptsList qemu_cpudef_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_SPICE
|
||||
+QemuOptsList qemu_spice_opts = {
|
||||
+ .name = "spice",
|
||||
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
|
||||
+ .desc = {
|
||||
+ {
|
||||
+ .name = "port",
|
||||
+ .type = QEMU_OPT_NUMBER,
|
||||
+ },{
|
||||
+ .name = "password",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "disable-ticketing",
|
||||
+ .type = QEMU_OPT_BOOL,
|
||||
+ },
|
||||
+ { /* end if list */ }
|
||||
+ },
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
static QemuOptsList *vm_config_groups[] = {
|
||||
&qemu_drive_opts,
|
||||
&qemu_chardev_opts,
|
||||
@@ -356,6 +376,9 @@ static QemuOptsList *vm_config_groups[] = {
|
||||
&qemu_global_opts,
|
||||
&qemu_mon_opts,
|
||||
&qemu_cpudef_opts,
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ &qemu_spice_opts,
|
||||
+#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
diff --git a/qemu-config.h b/qemu-config.h
|
||||
index dca69d4..3a90213 100644
|
||||
--- a/qemu-config.h
|
||||
+++ b/qemu-config.h
|
||||
@@ -14,6 +14,7 @@ extern QemuOptsList qemu_rtc_opts;
|
||||
extern QemuOptsList qemu_global_opts;
|
||||
extern QemuOptsList qemu_mon_opts;
|
||||
extern QemuOptsList qemu_cpudef_opts;
|
||||
+extern QemuOptsList qemu_spice_opts;
|
||||
|
||||
QemuOptsList *qemu_find_opts(const char *group);
|
||||
int qemu_set_option(const char *str);
|
||||
diff --git a/qemu-options.hx b/qemu-options.hx
|
||||
index 66c84a0..85551cc 100644
|
||||
--- a/qemu-options.hx
|
||||
+++ b/qemu-options.hx
|
||||
@@ -676,6 +676,14 @@ STEXI
|
||||
Enable SDL.
|
||||
ETEXI
|
||||
|
||||
+#ifdef CONFIG_SPICE
|
||||
+DEF("spice", HAS_ARG, QEMU_OPTION_spice,
|
||||
+ "-spice <args> use spice\n", QEMU_ARCH_ALL)
|
||||
+STEXI
|
||||
+Use Spice.
|
||||
+ETEXI
|
||||
+#endif
|
||||
+
|
||||
DEF("portrait", 0, QEMU_OPTION_portrait,
|
||||
"-portrait rotate graphical output 90 deg left (only PXA LCD)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
new file mode 100644
|
||||
index 0000000..5597576
|
||||
--- /dev/null
|
||||
+++ b/qemu-spice.h
|
||||
@@ -0,0 +1,22 @@
|
||||
+#ifndef QEMU_SPICE_H
|
||||
+#define QEMU_SPICE_H
|
||||
+
|
||||
+#ifdef CONFIG_SPICE
|
||||
+
|
||||
+#include <spice.h>
|
||||
+
|
||||
+#include "qemu-option.h"
|
||||
+#include "qemu-config.h"
|
||||
+
|
||||
+extern SpiceServer *spice_server;
|
||||
+extern int using_spice;
|
||||
+
|
||||
+void qemu_spice_init(void);
|
||||
+
|
||||
+#else /* CONFIG_SPICE */
|
||||
+
|
||||
+#define using_spice 0
|
||||
+
|
||||
+#endif /* CONFIG_SPICE */
|
||||
+
|
||||
+#endif /* QEMU_SPICE_H */
|
||||
diff --git a/spice.c b/spice.c
|
||||
new file mode 100644
|
||||
index 0000000..50fa5ca
|
||||
--- /dev/null
|
||||
+++ b/spice.c
|
||||
@@ -0,0 +1,151 @@
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "qemu-queue.h"
|
||||
+#include "monitor.h"
|
||||
+
|
||||
+/* core bits */
|
||||
+
|
||||
+SpiceServer *spice_server;
|
||||
+int using_spice = 0;
|
||||
+
|
||||
+struct SpiceTimer {
|
||||
+ QEMUTimer *timer;
|
||||
+ QTAILQ_ENTRY(SpiceTimer) next;
|
||||
+};
|
||||
+static QTAILQ_HEAD(, SpiceTimer) timers = QTAILQ_HEAD_INITIALIZER(timers);
|
||||
+
|
||||
+static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque)
|
||||
+{
|
||||
+ SpiceTimer *timer;
|
||||
+
|
||||
+ timer = qemu_mallocz(sizeof(*timer));
|
||||
+ timer->timer = qemu_new_timer(rt_clock, func, opaque);
|
||||
+ QTAILQ_INSERT_TAIL(&timers, timer, next);
|
||||
+ return timer;
|
||||
+}
|
||||
+
|
||||
+static void timer_start(SpiceTimer *timer, uint32_t ms)
|
||||
+{
|
||||
+ qemu_mod_timer(timer->timer, qemu_get_clock(rt_clock) + ms);
|
||||
+}
|
||||
+
|
||||
+static void timer_cancel(SpiceTimer *timer)
|
||||
+{
|
||||
+ qemu_del_timer(timer->timer);
|
||||
+}
|
||||
+
|
||||
+static void timer_remove(SpiceTimer *timer)
|
||||
+{
|
||||
+ qemu_del_timer(timer->timer);
|
||||
+ qemu_free_timer(timer->timer);
|
||||
+ QTAILQ_REMOVE(&timers, timer, next);
|
||||
+ free(timer);
|
||||
+}
|
||||
+
|
||||
+struct SpiceWatch {
|
||||
+ int fd;
|
||||
+ int event_mask;
|
||||
+ SpiceWatchFunc func;
|
||||
+ void *opaque;
|
||||
+ QTAILQ_ENTRY(SpiceWatch) next;
|
||||
+};
|
||||
+static QTAILQ_HEAD(, SpiceWatch) watches = QTAILQ_HEAD_INITIALIZER(watches);
|
||||
+
|
||||
+static void watch_read(void *opaque)
|
||||
+{
|
||||
+ SpiceWatch *watch = opaque;
|
||||
+ watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
|
||||
+}
|
||||
+
|
||||
+static void watch_write(void *opaque)
|
||||
+{
|
||||
+ SpiceWatch *watch = opaque;
|
||||
+ watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
|
||||
+}
|
||||
+
|
||||
+static void watch_update_mask(SpiceWatch *watch, int event_mask)
|
||||
+{
|
||||
+ IOHandler *on_read = NULL;
|
||||
+ IOHandler *on_write = NULL;
|
||||
+
|
||||
+ watch->event_mask = event_mask;
|
||||
+ if (watch->event_mask & SPICE_WATCH_EVENT_READ)
|
||||
+ on_read = watch_read;
|
||||
+ if (watch->event_mask & SPICE_WATCH_EVENT_WRITE)
|
||||
+ on_read = watch_write;
|
||||
+ qemu_set_fd_handler(watch->fd, on_read, on_write, watch);
|
||||
+}
|
||||
+
|
||||
+static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
|
||||
+{
|
||||
+ SpiceWatch *watch;
|
||||
+
|
||||
+ watch = qemu_mallocz(sizeof(*watch));
|
||||
+ watch->fd = fd;
|
||||
+ watch->func = func;
|
||||
+ watch->opaque = opaque;
|
||||
+ QTAILQ_INSERT_TAIL(&watches, watch, next);
|
||||
+
|
||||
+ watch_update_mask(watch, event_mask);
|
||||
+ return watch;
|
||||
+}
|
||||
+
|
||||
+static void watch_remove(SpiceWatch *watch)
|
||||
+{
|
||||
+ watch_update_mask(watch, 0);
|
||||
+ QTAILQ_REMOVE(&watches, watch, next);
|
||||
+ qemu_free(watch);
|
||||
+}
|
||||
+
|
||||
+static SpiceCoreInterface core_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_CORE,
|
||||
+ .base.description = "qemu core services",
|
||||
+ .base.major_version = SPICE_INTERFACE_CORE_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_CORE_MINOR,
|
||||
+
|
||||
+ .timer_add = timer_add,
|
||||
+ .timer_start = timer_start,
|
||||
+ .timer_cancel = timer_cancel,
|
||||
+ .timer_remove = timer_remove,
|
||||
+
|
||||
+ .watch_add = watch_add,
|
||||
+ .watch_update_mask = watch_update_mask,
|
||||
+ .watch_remove = watch_remove,
|
||||
+};
|
||||
+
|
||||
+/* functions for the rest of qemu */
|
||||
+
|
||||
+void qemu_spice_init(void)
|
||||
+{
|
||||
+ QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
+ const char *password;
|
||||
+ int port;
|
||||
+
|
||||
+ if (!opts)
|
||||
+ return;
|
||||
+ port = qemu_opt_get_number(opts, "port", 0);
|
||||
+ if (!port)
|
||||
+ return;
|
||||
+ password = qemu_opt_get(opts, "password");
|
||||
+
|
||||
+ spice_server = spice_server_new();
|
||||
+ spice_server_set_port(spice_server, port);
|
||||
+ if (password)
|
||||
+ spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
||||
+ if (qemu_opt_get_bool(opts, "disable-ticketing", 0))
|
||||
+ spice_server_set_noauth(spice_server);
|
||||
+
|
||||
+ /* TODO: make configurable via cmdline */
|
||||
+ spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
+
|
||||
+ spice_server_init(spice_server, &core_interface);
|
||||
+ using_spice = 1;
|
||||
+}
|
||||
diff --git a/vl.c b/vl.c
|
||||
index de8bad1..97897e0 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -162,6 +162,8 @@ int main(int argc, char **argv)
|
||||
#include "cpus.h"
|
||||
#include "arch_init.h"
|
||||
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
//#define DEBUG_NET
|
||||
//#define DEBUG_SLIRP
|
||||
|
||||
@@ -2677,6 +2679,15 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
break;
|
||||
}
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ case QEMU_OPTION_spice:
|
||||
+ opts = qemu_opts_parse(&qemu_spice_opts, optarg, 0);
|
||||
+ if (!opts) {
|
||||
+ fprintf(stderr, "parse error: %s\n", optarg);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ break;
|
||||
+#endif
|
||||
case QEMU_OPTION_writeconfig:
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -2951,6 +2962,10 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
qemu_add_globals();
|
||||
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ qemu_spice_init();
|
||||
+#endif
|
||||
+
|
||||
machine->init(ram_size, boot_devices,
|
||||
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
118
0005-spice-add-keyboard.patch
Normal file
118
0005-spice-add-keyboard.patch
Normal file
@ -0,0 +1,118 @@
|
||||
From 90f6ec84332857752c252b1c3b89d86eb9714b0e Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:28 -0300
|
||||
Subject: [PATCH 05/39] spice: add keyboard
|
||||
|
||||
Open keyboard channel. Now you can type into the spice client and the
|
||||
keyboard events are sent to your guest. You'll need some other display
|
||||
like vnc to actually see the guest responding to them though.
|
||||
---
|
||||
Makefile.objs | 2 +-
|
||||
qemu-spice.h | 1 +
|
||||
spice-input.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
spice.c | 2 ++
|
||||
4 files changed, 61 insertions(+), 1 deletions(-)
|
||||
create mode 100644 spice-input.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 569b458..023a0dc 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -89,7 +89,7 @@ common-obj-y += pflib.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
|
||||
-common-obj-$(CONFIG_SPICE) += spice.o
|
||||
+common-obj-$(CONFIG_SPICE) += spice.o spice-input.o
|
||||
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index 5597576..ceb3db2 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -12,6 +12,7 @@ extern SpiceServer *spice_server;
|
||||
extern int using_spice;
|
||||
|
||||
void qemu_spice_init(void);
|
||||
+void qemu_spice_input_init(void);
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
diff --git a/spice-input.c b/spice-input.c
|
||||
new file mode 100644
|
||||
index 0000000..e1014d7
|
||||
--- /dev/null
|
||||
+++ b/spice-input.c
|
||||
@@ -0,0 +1,57 @@
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <spice.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "console.h"
|
||||
+
|
||||
+/* keyboard bits */
|
||||
+
|
||||
+typedef struct QemuSpiceKbd {
|
||||
+ SpiceKbdInstance sin;
|
||||
+ int ledstate;
|
||||
+} QemuSpiceKbd;
|
||||
+
|
||||
+static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag);
|
||||
+static uint8_t kbd_get_leds(SpiceKbdInstance *sin);
|
||||
+static void kbd_leds(void *opaque, int l);
|
||||
+
|
||||
+static const SpiceKbdInterface kbd_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_KEYBOARD,
|
||||
+ .base.description = "qemu keyboard",
|
||||
+ .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
|
||||
+ .push_scan_freg = kbd_push_key,
|
||||
+ .get_leds = kbd_get_leds,
|
||||
+};
|
||||
+
|
||||
+static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
||||
+{
|
||||
+ kbd_put_keycode(frag);
|
||||
+}
|
||||
+
|
||||
+static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
|
||||
+{
|
||||
+ QemuSpiceKbd *kbd = container_of(sin, QemuSpiceKbd, sin);
|
||||
+ return kbd->ledstate;
|
||||
+}
|
||||
+
|
||||
+static void kbd_leds(void *opaque, int ledstate)
|
||||
+{
|
||||
+ QemuSpiceKbd *kbd = opaque;
|
||||
+ kbd->ledstate = ledstate;
|
||||
+ spice_server_kbd_leds(&kbd->sin, ledstate);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_input_init(void)
|
||||
+{
|
||||
+ QemuSpiceKbd *kbd;
|
||||
+
|
||||
+ kbd = qemu_mallocz(sizeof(*kbd));
|
||||
+ kbd->sin.base.sif = &kbd_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &kbd->sin.base);
|
||||
+ qemu_add_led_event_handler(kbd_leds, kbd);
|
||||
+}
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 50fa5ca..c763d52 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -148,4 +148,6 @@ void qemu_spice_init(void)
|
||||
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
+
|
||||
+ qemu_spice_input_init();
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
62
0006-spice-add-mouse.patch
Normal file
62
0006-spice-add-mouse.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From e18846175191cbc590ac46fa3820726aeebd6d48 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:29 -0300
|
||||
Subject: [PATCH 06/39] spice: add mouse
|
||||
|
||||
Open mouse channel. Now you can move the guests mouse pointer.
|
||||
No tablet / absolute positioning (yet) though.
|
||||
---
|
||||
spice-input.c | 31 +++++++++++++++++++++++++++++++
|
||||
1 files changed, 31 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/spice-input.c b/spice-input.c
|
||||
index e1014d7..8f3deb4 100644
|
||||
--- a/spice-input.c
|
||||
+++ b/spice-input.c
|
||||
@@ -46,12 +46,43 @@ static void kbd_leds(void *opaque, int ledstate)
|
||||
spice_server_kbd_leds(&kbd->sin, ledstate);
|
||||
}
|
||||
|
||||
+/* mouse bits */
|
||||
+
|
||||
+typedef struct QemuSpiceMouse {
|
||||
+ SpiceMouseInstance sin;
|
||||
+} QemuSpiceMouse;
|
||||
+
|
||||
+static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ kbd_mouse_event(dx, dy, dz, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state)
|
||||
+{
|
||||
+ kbd_mouse_event(0, 0, 0, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static const SpiceMouseInterface mouse_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_MOUSE,
|
||||
+ .base.description = "mouse",
|
||||
+ .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR,
|
||||
+ .motion = mouse_motion,
|
||||
+ .buttons = mouse_buttons,
|
||||
+};
|
||||
+
|
||||
void qemu_spice_input_init(void)
|
||||
{
|
||||
QemuSpiceKbd *kbd;
|
||||
+ QemuSpiceMouse *mouse;
|
||||
|
||||
kbd = qemu_mallocz(sizeof(*kbd));
|
||||
kbd->sin.base.sif = &kbd_interface.base;
|
||||
spice_server_add_interface(spice_server, &kbd->sin.base);
|
||||
qemu_add_led_event_handler(kbd_leds, kbd);
|
||||
+
|
||||
+ mouse = qemu_mallocz(sizeof(*mouse));
|
||||
+ mouse->sin.base.sif = &mouse_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &mouse->sin.base);
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
532
0007-spice-simple-display.patch
Normal file
532
0007-spice-simple-display.patch
Normal file
@ -0,0 +1,532 @@
|
||||
From 0143117eb5e6233fdeff3b679492b51148cc8f85 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 24 Mar 2010 15:47:18 +0100
|
||||
Subject: [PATCH 07/39] spice: simple display
|
||||
|
||||
With that patch applied you'll actually see the guests screen in the
|
||||
spice client. This does *not* bring qxl and full spice support though.
|
||||
This is basically the qxl vga mode made more generic, so it plays
|
||||
together with any qemu-emulated gfx card. You can display stdvga or
|
||||
cirrus via spice client. You can have both vnc and spice enabled and
|
||||
clients connected at the same time.
|
||||
---
|
||||
Makefile.objs | 2 +-
|
||||
qemu-spice.h | 1 +
|
||||
spice-display.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
spice-display.h | 52 ++++++++
|
||||
vl.c | 7 +-
|
||||
5 files changed, 454 insertions(+), 2 deletions(-)
|
||||
create mode 100644 spice-display.c
|
||||
create mode 100644 spice-display.h
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 023a0dc..d05643f 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -89,7 +89,7 @@ common-obj-y += pflib.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
|
||||
-common-obj-$(CONFIG_SPICE) += spice.o spice-input.o
|
||||
+common-obj-$(CONFIG_SPICE) += spice.o spice-input.o spice-display.o
|
||||
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index ceb3db2..f061004 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -13,6 +13,7 @@ extern int using_spice;
|
||||
|
||||
void qemu_spice_init(void);
|
||||
void qemu_spice_input_init(void);
|
||||
+void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
new file mode 100644
|
||||
index 0000000..13a620e
|
||||
--- /dev/null
|
||||
+++ b/spice-display.c
|
||||
@@ -0,0 +1,394 @@
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+#include <pthread.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "qemu-queue.h"
|
||||
+#include "monitor.h"
|
||||
+#include "console.h"
|
||||
+#include "sysemu.h"
|
||||
+
|
||||
+#include "spice-display.h"
|
||||
+
|
||||
+static int debug = 1;
|
||||
+
|
||||
+int qemu_spice_rect_is_empty(const QXLRect* r)
|
||||
+{
|
||||
+ return r->top == r->bottom || r->left == r->right;
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
|
||||
+{
|
||||
+ if (qemu_spice_rect_is_empty(r)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (qemu_spice_rect_is_empty(dest)) {
|
||||
+ *dest = *r;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dest->top = MIN(dest->top, r->top);
|
||||
+ dest->left = MIN(dest->left, r->left);
|
||||
+ dest->bottom = MAX(dest->bottom, r->bottom);
|
||||
+ dest->right = MAX(dest->right, r->right);
|
||||
+}
|
||||
+
|
||||
+SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ SimpleSpiceUpdate *update;
|
||||
+ QXLDrawable *drawable;
|
||||
+ QXLImage *image;
|
||||
+ QXLCommand *cmd;
|
||||
+ uint8_t *src, *dst;
|
||||
+ int by, bw, bh;
|
||||
+
|
||||
+ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
|
||||
+ return NULL;
|
||||
+ };
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__,
|
||||
+ ssd->dirty.left, ssd->dirty.right,
|
||||
+ ssd->dirty.top, ssd->dirty.bottom);
|
||||
+
|
||||
+ update = qemu_mallocz(sizeof(*update));
|
||||
+ drawable = &update->drawable;
|
||||
+ image = &update->image;
|
||||
+ cmd = &update->ext.cmd;
|
||||
+
|
||||
+ bw = ssd->dirty.right - ssd->dirty.left;
|
||||
+ bh = ssd->dirty.bottom - ssd->dirty.top;
|
||||
+ update->bitmap = qemu_malloc(bw * bh * 4);
|
||||
+
|
||||
+ drawable->bbox = ssd->dirty;
|
||||
+ drawable->clip.type = SPICE_CLIP_TYPE_NONE;
|
||||
+ drawable->effect = QXL_EFFECT_OPAQUE;
|
||||
+ drawable->release_info.id = (intptr_t)update;
|
||||
+ drawable->type = QXL_DRAW_COPY;
|
||||
+
|
||||
+ drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
|
||||
+ drawable->u.copy.src_bitmap = (intptr_t)image;
|
||||
+ drawable->u.copy.src_area.right = bw;
|
||||
+ drawable->u.copy.src_area.bottom = bh;
|
||||
+
|
||||
+ QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++);
|
||||
+ image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
|
||||
+ image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
|
||||
+ image->bitmap.stride = bw * 4;
|
||||
+ image->descriptor.width = image->bitmap.x = bw;
|
||||
+ image->descriptor.height = image->bitmap.y = bh;
|
||||
+ image->bitmap.data = (intptr_t)(update->bitmap);
|
||||
+ image->bitmap.palette = 0;
|
||||
+ image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
|
||||
+
|
||||
+ if (ssd->conv == NULL) {
|
||||
+ PixelFormat dst = qemu_default_pixelformat(32);
|
||||
+ ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf);
|
||||
+ assert(ssd->conv);
|
||||
+ }
|
||||
+
|
||||
+ src = ds_get_data(ssd->ds) +
|
||||
+ ssd->dirty.top * ds_get_linesize(ssd->ds) +
|
||||
+ ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds);
|
||||
+ dst = update->bitmap;
|
||||
+ for (by = 0; by < bh; by++) {
|
||||
+ qemu_pf_conv_run(ssd->conv, dst, src, bw);
|
||||
+ src += ds_get_linesize(ssd->ds);
|
||||
+ dst += image->bitmap.stride;
|
||||
+ }
|
||||
+
|
||||
+ cmd->type = QXL_CMD_DRAW;
|
||||
+ cmd->data = (intptr_t)drawable;
|
||||
+
|
||||
+ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+ return update;
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update)
|
||||
+{
|
||||
+ qemu_free(update->bitmap);
|
||||
+ qemu_free(update);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ QXLDevMemSlot memslot;
|
||||
+
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+
|
||||
+ memset(&memslot, 0, sizeof(memslot));
|
||||
+ memslot.slot_group_id = MEMSLOT_GROUP_HOST;
|
||||
+ memslot.virt_end = ~0;
|
||||
+ ssd->worker->add_memslot(ssd->worker, &memslot);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ QXLDevSurfaceCreate surface;
|
||||
+
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s: %dx%d\n", __FUNCTION__,
|
||||
+ ds_get_width(ssd->ds), ds_get_height(ssd->ds));
|
||||
+
|
||||
+ surface.format = SPICE_SURFACE_FMT_32_xRGB;
|
||||
+ surface.width = ds_get_width(ssd->ds);
|
||||
+ surface.height = ds_get_height(ssd->ds);
|
||||
+ surface.stride = -surface.width * 4;
|
||||
+ surface.mouse_mode = 0;
|
||||
+ surface.flags = 0;
|
||||
+ surface.type = 0;
|
||||
+ surface.mem = (intptr_t)ssd->buf;
|
||||
+ surface.group_id = MEMSLOT_GROUP_HOST;
|
||||
+ ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+
|
||||
+ ssd->worker->destroy_primary_surface(ssd->worker, 0);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = opaque;
|
||||
+
|
||||
+ if (running) {
|
||||
+ ssd->worker->start(ssd->worker);
|
||||
+ } else {
|
||||
+ ssd->worker->stop(ssd->worker);
|
||||
+ }
|
||||
+ ssd->running = running;
|
||||
+}
|
||||
+
|
||||
+/* display listener callbacks */
|
||||
+
|
||||
+void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
|
||||
+ int x, int y, int w, int h)
|
||||
+{
|
||||
+ QXLRect update_area;
|
||||
+
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s: x %d y %d w %d h %d\n", __FUNCTION__, x, y, w, h);
|
||||
+ update_area.left = x,
|
||||
+ update_area.right = x + w;
|
||||
+ update_area.top = y;
|
||||
+ update_area.bottom = y + h;
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
|
||||
+ ssd->notify++;
|
||||
+ }
|
||||
+ qemu_spice_rect_union(&ssd->dirty, &update_area);
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+
|
||||
+ qemu_spice_destroy_host_primary(ssd);
|
||||
+ qemu_spice_create_host_primary(ssd);
|
||||
+ qemu_pf_conv_put(ssd->conv);
|
||||
+ ssd->conv = NULL;
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ ssd->dirty.left = 0;
|
||||
+ ssd->dirty.right = ds_get_width(ssd->ds);
|
||||
+ ssd->dirty.top = 0;
|
||||
+ ssd->dirty.bottom = ds_get_height(ssd->ds);
|
||||
+ ssd->notify++;
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ vga_hw_update();
|
||||
+ if (ssd->notify) {
|
||||
+ ssd->notify = 0;
|
||||
+ ssd->worker->wakeup(ssd->worker);
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s: notify\n", __FUNCTION__);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* spice display interface callbacks */
|
||||
+
|
||||
+static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ ssd->worker = qxl_worker;
|
||||
+}
|
||||
+
|
||||
+static void interface_set_compression_level(QXLInstance *sin, int level)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ /* nothing to do */
|
||||
+}
|
||||
+
|
||||
+static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
+{
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ /* nothing to do */
|
||||
+}
|
||||
+
|
||||
+static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+
|
||||
+ info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
|
||||
+ info->memslot_id_bits = MEMSLOT_SLOT_BITS;
|
||||
+ info->num_memslots = NUM_MEMSLOTS;
|
||||
+ info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
|
||||
+ info->internal_groupslot_id = 0;
|
||||
+ info->qxl_ram_size = ssd->bufsize;
|
||||
+ info->n_surfaces = NUM_SURFACES;
|
||||
+}
|
||||
+
|
||||
+static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+ SimpleSpiceUpdate *update;
|
||||
+
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ update = qemu_spice_create_update(ssd);
|
||||
+ if (update == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ *ext = update->ext;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int interface_req_cmd_notification(QXLInstance *sin)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void interface_release_resource(QXLInstance *sin,
|
||||
+ struct QXLReleaseInfoExt ext)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+ uintptr_t id;
|
||||
+
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ id = ext.info->id;
|
||||
+ qemu_spice_destroy_update(ssd, (void*)id);
|
||||
+}
|
||||
+
|
||||
+static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
||||
+{
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static int interface_req_cursor_notification(QXLInstance *sin)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
|
||||
+{
|
||||
+ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
|
||||
+ abort();
|
||||
+}
|
||||
+
|
||||
+static int interface_flush_resources(QXLInstance *sin)
|
||||
+{
|
||||
+ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
|
||||
+ abort();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const QXLInterface dpy_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_QXL,
|
||||
+ .base.description = "qemu simple display",
|
||||
+ .base.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_QXL_MINOR,
|
||||
+
|
||||
+ .pci_vendor = REDHAT_PCI_VENDOR_ID,
|
||||
+ .pci_id = QXL_DEVICE_ID,
|
||||
+ .pci_revision = QXL_REVISION,
|
||||
+
|
||||
+ .attache_worker = interface_attach_worker,
|
||||
+ .set_compression_level = interface_set_compression_level,
|
||||
+ .set_mm_time = interface_set_mm_time,
|
||||
+
|
||||
+ .get_init_info = interface_get_init_info,
|
||||
+ .get_command = interface_get_command,
|
||||
+ .req_cmd_notification = interface_req_cmd_notification,
|
||||
+ .release_resource = interface_release_resource,
|
||||
+ .get_cursor_command = interface_get_cursor_command,
|
||||
+ .req_cursor_notification = interface_req_cursor_notification,
|
||||
+ .notify_update = interface_notify_update,
|
||||
+ .flush_resources = interface_flush_resources,
|
||||
+};
|
||||
+
|
||||
+static SimpleSpiceDisplay sdpy;
|
||||
+
|
||||
+static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
|
||||
+{
|
||||
+ qemu_spice_display_update(&sdpy, x, y, w, h);
|
||||
+}
|
||||
+
|
||||
+static void display_resize(struct DisplayState *ds)
|
||||
+{
|
||||
+ qemu_spice_display_resize(&sdpy);
|
||||
+}
|
||||
+
|
||||
+static void display_refresh(struct DisplayState *ds)
|
||||
+{
|
||||
+ qemu_spice_display_refresh(&sdpy);
|
||||
+}
|
||||
+
|
||||
+static DisplayChangeListener display_listener = {
|
||||
+ .dpy_update = display_update,
|
||||
+ .dpy_resize = display_resize,
|
||||
+ .dpy_refresh = display_refresh,
|
||||
+};
|
||||
+
|
||||
+void qemu_spice_display_init(DisplayState *ds)
|
||||
+{
|
||||
+ assert(sdpy.ds == NULL);
|
||||
+ sdpy.ds = ds;
|
||||
+ sdpy.bufsize = (16 * 1024 * 1024);
|
||||
+ sdpy.buf = qemu_malloc(sdpy.bufsize);
|
||||
+ pthread_mutex_init(&sdpy.lock, NULL);
|
||||
+ register_displaychangelistener(ds, &display_listener);
|
||||
+
|
||||
+ sdpy.qxl.base.sif = &dpy_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &sdpy.qxl.base);
|
||||
+ assert(sdpy.worker);
|
||||
+
|
||||
+ qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy);
|
||||
+ qemu_spice_create_host_memslot(&sdpy);
|
||||
+ qemu_spice_create_host_primary(&sdpy);
|
||||
+}
|
||||
diff --git a/spice-display.h b/spice-display.h
|
||||
new file mode 100644
|
||||
index 0000000..70a7be4
|
||||
--- /dev/null
|
||||
+++ b/spice-display.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+#include <spice/ipc_ring.h>
|
||||
+#include <spice/draw.h>
|
||||
+#include <spice/qxl_dev.h>
|
||||
+
|
||||
+#include "pflib.h"
|
||||
+
|
||||
+#define NUM_MEMSLOTS 8
|
||||
+#define MEMSLOT_GENERATION_BITS 8
|
||||
+#define MEMSLOT_SLOT_BITS 8
|
||||
+
|
||||
+#define MEMSLOT_GROUP_HOST 0
|
||||
+#define MEMSLOT_GROUP_GUEST 1
|
||||
+#define NUM_MEMSLOTS_GROUPS 2
|
||||
+
|
||||
+#define NUM_SURFACES 1024
|
||||
+
|
||||
+typedef struct SimpleSpiceDisplay {
|
||||
+ DisplayState *ds;
|
||||
+ void *buf;
|
||||
+ int bufsize;
|
||||
+ QXLWorker *worker;
|
||||
+ QXLInstance qxl;
|
||||
+ uint32_t unique;
|
||||
+ QemuPfConv *conv;
|
||||
+
|
||||
+ pthread_mutex_t lock;
|
||||
+ QXLRect dirty;
|
||||
+ int notify;
|
||||
+ int running;
|
||||
+} SimpleSpiceDisplay;
|
||||
+
|
||||
+typedef struct SimpleSpiceUpdate {
|
||||
+ QXLDrawable drawable;
|
||||
+ QXLImage image;
|
||||
+ QXLCommandExt ext;
|
||||
+ uint8_t *bitmap;
|
||||
+} SimpleSpiceUpdate;
|
||||
+
|
||||
+int qemu_spice_rect_is_empty(const QXLRect* r);
|
||||
+void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);
|
||||
+
|
||||
+SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *sdpy);
|
||||
+void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update);
|
||||
+void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason);
|
||||
+
|
||||
+void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
|
||||
+ int x, int y, int w, int h);
|
||||
+void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
|
||||
diff --git a/vl.c b/vl.c
|
||||
index 97897e0..2ccebc8 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -2993,7 +2993,7 @@ int main(int argc, char **argv, char **envp)
|
||||
/* just use the first displaystate for the moment */
|
||||
ds = get_displaystate();
|
||||
|
||||
- if (display_type == DT_DEFAULT) {
|
||||
+ if (display_type == DT_DEFAULT && !using_spice) {
|
||||
#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
|
||||
display_type = DT_SDL;
|
||||
#else
|
||||
@@ -3033,6 +3033,11 @@ int main(int argc, char **argv, char **envp)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ if (using_spice) {
|
||||
+ qemu_spice_display_init(ds);
|
||||
+ }
|
||||
+#endif
|
||||
dpy_resize(ds);
|
||||
|
||||
dcl = ds->listeners;
|
||||
--
|
||||
1.7.2.3
|
||||
|
160
0008-spice-add-tablet-support.patch
Normal file
160
0008-spice-add-tablet-support.patch
Normal file
@ -0,0 +1,160 @@
|
||||
From e3c6e18e27f0d598b37e9be1795dbcb42f740071 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 13 Apr 2010 09:05:03 +0200
|
||||
Subject: [PATCH 08/39] spice: add tablet support
|
||||
|
||||
Add support for the spice tablet interface. The tablet interface will
|
||||
be registered (and then used by the spice client) as soon as a absolute
|
||||
pointing device is available and used by the guest, i.e. you'll have to
|
||||
configure your guest with '-usbdevice tablet'.
|
||||
---
|
||||
spice-display.c | 2 +-
|
||||
spice-input.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 93 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
index 13a620e..a749e64 100644
|
||||
--- a/spice-display.c
|
||||
+++ b/spice-display.c
|
||||
@@ -143,7 +143,7 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
|
||||
surface.width = ds_get_width(ssd->ds);
|
||||
surface.height = ds_get_height(ssd->ds);
|
||||
surface.stride = -surface.width * 4;
|
||||
- surface.mouse_mode = 0;
|
||||
+ surface.mouse_mode = true;
|
||||
surface.flags = 0;
|
||||
surface.type = 0;
|
||||
surface.mem = (intptr_t)ssd->buf;
|
||||
diff --git a/spice-input.c b/spice-input.c
|
||||
index 8f3deb4..5646ff9 100644
|
||||
--- a/spice-input.c
|
||||
+++ b/spice-input.c
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
+#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <spice.h>
|
||||
@@ -48,9 +49,13 @@ static void kbd_leds(void *opaque, int ledstate)
|
||||
|
||||
/* mouse bits */
|
||||
|
||||
-typedef struct QemuSpiceMouse {
|
||||
- SpiceMouseInstance sin;
|
||||
-} QemuSpiceMouse;
|
||||
+typedef struct QemuSpicePointer {
|
||||
+ SpiceMouseInstance mouse;
|
||||
+ SpiceTabletInstance tablet;
|
||||
+ int width, height, x, y;
|
||||
+ Notifier mouse_mode;
|
||||
+ bool absolute;
|
||||
+} QemuSpicePointer;
|
||||
|
||||
static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
|
||||
uint32_t buttons_state)
|
||||
@@ -72,17 +77,97 @@ static const SpiceMouseInterface mouse_interface = {
|
||||
.buttons = mouse_buttons,
|
||||
};
|
||||
|
||||
+static void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ fprintf(stderr, "%s: %dx%d\n", __FUNCTION__, width, height);
|
||||
+ if (height < 16)
|
||||
+ height = 16;
|
||||
+ if (width < 16)
|
||||
+ width = 16;
|
||||
+ pointer->width = width;
|
||||
+ pointer->height = height;
|
||||
+}
|
||||
+
|
||||
+static void tablet_position(SpiceTabletInstance* sin, int x, int y,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ pointer->x = x * 0x7FFF / (pointer->width - 1);
|
||||
+ pointer->y = y * 0x7FFF / (pointer->height - 1);
|
||||
+ kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void tablet_wheel(SpiceTabletInstance* sin, int wheel,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ kbd_mouse_event(pointer->x, pointer->y, wheel, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static void tablet_buttons(SpiceTabletInstance *sin,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static const SpiceTabletInterface tablet_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_TABLET,
|
||||
+ .base.description = "tablet",
|
||||
+ .base.major_version = SPICE_INTERFACE_TABLET_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_TABLET_MINOR,
|
||||
+ .set_logical_size = tablet_set_logical_size,
|
||||
+ .position = tablet_position,
|
||||
+ .wheel = tablet_wheel,
|
||||
+ .buttons = tablet_buttons,
|
||||
+};
|
||||
+
|
||||
+static void mouse_mode_notifier(Notifier *notifier)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode);
|
||||
+ bool is_absolute = kbd_mouse_is_absolute();
|
||||
+ bool has_absolute = kbd_mouse_has_absolute();
|
||||
+
|
||||
+ fprintf(stderr, "%s: absolute pointer: %s%s\n", __FUNCTION__,
|
||||
+ has_absolute ? "present" : "not available",
|
||||
+ is_absolute ? "+active" : "");
|
||||
+
|
||||
+ if (pointer->absolute == is_absolute)
|
||||
+ return;
|
||||
+
|
||||
+ if (is_absolute) {
|
||||
+ fprintf(stderr, "%s: using absolute pointer (client mode)\n", __FUNCTION__);
|
||||
+ spice_server_add_interface(spice_server, &pointer->tablet.base);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "%s: using relative pointer (server mode)\n", __FUNCTION__);
|
||||
+ spice_server_remove_interface(&pointer->tablet.base);
|
||||
+ }
|
||||
+ pointer->absolute = is_absolute;
|
||||
+}
|
||||
+
|
||||
void qemu_spice_input_init(void)
|
||||
{
|
||||
QemuSpiceKbd *kbd;
|
||||
- QemuSpiceMouse *mouse;
|
||||
+ QemuSpicePointer *pointer;
|
||||
|
||||
kbd = qemu_mallocz(sizeof(*kbd));
|
||||
kbd->sin.base.sif = &kbd_interface.base;
|
||||
spice_server_add_interface(spice_server, &kbd->sin.base);
|
||||
qemu_add_led_event_handler(kbd_leds, kbd);
|
||||
|
||||
- mouse = qemu_mallocz(sizeof(*mouse));
|
||||
- mouse->sin.base.sif = &mouse_interface.base;
|
||||
- spice_server_add_interface(spice_server, &mouse->sin.base);
|
||||
+ pointer = qemu_mallocz(sizeof(*pointer));
|
||||
+ pointer->mouse.base.sif = &mouse_interface.base;
|
||||
+ pointer->tablet.base.sif = &tablet_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &pointer->mouse.base);
|
||||
+
|
||||
+ pointer->absolute = false;
|
||||
+ pointer->mouse_mode.notify = mouse_mode_notifier;
|
||||
+ qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode);
|
||||
+ mouse_mode_notifier(&pointer->mouse_mode);
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
28
0009-vgabios-update-to-0.6c-pcibios-patches.patch
Normal file
28
0009-vgabios-update-to-0.6c-pcibios-patches.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 0920337756cdf82dcd585efb23ae18f8086696c8 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 24 Mar 2010 11:16:54 +0100
|
||||
Subject: [PATCH 09/39] vgabios update to 0.6c + pcibios patches.
|
||||
|
||||
---
|
||||
Makefile | 5 +++--
|
||||
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 3cd07e0..e40c9a2 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -154,8 +154,9 @@ ar de en-us fi fr-be hr it lv nl pl ru th \
|
||||
common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
|
||||
|
||||
ifdef INSTALL_BLOBS
|
||||
-BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
|
||||
-video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
|
||||
+BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
+vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-qxldev.bin \
|
||||
+ppc_rom.bin video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
|
||||
gpxe-eepro100-80861209.rom \
|
||||
gpxe-eepro100-80861229.rom \
|
||||
pxe-e1000.bin \
|
||||
--
|
||||
1.7.2.3
|
||||
|
31
0010-switch-stdvga-to-pci-vgabios.patch
Normal file
31
0010-switch-stdvga-to-pci-vgabios.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 6ac04dff1ee3932d2ef94c1e42f4e8208fbf92bf Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 6 May 2010 11:13:11 +0200
|
||||
Subject: [PATCH 10/39] switch stdvga to pci vgabios
|
||||
|
||||
---
|
||||
hw/vga-pci.c | 7 +++----
|
||||
1 files changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
|
||||
index 3907871..8e1ed35 100644
|
||||
--- a/hw/vga-pci.c
|
||||
+++ b/hw/vga-pci.c
|
||||
@@ -105,11 +105,10 @@ static int pci_vga_initfn(PCIDevice *dev)
|
||||
bios_total_size <<= 1;
|
||||
pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
|
||||
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
|
||||
+ } else {
|
||||
+ if (dev->romfile == NULL)
|
||||
+ dev->romfile = qemu_strdup("vgabios-stdvga.bin");
|
||||
}
|
||||
-
|
||||
- vga_init_vbe(s);
|
||||
- /* ROM BIOS */
|
||||
- rom_add_vga(VGABIOS_FILENAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
50
0011-switch-vmware_vga-to-pci-vgabios.patch
Normal file
50
0011-switch-vmware_vga-to-pci-vgabios.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 07cdc867f1e12a4e8b4096e7f1f3ffda2f4e7d02 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 6 May 2010 11:14:11 +0200
|
||||
Subject: [PATCH 11/39] switch vmware_vga to pci vgabios
|
||||
|
||||
---
|
||||
hw/vmware_vga.c | 7 +------
|
||||
1 files changed, 1 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
|
||||
index 12bff48..682f287 100644
|
||||
--- a/hw/vmware_vga.c
|
||||
+++ b/hw/vmware_vga.c
|
||||
@@ -114,14 +114,12 @@ struct pci_vmsvga_state_s {
|
||||
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
|
||||
# define SVGA_IO_MUL 1
|
||||
# define SVGA_FIFO_SIZE 0x10000
|
||||
-# define SVGA_MEM_BASE 0xe0000000
|
||||
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2
|
||||
#else
|
||||
# define SVGA_ID SVGA_ID_1
|
||||
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
|
||||
# define SVGA_IO_MUL 4
|
||||
# define SVGA_FIFO_SIZE 0x10000
|
||||
-# define SVGA_MEM_BASE 0xe0000000
|
||||
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
|
||||
#endif
|
||||
|
||||
@@ -1171,10 +1169,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
|
||||
vga_init(&s->vga);
|
||||
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
||||
|
||||
- vga_init_vbe(&s->vga);
|
||||
-
|
||||
- rom_add_vga(VGABIOS_FILENAME);
|
||||
-
|
||||
vmsvga_reset(s);
|
||||
}
|
||||
|
||||
@@ -1272,6 +1266,7 @@ static PCIDeviceInfo vmsvga_info = {
|
||||
.qdev.size = sizeof(struct pci_vmsvga_state_s),
|
||||
.qdev.vmsd = &vmstate_vmware_vga,
|
||||
.init = pci_vmsvga_initfn,
|
||||
+ .romfile = "vgabios-vmware.bin",
|
||||
};
|
||||
|
||||
static void vmsvga_register(void)
|
||||
--
|
||||
1.7.2.3
|
||||
|
61
0012-all-vga-refuse-hotplugging.patch
Normal file
61
0012-all-vga-refuse-hotplugging.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From a659f6b472d95503657ac68a52242ce769006f17 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 11 May 2010 22:28:44 +0200
|
||||
Subject: [PATCH 12/39] all vga: refuse hotplugging.
|
||||
|
||||
Try to pci hotplug a vga card, watch qemu die with hw_error().
|
||||
This patch fixes it.
|
||||
---
|
||||
hw/cirrus_vga.c | 4 ++++
|
||||
hw/vga-pci.c | 4 ++++
|
||||
hw/vmware_vga.c | 4 ++++
|
||||
3 files changed, 12 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
|
||||
index efa7a42..dadaa80 100644
|
||||
--- a/hw/cirrus_vga.c
|
||||
+++ b/hw/cirrus_vga.c
|
||||
@@ -3206,6 +3206,10 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
|
||||
uint8_t *pci_conf = d->dev.config;
|
||||
int device_id = CIRRUS_ID_CLGD5446;
|
||||
|
||||
+ if (dev->qdev.hotplugged) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/* setup VGA */
|
||||
vga_common_init(&s->vga, VGA_RAM_SIZE);
|
||||
cirrus_init_common(s, device_id, 1);
|
||||
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
|
||||
index 8e1ed35..4e673a5 100644
|
||||
--- a/hw/vga-pci.c
|
||||
+++ b/hw/vga-pci.c
|
||||
@@ -81,6 +81,10 @@ static int pci_vga_initfn(PCIDevice *dev)
|
||||
VGACommonState *s = &d->vga;
|
||||
uint8_t *pci_conf = d->dev.config;
|
||||
|
||||
+ if (dev->qdev.hotplugged) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
// vga + console init
|
||||
vga_common_init(s, VGA_RAM_SIZE);
|
||||
vga_init(s);
|
||||
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
|
||||
index 682f287..7ff89aa 100644
|
||||
--- a/hw/vmware_vga.c
|
||||
+++ b/hw/vmware_vga.c
|
||||
@@ -1232,6 +1232,10 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
|
||||
struct pci_vmsvga_state_s *s =
|
||||
DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
|
||||
|
||||
+ if (dev->qdev.hotplugged) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
|
||||
pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
|
||||
pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
|
||||
--
|
||||
1.7.2.3
|
||||
|
168
0013-spice-tls-support.patch
Normal file
168
0013-spice-tls-support.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From e0d06d42a83e7796b2c39ad6cab3630c0a8c2845 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:32 -0300
|
||||
Subject: [PATCH 13/39] spice: tls support
|
||||
|
||||
Add options to the -spice command line switch to setup tls:
|
||||
|
||||
tls-port
|
||||
listening port
|
||||
|
||||
x509-dir
|
||||
x509 file directory. Expects same filenames as
|
||||
-vnc $display,x509=$dir
|
||||
|
||||
x509-key-file
|
||||
x509-key-password
|
||||
x509-cert-file
|
||||
x509-cacert-file
|
||||
x509-dh-key-file
|
||||
x509 files can also be set individually.
|
||||
|
||||
tls-ciphers
|
||||
which ciphers to use.
|
||||
---
|
||||
qemu-config.c | 24 ++++++++++++++++++++
|
||||
spice.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 86 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/qemu-config.c b/qemu-config.c
|
||||
index 8a894cf..74bfc62 100644
|
||||
--- a/qemu-config.c
|
||||
+++ b/qemu-config.c
|
||||
@@ -355,11 +355,35 @@ QemuOptsList qemu_spice_opts = {
|
||||
.name = "port",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},{
|
||||
+ .name = "tls-port",
|
||||
+ .type = QEMU_OPT_NUMBER,
|
||||
+ },{
|
||||
.name = "password",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "disable-ticketing",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
+ },{
|
||||
+ .name = "x509-dir",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-key-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-key-password",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-cert-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-cacert-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-dh-key-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "tls-ciphers",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end if list */ }
|
||||
},
|
||||
diff --git a/spice.c b/spice.c
|
||||
index c763d52..3fe76cd 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "qemu-spice.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qemu-queue.h"
|
||||
+#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
|
||||
/* core bits */
|
||||
@@ -126,18 +127,71 @@ static SpiceCoreInterface core_interface = {
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
- const char *password;
|
||||
- int port;
|
||||
+ const char *password, *str, *x509_dir,
|
||||
+ *x509_key_password = NULL,
|
||||
+ *x509_dh_file = NULL,
|
||||
+ *tls_ciphers = NULL;
|
||||
+ char *x509_key_file = NULL,
|
||||
+ *x509_cert_file = NULL,
|
||||
+ *x509_cacert_file = NULL;
|
||||
+ int port, tls_port, len;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
port = qemu_opt_get_number(opts, "port", 0);
|
||||
- if (!port)
|
||||
+ tls_port = qemu_opt_get_number(opts, "tls-port", 0);
|
||||
+ if (!port && !tls_port)
|
||||
return;
|
||||
password = qemu_opt_get(opts, "password");
|
||||
|
||||
+ if (tls_port) {
|
||||
+ x509_dir = qemu_opt_get(opts, "x509-dir");
|
||||
+ if (NULL == x509_dir)
|
||||
+ x509_dir = ".";
|
||||
+ len = strlen(x509_dir) + 32;
|
||||
+
|
||||
+ str = qemu_opt_get(opts, "x509-key-file");
|
||||
+ if (str) {
|
||||
+ x509_key_file = qemu_strdup(str);
|
||||
+ } else {
|
||||
+ x509_key_file = qemu_malloc(len);
|
||||
+ snprintf(x509_key_file, len, "%s/%s", x509_dir, X509_SERVER_KEY_FILE);
|
||||
+ }
|
||||
+
|
||||
+ str = qemu_opt_get(opts, "x509-cert-file");
|
||||
+ if (str) {
|
||||
+ x509_cert_file = qemu_strdup(str);
|
||||
+ } else {
|
||||
+ x509_cert_file = qemu_malloc(len);
|
||||
+ snprintf(x509_cert_file, len, "%s/%s", x509_dir, X509_SERVER_CERT_FILE);
|
||||
+ }
|
||||
+
|
||||
+ str = qemu_opt_get(opts, "x509-cacert-file");
|
||||
+ if (str) {
|
||||
+ x509_cacert_file = qemu_strdup(str);
|
||||
+ } else {
|
||||
+ x509_cacert_file = qemu_malloc(len);
|
||||
+ snprintf(x509_cacert_file, len, "%s/%s", x509_dir, X509_CA_CERT_FILE);
|
||||
+ }
|
||||
+
|
||||
+ x509_key_password = qemu_opt_get(opts, "x509-key-password");
|
||||
+ x509_dh_file = qemu_opt_get(opts, "x509-dh-file");
|
||||
+ tls_ciphers = qemu_opt_get(opts, "tls-ciphers");
|
||||
+ }
|
||||
+
|
||||
spice_server = spice_server_new();
|
||||
- spice_server_set_port(spice_server, port);
|
||||
+ if (port) {
|
||||
+ spice_server_set_port(spice_server, port);
|
||||
+ }
|
||||
+ if (tls_port) {
|
||||
+ spice_server_set_tls(spice_server, tls_port,
|
||||
+ x509_cacert_file,
|
||||
+ x509_cert_file,
|
||||
+ x509_key_file,
|
||||
+ x509_key_password,
|
||||
+ x509_dh_file,
|
||||
+ tls_ciphers);
|
||||
+ }
|
||||
if (password)
|
||||
spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
||||
if (qemu_opt_get_bool(opts, "disable-ticketing", 0))
|
||||
@@ -150,4 +204,8 @@ void qemu_spice_init(void)
|
||||
using_spice = 1;
|
||||
|
||||
qemu_spice_input_init();
|
||||
+
|
||||
+ qemu_free(x509_key_file);
|
||||
+ qemu_free(x509_cert_file);
|
||||
+ qemu_free(x509_cacert_file);
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
2085
0014-spice-add-qxl-device.patch
Normal file
2085
0014-spice-add-qxl-device.patch
Normal file
File diff suppressed because it is too large
Load Diff
405
0015-spice-add-audio.patch
Normal file
405
0015-spice-add-audio.patch
Normal file
@ -0,0 +1,405 @@
|
||||
From f3e02bc08c4521dc53d858174612341462d588ce Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 13 Apr 2010 10:34:46 +0200
|
||||
Subject: [PATCH 15/39] spice: add audio
|
||||
|
||||
Add support for the spice audio interface.
|
||||
|
||||
The driver is first in the driver list, but can_be_default is set only
|
||||
in case spice is active. So if you are using spice the spice audio
|
||||
driver is the default one, otherwise whatever comes first after spice in
|
||||
the list. Overriding the default using QEMU_AUDIO_DRV works in any
|
||||
case.
|
||||
---
|
||||
Makefile.objs | 1 +
|
||||
audio/audio.c | 3 +
|
||||
audio/audio_int.h | 1 +
|
||||
audio/spiceaudio.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
qemu-spice.h | 1 +
|
||||
spice.c | 1 +
|
||||
6 files changed, 319 insertions(+), 0 deletions(-)
|
||||
create mode 100644 audio/spiceaudio.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index d05643f..9a6b0f3 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -94,6 +94,7 @@ common-obj-$(CONFIG_SPICE) += spice.o spice-input.o spice-display.o
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
audio-obj-$(CONFIG_OSS) += ossaudio.o
|
||||
+audio-obj-$(CONFIG_SPICE) += spiceaudio.o
|
||||
audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
|
||||
audio-obj-$(CONFIG_ALSA) += alsaaudio.o
|
||||
audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
|
||||
diff --git a/audio/audio.c b/audio/audio.c
|
||||
index ad51077..ade342e 100644
|
||||
--- a/audio/audio.c
|
||||
+++ b/audio/audio.c
|
||||
@@ -44,6 +44,9 @@
|
||||
that we generate the list.
|
||||
*/
|
||||
static struct audio_driver *drvtab[] = {
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ &spice_audio_driver,
|
||||
+#endif
|
||||
CONFIG_AUDIO_DRIVERS
|
||||
&no_audio_driver,
|
||||
&wav_audio_driver
|
||||
diff --git a/audio/audio_int.h b/audio/audio_int.h
|
||||
index 06e313f..d1f6c2d 100644
|
||||
--- a/audio/audio_int.h
|
||||
+++ b/audio/audio_int.h
|
||||
@@ -209,6 +209,7 @@ extern struct audio_driver coreaudio_audio_driver;
|
||||
extern struct audio_driver dsound_audio_driver;
|
||||
extern struct audio_driver esd_audio_driver;
|
||||
extern struct audio_driver pa_audio_driver;
|
||||
+extern struct audio_driver spice_audio_driver;
|
||||
extern struct audio_driver winwave_audio_driver;
|
||||
extern struct mixeng_volume nominal_volume;
|
||||
|
||||
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
|
||||
new file mode 100644
|
||||
index 0000000..8ae7499
|
||||
--- /dev/null
|
||||
+++ b/audio/spiceaudio.c
|
||||
@@ -0,0 +1,312 @@
|
||||
+#include "hw/hw.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
+#define AUDIO_CAP "spice"
|
||||
+#include "audio.h"
|
||||
+#include "audio_int.h"
|
||||
+
|
||||
+#define LINE_IN_SAMPLES 1024
|
||||
+#define LINE_OUT_SAMPLES 1024
|
||||
+
|
||||
+typedef struct SpiceVoiceOut {
|
||||
+ HWVoiceOut hw;
|
||||
+ SpicePlaybackInstance sin;
|
||||
+ int64_t prev_ticks;
|
||||
+ int active;
|
||||
+ uint32_t *frame;
|
||||
+ uint32_t *fpos;
|
||||
+ uint32_t fsize;
|
||||
+} SpiceVoiceOut;
|
||||
+
|
||||
+typedef struct SpiceVoiceIn {
|
||||
+ HWVoiceIn hw;
|
||||
+ SpiceRecordInstance sin;
|
||||
+ int64_t prev_ticks;
|
||||
+ int active;
|
||||
+ uint32_t samples[LINE_IN_SAMPLES];
|
||||
+} SpiceVoiceIn;
|
||||
+
|
||||
+static const SpicePlaybackInterface playback_sif = {
|
||||
+ .base.type = SPICE_INTERFACE_PLAYBACK,
|
||||
+ .base.description = "playback",
|
||||
+ .base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR,
|
||||
+};
|
||||
+
|
||||
+static const SpiceRecordInterface record_sif = {
|
||||
+ .base.type = SPICE_INTERFACE_RECORD,
|
||||
+ .base.description = "record",
|
||||
+ .base.major_version = SPICE_INTERFACE_RECORD_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_RECORD_MINOR,
|
||||
+};
|
||||
+
|
||||
+static void *spice_audio_init(void)
|
||||
+{
|
||||
+ if (!using_spice) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return &spice_audio_init;
|
||||
+}
|
||||
+
|
||||
+static void spice_audio_fini(void *opaque)
|
||||
+{
|
||||
+ /* nothing */
|
||||
+}
|
||||
+
|
||||
+static int calculate_samples(struct audio_pcm_info *info, int64_t *old_ticks)
|
||||
+{
|
||||
+ int64_t now;
|
||||
+ int64_t ticks;
|
||||
+ int64_t bytes;
|
||||
+ int samples;
|
||||
+
|
||||
+ now = qemu_get_clock (vm_clock);
|
||||
+ ticks = now - *old_ticks;
|
||||
+ *old_ticks = now;
|
||||
+ bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
|
||||
+ bytes = audio_MIN (bytes, INT_MAX);
|
||||
+ samples = bytes >> info->shift;
|
||||
+ return samples;
|
||||
+}
|
||||
+
|
||||
+/* playback */
|
||||
+
|
||||
+static int line_out_init(HWVoiceOut *hw, struct audsettings *as)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+ struct audsettings settings;
|
||||
+
|
||||
+ settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ;
|
||||
+ settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN;
|
||||
+ settings.fmt = AUD_FMT_S16;
|
||||
+ settings.endianness = AUDIO_HOST_ENDIANNESS;
|
||||
+
|
||||
+ audio_pcm_init_info(&hw->info, &settings);
|
||||
+ hw->samples = LINE_OUT_SAMPLES;
|
||||
+ out->active = 0;
|
||||
+
|
||||
+ out->sin.base.sif = &playback_sif.base;
|
||||
+ spice_server_add_interface(spice_server, &out->sin.base);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void line_out_fini(HWVoiceOut *hw)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+
|
||||
+ spice_server_remove_interface(&out->sin.base);
|
||||
+}
|
||||
+
|
||||
+static int line_out_run(HWVoiceOut *hw, int live)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+ int rpos, decr;
|
||||
+ int samples;
|
||||
+
|
||||
+ if (!live) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ decr = calculate_samples(&hw->info, &out->prev_ticks);
|
||||
+ decr = audio_MIN(live, decr);
|
||||
+
|
||||
+ samples = decr;
|
||||
+ rpos = hw->rpos;
|
||||
+ while (samples) {
|
||||
+ int left_till_end_samples = hw->samples - rpos;
|
||||
+ int len = audio_MIN(samples, left_till_end_samples);
|
||||
+
|
||||
+ if (!out->frame) {
|
||||
+ spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize);
|
||||
+ out->fpos = out->frame;
|
||||
+ }
|
||||
+ if (out->frame) {
|
||||
+ len = audio_MIN(len, out->fsize);
|
||||
+ hw->clip(out->fpos, hw->mix_buf + rpos, len);
|
||||
+ out->fsize -= len;
|
||||
+ out->fpos += len;
|
||||
+ if (out->fsize == 0) {
|
||||
+ spice_server_playback_put_samples(&out->sin, out->frame);
|
||||
+ out->frame = out->fpos = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ rpos = (rpos + len) % hw->samples;
|
||||
+ samples -= len;
|
||||
+ }
|
||||
+ hw->rpos = rpos;
|
||||
+ return decr;
|
||||
+}
|
||||
+
|
||||
+static int line_out_write(SWVoiceOut *sw, void *buf, int len)
|
||||
+{
|
||||
+ return audio_pcm_sw_write(sw, buf, len);
|
||||
+}
|
||||
+
|
||||
+static int line_out_ctl(HWVoiceOut *hw, int cmd, ...)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case VOICE_ENABLE:
|
||||
+ if (out->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ out->active = 1;
|
||||
+ out->prev_ticks = qemu_get_clock (vm_clock);
|
||||
+ spice_server_playback_start(&out->sin);
|
||||
+ break;
|
||||
+ case VOICE_DISABLE:
|
||||
+ if (!out->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ out->active = 0;
|
||||
+ if (out->frame) {
|
||||
+ memset(out->fpos, 0, out->fsize << 2);
|
||||
+ spice_server_playback_put_samples(&out->sin, out->frame);
|
||||
+ out->frame = out->fpos = NULL;
|
||||
+ }
|
||||
+ spice_server_playback_stop(&out->sin);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* record */
|
||||
+
|
||||
+static int line_in_init(HWVoiceIn *hw, struct audsettings *as)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+ struct audsettings settings;
|
||||
+
|
||||
+ settings.freq = SPICE_INTERFACE_RECORD_FREQ;
|
||||
+ settings.nchannels = SPICE_INTERFACE_RECORD_CHAN;
|
||||
+ settings.fmt = AUD_FMT_S16;
|
||||
+ settings.endianness = AUDIO_HOST_ENDIANNESS;
|
||||
+
|
||||
+ audio_pcm_init_info(&hw->info, &settings);
|
||||
+ hw->samples = LINE_IN_SAMPLES;
|
||||
+ in->active = 0;
|
||||
+
|
||||
+ in->sin.base.sif = &record_sif.base;
|
||||
+ spice_server_add_interface(spice_server, &in->sin.base);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void line_in_fini(HWVoiceIn *hw)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+
|
||||
+ spice_server_remove_interface(&in->sin.base);
|
||||
+}
|
||||
+
|
||||
+static int line_in_run(HWVoiceIn *hw)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+ int num_samples;
|
||||
+ int ready;
|
||||
+ int len[2];
|
||||
+ uint64_t delta_samp;
|
||||
+ uint32_t *samples;
|
||||
+
|
||||
+ if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in(hw))) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ delta_samp = calculate_samples(&hw->info, &in->prev_ticks);
|
||||
+ num_samples = audio_MIN(num_samples, delta_samp);
|
||||
+
|
||||
+ ready = spice_server_record_get_samples(&in->sin, in->samples, num_samples);
|
||||
+ samples = in->samples;
|
||||
+ if (ready == 0) {
|
||||
+ static uint32_t silence[LINE_IN_SAMPLES];
|
||||
+ samples = silence;
|
||||
+ ready = LINE_IN_SAMPLES;
|
||||
+ }
|
||||
+
|
||||
+ num_samples = audio_MIN(ready, num_samples);
|
||||
+
|
||||
+ if (hw->wpos + num_samples > hw->samples) {
|
||||
+ len[0] = hw->samples - hw->wpos;
|
||||
+ len[1] = num_samples - len[0];
|
||||
+ } else {
|
||||
+ len[0] = num_samples;
|
||||
+ len[1] = 0;
|
||||
+ }
|
||||
+
|
||||
+ hw->conv(hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
|
||||
+
|
||||
+ if (len[1]) {
|
||||
+ hw->conv(hw->conv_buf, samples + len[0], len[1],
|
||||
+ &nominal_volume);
|
||||
+ }
|
||||
+
|
||||
+ hw->wpos = (hw->wpos + num_samples) % hw->samples;
|
||||
+
|
||||
+ return num_samples;
|
||||
+}
|
||||
+
|
||||
+static int line_in_read(SWVoiceIn *sw, void *buf, int size)
|
||||
+{
|
||||
+ return audio_pcm_sw_read(sw, buf, size);
|
||||
+}
|
||||
+
|
||||
+static int line_in_ctl(HWVoiceIn *hw, int cmd, ...)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case VOICE_ENABLE:
|
||||
+ if (in->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ in->active = 1;
|
||||
+ in->prev_ticks = qemu_get_clock (vm_clock);
|
||||
+ spice_server_record_start(&in->sin);
|
||||
+ break;
|
||||
+ case VOICE_DISABLE:
|
||||
+ if (!in->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ in->active = 0;
|
||||
+ spice_server_record_stop(&in->sin);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct audio_option audio_options[] = {
|
||||
+ { /* end of list */ },
|
||||
+};
|
||||
+
|
||||
+static struct audio_pcm_ops audio_callbacks = {
|
||||
+ .init_out = line_out_init,
|
||||
+ .fini_out = line_out_fini,
|
||||
+ .run_out = line_out_run,
|
||||
+ .write = line_out_write,
|
||||
+ .ctl_out = line_out_ctl,
|
||||
+
|
||||
+ .init_in = line_in_init,
|
||||
+ .fini_in = line_in_fini,
|
||||
+ .run_in = line_in_run,
|
||||
+ .read = line_in_read,
|
||||
+ .ctl_in = line_in_ctl,
|
||||
+};
|
||||
+
|
||||
+struct audio_driver spice_audio_driver = {
|
||||
+ .name = "spice",
|
||||
+ .descr = "spice audio driver",
|
||||
+ .options = audio_options,
|
||||
+ .init = spice_audio_init,
|
||||
+ .fini = spice_audio_fini,
|
||||
+ .pcm_ops = &audio_callbacks,
|
||||
+ .max_voices_out = 1,
|
||||
+ .max_voices_in = 1,
|
||||
+ .voice_size_out = sizeof(SpiceVoiceOut),
|
||||
+ .voice_size_in = sizeof(SpiceVoiceIn),
|
||||
+};
|
||||
+
|
||||
+void qemu_spice_audio_init(void)
|
||||
+{
|
||||
+ spice_audio_driver.can_be_default = 1;
|
||||
+}
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index f061004..6f19ba7 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -13,6 +13,7 @@ extern int using_spice;
|
||||
|
||||
void qemu_spice_init(void);
|
||||
void qemu_spice_input_init(void);
|
||||
+void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 3fe76cd..fc76ef7 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -204,6 +204,7 @@ void qemu_spice_init(void)
|
||||
using_spice = 1;
|
||||
|
||||
qemu_spice_input_init();
|
||||
+ qemu_spice_audio_init();
|
||||
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
--
|
||||
1.7.2.3
|
||||
|
238
0016-spice-add-virtio-serial-based-vdi-port-backend.patch
Normal file
238
0016-spice-add-virtio-serial-based-vdi-port-backend.patch
Normal file
@ -0,0 +1,238 @@
|
||||
From ebf4cebd082442ed2bc11475fde301c18648298d Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 20 Apr 2010 13:33:54 +0200
|
||||
Subject: [PATCH 16/39] spice: add virtio-serial based vdi port backend.
|
||||
|
||||
Adds the spicevmc device. This is a communication channel between the
|
||||
spice client and the guest. It is used to send display information and
|
||||
mouse events from the spice clients to the guest.
|
||||
---
|
||||
Makefile.target | 1 +
|
||||
hw/spice-vmc.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 204 insertions(+), 0 deletions(-)
|
||||
create mode 100644 hw/spice-vmc.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 4da33b5..90544c5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,6 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
new file mode 100644
|
||||
index 0000000..3f6a2bb
|
||||
--- /dev/null
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -0,0 +1,203 @@
|
||||
+/*
|
||||
+
|
||||
+ Spice Virtual Machine Channel (VMC).
|
||||
+
|
||||
+ A virtio-serial port used for spice to guest communication, over
|
||||
+ which spice client and a daemon in the guest operating system
|
||||
+ communicate.
|
||||
+
|
||||
+ Replaces the old vdi_port PCI device.
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+
|
||||
+#include "virtio-serial.h"
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
+#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
+#define VMC_DEVICE_NAME "spicevmc"
|
||||
+
|
||||
+#define dprintf(_svc, _level, _fmt, ...) \
|
||||
+ do { \
|
||||
+ if (_svc->debug >= _level) { \
|
||||
+ fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
+ } \
|
||||
+ } while (0)
|
||||
+
|
||||
+typedef struct SpiceVirtualChannel {
|
||||
+ VirtIOSerialPort port;
|
||||
+ VMChangeStateEntry *vmstate;
|
||||
+ SpiceVDIPortInstance sin;
|
||||
+ bool active;
|
||||
+ uint8_t *buffer;
|
||||
+ uint8_t *datapos;
|
||||
+ ssize_t bufsize, datalen;
|
||||
+ uint32_t debug;
|
||||
+} SpiceVirtualChannel;
|
||||
+
|
||||
+static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ ssize_t out;
|
||||
+
|
||||
+ out = virtio_serial_write(&svc->port, buf, len);
|
||||
+ dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
+static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ int bytes = MIN(len, svc->datalen);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
+ if (bytes) {
|
||||
+ memcpy(buf, svc->datapos, bytes);
|
||||
+ svc->datapos += bytes;
|
||||
+ svc->datalen -= bytes;
|
||||
+ if (0 == svc->datalen) {
|
||||
+ virtio_serial_throttle_port(&svc->port, false);
|
||||
+ }
|
||||
+ }
|
||||
+ return bytes;
|
||||
+}
|
||||
+
|
||||
+static SpiceVDIPortInterface vmc_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
+ .base.description = "spice virtual channel vdi port",
|
||||
+ .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
+ .write = vmc_write,
|
||||
+ .read = vmc_read,
|
||||
+};
|
||||
+
|
||||
+static void vmc_register_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ svc->sin.base.sif = &vmc_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &svc->sin.base);
|
||||
+ svc->active = true;
|
||||
+}
|
||||
+
|
||||
+static void vmc_unregister_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (!svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ spice_server_remove_interface(&svc->sin.base);
|
||||
+ svc->active = false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void vmc_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = opaque;
|
||||
+
|
||||
+ if (running && svc->active) {
|
||||
+ spice_server_vdi_port_wakeup(&svc->sin);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * virtio-serial callbacks
|
||||
+ */
|
||||
+
|
||||
+static void vmc_guest_open(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_register_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_close(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_ready(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ if (svc->active)
|
||||
+ spice_server_vdi_port_wakeup(&svc->sin);
|
||||
+}
|
||||
+
|
||||
+static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
+ assert(svc->datapos == 0);
|
||||
+ if (svc->bufsize < len) {
|
||||
+ svc->bufsize = len;
|
||||
+ svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
+ }
|
||||
+ memcpy(svc->buffer, buf, len);
|
||||
+ svc->datapos = svc->buffer;
|
||||
+ svc->datalen = len;
|
||||
+ virtio_serial_throttle_port(&svc->port, true);
|
||||
+ spice_server_vdi_port_wakeup(&svc->sin);
|
||||
+}
|
||||
+
|
||||
+static int vmc_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ if (!using_spice)
|
||||
+ return -1;
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
|
||||
+ svc->vmstate = qemu_add_vm_change_state_handler(
|
||||
+ vmc_change_state_handler, svc);
|
||||
+ virtio_serial_open(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vmc_exitfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+ qemu_del_vm_change_state_handler(svc->vmstate);
|
||||
+ virtio_serial_close(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo vmc_info = {
|
||||
+ .qdev.name = VMC_DEVICE_NAME,
|
||||
+ .qdev.size = sizeof(SpiceVirtualChannel),
|
||||
+ .init = vmc_initfn,
|
||||
+ .exit = vmc_exitfn,
|
||||
+ .guest_open = vmc_guest_open,
|
||||
+ .guest_close = vmc_guest_close,
|
||||
+ .guest_ready = vmc_guest_ready,
|
||||
+ .have_data = vmc_have_data,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
+ DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static void vmc_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&vmc_info);
|
||||
+}
|
||||
+device_init(vmc_register)
|
||||
--
|
||||
1.7.2.3
|
||||
|
592
0017-spice-add-pci-vdi-port-backend-obsolete.patch
Normal file
592
0017-spice-add-pci-vdi-port-backend-obsolete.patch
Normal file
@ -0,0 +1,592 @@
|
||||
From ee782dec6adaced9c5bb99d02253505fb635fa12 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 12 Mar 2010 16:26:18 +0100
|
||||
Subject: [PATCH 17/39] spice: add pci vdi port backend (obsolete).
|
||||
|
||||
This is *not* intended to be merged upstream. It is just here
|
||||
because the virtio-serial windows guest drivers are not ready,
|
||||
so you can't go with the new spice-vmc yet.
|
||||
---
|
||||
Makefile.target | 2 +-
|
||||
hw/spice-vdi.c | 556 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 557 insertions(+), 1 deletions(-)
|
||||
create mode 100644 hw/spice-vdi.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 90544c5..025bdb8 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,7 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o spice-vdi.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vdi.c b/hw/spice-vdi.c
|
||||
new file mode 100644
|
||||
index 0000000..23cbbe1
|
||||
--- /dev/null
|
||||
+++ b/hw/spice-vdi.c
|
||||
@@ -0,0 +1,556 @@
|
||||
+#include <pthread.h>
|
||||
+#include <signal.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "hw/hw.h"
|
||||
+#include "hw/pc.h"
|
||||
+#include "hw/pci.h"
|
||||
+#include "console.h"
|
||||
+#include "hw/vga_int.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "sysemu.h"
|
||||
+#include "console.h"
|
||||
+#include "pci.h"
|
||||
+#include "hw.h"
|
||||
+#include "cpu-common.h"
|
||||
+
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+#include <spice/ipc_ring.h>
|
||||
+#include <spice/barrier.h>
|
||||
+
|
||||
+#undef SPICE_RING_PROD_ITEM
|
||||
+#define SPICE_RING_PROD_ITEM(r, ret) { \
|
||||
+ typeof(r) start = r; \
|
||||
+ typeof(r) end = r + 1; \
|
||||
+ uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
||||
+ typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
||||
+ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
+ abort(); \
|
||||
+ } \
|
||||
+ ret = &m_item->el; \
|
||||
+ }
|
||||
+
|
||||
+#undef SPICE_RING_CONS_ITEM
|
||||
+#define SPICE_RING_CONS_ITEM(r, ret) { \
|
||||
+ typeof(r) start = r; \
|
||||
+ typeof(r) end = r + 1; \
|
||||
+ uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
||||
+ typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
||||
+ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
+ abort(); \
|
||||
+ } \
|
||||
+ ret = &m_item->el; \
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+#undef ALIGN
|
||||
+#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
||||
+
|
||||
+#define REDHAT_PCI_VENDOR_ID 0x1b36
|
||||
+#define VDI_PORT_DEVICE_ID 0x0105
|
||||
+#define VDI_PORT_REVISION 0x01
|
||||
+
|
||||
+#define VDI_PORT_INTERRUPT (1 << 0)
|
||||
+
|
||||
+#define VDI_PORT_MAGIC (*(uint32_t*)"VDIP")
|
||||
+
|
||||
+#define VDI_PORT_DEV_NAME "vdi_port"
|
||||
+#define VDI_PORT_SAVE_VERSION 20
|
||||
+
|
||||
+#include <spice/start-packed.h>
|
||||
+
|
||||
+typedef struct SPICE_ATTR_PACKED VDIPortPacket {
|
||||
+ uint32_t gen;
|
||||
+ uint32_t size;
|
||||
+ uint8_t data[512 - 2 * sizeof(uint32_t)];
|
||||
+} VDIPortPacket;
|
||||
+
|
||||
+SPICE_RING_DECLARE(VDIPortRing, VDIPortPacket, 32);
|
||||
+
|
||||
+enum {
|
||||
+ VDI_PORT_IO_RANGE_INDEX,
|
||||
+ VDI_PORT_RAM_RANGE_INDEX,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ VDI_PORT_IO_CONNECTION,
|
||||
+ VDI_PORT_IO_NOTIFY = 4,
|
||||
+ VDI_PORT_IO_UPDATE_IRQ = 8,
|
||||
+
|
||||
+ VDI_PORT_IO_RANGE_SIZE = 12
|
||||
+};
|
||||
+
|
||||
+typedef struct SPICE_ATTR_PACKED VDIPortRam {
|
||||
+ uint32_t magic;
|
||||
+ uint32_t generation;
|
||||
+ uint32_t int_pending;
|
||||
+ uint32_t int_mask;
|
||||
+ VDIPortRing input;
|
||||
+ VDIPortRing output;
|
||||
+ uint32_t reserv[32];
|
||||
+} VDIPortRam;
|
||||
+
|
||||
+#include <spice/end-packed.h>
|
||||
+
|
||||
+typedef struct PCIVDIPortDevice {
|
||||
+ PCIDevice pci_dev;
|
||||
+ uint32_t io_base;
|
||||
+ uint64_t ram_offset;
|
||||
+ uint32_t ram_size;
|
||||
+ VDIPortRam *ram;
|
||||
+ uint32_t connected;
|
||||
+ int running;
|
||||
+ int new_gen_on_resume;
|
||||
+ int active_interface;
|
||||
+ SpiceVDIPortInstance sin;
|
||||
+ int plug_read_pos;
|
||||
+} PCIVDIPortDevice;
|
||||
+
|
||||
+static int debug = 1;
|
||||
+
|
||||
+static inline uint32_t msb_mask(uint32_t val)
|
||||
+{
|
||||
+ uint32_t mask;
|
||||
+
|
||||
+ do {
|
||||
+ mask = ~(val - 1) & val;
|
||||
+ val &= ~mask;
|
||||
+ } while (mask < val);
|
||||
+
|
||||
+ return mask;
|
||||
+}
|
||||
+
|
||||
+static inline void atomic_or(uint32_t *var, uint32_t add)
|
||||
+{
|
||||
+ __asm__ __volatile__ ("lock; orl %1, %0" : "+m" (*var) : "r" (add) : "memory");
|
||||
+}
|
||||
+
|
||||
+static inline uint32_t atomic_exchange(uint32_t val, uint32_t *ptr)
|
||||
+{
|
||||
+ __asm__ __volatile__("xchgl %0, %1" : "+q"(val), "+m" (*ptr) : : "memory");
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static void set_dirty(void *base, ram_addr_t offset, void *start, uint32_t length)
|
||||
+{
|
||||
+ assert(start >= base);
|
||||
+
|
||||
+ ram_addr_t addr = (ram_addr_t)((uint8_t*)start - (uint8_t*)base) + offset;
|
||||
+ ram_addr_t end = ALIGN(addr + length, TARGET_PAGE_SIZE);
|
||||
+
|
||||
+ do {
|
||||
+ cpu_physical_memory_set_dirty(addr);
|
||||
+ addr += TARGET_PAGE_SIZE;
|
||||
+ } while ( addr < end );
|
||||
+}
|
||||
+
|
||||
+static inline void vdi_port_set_dirty(PCIVDIPortDevice *d, void *start, uint32_t length)
|
||||
+{
|
||||
+ set_dirty(d->ram, d->ram_offset, start, length);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_new_gen(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ d->ram->generation = (d->ram->generation + 1 == 0) ? 1 : d->ram->generation + 1;
|
||||
+ vdi_port_set_dirty(d, &d->ram->generation, sizeof(d->ram->generation));
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_irq_level(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ return !!(d->ram->int_pending & d->ram->int_mask);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_notify_guest(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ uint32_t events = VDI_PORT_INTERRUPT;
|
||||
+ uint32_t old_pending;
|
||||
+
|
||||
+ if (!d->connected) {
|
||||
+ return;
|
||||
+ }
|
||||
+ old_pending = __sync_fetch_and_or(&d->ram->int_pending, events);
|
||||
+ if ((old_pending & events) == events) {
|
||||
+ return;
|
||||
+ }
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+ vdi_port_set_dirty(d, &d->ram->int_pending, sizeof(d->ram->int_pending));
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_interface_write(SpiceVDIPortInstance *sin,
|
||||
+ const uint8_t *buf, int len)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
+ VDIPortRing *ring = &d->ram->output;
|
||||
+ int do_notify = false;
|
||||
+ int actual_write = 0;
|
||||
+ int l = len;
|
||||
+
|
||||
+ if (!d->running) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ while (len) {
|
||||
+ VDIPortPacket *packet;
|
||||
+ int notify;
|
||||
+ int wait;
|
||||
+
|
||||
+ SPICE_RING_PROD_WAIT(ring, wait);
|
||||
+ if (wait) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SPICE_RING_PROD_ITEM(ring, packet);
|
||||
+ packet->gen = d->ram->generation;
|
||||
+ packet->size = MIN(len, sizeof(packet->data));
|
||||
+ memcpy(packet->data, buf, packet->size);
|
||||
+ vdi_port_set_dirty(d, packet, sizeof(*packet) - (sizeof(packet->data) - packet->size));
|
||||
+
|
||||
+ SPICE_RING_PUSH(ring, notify);
|
||||
+ do_notify = do_notify || notify;
|
||||
+ len -= packet->size;
|
||||
+ buf += packet->size;
|
||||
+ actual_write += packet->size;
|
||||
+ }
|
||||
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
+
|
||||
+ if (do_notify) {
|
||||
+ vdi_port_notify_guest(d);
|
||||
+ }
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_write, l);
|
||||
+ }
|
||||
+ return actual_write;
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_interface_read(SpiceVDIPortInstance *sin,
|
||||
+ uint8_t *buf, int len)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
+ VDIPortRing *ring = &d->ram->input;
|
||||
+ uint32_t gen = d->ram->generation;
|
||||
+ VDIPortPacket *packet;
|
||||
+ int do_notify = false;
|
||||
+ int actual_read = 0;
|
||||
+ int l = len;
|
||||
+
|
||||
+ if (!d->running) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ while (!SPICE_RING_IS_EMPTY(ring)) {
|
||||
+ int notify;
|
||||
+
|
||||
+ SPICE_RING_CONS_ITEM(ring, packet);
|
||||
+ if (packet->gen == gen) {
|
||||
+ break;
|
||||
+ }
|
||||
+ SPICE_RING_POP(ring, notify);
|
||||
+ do_notify = do_notify || notify;
|
||||
+ }
|
||||
+ while (len) {
|
||||
+ VDIPortPacket *packet;
|
||||
+ int wait;
|
||||
+ int now;
|
||||
+
|
||||
+ SPICE_RING_CONS_WAIT(ring, wait);
|
||||
+
|
||||
+ if (wait) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SPICE_RING_CONS_ITEM(ring, packet);
|
||||
+ if (packet->size > sizeof(packet->data)) {
|
||||
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
+ printf("%s: bad packet size\n", __FUNCTION__);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ now = MIN(len, packet->size - d->plug_read_pos);
|
||||
+ memcpy(buf, packet->data + d->plug_read_pos, now);
|
||||
+ len -= now;
|
||||
+ buf += now;
|
||||
+ actual_read += now;
|
||||
+ if ((d->plug_read_pos += now) == packet->size) {
|
||||
+ int notify;
|
||||
+
|
||||
+ d->plug_read_pos = 0;
|
||||
+ SPICE_RING_POP(ring, notify);
|
||||
+ do_notify = do_notify || notify;
|
||||
+ }
|
||||
+ }
|
||||
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
+
|
||||
+ if (do_notify) {
|
||||
+ vdi_port_notify_guest(d);
|
||||
+ }
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_read, l);
|
||||
+ }
|
||||
+ return actual_read;
|
||||
+}
|
||||
+
|
||||
+static SpiceVDIPortInterface vdi_port_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
+ .base.description = "vdi port",
|
||||
+ .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
+
|
||||
+ .write = vdi_port_interface_write,
|
||||
+ .read = vdi_port_interface_read,
|
||||
+};
|
||||
+
|
||||
+static void vdi_port_register_interface(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (d->active_interface ) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
+ }
|
||||
+ d->sin.base.sif = &vdi_port_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &d->sin.base);
|
||||
+ d->active_interface = true;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_unregister_interface(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (!d->active_interface ) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
+ }
|
||||
+ spice_server_remove_interface(&d->sin.base);
|
||||
+ d->active_interface = false;
|
||||
+}
|
||||
+
|
||||
+static uint32_t vdi_port_dev_connect(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (d->connected) {
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: already connected\n", __FUNCTION__);
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+ vdi_port_new_gen(d);
|
||||
+ d->connected = true;
|
||||
+ vdi_port_register_interface(d);
|
||||
+ return d->ram->generation;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_dev_disconnect(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (!d->connected) {
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ d->connected = false;
|
||||
+ vdi_port_unregister_interface(d);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_dev_notify(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ spice_server_vdi_port_wakeup(&d->sin);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_write_dword(void *opaque, uint32_t addr, uint32_t val)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = opaque;
|
||||
+ uint32_t io_port = addr - d->io_base;
|
||||
+
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: addr 0x%x val 0x%x\n", __FUNCTION__, addr, val);
|
||||
+ }
|
||||
+ switch (io_port) {
|
||||
+ case VDI_PORT_IO_NOTIFY:
|
||||
+ if (!d->connected) {
|
||||
+ fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
+ return;
|
||||
+ }
|
||||
+ vdi_port_dev_notify(d);
|
||||
+ break;
|
||||
+ case VDI_PORT_IO_UPDATE_IRQ:
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+ break;
|
||||
+ case VDI_PORT_IO_CONNECTION:
|
||||
+ vdi_port_dev_disconnect(d);
|
||||
+ break;
|
||||
+ default:
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: unexpected addr 0x%x val 0x%x\n",
|
||||
+ __FUNCTION__, addr, val);
|
||||
+ }
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+static uint32_t vdi_port_read_dword(void *opaque, uint32_t addr)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = opaque;
|
||||
+ uint32_t io_port = addr - d->io_base;
|
||||
+
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: addr 0x%x\n", __FUNCTION__, addr);
|
||||
+ }
|
||||
+ if (io_port == VDI_PORT_IO_CONNECTION) {
|
||||
+ return vdi_port_dev_connect(d);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "%s: unexpected addr 0x%x\n", __FUNCTION__, addr);
|
||||
+ }
|
||||
+ return 0xffffffff;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_io_map(PCIDevice *pci_dev, int region_num,
|
||||
+ pcibus_t addr, pcibus_t size, int type)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
+
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: base 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
+ }
|
||||
+ d->io_base = addr;
|
||||
+ register_ioport_write(addr, size, 4, vdi_port_write_dword, pci_dev);
|
||||
+ register_ioport_read(addr, size, 4, vdi_port_read_dword, pci_dev);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_ram_map(PCIDevice *pci_dev, int region_num,
|
||||
+ pcibus_t addr, pcibus_t size, int type)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
+
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: addr 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
+ }
|
||||
+
|
||||
+ assert((addr & (size - 1)) == 0);
|
||||
+ assert(size == d->ram_size);
|
||||
+
|
||||
+ cpu_register_physical_memory(addr, size, d->ram_offset | IO_MEM_RAM);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_reset(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ memset(d->ram, 0, sizeof(*d->ram));
|
||||
+ SPICE_RING_INIT(&d->ram->input);
|
||||
+ SPICE_RING_INIT(&d->ram->output);
|
||||
+ d->ram->magic = VDI_PORT_MAGIC;
|
||||
+ d->ram->generation = 0;
|
||||
+ d->ram->int_pending = 0;
|
||||
+ d->ram->int_mask = 0;
|
||||
+ d->connected = false;
|
||||
+ d->plug_read_pos = 0;
|
||||
+ vdi_port_set_dirty(d, d->ram, sizeof(*d->ram));
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_reset_handler(DeviceState *dev)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev.qdev, dev);
|
||||
+
|
||||
+ if (d->connected) {
|
||||
+ vdi_port_dev_disconnect(d);
|
||||
+ }
|
||||
+
|
||||
+ vdi_port_reset(d);
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_pre_load(void* opaque)
|
||||
+{
|
||||
+ PCIVDIPortDevice* d = opaque;
|
||||
+
|
||||
+ vdi_port_unregister_interface(d);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_post_load(void* opaque,int version_id)
|
||||
+{
|
||||
+ PCIVDIPortDevice* d = opaque;
|
||||
+
|
||||
+ if (d->connected) {
|
||||
+ vdi_port_register_interface(d);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ PCIVDIPortDevice* d = opaque;
|
||||
+
|
||||
+ if (running) {
|
||||
+ d->running = true;
|
||||
+ if (d->new_gen_on_resume) {
|
||||
+ d->new_gen_on_resume = false;
|
||||
+ vdi_port_new_gen(d);
|
||||
+ vdi_port_notify_guest(d);
|
||||
+ }
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+ vdi_port_dev_notify(d);
|
||||
+ } else {
|
||||
+ d->running = false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_init(PCIDevice *dev)
|
||||
+{
|
||||
+ PCIVDIPortDevice *vdi = (PCIVDIPortDevice *)dev;
|
||||
+ uint8_t* config = vdi->pci_dev.config;
|
||||
+ uint32_t ram_size = msb_mask(sizeof(VDIPortRam) * 2 - 1);
|
||||
+
|
||||
+ vdi->ram_offset = qemu_ram_alloc(&vdi->pci_dev.qdev, "bar1", ram_size);
|
||||
+ vdi->ram = qemu_get_ram_ptr(vdi->ram_offset);
|
||||
+ vdi_port_reset(vdi);
|
||||
+ vdi->ram_size = ram_size;
|
||||
+ vdi->new_gen_on_resume = false;
|
||||
+ vdi->running = false;
|
||||
+
|
||||
+ pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
|
||||
+ pci_config_set_device_id(config, VDI_PORT_DEVICE_ID);
|
||||
+ pci_config_set_class(config, PCI_CLASS_COMMUNICATION_OTHER);
|
||||
+ pci_set_byte(&config[PCI_REVISION_ID], VDI_PORT_REVISION);
|
||||
+ pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
||||
+
|
||||
+ pci_register_bar(dev, VDI_PORT_IO_RANGE_INDEX,
|
||||
+ msb_mask(VDI_PORT_IO_RANGE_SIZE * 2 - 1),
|
||||
+ PCI_BASE_ADDRESS_SPACE_IO, vdi_port_io_map);
|
||||
+
|
||||
+ pci_register_bar(dev, VDI_PORT_RAM_RANGE_INDEX,
|
||||
+ vdi->ram_size , PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||
+ vdi_port_ram_map);
|
||||
+
|
||||
+ qemu_add_vm_change_state_handler(vdi_port_vm_change_state_handler, vdi);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VMStateDescription vdi_port_vmstate = {
|
||||
+ .name = VDI_PORT_DEV_NAME,
|
||||
+ .version_id = VDI_PORT_SAVE_VERSION,
|
||||
+ .minimum_version_id = VDI_PORT_SAVE_VERSION,
|
||||
+ .pre_load = vdi_port_pre_load,
|
||||
+ .post_load = vdi_port_post_load,
|
||||
+ .fields = (VMStateField []) {
|
||||
+ VMSTATE_PCI_DEVICE(pci_dev, PCIVDIPortDevice),
|
||||
+ VMSTATE_UINT32(connected, PCIVDIPortDevice),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static PCIDeviceInfo vdi_port_info = {
|
||||
+ .qdev.name = VDI_PORT_DEV_NAME,
|
||||
+ .qdev.desc = "spice virtual desktop port (obsolete)",
|
||||
+ .qdev.size = sizeof(PCIVDIPortDevice),
|
||||
+ .qdev.vmsd = &vdi_port_vmstate,
|
||||
+ .qdev.reset = vdi_port_reset_handler,
|
||||
+
|
||||
+ .init = vdi_port_init,
|
||||
+};
|
||||
+
|
||||
+static void vdi_port_register(void)
|
||||
+{
|
||||
+ pci_qdev_register(&vdi_port_info);
|
||||
+}
|
||||
+
|
||||
+device_init(vdi_port_register);
|
||||
--
|
||||
1.7.2.3
|
||||
|
29
0018-use-memalign-instead-of-posix_memalign.patch
Normal file
29
0018-use-memalign-instead-of-posix_memalign.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From 898303cfd535d76ce971f3ac1310696937fbd286 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 09:53:48 +0200
|
||||
Subject: [PATCH 18/39] use memalign instead of posix_memalign
|
||||
|
||||
---
|
||||
osdep.c | 5 +++++
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/osdep.c b/osdep.c
|
||||
index 2375a69..ed2fd40 100644
|
||||
--- a/osdep.c
|
||||
+++ b/osdep.c
|
||||
@@ -100,7 +100,12 @@ void *qemu_memalign(size_t alignment, size_t size)
|
||||
#if defined(_POSIX_C_SOURCE) && !defined(__sun__)
|
||||
int ret;
|
||||
void *ptr;
|
||||
+#if 0
|
||||
ret = posix_memalign(&ptr, alignment, size);
|
||||
+#else
|
||||
+ ptr = memalign(alignment, size);
|
||||
+ ret = (ptr == NULL) ? -1 : 0;
|
||||
+#endif
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to allocate %zu B: %s\n",
|
||||
size, strerror(ret));
|
||||
--
|
||||
1.7.2.3
|
||||
|
179
0019-spice-live-migration-wip.patch
Normal file
179
0019-spice-live-migration-wip.patch
Normal file
@ -0,0 +1,179 @@
|
||||
From 80b1dac2be1487d31e6766abe2359fcff1bf0481 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 23 Apr 2010 13:28:21 +0200
|
||||
Subject: [PATCH 19/39] spice: live migration (wip).
|
||||
|
||||
Handle spice client migration, i.e. inform a spice client connected
|
||||
about the new host and connection parameters, so it can move over the
|
||||
connection automatically.
|
||||
---
|
||||
monitor.c | 1 +
|
||||
qemu-monitor.hx | 11 +++++++
|
||||
qemu-spice.h | 2 +
|
||||
spice.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 101 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index e51df62..6674a8c 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "osdep.h"
|
||||
#include "exec-all.h"
|
||||
#include "qemu-kvm.h"
|
||||
+#include "qemu-spice.h"
|
||||
|
||||
//#define DEBUG
|
||||
//#define DEBUG_COMPLETION
|
||||
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
|
||||
index da7b796..c2570d9 100644
|
||||
--- a/qemu-monitor.hx
|
||||
+++ b/qemu-monitor.hx
|
||||
@@ -2510,6 +2510,17 @@ ETEXI
|
||||
|
||||
HXCOMM DO NOT add new commands after 'info', move your addition before it!
|
||||
|
||||
+#if defined(CONFIG_SPICE)
|
||||
+ {
|
||||
+ .name = "spice_migrate_info",
|
||||
+ .args_type = "hostname:s,port:i?,tls-port:i?,cert-subject:s?",
|
||||
+ .params = "hostname port tls-port cert-subject",
|
||||
+ .help = "send migration info to spice client",
|
||||
+ .user_print = monitor_user_noop,
|
||||
+ .mhandler.cmd_new = mon_spice_migrate,
|
||||
+ },
|
||||
+#endif
|
||||
+
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index 6f19ba7..3c8e959 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -16,6 +16,8 @@ void qemu_spice_input_init(void);
|
||||
void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
+int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
+
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
#define using_spice 0
|
||||
diff --git a/spice.c b/spice.c
|
||||
index fc76ef7..1109b4f 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
+#include "hw/hw.h"
|
||||
|
||||
/* core bits */
|
||||
|
||||
@@ -122,8 +123,90 @@ static SpiceCoreInterface core_interface = {
|
||||
.watch_remove = watch_remove,
|
||||
};
|
||||
|
||||
+/* handle client migration */
|
||||
+
|
||||
+static int spice_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
|
||||
+{
|
||||
+ static int last_stage;
|
||||
+ static int migrate_client, client_connected;
|
||||
+ int ret = 1;
|
||||
+
|
||||
+ if (last_stage != stage) {
|
||||
+ last_stage = stage;
|
||||
+ fprintf(stderr, "%s: stage %d\n", __FUNCTION__, stage);
|
||||
+ } else {
|
||||
+ fprintf(stderr, ".");
|
||||
+ }
|
||||
+
|
||||
+ switch (stage) {
|
||||
+ case 1:
|
||||
+ migrate_client = 1;
|
||||
+ client_connected = 0;
|
||||
+ fprintf(stderr, "%s: start client migration\n", __FUNCTION__);
|
||||
+ if (spice_server_migrate_start(spice_server) != 0) {
|
||||
+ fprintf(stderr, "%s: fail -> no client migration\n", __FUNCTION__);
|
||||
+ migrate_client = 0;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ if (!migrate_client)
|
||||
+ break;
|
||||
+ switch (spice_server_migrate_client_state(spice_server)) {
|
||||
+ case SPICE_MIGRATE_CLIENT_NONE:
|
||||
+ fprintf(stderr, "%s: no client connected\n", __FUNCTION__);
|
||||
+ migrate_client = 0;
|
||||
+ break;
|
||||
+ case SPICE_MIGRATE_CLIENT_WAITING:
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ case SPICE_MIGRATE_CLIENT_READY:
|
||||
+ if (!client_connected) {
|
||||
+ fprintf(stderr, "%s: client connected to target\n", __FUNCTION__);
|
||||
+ client_connected = 1;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ if (migrate_client && client_connected) {
|
||||
+ fprintf(stderr, "%s: finish client migration\n", __FUNCTION__);
|
||||
+ spice_server_migrate_end(spice_server, 1);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void spice_save(QEMUFile *f, void *opaque)
|
||||
+{
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+}
|
||||
+
|
||||
+static int spice_load(QEMUFile *f, void *opaque, int version_id)
|
||||
+{
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* functions for the rest of qemu */
|
||||
|
||||
+int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
+{
|
||||
+ const char *hostname = qdict_get_str(qdict, "hostname");
|
||||
+ const char *subject = qdict_get_try_str(qdict, "cert-subject");
|
||||
+ int port = qdict_get_try_int(qdict, "port", -1);
|
||||
+ int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
|
||||
+
|
||||
+ if (!spice_server) {
|
||||
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* TODO: Convert to QError */
|
||||
+ return spice_server_migrate_info(spice_server, hostname,
|
||||
+ port, tls_port, subject);
|
||||
+}
|
||||
+
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
@@ -206,6 +289,10 @@ void qemu_spice_init(void)
|
||||
qemu_spice_input_init();
|
||||
qemu_spice_audio_init();
|
||||
|
||||
+ register_savevm_live(NULL, "spice", -1, 1, NULL,
|
||||
+ spice_live, spice_save, spice_load,
|
||||
+ spice_server);
|
||||
+
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
qemu_free(x509_cacert_file);
|
||||
--
|
||||
1.7.2.3
|
||||
|
23
0020-spice-display-draw.h-is-internal-now.patch
Normal file
23
0020-spice-display-draw.h-is-internal-now.patch
Normal file
@ -0,0 +1,23 @@
|
||||
From 7241cc479a0f4a148ae60336add6d7be80da9ff0 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 14:11:18 +0200
|
||||
Subject: [PATCH 20/39] spice-display: draw.h is internal now
|
||||
|
||||
---
|
||||
spice-display.h | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/spice-display.h b/spice-display.h
|
||||
index 70a7be4..b55e7ea 100644
|
||||
--- a/spice-display.h
|
||||
+++ b/spice-display.h
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <spice/ipc_ring.h>
|
||||
-#include <spice/draw.h>
|
||||
+#include <spice/enums.h>
|
||||
#include <spice/qxl_dev.h>
|
||||
|
||||
#include "pflib.h"
|
||||
--
|
||||
1.7.2.3
|
||||
|
25
0021-spice-display-disable-debug.patch
Normal file
25
0021-spice-display-disable-debug.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From c269c8b87769b25c9d69d40944de0e883458af86 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 14:31:10 +0200
|
||||
Subject: [PATCH 21/39] spice-display: disable debug
|
||||
|
||||
---
|
||||
spice-display.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
index a749e64..2291cc7 100644
|
||||
--- a/spice-display.c
|
||||
+++ b/spice-display.c
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "spice-display.h"
|
||||
|
||||
-static int debug = 1;
|
||||
+static int debug = 0;
|
||||
|
||||
int qemu_spice_rect_is_empty(const QXLRect* r)
|
||||
{
|
||||
--
|
||||
1.7.2.3
|
||||
|
27
0022-spice-display-pci-rev-fixups.patch
Normal file
27
0022-spice-display-pci-rev-fixups.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 2912f038b4bfddd4c3dacb3b0102e45553859632 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 16:29:15 +0200
|
||||
Subject: [PATCH 22/39] spice-display: pci rev fixups
|
||||
|
||||
---
|
||||
spice-display.c | 4 ----
|
||||
1 files changed, 0 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
index 2291cc7..87a71cd 100644
|
||||
--- a/spice-display.c
|
||||
+++ b/spice-display.c
|
||||
@@ -334,10 +334,6 @@ static const QXLInterface dpy_interface = {
|
||||
.base.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
.base.minor_version = SPICE_INTERFACE_QXL_MINOR,
|
||||
|
||||
- .pci_vendor = REDHAT_PCI_VENDOR_ID,
|
||||
- .pci_id = QXL_DEVICE_ID,
|
||||
- .pci_revision = QXL_REVISION,
|
||||
-
|
||||
.attache_worker = interface_attach_worker,
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
--
|
||||
1.7.2.3
|
||||
|
52
0023-qxl-pci-rev-fixups.patch
Normal file
52
0023-qxl-pci-rev-fixups.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 727553e1a33dccab2b27ee5e184e003440765289 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 16:29:27 +0200
|
||||
Subject: [PATCH 23/39] qxl: pci rev fixups
|
||||
|
||||
---
|
||||
hw/qxl.c | 20 ++++++++------------
|
||||
1 files changed, 8 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 475360c..2a0ea4e 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -511,10 +511,6 @@ static const QXLInterface qxl_interface = {
|
||||
.base.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
.base.minor_version = SPICE_INTERFACE_QXL_MINOR,
|
||||
|
||||
- .pci_vendor = REDHAT_PCI_VENDOR_ID,
|
||||
- .pci_id = QXL_DEVICE_ID,
|
||||
- .pci_revision = QXL_REVISION,
|
||||
-
|
||||
.attache_worker = interface_attach_worker,
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
@@ -1136,16 +1132,16 @@ static int qxl_init(PCIDevice *dev)
|
||||
qxl->generation = 1;
|
||||
|
||||
switch (qxl->revision) {
|
||||
- case 1: /* qxl-1 */
|
||||
- pci_device_id = 0x0100;
|
||||
- pci_device_rev = 1;
|
||||
+ case 1: /* spice 0.4 -- qxl-1 */
|
||||
+ pci_device_id = QXL_DEVICE_ID_STABLE;
|
||||
+ pci_device_rev = QXL_REVISION_STABLE_V04;
|
||||
break;
|
||||
- case 2: /* qxl-2 */
|
||||
- pci_device_id = 0x0100;
|
||||
- pci_device_rev = 2;
|
||||
+ case 2: /* spice 0.6 -- qxl-2 */
|
||||
+ pci_device_id = QXL_DEVICE_ID_STABLE;
|
||||
+ pci_device_rev = QXL_REVISION_STABLE_V06;
|
||||
break;
|
||||
- default: /* unstable */
|
||||
- pci_device_id = 0x01ff;
|
||||
+ default: /* experimental */
|
||||
+ pci_device_id = QXL_DEVICE_ID_DEVEL;
|
||||
pci_device_rev = 1;
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
26
0024-qxl-support-QXL_IO_DESTROY_ALL_SURFACES.patch
Normal file
26
0024-qxl-support-QXL_IO_DESTROY_ALL_SURFACES.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From c9f9044475d392e55de4dd6e343477ce1a57eabc Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 17:51:09 +0200
|
||||
Subject: [PATCH 24/39] qxl: support QXL_IO_DESTROY_ALL_SURFACES
|
||||
|
||||
---
|
||||
hw/qxl.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 2a0ea4e..7bd4467 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -930,6 +930,9 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
case QXL_IO_DESTROY_SURFACE_WAIT:
|
||||
d->ssd.worker->destroy_surface_wait(d->ssd.worker, val);
|
||||
break;
|
||||
+ case QXL_IO_DESTROY_ALL_SURFACES:
|
||||
+ d->ssd.worker->destroy_surfaces(d->ssd.worker);
|
||||
+ break;
|
||||
default:
|
||||
fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
|
||||
abort();
|
||||
--
|
||||
1.7.2.3
|
||||
|
57
0025-spice-vmc-two-bugfixes-in-vmc_read.patch
Normal file
57
0025-spice-vmc-two-bugfixes-in-vmc_read.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From c8fa37e075cf59e8b21af9211f6a6348c92ed098 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Mon, 12 Jul 2010 22:48:59 +0300
|
||||
Subject: [PATCH 25/39] spice-vmc: two bugfixes in vmc_read
|
||||
|
||||
* throttling with no discard means possible recursion, make
|
||||
vmc_read handle that.
|
||||
* zero datapos when data is done (from rhel6 version)
|
||||
---
|
||||
hw/spice-vmc.c | 13 ++++++++-----
|
||||
1 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 3f6a2bb..06e30e6 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -45,7 +45,7 @@ static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
ssize_t out;
|
||||
|
||||
out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -54,13 +54,16 @@ static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
int bytes = MIN(len, svc->datalen);
|
||||
|
||||
- dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
- if (bytes) {
|
||||
+ dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
|
||||
+ if (bytes > 0) {
|
||||
memcpy(buf, svc->datapos, bytes);
|
||||
svc->datapos += bytes;
|
||||
svc->datalen -= bytes;
|
||||
- if (0 == svc->datalen) {
|
||||
+ assert(svc->datalen >= 0);
|
||||
+ if (svc->datalen == 0) {
|
||||
+ svc->datapos = 0;
|
||||
virtio_serial_throttle_port(&svc->port, false);
|
||||
+ // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
@@ -140,7 +143,7 @@ static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len
|
||||
SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
|
||||
dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
- assert(svc->datapos == 0);
|
||||
+ assert(svc->datalen == 0);
|
||||
if (svc->bufsize < len) {
|
||||
svc->bufsize = len;
|
||||
svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -0,0 +1,84 @@
|
||||
From 0045574847883167f5c2b569811e049616ee611d Mon Sep 17 00:00:00 2001
|
||||
From: Yonit Halperin <yhalperi@redhat.com>
|
||||
Date: Wed, 14 Jul 2010 13:26:34 +0300
|
||||
Subject: [PATCH 26/39] spice: enabling/disabling jpeg and zlib-over-glz via spice command line args
|
||||
|
||||
---
|
||||
qemu-config.c | 6 ++++++
|
||||
spice.c | 29 +++++++++++++++++++++++++++++
|
||||
2 files changed, 35 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/qemu-config.c b/qemu-config.c
|
||||
index 74bfc62..3e4fcf9 100644
|
||||
--- a/qemu-config.c
|
||||
+++ b/qemu-config.c
|
||||
@@ -384,6 +384,12 @@ QemuOptsList qemu_spice_opts = {
|
||||
},{
|
||||
.name = "tls-ciphers",
|
||||
.type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "jpeg",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "zlib-glz",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end if list */ }
|
||||
},
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 1109b4f..201e53c 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -207,6 +207,23 @@ int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
port, tls_port, subject);
|
||||
}
|
||||
|
||||
+static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
+{
|
||||
+ if (!strcmp(str, "wan")) {
|
||||
+ return SPICE_WAN_COMPRESSION_AUTO;
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(str, "never")) {
|
||||
+ return SPICE_WAN_COMPRESSION_NEVER;
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(str, "always")) {
|
||||
+ return SPICE_WAN_COMPRESSION_ALWAYS;
|
||||
+ }
|
||||
+
|
||||
+ return SPICE_WAN_COMPRESSION_INVALID;
|
||||
+}
|
||||
+
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
@@ -218,6 +235,7 @@ void qemu_spice_init(void)
|
||||
*x509_cert_file = NULL,
|
||||
*x509_cacert_file = NULL;
|
||||
int port, tls_port, len;
|
||||
+ const char *jpeg, *zlib_glz;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
@@ -283,6 +301,17 @@ void qemu_spice_init(void)
|
||||
/* TODO: make configurable via cmdline */
|
||||
spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
|
||||
+ jpeg = qemu_opt_get(opts, "jpeg");
|
||||
+ zlib_glz = qemu_opt_get(opts, "zlib-glz");
|
||||
+
|
||||
+ if (jpeg) {
|
||||
+ spice_server_set_jpeg_compression(spice_server, get_wan_compression_value(jpeg));
|
||||
+ }
|
||||
+
|
||||
+ if (zlib_glz) {
|
||||
+ spice_server_set_zlib_glz_compression(spice_server, get_wan_compression_value(zlib_glz));
|
||||
+ }
|
||||
+
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
57
0027-ifdef-new-config-options.patch
Normal file
57
0027-ifdef-new-config-options.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From 9200133d24ee5b5dab71ce922882c3534d9e8a5a Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 15 Jul 2010 09:01:28 +0200
|
||||
Subject: [PATCH 27/39] ifdef new config options.
|
||||
|
||||
---
|
||||
spice.c | 6 +++++-
|
||||
1 files changed, 5 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 201e53c..76e6ac1 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -207,6 +207,7 @@ int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
port, tls_port, subject);
|
||||
}
|
||||
|
||||
+#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
|
||||
static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
{
|
||||
if (!strcmp(str, "wan")) {
|
||||
@@ -223,6 +224,7 @@ static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
|
||||
return SPICE_WAN_COMPRESSION_INVALID;
|
||||
}
|
||||
+#endif
|
||||
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
@@ -235,7 +237,6 @@ void qemu_spice_init(void)
|
||||
*x509_cert_file = NULL,
|
||||
*x509_cacert_file = NULL;
|
||||
int port, tls_port, len;
|
||||
- const char *jpeg, *zlib_glz;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
@@ -301,6 +302,8 @@ void qemu_spice_init(void)
|
||||
/* TODO: make configurable via cmdline */
|
||||
spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
|
||||
+#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
|
||||
+ const char *jpeg, *zlib_glz;
|
||||
jpeg = qemu_opt_get(opts, "jpeg");
|
||||
zlib_glz = qemu_opt_get(opts, "zlib-glz");
|
||||
|
||||
@@ -311,6 +314,7 @@ void qemu_spice_init(void)
|
||||
if (zlib_glz) {
|
||||
spice_server_set_zlib_glz_compression(spice_server, get_wan_compression_value(zlib_glz));
|
||||
}
|
||||
+#endif
|
||||
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
--
|
||||
1.7.2.3
|
||||
|
27
0028-spice-vmc-add-counter-to-debug-statements.patch
Normal file
27
0028-spice-vmc-add-counter-to-debug-statements.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 2165916a311108d39c7aa45e5189af26712234b8 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Wed, 14 Jul 2010 16:30:35 +0300
|
||||
Subject: [PATCH 28/39] spice-vmc: add counter to debug statements
|
||||
|
||||
---
|
||||
hw/spice-vmc.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 06e30e6..041f243 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -23,8 +23,9 @@
|
||||
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
+ static unsigned __dprintf_counter = 0; \
|
||||
if (_svc->debug >= _level) { \
|
||||
- fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
+ fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -0,0 +1,53 @@
|
||||
From f86c044ae075d142e658e866572eb0a37ecad2e1 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Thu, 22 Jul 2010 00:21:18 +0300
|
||||
Subject: [PATCH 29/39] spice-vmc: split vmc_write to max sized virtio_serial_write calls
|
||||
|
||||
workaround for current windows driver limitation (RHBZ 617000)
|
||||
---
|
||||
hw/spice-vmc.c | 21 ++++++++++++++++++---
|
||||
1 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 041f243..b9d64a2 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
#define VMC_DEVICE_NAME "spicevmc"
|
||||
|
||||
+#define VMC_MAX_HOST_WRITE 2048
|
||||
+
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
static unsigned __dprintf_counter = 0; \
|
||||
@@ -43,10 +45,23 @@ typedef struct SpiceVirtualChannel {
|
||||
static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- ssize_t out;
|
||||
+ ssize_t out = 0;
|
||||
+ ssize_t last_out;
|
||||
+ uint8_t* p = (uint8_t*)buf;
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ last_out = virtio_serial_write(&svc->port, p,
|
||||
+ MIN(len, VMC_MAX_HOST_WRITE));
|
||||
+ if (last_out > 0) {
|
||||
+ out += last_out;
|
||||
+ len -= last_out;
|
||||
+ p += last_out;
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
|
||||
return out;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -0,0 +1,24 @@
|
||||
From be78cc4a136f8ec63dc6d7efd8356625c639a877 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Tue, 3 Aug 2010 11:37:51 +0300
|
||||
Subject: [PATCH 30/39] qxl: add 800x480 resolution to qxl_modes (n900 native)
|
||||
|
||||
---
|
||||
hw/qxl.c | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 7bd4467..86c0e03 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -64,6 +64,7 @@
|
||||
|
||||
static QXLMode qxl_modes[] = {
|
||||
QXL_MODE_EX(640, 480),
|
||||
+ QXL_MODE_EX(800, 480),
|
||||
QXL_MODE_EX(800, 600),
|
||||
QXL_MODE_EX(832, 624),
|
||||
QXL_MODE_EX(1024, 768),
|
||||
--
|
||||
1.7.2.3
|
||||
|
259
0031-qxl-savevm-fixes.patch
Normal file
259
0031-qxl-savevm-fixes.patch
Normal file
@ -0,0 +1,259 @@
|
||||
From e55e5fd43113a5b266efa6d17e44f0e9231a98ed Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 25 Aug 2010 16:08:37 +0000
|
||||
Subject: [PATCH 31/39] qxl: savevm fixes
|
||||
|
||||
---
|
||||
hw/qxl.c | 125 +++++++++++++++++++++++++++++++++++++++++++++----------------
|
||||
hw/qxl.h | 6 +++
|
||||
2 files changed, 98 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 86c0e03..4a15200 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1087,6 +1087,14 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
{
|
||||
PCIQXLDevice *qxl = opaque;
|
||||
qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
|
||||
+
|
||||
+ if (!running && qxl->mode == QXL_MODE_NATIVE) {
|
||||
+ /* dirty all vram (which holds surfaces) to make sure it is saved */
|
||||
+ /* FIXME #1: should go out during "live" stage */
|
||||
+ /* FIXME #2: we only need to save the areas which are actually used */
|
||||
+ ram_addr_t addr = qxl->vram_offset;
|
||||
+ qxl_set_dirty(addr, addr + qxl->vram_size);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* display change listener */
|
||||
@@ -1134,6 +1142,8 @@ static int qxl_init(PCIDevice *dev)
|
||||
qxl->id = device_id;
|
||||
qxl->mode = QXL_MODE_UNDEFINED;
|
||||
qxl->generation = 1;
|
||||
+ qxl->num_memslots = NUM_MEMSLOTS;
|
||||
+ qxl->num_surfaces = NUM_SURFACES;
|
||||
|
||||
switch (qxl->revision) {
|
||||
case 1: /* spice 0.4 -- qxl-1 */
|
||||
@@ -1183,7 +1193,8 @@ static int qxl_init(PCIDevice *dev)
|
||||
if (ram_size < 16 * 1024 * 1024)
|
||||
ram_size = 16 * 1024 * 1024;
|
||||
qxl->vga.vram_size = ram_size;
|
||||
- qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar0", qxl->vga.vram_size);
|
||||
+ qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
|
||||
+ qxl->vga.vram_size);
|
||||
qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
|
||||
|
||||
pci_config_set_class(config, PCI_CLASS_DISPLAY_OTHER);
|
||||
@@ -1195,14 +1206,14 @@ static int qxl_init(PCIDevice *dev)
|
||||
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
||||
|
||||
qxl->rom_size = qxl_rom_size();
|
||||
- qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar2", qxl->rom_size);
|
||||
+ qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
|
||||
init_qxl_rom(qxl);
|
||||
init_qxl_ram(qxl);
|
||||
|
||||
if (qxl->vram_size < 16 * 1024 * 1024)
|
||||
qxl->vram_size = 16 * 1024 * 1024;
|
||||
qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
|
||||
- qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar1", qxl->vram_size);
|
||||
+ qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
|
||||
|
||||
pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
|
||||
msb_mask(QXL_IO_RANGE_SIZE * 2 - 1),
|
||||
@@ -1237,14 +1248,12 @@ static void qxl_pre_save(void *opaque)
|
||||
uint8_t *ram_start = d->vga.vram_ptr;
|
||||
|
||||
dprintf(d, 1, "%s:\n", __FUNCTION__);
|
||||
-#if 1 /* wanna zap this */
|
||||
if (d->last_release == NULL) {
|
||||
d->last_release_offset = 0;
|
||||
} else {
|
||||
d->last_release_offset = (uint8_t *)d->last_release - ram_start;
|
||||
}
|
||||
assert(d->last_release_offset < d->vga.vram_size);
|
||||
-#endif
|
||||
}
|
||||
|
||||
static int qxl_pre_load(void *opaque)
|
||||
@@ -1306,29 +1315,55 @@ static int qxl_post_load(void *opaque, int version)
|
||||
}
|
||||
dprintf(d, 1, "%s: done\n", __FUNCTION__);
|
||||
|
||||
-#if 1 /* wanna zap this */
|
||||
- if (d->last_release_offset >= d->vga.vram_size) {
|
||||
- dprintf(d, 1, "%s: invalid last_release_offset %u, ram_size %u\n",
|
||||
- __FUNCTION__, d->last_release_offset, d->vga.vram_size);
|
||||
- exit(-1);
|
||||
- }
|
||||
-
|
||||
+ assert(d->last_release_offset < d->vga.vram_size);
|
||||
if (d->last_release_offset == 0) {
|
||||
d->last_release = NULL;
|
||||
} else {
|
||||
d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
|
||||
}
|
||||
-#endif
|
||||
+
|
||||
+ /* spice 0.4 compatibility -- accept but ignore */
|
||||
+ free(d->worker_data);
|
||||
+ d->worker_data = NULL;
|
||||
+ d->worker_data_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-#define QXL_VER 1
|
||||
+#define QXL_SAVE_VERSION 20
|
||||
+
|
||||
+static bool qxl_test_worker_data(void *opaque, int version_id)
|
||||
+{
|
||||
+ PCIQXLDevice* d = opaque;
|
||||
+
|
||||
+ if (d->revision != 1) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!d->worker_data_size) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!d->worker_data) {
|
||||
+ d->worker_data = qemu_malloc(d->worker_data_size);
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool qxl_test_spice04(void *opaque, int version_id)
|
||||
+{
|
||||
+ PCIQXLDevice* d = opaque;
|
||||
+ return d->revision == 1;
|
||||
+}
|
||||
+
|
||||
+static bool qxl_test_spice06(void *opaque)
|
||||
+{
|
||||
+ PCIQXLDevice* d = opaque;
|
||||
+ return d->revision > 1;
|
||||
+}
|
||||
|
||||
static VMStateDescription qxl_memslot = {
|
||||
.name = "qxl-memslot",
|
||||
- .version_id = QXL_VER,
|
||||
- .minimum_version_id = QXL_VER,
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(slot.mem_start, struct guest_slots),
|
||||
VMSTATE_UINT64(slot.mem_end, struct guest_slots),
|
||||
@@ -1339,8 +1374,8 @@ static VMStateDescription qxl_memslot = {
|
||||
|
||||
static VMStateDescription qxl_surface = {
|
||||
.name = "qxl-surface",
|
||||
- .version_id = QXL_VER,
|
||||
- .minimum_version_id = QXL_VER,
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(width, QXLSurfaceCreate),
|
||||
VMSTATE_UINT32(height, QXLSurfaceCreate),
|
||||
@@ -1355,34 +1390,58 @@ static VMStateDescription qxl_surface = {
|
||||
}
|
||||
};
|
||||
|
||||
+static VMStateDescription qxl_vmstate_spice06 = {
|
||||
+ .name = "qxl/spice06",
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
+ .fields = (VMStateField []) {
|
||||
+ VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
|
||||
+ VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
|
||||
+ qxl_memslot, struct guest_slots),
|
||||
+ VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
|
||||
+ qxl_surface, QXLSurfaceCreate),
|
||||
+ VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
|
||||
+ VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
|
||||
+ vmstate_info_uint64, uint64_t),
|
||||
+ VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static VMStateDescription qxl_vmstate = {
|
||||
.name = "qxl",
|
||||
- .version_id = QXL_VER,
|
||||
- .minimum_version_id = QXL_VER,
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
.pre_save = qxl_pre_save,
|
||||
.pre_load = qxl_pre_load,
|
||||
.post_load = qxl_post_load,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
|
||||
- VMSTATE_STRUCT(vga, PCIQXLDevice, QXL_VER, vmstate_vga_common, VGACommonState),
|
||||
+ VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
|
||||
VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
|
||||
-#if 1 /* wanna zap this */
|
||||
VMSTATE_UINT32(num_free_res, PCIQXLDevice),
|
||||
VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
|
||||
-#endif
|
||||
VMSTATE_UINT32(mode, PCIQXLDevice),
|
||||
VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
|
||||
-#if 1 /* new stuff */
|
||||
- VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, QXL_VER,
|
||||
- qxl_memslot, struct guest_slots),
|
||||
- VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, QXL_VER,
|
||||
- qxl_surface, QXLSurfaceCreate),
|
||||
- VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, QXL_VER,
|
||||
- vmstate_info_uint64, uint64_t),
|
||||
- VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
|
||||
-#endif
|
||||
+
|
||||
+ /* spice 0.4 sends/expects them */
|
||||
+ VMSTATE_VBUFFER_UINT32(vga.vram_ptr, PCIQXLDevice, 0, qxl_test_spice04, 0,
|
||||
+ vga.vram_size),
|
||||
+ VMSTATE_UINT32_TEST(worker_data_size, PCIQXLDevice, qxl_test_spice04),
|
||||
+ VMSTATE_VBUFFER_UINT32(worker_data, PCIQXLDevice, 0, qxl_test_worker_data, 0,
|
||||
+ worker_data_size),
|
||||
+
|
||||
VMSTATE_END_OF_LIST()
|
||||
- }
|
||||
+ },
|
||||
+ .subsections = (VMStateSubsection[]) {
|
||||
+ {
|
||||
+ /* additional spice 0.6 state */
|
||||
+ .vmsd = &qxl_vmstate_spice06,
|
||||
+ .needed = qxl_test_spice06,
|
||||
+ },{
|
||||
+ /* end of list */
|
||||
+ },
|
||||
+ },
|
||||
};
|
||||
|
||||
static PCIDeviceInfo qxl_info = {
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index 1216405..caf3684 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -24,6 +24,9 @@ typedef struct PCIQXLDevice {
|
||||
int generation;
|
||||
uint32_t revision;
|
||||
|
||||
+ int32_t num_memslots;
|
||||
+ int32_t num_surfaces;
|
||||
+
|
||||
struct guest_slots {
|
||||
QXLMemSlot slot;
|
||||
void *ptr;
|
||||
@@ -74,6 +77,9 @@ typedef struct PCIQXLDevice {
|
||||
/* io bar */
|
||||
uint32_t io_base;
|
||||
|
||||
+ /* spice 0.4 loadvm compatibility */
|
||||
+ void *worker_data;
|
||||
+ uint32_t worker_data_size;
|
||||
} PCIQXLDevice;
|
||||
|
||||
#define PANIC_ON(x) if ((x)) { \
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -0,0 +1,53 @@
|
||||
From f48f184b9d22bbd2e34fb4f3a7a760f0e98fae64 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:45:30 +0200
|
||||
Subject: [PATCH 32/39] Revert "spice-vmc: split vmc_write to max sized virtio_serial_write calls"
|
||||
|
||||
This reverts commit 380b75548db5116e538dc646e84bceb1c4b0e61b.
|
||||
---
|
||||
hw/spice-vmc.c | 21 +++------------------
|
||||
1 files changed, 3 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index b9d64a2..041f243 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -21,8 +21,6 @@
|
||||
#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
#define VMC_DEVICE_NAME "spicevmc"
|
||||
|
||||
-#define VMC_MAX_HOST_WRITE 2048
|
||||
-
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
static unsigned __dprintf_counter = 0; \
|
||||
@@ -45,23 +43,10 @@ typedef struct SpiceVirtualChannel {
|
||||
static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- ssize_t out = 0;
|
||||
- ssize_t last_out;
|
||||
- uint8_t* p = (uint8_t*)buf;
|
||||
-
|
||||
- while (len > 0) {
|
||||
- last_out = virtio_serial_write(&svc->port, p,
|
||||
- MIN(len, VMC_MAX_HOST_WRITE));
|
||||
- if (last_out > 0) {
|
||||
- out += last_out;
|
||||
- len -= last_out;
|
||||
- p += last_out;
|
||||
- } else {
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
+ ssize_t out;
|
||||
|
||||
- dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
|
||||
+ out = virtio_serial_write(&svc->port, buf, len);
|
||||
+ dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
28
0033-Revert-spice-vmc-add-counter-to-debug-statements.patch
Normal file
28
0033-Revert-spice-vmc-add-counter-to-debug-statements.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From a5d6e7e76bf5f5fb0e2c8232ddca2b850bfc1afa Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:45:49 +0200
|
||||
Subject: [PATCH 33/39] Revert "spice-vmc: add counter to debug statements"
|
||||
|
||||
This reverts commit f3ab5192a20ee9dc7776b13ec0ba75030bb52a20.
|
||||
---
|
||||
hw/spice-vmc.c | 3 +--
|
||||
1 files changed, 1 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 041f243..06e30e6 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -23,9 +23,8 @@
|
||||
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
- static unsigned __dprintf_counter = 0; \
|
||||
if (_svc->debug >= _level) { \
|
||||
- fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
|
||||
+ fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
55
0034-Revert-spice-vmc-two-bugfixes-in-vmc_read.patch
Normal file
55
0034-Revert-spice-vmc-two-bugfixes-in-vmc_read.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 84115ef1adf343c34eebfb1045cbc5c72892e3b2 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:46:18 +0200
|
||||
Subject: [PATCH 34/39] Revert "spice-vmc: two bugfixes in vmc_read"
|
||||
|
||||
This reverts commit 71983a37e30c68beab5e9056a4600d2958f77a04.
|
||||
---
|
||||
hw/spice-vmc.c | 13 +++++--------
|
||||
1 files changed, 5 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 06e30e6..3f6a2bb 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -45,7 +45,7 @@ static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
ssize_t out;
|
||||
|
||||
out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -54,16 +54,13 @@ static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
int bytes = MIN(len, svc->datalen);
|
||||
|
||||
- dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
|
||||
- if (bytes > 0) {
|
||||
+ dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
+ if (bytes) {
|
||||
memcpy(buf, svc->datapos, bytes);
|
||||
svc->datapos += bytes;
|
||||
svc->datalen -= bytes;
|
||||
- assert(svc->datalen >= 0);
|
||||
- if (svc->datalen == 0) {
|
||||
- svc->datapos = 0;
|
||||
+ if (0 == svc->datalen) {
|
||||
virtio_serial_throttle_port(&svc->port, false);
|
||||
- // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
@@ -143,7 +140,7 @@ static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len
|
||||
SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
|
||||
dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
- assert(svc->datalen == 0);
|
||||
+ assert(svc->datapos == 0);
|
||||
if (svc->bufsize < len) {
|
||||
svc->bufsize = len;
|
||||
svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
--
|
||||
1.7.2.3
|
||||
|
181
0035-Revert-spice-live-migration-wip.patch
Normal file
181
0035-Revert-spice-live-migration-wip.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 3e0d1b6ed5f8e8b871803337008e104398e4db0a Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:48:57 +0200
|
||||
Subject: [PATCH 35/39] Revert "spice: live migration (wip)."
|
||||
|
||||
This reverts commit 85b9db9ba993af737c9c402cf2f67db7b1b3cbce.
|
||||
|
||||
Conflicts:
|
||||
|
||||
spice.c
|
||||
---
|
||||
monitor.c | 1 -
|
||||
qemu-monitor.hx | 11 -------
|
||||
qemu-spice.h | 2 -
|
||||
spice.c | 87 -------------------------------------------------------
|
||||
4 files changed, 0 insertions(+), 101 deletions(-)
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index 6674a8c..e51df62 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -57,7 +57,6 @@
|
||||
#include "osdep.h"
|
||||
#include "exec-all.h"
|
||||
#include "qemu-kvm.h"
|
||||
-#include "qemu-spice.h"
|
||||
|
||||
//#define DEBUG
|
||||
//#define DEBUG_COMPLETION
|
||||
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
|
||||
index c2570d9..da7b796 100644
|
||||
--- a/qemu-monitor.hx
|
||||
+++ b/qemu-monitor.hx
|
||||
@@ -2510,17 +2510,6 @@ ETEXI
|
||||
|
||||
HXCOMM DO NOT add new commands after 'info', move your addition before it!
|
||||
|
||||
-#if defined(CONFIG_SPICE)
|
||||
- {
|
||||
- .name = "spice_migrate_info",
|
||||
- .args_type = "hostname:s,port:i?,tls-port:i?,cert-subject:s?",
|
||||
- .params = "hostname port tls-port cert-subject",
|
||||
- .help = "send migration info to spice client",
|
||||
- .user_print = monitor_user_noop,
|
||||
- .mhandler.cmd_new = mon_spice_migrate,
|
||||
- },
|
||||
-#endif
|
||||
-
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index 3c8e959..6f19ba7 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -16,8 +16,6 @@ void qemu_spice_input_init(void);
|
||||
void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
-int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
-
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
#define using_spice 0
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 76e6ac1..e6f047d 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
-#include "hw/hw.h"
|
||||
|
||||
/* core bits */
|
||||
|
||||
@@ -123,90 +122,8 @@ static SpiceCoreInterface core_interface = {
|
||||
.watch_remove = watch_remove,
|
||||
};
|
||||
|
||||
-/* handle client migration */
|
||||
-
|
||||
-static int spice_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
|
||||
-{
|
||||
- static int last_stage;
|
||||
- static int migrate_client, client_connected;
|
||||
- int ret = 1;
|
||||
-
|
||||
- if (last_stage != stage) {
|
||||
- last_stage = stage;
|
||||
- fprintf(stderr, "%s: stage %d\n", __FUNCTION__, stage);
|
||||
- } else {
|
||||
- fprintf(stderr, ".");
|
||||
- }
|
||||
-
|
||||
- switch (stage) {
|
||||
- case 1:
|
||||
- migrate_client = 1;
|
||||
- client_connected = 0;
|
||||
- fprintf(stderr, "%s: start client migration\n", __FUNCTION__);
|
||||
- if (spice_server_migrate_start(spice_server) != 0) {
|
||||
- fprintf(stderr, "%s: fail -> no client migration\n", __FUNCTION__);
|
||||
- migrate_client = 0;
|
||||
- }
|
||||
- break;
|
||||
- case 2:
|
||||
- if (!migrate_client)
|
||||
- break;
|
||||
- switch (spice_server_migrate_client_state(spice_server)) {
|
||||
- case SPICE_MIGRATE_CLIENT_NONE:
|
||||
- fprintf(stderr, "%s: no client connected\n", __FUNCTION__);
|
||||
- migrate_client = 0;
|
||||
- break;
|
||||
- case SPICE_MIGRATE_CLIENT_WAITING:
|
||||
- ret = 0;
|
||||
- break;
|
||||
- case SPICE_MIGRATE_CLIENT_READY:
|
||||
- if (!client_connected) {
|
||||
- fprintf(stderr, "%s: client connected to target\n", __FUNCTION__);
|
||||
- client_connected = 1;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- break;
|
||||
- case 3:
|
||||
- if (migrate_client && client_connected) {
|
||||
- fprintf(stderr, "%s: finish client migration\n", __FUNCTION__);
|
||||
- spice_server_migrate_end(spice_server, 1);
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static void spice_save(QEMUFile *f, void *opaque)
|
||||
-{
|
||||
- fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
-}
|
||||
-
|
||||
-static int spice_load(QEMUFile *f, void *opaque, int version_id)
|
||||
-{
|
||||
- fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
/* functions for the rest of qemu */
|
||||
|
||||
-int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
-{
|
||||
- const char *hostname = qdict_get_str(qdict, "hostname");
|
||||
- const char *subject = qdict_get_try_str(qdict, "cert-subject");
|
||||
- int port = qdict_get_try_int(qdict, "port", -1);
|
||||
- int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
|
||||
-
|
||||
- if (!spice_server) {
|
||||
- qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* TODO: Convert to QError */
|
||||
- return spice_server_migrate_info(spice_server, hostname,
|
||||
- port, tls_port, subject);
|
||||
-}
|
||||
-
|
||||
#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
|
||||
static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
{
|
||||
@@ -322,10 +239,6 @@ void qemu_spice_init(void)
|
||||
qemu_spice_input_init();
|
||||
qemu_spice_audio_init();
|
||||
|
||||
- register_savevm_live(NULL, "spice", -1, 1, NULL,
|
||||
- spice_live, spice_save, spice_load,
|
||||
- spice_server);
|
||||
-
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
qemu_free(x509_cacert_file);
|
||||
--
|
||||
1.7.2.3
|
||||
|
590
0036-Revert-spice-add-pci-vdi-port-backend-obsolete.patch
Normal file
590
0036-Revert-spice-add-pci-vdi-port-backend-obsolete.patch
Normal file
@ -0,0 +1,590 @@
|
||||
From 7bad8970dd7db3e3e0e0b11626656c68f4238884 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:49:22 +0200
|
||||
Subject: [PATCH 36/39] Revert "spice: add pci vdi port backend (obsolete)."
|
||||
|
||||
This reverts commit b56a2ed131bdb4ce42db8f33f87603c416e7a60a.
|
||||
---
|
||||
Makefile.target | 2 +-
|
||||
hw/spice-vdi.c | 556 -------------------------------------------------------
|
||||
2 files changed, 1 insertions(+), 557 deletions(-)
|
||||
delete mode 100644 hw/spice-vdi.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 025bdb8..90544c5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,7 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o spice-vdi.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vdi.c b/hw/spice-vdi.c
|
||||
deleted file mode 100644
|
||||
index 23cbbe1..0000000
|
||||
--- a/hw/spice-vdi.c
|
||||
+++ /dev/null
|
||||
@@ -1,556 +0,0 @@
|
||||
-#include <pthread.h>
|
||||
-#include <signal.h>
|
||||
-
|
||||
-#include "qemu-common.h"
|
||||
-#include "qemu-spice.h"
|
||||
-#include "hw/hw.h"
|
||||
-#include "hw/pc.h"
|
||||
-#include "hw/pci.h"
|
||||
-#include "console.h"
|
||||
-#include "hw/vga_int.h"
|
||||
-#include "qemu-timer.h"
|
||||
-#include "sysemu.h"
|
||||
-#include "console.h"
|
||||
-#include "pci.h"
|
||||
-#include "hw.h"
|
||||
-#include "cpu-common.h"
|
||||
-
|
||||
-#include <spice.h>
|
||||
-#include <spice-experimental.h>
|
||||
-#include <spice/ipc_ring.h>
|
||||
-#include <spice/barrier.h>
|
||||
-
|
||||
-#undef SPICE_RING_PROD_ITEM
|
||||
-#define SPICE_RING_PROD_ITEM(r, ret) { \
|
||||
- typeof(r) start = r; \
|
||||
- typeof(r) end = r + 1; \
|
||||
- uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
||||
- typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
||||
- if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
- abort(); \
|
||||
- } \
|
||||
- ret = &m_item->el; \
|
||||
- }
|
||||
-
|
||||
-#undef SPICE_RING_CONS_ITEM
|
||||
-#define SPICE_RING_CONS_ITEM(r, ret) { \
|
||||
- typeof(r) start = r; \
|
||||
- typeof(r) end = r + 1; \
|
||||
- uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
||||
- typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
||||
- if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
- abort(); \
|
||||
- } \
|
||||
- ret = &m_item->el; \
|
||||
- }
|
||||
-
|
||||
-
|
||||
-#undef ALIGN
|
||||
-#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
||||
-
|
||||
-#define REDHAT_PCI_VENDOR_ID 0x1b36
|
||||
-#define VDI_PORT_DEVICE_ID 0x0105
|
||||
-#define VDI_PORT_REVISION 0x01
|
||||
-
|
||||
-#define VDI_PORT_INTERRUPT (1 << 0)
|
||||
-
|
||||
-#define VDI_PORT_MAGIC (*(uint32_t*)"VDIP")
|
||||
-
|
||||
-#define VDI_PORT_DEV_NAME "vdi_port"
|
||||
-#define VDI_PORT_SAVE_VERSION 20
|
||||
-
|
||||
-#include <spice/start-packed.h>
|
||||
-
|
||||
-typedef struct SPICE_ATTR_PACKED VDIPortPacket {
|
||||
- uint32_t gen;
|
||||
- uint32_t size;
|
||||
- uint8_t data[512 - 2 * sizeof(uint32_t)];
|
||||
-} VDIPortPacket;
|
||||
-
|
||||
-SPICE_RING_DECLARE(VDIPortRing, VDIPortPacket, 32);
|
||||
-
|
||||
-enum {
|
||||
- VDI_PORT_IO_RANGE_INDEX,
|
||||
- VDI_PORT_RAM_RANGE_INDEX,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- VDI_PORT_IO_CONNECTION,
|
||||
- VDI_PORT_IO_NOTIFY = 4,
|
||||
- VDI_PORT_IO_UPDATE_IRQ = 8,
|
||||
-
|
||||
- VDI_PORT_IO_RANGE_SIZE = 12
|
||||
-};
|
||||
-
|
||||
-typedef struct SPICE_ATTR_PACKED VDIPortRam {
|
||||
- uint32_t magic;
|
||||
- uint32_t generation;
|
||||
- uint32_t int_pending;
|
||||
- uint32_t int_mask;
|
||||
- VDIPortRing input;
|
||||
- VDIPortRing output;
|
||||
- uint32_t reserv[32];
|
||||
-} VDIPortRam;
|
||||
-
|
||||
-#include <spice/end-packed.h>
|
||||
-
|
||||
-typedef struct PCIVDIPortDevice {
|
||||
- PCIDevice pci_dev;
|
||||
- uint32_t io_base;
|
||||
- uint64_t ram_offset;
|
||||
- uint32_t ram_size;
|
||||
- VDIPortRam *ram;
|
||||
- uint32_t connected;
|
||||
- int running;
|
||||
- int new_gen_on_resume;
|
||||
- int active_interface;
|
||||
- SpiceVDIPortInstance sin;
|
||||
- int plug_read_pos;
|
||||
-} PCIVDIPortDevice;
|
||||
-
|
||||
-static int debug = 1;
|
||||
-
|
||||
-static inline uint32_t msb_mask(uint32_t val)
|
||||
-{
|
||||
- uint32_t mask;
|
||||
-
|
||||
- do {
|
||||
- mask = ~(val - 1) & val;
|
||||
- val &= ~mask;
|
||||
- } while (mask < val);
|
||||
-
|
||||
- return mask;
|
||||
-}
|
||||
-
|
||||
-static inline void atomic_or(uint32_t *var, uint32_t add)
|
||||
-{
|
||||
- __asm__ __volatile__ ("lock; orl %1, %0" : "+m" (*var) : "r" (add) : "memory");
|
||||
-}
|
||||
-
|
||||
-static inline uint32_t atomic_exchange(uint32_t val, uint32_t *ptr)
|
||||
-{
|
||||
- __asm__ __volatile__("xchgl %0, %1" : "+q"(val), "+m" (*ptr) : : "memory");
|
||||
- return val;
|
||||
-}
|
||||
-
|
||||
-static void set_dirty(void *base, ram_addr_t offset, void *start, uint32_t length)
|
||||
-{
|
||||
- assert(start >= base);
|
||||
-
|
||||
- ram_addr_t addr = (ram_addr_t)((uint8_t*)start - (uint8_t*)base) + offset;
|
||||
- ram_addr_t end = ALIGN(addr + length, TARGET_PAGE_SIZE);
|
||||
-
|
||||
- do {
|
||||
- cpu_physical_memory_set_dirty(addr);
|
||||
- addr += TARGET_PAGE_SIZE;
|
||||
- } while ( addr < end );
|
||||
-}
|
||||
-
|
||||
-static inline void vdi_port_set_dirty(PCIVDIPortDevice *d, void *start, uint32_t length)
|
||||
-{
|
||||
- set_dirty(d->ram, d->ram_offset, start, length);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_new_gen(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- d->ram->generation = (d->ram->generation + 1 == 0) ? 1 : d->ram->generation + 1;
|
||||
- vdi_port_set_dirty(d, &d->ram->generation, sizeof(d->ram->generation));
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_irq_level(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- return !!(d->ram->int_pending & d->ram->int_mask);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_notify_guest(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- uint32_t events = VDI_PORT_INTERRUPT;
|
||||
- uint32_t old_pending;
|
||||
-
|
||||
- if (!d->connected) {
|
||||
- return;
|
||||
- }
|
||||
- old_pending = __sync_fetch_and_or(&d->ram->int_pending, events);
|
||||
- if ((old_pending & events) == events) {
|
||||
- return;
|
||||
- }
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
- vdi_port_set_dirty(d, &d->ram->int_pending, sizeof(d->ram->int_pending));
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_interface_write(SpiceVDIPortInstance *sin,
|
||||
- const uint8_t *buf, int len)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
- VDIPortRing *ring = &d->ram->output;
|
||||
- int do_notify = false;
|
||||
- int actual_write = 0;
|
||||
- int l = len;
|
||||
-
|
||||
- if (!d->running) {
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- while (len) {
|
||||
- VDIPortPacket *packet;
|
||||
- int notify;
|
||||
- int wait;
|
||||
-
|
||||
- SPICE_RING_PROD_WAIT(ring, wait);
|
||||
- if (wait) {
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- SPICE_RING_PROD_ITEM(ring, packet);
|
||||
- packet->gen = d->ram->generation;
|
||||
- packet->size = MIN(len, sizeof(packet->data));
|
||||
- memcpy(packet->data, buf, packet->size);
|
||||
- vdi_port_set_dirty(d, packet, sizeof(*packet) - (sizeof(packet->data) - packet->size));
|
||||
-
|
||||
- SPICE_RING_PUSH(ring, notify);
|
||||
- do_notify = do_notify || notify;
|
||||
- len -= packet->size;
|
||||
- buf += packet->size;
|
||||
- actual_write += packet->size;
|
||||
- }
|
||||
- vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
-
|
||||
- if (do_notify) {
|
||||
- vdi_port_notify_guest(d);
|
||||
- }
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_write, l);
|
||||
- }
|
||||
- return actual_write;
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_interface_read(SpiceVDIPortInstance *sin,
|
||||
- uint8_t *buf, int len)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
- VDIPortRing *ring = &d->ram->input;
|
||||
- uint32_t gen = d->ram->generation;
|
||||
- VDIPortPacket *packet;
|
||||
- int do_notify = false;
|
||||
- int actual_read = 0;
|
||||
- int l = len;
|
||||
-
|
||||
- if (!d->running) {
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- while (!SPICE_RING_IS_EMPTY(ring)) {
|
||||
- int notify;
|
||||
-
|
||||
- SPICE_RING_CONS_ITEM(ring, packet);
|
||||
- if (packet->gen == gen) {
|
||||
- break;
|
||||
- }
|
||||
- SPICE_RING_POP(ring, notify);
|
||||
- do_notify = do_notify || notify;
|
||||
- }
|
||||
- while (len) {
|
||||
- VDIPortPacket *packet;
|
||||
- int wait;
|
||||
- int now;
|
||||
-
|
||||
- SPICE_RING_CONS_WAIT(ring, wait);
|
||||
-
|
||||
- if (wait) {
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- SPICE_RING_CONS_ITEM(ring, packet);
|
||||
- if (packet->size > sizeof(packet->data)) {
|
||||
- vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
- printf("%s: bad packet size\n", __FUNCTION__);
|
||||
- return 0;
|
||||
- }
|
||||
- now = MIN(len, packet->size - d->plug_read_pos);
|
||||
- memcpy(buf, packet->data + d->plug_read_pos, now);
|
||||
- len -= now;
|
||||
- buf += now;
|
||||
- actual_read += now;
|
||||
- if ((d->plug_read_pos += now) == packet->size) {
|
||||
- int notify;
|
||||
-
|
||||
- d->plug_read_pos = 0;
|
||||
- SPICE_RING_POP(ring, notify);
|
||||
- do_notify = do_notify || notify;
|
||||
- }
|
||||
- }
|
||||
- vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
-
|
||||
- if (do_notify) {
|
||||
- vdi_port_notify_guest(d);
|
||||
- }
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_read, l);
|
||||
- }
|
||||
- return actual_read;
|
||||
-}
|
||||
-
|
||||
-static SpiceVDIPortInterface vdi_port_interface = {
|
||||
- .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
- .base.description = "vdi port",
|
||||
- .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
- .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
-
|
||||
- .write = vdi_port_interface_write,
|
||||
- .read = vdi_port_interface_read,
|
||||
-};
|
||||
-
|
||||
-static void vdi_port_register_interface(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (d->active_interface ) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
- }
|
||||
- d->sin.base.sif = &vdi_port_interface.base;
|
||||
- spice_server_add_interface(spice_server, &d->sin.base);
|
||||
- d->active_interface = true;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_unregister_interface(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (!d->active_interface ) {
|
||||
- return;
|
||||
- }
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
- }
|
||||
- spice_server_remove_interface(&d->sin.base);
|
||||
- d->active_interface = false;
|
||||
-}
|
||||
-
|
||||
-static uint32_t vdi_port_dev_connect(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (d->connected) {
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: already connected\n", __FUNCTION__);
|
||||
- }
|
||||
- return 0;
|
||||
- }
|
||||
- vdi_port_new_gen(d);
|
||||
- d->connected = true;
|
||||
- vdi_port_register_interface(d);
|
||||
- return d->ram->generation;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_dev_disconnect(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (!d->connected) {
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
- }
|
||||
- return;
|
||||
- }
|
||||
- d->connected = false;
|
||||
- vdi_port_unregister_interface(d);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_dev_notify(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- spice_server_vdi_port_wakeup(&d->sin);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_write_dword(void *opaque, uint32_t addr, uint32_t val)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = opaque;
|
||||
- uint32_t io_port = addr - d->io_base;
|
||||
-
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: addr 0x%x val 0x%x\n", __FUNCTION__, addr, val);
|
||||
- }
|
||||
- switch (io_port) {
|
||||
- case VDI_PORT_IO_NOTIFY:
|
||||
- if (!d->connected) {
|
||||
- fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
- return;
|
||||
- }
|
||||
- vdi_port_dev_notify(d);
|
||||
- break;
|
||||
- case VDI_PORT_IO_UPDATE_IRQ:
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
- break;
|
||||
- case VDI_PORT_IO_CONNECTION:
|
||||
- vdi_port_dev_disconnect(d);
|
||||
- break;
|
||||
- default:
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: unexpected addr 0x%x val 0x%x\n",
|
||||
- __FUNCTION__, addr, val);
|
||||
- }
|
||||
- };
|
||||
-}
|
||||
-
|
||||
-static uint32_t vdi_port_read_dword(void *opaque, uint32_t addr)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = opaque;
|
||||
- uint32_t io_port = addr - d->io_base;
|
||||
-
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: addr 0x%x\n", __FUNCTION__, addr);
|
||||
- }
|
||||
- if (io_port == VDI_PORT_IO_CONNECTION) {
|
||||
- return vdi_port_dev_connect(d);
|
||||
- } else {
|
||||
- fprintf(stderr, "%s: unexpected addr 0x%x\n", __FUNCTION__, addr);
|
||||
- }
|
||||
- return 0xffffffff;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_io_map(PCIDevice *pci_dev, int region_num,
|
||||
- pcibus_t addr, pcibus_t size, int type)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
-
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: base 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
- }
|
||||
- d->io_base = addr;
|
||||
- register_ioport_write(addr, size, 4, vdi_port_write_dword, pci_dev);
|
||||
- register_ioport_read(addr, size, 4, vdi_port_read_dword, pci_dev);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_ram_map(PCIDevice *pci_dev, int region_num,
|
||||
- pcibus_t addr, pcibus_t size, int type)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
-
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: addr 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
- }
|
||||
-
|
||||
- assert((addr & (size - 1)) == 0);
|
||||
- assert(size == d->ram_size);
|
||||
-
|
||||
- cpu_register_physical_memory(addr, size, d->ram_offset | IO_MEM_RAM);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_reset(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- memset(d->ram, 0, sizeof(*d->ram));
|
||||
- SPICE_RING_INIT(&d->ram->input);
|
||||
- SPICE_RING_INIT(&d->ram->output);
|
||||
- d->ram->magic = VDI_PORT_MAGIC;
|
||||
- d->ram->generation = 0;
|
||||
- d->ram->int_pending = 0;
|
||||
- d->ram->int_mask = 0;
|
||||
- d->connected = false;
|
||||
- d->plug_read_pos = 0;
|
||||
- vdi_port_set_dirty(d, d->ram, sizeof(*d->ram));
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_reset_handler(DeviceState *dev)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev.qdev, dev);
|
||||
-
|
||||
- if (d->connected) {
|
||||
- vdi_port_dev_disconnect(d);
|
||||
- }
|
||||
-
|
||||
- vdi_port_reset(d);
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_pre_load(void* opaque)
|
||||
-{
|
||||
- PCIVDIPortDevice* d = opaque;
|
||||
-
|
||||
- vdi_port_unregister_interface(d);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_post_load(void* opaque,int version_id)
|
||||
-{
|
||||
- PCIVDIPortDevice* d = opaque;
|
||||
-
|
||||
- if (d->connected) {
|
||||
- vdi_port_register_interface(d);
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
-{
|
||||
- PCIVDIPortDevice* d = opaque;
|
||||
-
|
||||
- if (running) {
|
||||
- d->running = true;
|
||||
- if (d->new_gen_on_resume) {
|
||||
- d->new_gen_on_resume = false;
|
||||
- vdi_port_new_gen(d);
|
||||
- vdi_port_notify_guest(d);
|
||||
- }
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
- vdi_port_dev_notify(d);
|
||||
- } else {
|
||||
- d->running = false;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_init(PCIDevice *dev)
|
||||
-{
|
||||
- PCIVDIPortDevice *vdi = (PCIVDIPortDevice *)dev;
|
||||
- uint8_t* config = vdi->pci_dev.config;
|
||||
- uint32_t ram_size = msb_mask(sizeof(VDIPortRam) * 2 - 1);
|
||||
-
|
||||
- vdi->ram_offset = qemu_ram_alloc(&vdi->pci_dev.qdev, "bar1", ram_size);
|
||||
- vdi->ram = qemu_get_ram_ptr(vdi->ram_offset);
|
||||
- vdi_port_reset(vdi);
|
||||
- vdi->ram_size = ram_size;
|
||||
- vdi->new_gen_on_resume = false;
|
||||
- vdi->running = false;
|
||||
-
|
||||
- pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
|
||||
- pci_config_set_device_id(config, VDI_PORT_DEVICE_ID);
|
||||
- pci_config_set_class(config, PCI_CLASS_COMMUNICATION_OTHER);
|
||||
- pci_set_byte(&config[PCI_REVISION_ID], VDI_PORT_REVISION);
|
||||
- pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
||||
-
|
||||
- pci_register_bar(dev, VDI_PORT_IO_RANGE_INDEX,
|
||||
- msb_mask(VDI_PORT_IO_RANGE_SIZE * 2 - 1),
|
||||
- PCI_BASE_ADDRESS_SPACE_IO, vdi_port_io_map);
|
||||
-
|
||||
- pci_register_bar(dev, VDI_PORT_RAM_RANGE_INDEX,
|
||||
- vdi->ram_size , PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||
- vdi_port_ram_map);
|
||||
-
|
||||
- qemu_add_vm_change_state_handler(vdi_port_vm_change_state_handler, vdi);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static VMStateDescription vdi_port_vmstate = {
|
||||
- .name = VDI_PORT_DEV_NAME,
|
||||
- .version_id = VDI_PORT_SAVE_VERSION,
|
||||
- .minimum_version_id = VDI_PORT_SAVE_VERSION,
|
||||
- .pre_load = vdi_port_pre_load,
|
||||
- .post_load = vdi_port_post_load,
|
||||
- .fields = (VMStateField []) {
|
||||
- VMSTATE_PCI_DEVICE(pci_dev, PCIVDIPortDevice),
|
||||
- VMSTATE_UINT32(connected, PCIVDIPortDevice),
|
||||
- VMSTATE_END_OF_LIST()
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static PCIDeviceInfo vdi_port_info = {
|
||||
- .qdev.name = VDI_PORT_DEV_NAME,
|
||||
- .qdev.desc = "spice virtual desktop port (obsolete)",
|
||||
- .qdev.size = sizeof(PCIVDIPortDevice),
|
||||
- .qdev.vmsd = &vdi_port_vmstate,
|
||||
- .qdev.reset = vdi_port_reset_handler,
|
||||
-
|
||||
- .init = vdi_port_init,
|
||||
-};
|
||||
-
|
||||
-static void vdi_port_register(void)
|
||||
-{
|
||||
- pci_qdev_register(&vdi_port_info);
|
||||
-}
|
||||
-
|
||||
-device_init(vdi_port_register);
|
||||
--
|
||||
1.7.2.3
|
||||
|
236
0037-Revert-spice-add-virtio-serial-based-vdi-port-backen.patch
Normal file
236
0037-Revert-spice-add-virtio-serial-based-vdi-port-backen.patch
Normal file
@ -0,0 +1,236 @@
|
||||
From bebcc44cfe5da8a4881292fa564869a481eea4ae Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:49:40 +0200
|
||||
Subject: [PATCH 37/39] Revert "spice: add virtio-serial based vdi port backend."
|
||||
|
||||
This reverts commit ef9e975b1d34c1426867cef832ba6238a401b740.
|
||||
---
|
||||
Makefile.target | 1 -
|
||||
hw/spice-vmc.c | 203 -------------------------------------------------------
|
||||
2 files changed, 0 insertions(+), 204 deletions(-)
|
||||
delete mode 100644 hw/spice-vmc.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 90544c5..4da33b5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,7 +217,6 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
deleted file mode 100644
|
||||
index 3f6a2bb..0000000
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ /dev/null
|
||||
@@ -1,203 +0,0 @@
|
||||
-/*
|
||||
-
|
||||
- Spice Virtual Machine Channel (VMC).
|
||||
-
|
||||
- A virtio-serial port used for spice to guest communication, over
|
||||
- which spice client and a daemon in the guest operating system
|
||||
- communicate.
|
||||
-
|
||||
- Replaces the old vdi_port PCI device.
|
||||
-
|
||||
-*/
|
||||
-
|
||||
-#include <stdio.h>
|
||||
-#include <stdbool.h>
|
||||
-#include <spice.h>
|
||||
-#include <spice-experimental.h>
|
||||
-
|
||||
-#include "virtio-serial.h"
|
||||
-#include "qemu-spice.h"
|
||||
-
|
||||
-#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
-#define VMC_DEVICE_NAME "spicevmc"
|
||||
-
|
||||
-#define dprintf(_svc, _level, _fmt, ...) \
|
||||
- do { \
|
||||
- if (_svc->debug >= _level) { \
|
||||
- fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
- } \
|
||||
- } while (0)
|
||||
-
|
||||
-typedef struct SpiceVirtualChannel {
|
||||
- VirtIOSerialPort port;
|
||||
- VMChangeStateEntry *vmstate;
|
||||
- SpiceVDIPortInstance sin;
|
||||
- bool active;
|
||||
- uint8_t *buffer;
|
||||
- uint8_t *datapos;
|
||||
- ssize_t bufsize, datalen;
|
||||
- uint32_t debug;
|
||||
-} SpiceVirtualChannel;
|
||||
-
|
||||
-static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- ssize_t out;
|
||||
-
|
||||
- out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
- return out;
|
||||
-}
|
||||
-
|
||||
-static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- int bytes = MIN(len, svc->datalen);
|
||||
-
|
||||
- dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
- if (bytes) {
|
||||
- memcpy(buf, svc->datapos, bytes);
|
||||
- svc->datapos += bytes;
|
||||
- svc->datalen -= bytes;
|
||||
- if (0 == svc->datalen) {
|
||||
- virtio_serial_throttle_port(&svc->port, false);
|
||||
- }
|
||||
- }
|
||||
- return bytes;
|
||||
-}
|
||||
-
|
||||
-static SpiceVDIPortInterface vmc_interface = {
|
||||
- .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
- .base.description = "spice virtual channel vdi port",
|
||||
- .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
- .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
- .write = vmc_write,
|
||||
- .read = vmc_read,
|
||||
-};
|
||||
-
|
||||
-static void vmc_register_interface(SpiceVirtualChannel *svc)
|
||||
-{
|
||||
- if (svc->active) {
|
||||
- return;
|
||||
- }
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- svc->sin.base.sif = &vmc_interface.base;
|
||||
- spice_server_add_interface(spice_server, &svc->sin.base);
|
||||
- svc->active = true;
|
||||
-}
|
||||
-
|
||||
-static void vmc_unregister_interface(SpiceVirtualChannel *svc)
|
||||
-{
|
||||
- if (!svc->active) {
|
||||
- return;
|
||||
- }
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- spice_server_remove_interface(&svc->sin.base);
|
||||
- svc->active = false;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void vmc_change_state_handler(void *opaque, int running, int reason)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = opaque;
|
||||
-
|
||||
- if (running && svc->active) {
|
||||
- spice_server_vdi_port_wakeup(&svc->sin);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * virtio-serial callbacks
|
||||
- */
|
||||
-
|
||||
-static void vmc_guest_open(VirtIOSerialPort *port)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- vmc_register_interface(svc);
|
||||
-}
|
||||
-
|
||||
-static void vmc_guest_close(VirtIOSerialPort *port)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- vmc_unregister_interface(svc);
|
||||
-}
|
||||
-
|
||||
-static void vmc_guest_ready(VirtIOSerialPort *port)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- if (svc->active)
|
||||
- spice_server_vdi_port_wakeup(&svc->sin);
|
||||
-}
|
||||
-
|
||||
-static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
- assert(svc->datapos == 0);
|
||||
- if (svc->bufsize < len) {
|
||||
- svc->bufsize = len;
|
||||
- svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
- }
|
||||
- memcpy(svc->buffer, buf, len);
|
||||
- svc->datapos = svc->buffer;
|
||||
- svc->datalen = len;
|
||||
- virtio_serial_throttle_port(&svc->port, true);
|
||||
- spice_server_vdi_port_wakeup(&svc->sin);
|
||||
-}
|
||||
-
|
||||
-static int vmc_initfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- if (!using_spice)
|
||||
- return -1;
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
|
||||
- svc->vmstate = qemu_add_vm_change_state_handler(
|
||||
- vmc_change_state_handler, svc);
|
||||
- virtio_serial_open(port);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int vmc_exitfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- vmc_unregister_interface(svc);
|
||||
- qemu_del_vm_change_state_handler(svc->vmstate);
|
||||
- virtio_serial_close(port);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static VirtIOSerialPortInfo vmc_info = {
|
||||
- .qdev.name = VMC_DEVICE_NAME,
|
||||
- .qdev.size = sizeof(SpiceVirtualChannel),
|
||||
- .init = vmc_initfn,
|
||||
- .exit = vmc_exitfn,
|
||||
- .guest_open = vmc_guest_open,
|
||||
- .guest_close = vmc_guest_close,
|
||||
- .guest_ready = vmc_guest_ready,
|
||||
- .have_data = vmc_have_data,
|
||||
- .qdev.props = (Property[]) {
|
||||
- DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
- DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
|
||||
- DEFINE_PROP_END_OF_LIST(),
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static void vmc_register(void)
|
||||
-{
|
||||
- virtio_serial_port_qdev_register(&vmc_info);
|
||||
-}
|
||||
-device_init(vmc_register)
|
||||
--
|
||||
1.7.2.3
|
||||
|
297
0038-spice-add-virtio-serial-based-spice-vmchannel-backen.patch
Normal file
297
0038-spice-add-virtio-serial-based-spice-vmchannel-backen.patch
Normal file
@ -0,0 +1,297 @@
|
||||
From 5bdc01e675a51a123a813d62a8ae837db9360b7f Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 20 Apr 2010 13:33:54 +0200
|
||||
Subject: [PATCH 38/39] spice: add virtio-serial based spice vmchannel backend.
|
||||
|
||||
Adds the spicevmc device. This is a communication channel between the
|
||||
spice client and the guest. It is used to send display information and
|
||||
mouse events from the spice clients to the guest.
|
||||
---
|
||||
Makefile.target | 1 +
|
||||
hw/spice-vmc.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 263 insertions(+), 0 deletions(-)
|
||||
create mode 100644 hw/spice-vmc.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 4da33b5..90544c5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,6 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
new file mode 100644
|
||||
index 0000000..b77fc60
|
||||
--- /dev/null
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -0,0 +1,262 @@
|
||||
+/*
|
||||
+
|
||||
+ Spice Virtual Machine Channel (VMC).
|
||||
+
|
||||
+ A virtio-serial port used for spice to guest communication, over
|
||||
+ which spice client and a daemon in the guest operating system
|
||||
+ communicate.
|
||||
+
|
||||
+ Replaces the old vdi_port PCI device.
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+
|
||||
+#include "virtio-serial.h"
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
+#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
+#define VMC_DEVICE_NAME "spicevmc"
|
||||
+
|
||||
+/* windows guest driver bug workaround */
|
||||
+#define VMC_MAX_HOST_WRITE 2048
|
||||
+
|
||||
+#define dprintf(_svc, _level, _fmt, ...) \
|
||||
+ do { \
|
||||
+ static unsigned __dprintf_counter = 0; \
|
||||
+ if (_svc->debug >= _level) { \
|
||||
+ fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
|
||||
+ } \
|
||||
+ } while (0)
|
||||
+
|
||||
+typedef struct SpiceVirtualChannel {
|
||||
+ VirtIOSerialPort port;
|
||||
+ VMChangeStateEntry *vmstate;
|
||||
+ SpiceCharDeviceInstance sin;
|
||||
+ char *subtype;
|
||||
+ bool active;
|
||||
+ uint8_t *buffer;
|
||||
+ uint8_t *datapos;
|
||||
+ ssize_t bufsize, datalen;
|
||||
+ uint32_t debug;
|
||||
+} SpiceVirtualChannel;
|
||||
+
|
||||
+static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ ssize_t out = 0;
|
||||
+ ssize_t last_out;
|
||||
+ uint8_t* p = (uint8_t*)buf;
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ last_out = virtio_serial_write(&svc->port, p,
|
||||
+ MIN(len, VMC_MAX_HOST_WRITE));
|
||||
+ if (last_out > 0) {
|
||||
+ out += last_out;
|
||||
+ len -= last_out;
|
||||
+ p += last_out;
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
+static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ int bytes = MIN(len, svc->datalen);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
|
||||
+ if (bytes > 0) {
|
||||
+ memcpy(buf, svc->datapos, bytes);
|
||||
+ svc->datapos += bytes;
|
||||
+ svc->datalen -= bytes;
|
||||
+ assert(svc->datalen >= 0);
|
||||
+ if (svc->datalen == 0) {
|
||||
+ svc->datapos = 0;
|
||||
+ virtio_serial_throttle_port(&svc->port, false);
|
||||
+ // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
|
||||
+ }
|
||||
+ }
|
||||
+ return bytes;
|
||||
+}
|
||||
+
|
||||
+static SpiceCharDeviceInterface vmc_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_CHAR_DEVICE,
|
||||
+ .base.description = "spice virtual channel char device",
|
||||
+ .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
|
||||
+ .write = vmc_write,
|
||||
+ .read = vmc_read,
|
||||
+};
|
||||
+
|
||||
+static void vmc_register_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ svc->sin.base.sif = &vmc_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &svc->sin.base);
|
||||
+ svc->active = true;
|
||||
+}
|
||||
+
|
||||
+static void vmc_unregister_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (!svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ spice_server_remove_interface(&svc->sin.base);
|
||||
+ svc->active = false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void vmc_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = opaque;
|
||||
+
|
||||
+ if (running && svc->active) {
|
||||
+ spice_server_char_device_wakeup(&svc->sin);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * virtio-serial callbacks
|
||||
+ */
|
||||
+
|
||||
+static void vmc_guest_open(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_register_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_close(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_ready(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ if (svc->active) {
|
||||
+ spice_server_char_device_wakeup(&svc->sin);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
+ assert(svc->datalen == 0);
|
||||
+ if (svc->bufsize < len) {
|
||||
+ svc->bufsize = len;
|
||||
+ svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
+ }
|
||||
+ memcpy(svc->buffer, buf, len);
|
||||
+ svc->datapos = svc->buffer;
|
||||
+ svc->datalen = len;
|
||||
+ virtio_serial_throttle_port(&svc->port, true);
|
||||
+ spice_server_char_device_wakeup(&svc->sin);
|
||||
+}
|
||||
+
|
||||
+static void vmc_print_optional_subtypes(void)
|
||||
+{
|
||||
+ const char** psubtype = spice_server_char_device_recognized_subtypes();
|
||||
+ int i;
|
||||
+
|
||||
+ fprintf(stderr, "supported subtypes: ");
|
||||
+ for(i=0; *psubtype != NULL; ++psubtype, ++i) {
|
||||
+ if (i == 0) {
|
||||
+ fprintf(stderr, *psubtype);
|
||||
+ } else {
|
||||
+ fprintf(stderr, ", %s", *psubtype);
|
||||
+ }
|
||||
+ }
|
||||
+ fprintf(stderr, "\n");
|
||||
+}
|
||||
+
|
||||
+static int vmc_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+ const char** psubtype = spice_server_char_device_recognized_subtypes();
|
||||
+ const char *subtype = NULL;
|
||||
+
|
||||
+ if (!using_spice) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+
|
||||
+ if (svc->subtype == NULL) {
|
||||
+ svc->subtype = strdup("vdagent");
|
||||
+ }
|
||||
+
|
||||
+ for(;*psubtype != NULL; ++psubtype) {
|
||||
+ if (strcmp(svc->subtype, *psubtype) == 0) {
|
||||
+ subtype = *psubtype;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (subtype == NULL) {
|
||||
+ fprintf(stderr, "spice-vmc: unsupported subtype\n");
|
||||
+ vmc_print_optional_subtypes();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
|
||||
+ svc->vmstate = qemu_add_vm_change_state_handler
|
||||
+ (vmc_change_state_handler, svc);
|
||||
+ svc->sin.subtype = svc->subtype;
|
||||
+ virtio_serial_open(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vmc_exitfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+ qemu_del_vm_change_state_handler(svc->vmstate);
|
||||
+ virtio_serial_close(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo vmc_info = {
|
||||
+ .qdev.name = VMC_DEVICE_NAME,
|
||||
+ .qdev.size = sizeof(SpiceVirtualChannel),
|
||||
+ .init = vmc_initfn,
|
||||
+ .exit = vmc_exitfn,
|
||||
+ .guest_open = vmc_guest_open,
|
||||
+ .guest_close = vmc_guest_close,
|
||||
+ .guest_ready = vmc_guest_ready,
|
||||
+ .have_data = vmc_have_data,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
+ DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
|
||||
+ DEFINE_PROP_STRING("subtype", SpiceVirtualChannel, subtype),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static void vmc_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&vmc_info);
|
||||
+}
|
||||
+device_init(vmc_register)
|
||||
--
|
||||
1.7.2.3
|
||||
|
30
0039-qxl-fix-release-ring-overrun.patch
Normal file
30
0039-qxl-fix-release-ring-overrun.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 9394cbaab7701fe421d5c0168854d39d6a8ecfc2 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 7 Sep 2010 16:45:27 +0200
|
||||
Subject: [PATCH 39/39] qxl: fix release ring overrun
|
||||
|
||||
---
|
||||
hw/qxl.c | 6 +++---
|
||||
1 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 4a15200..8448893 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -377,10 +377,10 @@ static inline void qxl_push_free_res(PCIQXLDevice *d)
|
||||
QXLReleaseRing *ring = &d->ram->release_ring;
|
||||
uint64_t *item;
|
||||
|
||||
-#define QXL_FREE_BUNCH_SIZE 10
|
||||
+#define QXL_FREE_BUNCH_SIZE 32
|
||||
|
||||
- if (SPICE_RING_IS_EMPTY(ring) || (d->num_free_res == QXL_FREE_BUNCH_SIZE &&
|
||||
- ring->prod - ring->cons + 1 != ring->num_items)) {
|
||||
+ if (SPICE_RING_IS_EMPTY(ring) || (d->num_free_res >= QXL_FREE_BUNCH_SIZE &&
|
||||
+ ring->prod - ring->cons + 2 != ring->num_items)) {
|
||||
int notify;
|
||||
|
||||
SPICE_RING_PUSH(ring, notify);
|
||||
--
|
||||
1.7.2.3
|
||||
|
37
pc-add-a-Fedora-13-machine-type-for-backward-compat.patch
Normal file
37
pc-add-a-Fedora-13-machine-type-for-backward-compat.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From: Justin M. Forbes <jforbes@redhat.com>
|
||||
Date: Thu, Aug 19 09:13:45 2010 -0500
|
||||
Subject: pc: Add a Fedora-13 machine type for backwards compatibility.
|
||||
|
||||
In Fedora 13 a fedora-13 machine type was added as default to allow
|
||||
interaction with upstream stable qemu which did not support the same
|
||||
feature set. As a result we need to support this machine type through
|
||||
the Fedora 15 release.
|
||||
|
||||
|
||||
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
|
||||
index 9e4bac8..eb1ed05 100644
|
||||
--- a/hw/pc_piix.c
|
||||
+++ b/hw/pc_piix.c
|
||||
@@ -237,6 +237,14 @@ static QEMUMachine pc_machine = {
|
||||
.is_default = 1,
|
||||
};
|
||||
|
||||
+static QEMUMachine pc_machine_f13 = {
|
||||
+ .name = "fedora-13",
|
||||
+ .desc = "Standard PC",
|
||||
+ .init = pc_init_pci,
|
||||
+ .max_cpus = 255,
|
||||
+ .is_default = 0,
|
||||
+};
|
||||
+
|
||||
static QEMUMachine pc_machine_v0_12 = {
|
||||
.name = "pc-0.12",
|
||||
.desc = "Standard PC",
|
||||
@@ -348,6 +356,7 @@ static QEMUMachine isapc_machine = {
|
||||
static void pc_machine_init(void)
|
||||
{
|
||||
qemu_register_machine(&pc_machine);
|
||||
+ qemu_register_machine(&pc_machine_f13);
|
||||
qemu_register_machine(&pc_machine_v0_12);
|
||||
qemu_register_machine(&pc_machine_v0_11);
|
||||
qemu_register_machine(&pc_machine_v0_10);
|
105
qemu.spec
105
qemu.spec
@ -1,9 +1,7 @@
|
||||
%define githead 25fdf4a
|
||||
|
||||
Summary: QEMU is a FAST! processor emulator
|
||||
Name: qemu
|
||||
Version: 0.13.0
|
||||
Release: 0.5.20100809git%{githead}%{?dist}
|
||||
Release: 0.6.rc1%{?dist}
|
||||
# Epoch because we pushed a qemu-1.0 package
|
||||
Epoch: 2
|
||||
License: GPLv2+ and LGPLv2+ and BSD
|
||||
@ -19,11 +17,7 @@ URL: http://www.qemu.org/
|
||||
%define _smp_mflags %{nil}
|
||||
%endif
|
||||
|
||||
# Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}.tar.gz
|
||||
# The source for this package was pulled from upstream's git. Use the
|
||||
# following commands to generate the tarball:
|
||||
# git archive --format=tar --prefix=qemu-kvm-0.13/ b81fe95 | gzip > qemu-kvm-0.13-b81fe95.tar.gz
|
||||
Source0: qemu-kvm-%{version}-%{githead}.tar.gz
|
||||
Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}-rc1.tar.gz
|
||||
Source1: qemu.init
|
||||
|
||||
# Loads kvm kernel modules at boot
|
||||
@ -39,6 +33,51 @@ Source6: ksmtuned.init
|
||||
Source7: ksmtuned
|
||||
Source8: ksmtuned.conf
|
||||
|
||||
# This patch must be carried through F-15 to support guests created
|
||||
# with F-13/
|
||||
Patch00: pc-add-a-Fedora-13-machine-type-for-backward-compat.patch
|
||||
|
||||
# Patches from Fedora qemu git (http://git.fedorahosted.org/git/qemu-kvm-fedora.git)
|
||||
Patch01: 0001-add-pflib-PixelFormat-conversion-library.patch
|
||||
Patch02: 0002-configure-add-logging.patch
|
||||
Patch03: 0003-add-spice-into-the-configure-file.patch
|
||||
Patch04: 0004-spice-core-bits.patch
|
||||
Patch05: 0005-spice-add-keyboard.patch
|
||||
Patch06: 0006-spice-add-mouse.patch
|
||||
Patch07: 0007-spice-simple-display.patch
|
||||
Patch08: 0008-spice-add-tablet-support.patch
|
||||
Patch09: 0009-vgabios-update-to-0.6c-pcibios-patches.patch
|
||||
Patch10: 0010-switch-stdvga-to-pci-vgabios.patch
|
||||
Patch11: 0011-switch-vmware_vga-to-pci-vgabios.patch
|
||||
Patch12: 0012-all-vga-refuse-hotplugging.patch
|
||||
Patch13: 0013-spice-tls-support.patch
|
||||
Patch14: 0014-spice-add-qxl-device.patch
|
||||
Patch15: 0015-spice-add-audio.patch
|
||||
Patch16: 0016-spice-add-virtio-serial-based-vdi-port-backend.patch
|
||||
Patch17: 0017-spice-add-pci-vdi-port-backend-obsolete.patch
|
||||
Patch18: 0018-use-memalign-instead-of-posix_memalign.patch
|
||||
Patch19: 0019-spice-live-migration-wip.patch
|
||||
Patch20: 0020-spice-display-draw.h-is-internal-now.patch
|
||||
Patch21: 0021-spice-display-disable-debug.patch
|
||||
Patch22: 0022-spice-display-pci-rev-fixups.patch
|
||||
Patch23: 0023-qxl-pci-rev-fixups.patch
|
||||
Patch24: 0024-qxl-support-QXL_IO_DESTROY_ALL_SURFACES.patch
|
||||
Patch25: 0025-spice-vmc-two-bugfixes-in-vmc_read.patch
|
||||
Patch26: 0026-spice-enabling-disabling-jpeg-and-zlib-over-glz-via-.patch
|
||||
Patch27: 0027-ifdef-new-config-options.patch
|
||||
Patch28: 0028-spice-vmc-add-counter-to-debug-statements.patch
|
||||
Patch29: 0029-spice-vmc-split-vmc_write-to-max-sized-virtio_serial.patch
|
||||
Patch30: 0030-qxl-add-800x480-resolution-to-qxl_modes-n900-native.patch
|
||||
Patch31: 0031-qxl-savevm-fixes.patch
|
||||
Patch32: 0032-Revert-spice-vmc-split-vmc_write-to-max-sized-virtio.patch
|
||||
Patch33: 0033-Revert-spice-vmc-add-counter-to-debug-statements.patch
|
||||
Patch34: 0034-Revert-spice-vmc-two-bugfixes-in-vmc_read.patch
|
||||
Patch35: 0035-Revert-spice-live-migration-wip.patch
|
||||
Patch36: 0036-Revert-spice-add-pci-vdi-port-backend-obsolete.patch
|
||||
Patch37: 0037-Revert-spice-add-virtio-serial-based-vdi-port-backen.patch
|
||||
Patch38: 0038-spice-add-virtio-serial-based-spice-vmchannel-backen.patch
|
||||
Patch39: 0039-qxl-fix-release-ring-overrun.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: SDL-devel zlib-devel which texi2html gnutls-devel cyrus-sasl-devel
|
||||
BuildRequires: libaio-devel
|
||||
@ -48,7 +87,8 @@ BuildRequires: pulseaudio-libs-devel
|
||||
BuildRequires: ncurses-devel
|
||||
BuildRequires: texinfo
|
||||
%ifarch x86_64
|
||||
BuildRequires: spice-protocol spice-server-devel
|
||||
BuildRequires: spice-protocol >= 0.6.0
|
||||
BuildRequires: spice-server-devel >= 0.6.0
|
||||
%endif
|
||||
Requires: %{name}-user = %{epoch}:%{version}-%{release}
|
||||
Requires: %{name}-system-x86 = %{epoch}:%{version}-%{release}
|
||||
@ -231,7 +271,48 @@ such as kvm_stat.
|
||||
%endif
|
||||
|
||||
%prep
|
||||
%setup -q -n qemu-kvm-%{version}
|
||||
%setup -q -n qemu-kvm-%{version}-rc1
|
||||
|
||||
%patch00 -p1
|
||||
%patch01 -p1
|
||||
%patch02 -p1
|
||||
%patch03 -p1
|
||||
%patch04 -p1
|
||||
%patch05 -p1
|
||||
%patch06 -p1
|
||||
%patch07 -p1
|
||||
%patch08 -p1
|
||||
%patch09 -p1
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
%patch17 -p1
|
||||
%patch18 -p1
|
||||
%patch19 -p1
|
||||
%patch20 -p1
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
%patch35 -p1
|
||||
%patch36 -p1
|
||||
%patch37 -p1
|
||||
%patch38 -p1
|
||||
%patch39 -p1
|
||||
|
||||
%build
|
||||
# By default we build everything, but allow x86 to build a minimal version
|
||||
@ -546,6 +627,10 @@ fi
|
||||
%{_mandir}/man1/qemu-img.1*
|
||||
|
||||
%changelog
|
||||
* Tue Aug 10 2010 Justin M. Forbes <jforbes@redhat.com> - 2:0.13.0-0.6.rc1
|
||||
- Move away from git snapshots as 0.13 is close to release
|
||||
- Updates for spice 0.6
|
||||
|
||||
* Tue Aug 10 2010 Justin M. Forbes <jforbes@redhat.com> - 2:0.13.0-0.5.20100809git25fdf4a
|
||||
- Fix typo in e1000 gpxe rom requires.
|
||||
- Add links to newer vgabios
|
||||
|
Loading…
x
Reference in New Issue
Block a user