Blame 0510-hw-qxl-support-client-monitor-configuration-via-devi.patch

5544c1
From f5c2bd00890dc32e940e8b2fae09f62f758317eb Mon Sep 17 00:00:00 2001
93b7e3
From: Alon Levy <alevy@redhat.com>
93b7e3
Date: Wed, 12 Sep 2012 16:13:28 +0300
5544c1
Subject: [PATCH] hw/qxl: support client monitor configuration via device
93b7e3
93b7e3
Until now we used only the agent to change the monitor count and each
93b7e3
monitor resolution. This patch introduces the qemu part of using the
93b7e3
device as the mediator instead of the agent via virtio-serial.
93b7e3
93b7e3
Spice (>=0.11.5) calls the new QXLInterface::client_monitors_config,
93b7e3
which returns wether the interrupt is enabled, and if so and given a non
93b7e3
NULL monitors config will
93b7e3
generate an interrupt QXL_INTERRUPT_CLIENT_MONITORS_CONFIG with crc
93b7e3
checksum for the guest to verify a second call hasn't interfered.
93b7e3
93b7e3
The maximal number of monitors is limited on the QXLRom to 64.
93b7e3
93b7e3
Signed-off-by: Alon Levy <alevy@redhat.com>
93b7e3
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
93b7e3
---
93b7e3
 configure    |  7 ++++++
93b7e3
 hw/qxl.c     | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
93b7e3
 trace-events |  6 ++++-
93b7e3
 3 files changed, 91 insertions(+), 1 deletion(-)
93b7e3
93b7e3
diff --git a/configure b/configure
5544c1
index f528146..83c478c 100755
93b7e3
--- a/configure
93b7e3
+++ b/configure
5544c1
@@ -2706,6 +2706,9 @@ EOF
93b7e3
     if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
93b7e3
         spice_qxl_io_monitors_config_async="yes"
93b7e3
     fi
93b7e3
+    if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then
93b7e3
+        spice_qxl_client_monitors_config="yes"
93b7e3
+    fi
93b7e3
   else
93b7e3
     if test "$spice" = "yes" ; then
93b7e3
       feature_not_found "spice"
5544c1
@@ -3453,6 +3456,10 @@ if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
93b7e3
   echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
93b7e3
 fi
93b7e3
 
93b7e3
+if test "$spice_qxl_client_monitors_config" = "yes" ; then
93b7e3
+  echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak
93b7e3
+fi
93b7e3
+
93b7e3
 if test "$smartcard" = "yes" ; then
93b7e3
   echo "CONFIG_SMARTCARD=y" >> $config_host_mak
93b7e3
 fi
93b7e3
diff --git a/hw/qxl.c b/hw/qxl.c
93b7e3
index 1ef117a..0695872 100644
93b7e3
--- a/hw/qxl.c
93b7e3
+++ b/hw/qxl.c
93b7e3
@@ -18,6 +18,8 @@
93b7e3
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
93b7e3
  */
93b7e3
 
93b7e3
+#include <zlib.h>
93b7e3
+
93b7e3
 #include "qemu-common.h"
93b7e3
 #include "qemu-timer.h"
93b7e3
 #include "qemu-queue.h"
93b7e3
@@ -971,6 +973,79 @@ static void interface_set_client_capabilities(QXLInstance *sin,
93b7e3
 
93b7e3
 #endif
93b7e3
 
93b7e3
+#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \
93b7e3
+    && SPICE_SERVER_VERSION >= 0x000b05
93b7e3
+
93b7e3
+static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
93b7e3
+{
93b7e3
+    /*
93b7e3
+     * zlib xors the seed with 0xffffffff, and xors the result
93b7e3
+     * again with 0xffffffff; Both are not done with linux's crc32,
93b7e3
+     * which we want to be compatible with, so undo that.
93b7e3
+     */
93b7e3
+    return crc32(0xffffffff, p, len) ^ 0xffffffff;
93b7e3
+}
93b7e3
+
93b7e3
+/* called from main context only */
93b7e3
+static int interface_client_monitors_config(QXLInstance *sin,
93b7e3
+                                        VDAgentMonitorsConfig *monitors_config)
93b7e3
+{
93b7e3
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
93b7e3
+    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
93b7e3
+    int i;
93b7e3
+
93b7e3
+    /*
93b7e3
+     * Older windows drivers set int_mask to 0 when their ISR is called,
93b7e3
+     * then later set it to ~0. So it doesn't relate to the actual interrupts
93b7e3
+     * handled. However, they are old, so clearly they don't support this
93b7e3
+     * interrupt
93b7e3
+     */
93b7e3
+    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
93b7e3
+        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {
93b7e3
+        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
93b7e3
+                                                            qxl->ram->int_mask,
93b7e3
+                                                            monitors_config);
93b7e3
+        return 0;
93b7e3
+    }
93b7e3
+    if (!monitors_config) {
93b7e3
+        return 1;
93b7e3
+    }
93b7e3
+    memset(&rom->client_monitors_config, 0,
93b7e3
+           sizeof(rom->client_monitors_config));
93b7e3
+    rom->client_monitors_config.count = monitors_config->num_of_monitors;
93b7e3
+    /* monitors_config->flags ignored */
93b7e3
+    if (rom->client_monitors_config.count >=
93b7e3
+            ARRAY_SIZE(rom->client_monitors_config.heads)) {
93b7e3
+        trace_qxl_client_monitors_config_capped(qxl->id,
93b7e3
+                                monitors_config->num_of_monitors,
93b7e3
+                                ARRAY_SIZE(rom->client_monitors_config.heads));
93b7e3
+        rom->client_monitors_config.count =
93b7e3
+            ARRAY_SIZE(rom->client_monitors_config.heads);
93b7e3
+    }
93b7e3
+    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
93b7e3
+        VDAgentMonConfig *monitor = &monitors_config->monitors[i];
93b7e3
+        QXLURect *rect = &rom->client_monitors_config.heads[i];
93b7e3
+        /* monitor->depth ignored */
93b7e3
+        rect->left = monitor->x;
93b7e3
+        rect->top = monitor->y;
93b7e3
+        rect->right = monitor->x + monitor->width;
93b7e3
+        rect->bottom = monitor->y + monitor->height;
93b7e3
+    }
93b7e3
+    rom->client_monitors_config_crc = qxl_crc32(
93b7e3
+            (const uint8_t *)&rom->client_monitors_config,
93b7e3
+            sizeof(rom->client_monitors_config));
93b7e3
+    trace_qxl_client_monitors_config_crc(qxl->id,
93b7e3
+            sizeof(rom->client_monitors_config),
93b7e3
+            rom->client_monitors_config_crc);
93b7e3
+
93b7e3
+    trace_qxl_interrupt_client_monitors_config(qxl->id,
93b7e3
+                        rom->client_monitors_config.count,
93b7e3
+                        rom->client_monitors_config.heads);
93b7e3
+    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
93b7e3
+    return 1;
93b7e3
+}
93b7e3
+#endif
93b7e3
+
93b7e3
 static const QXLInterface qxl_interface = {
93b7e3
     .base.type               = SPICE_INTERFACE_QXL,
93b7e3
     .base.description        = "qxl gpu",
93b7e3
@@ -995,6 +1070,10 @@ static const QXLInterface qxl_interface = {
93b7e3
 #if SPICE_SERVER_VERSION >= 0x000b04
93b7e3
     .set_client_capabilities = interface_set_client_capabilities,
93b7e3
 #endif
93b7e3
+#if SPICE_SERVER_VERSION >= 0x000b05 && \
93b7e3
+    defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG)
93b7e3
+    .client_monitors_config = interface_client_monitors_config,
93b7e3
+#endif
93b7e3
 };
93b7e3
 
93b7e3
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
93b7e3
diff --git a/trace-events b/trace-events
5544c1
index 80a52d9..07b63f1 100644
93b7e3
--- a/trace-events
93b7e3
+++ b/trace-events
5544c1
@@ -930,7 +930,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d
93b7e3
 qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
93b7e3
 qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
93b7e3
 qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
93b7e3
-qxl_io_log(int qid, const uint8_t *str) "%d %s"
93b7e3
+qxl_io_log(int qid, const uint8_t *log_buf) "%d %s"
93b7e3
 qxl_io_read_unexpected(int qid) "%d"
93b7e3
 qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
93b7e3
 qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
5544c1
@@ -974,6 +974,10 @@ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dir
93b7e3
 qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
93b7e3
 qxl_send_events(int qid, uint32_t events) "%d %d"
93b7e3
 qxl_set_guest_bug(int qid) "%d"
93b7e3
+qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p"
93b7e3
+qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p"
93b7e3
+qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
93b7e3
+qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u"
93b7e3
 
93b7e3
 # hw/qxl-render.c
93b7e3
 qxl_render_blit_guest_primary_initialized(void) ""
93b7e3
-- 
5544c1
1.7.12.1
93b7e3