Initial commit with version 1.2.0-24
[packages/centos6/qemu.git] / 0510-hw-qxl-support-client-monitor-configuration-via-devi.patch
1 From f5c2bd00890dc32e940e8b2fae09f62f758317eb Mon Sep 17 00:00:00 2001
2 From: Alon Levy <alevy@redhat.com>
3 Date: Wed, 12 Sep 2012 16:13:28 +0300
4 Subject: [PATCH] hw/qxl: support client monitor configuration via device
5
6 Until now we used only the agent to change the monitor count and each
7 monitor resolution. This patch introduces the qemu part of using the
8 device as the mediator instead of the agent via virtio-serial.
9
10 Spice (>=0.11.5) calls the new QXLInterface::client_monitors_config,
11 which returns wether the interrupt is enabled, and if so and given a non
12 NULL monitors config will
13 generate an interrupt QXL_INTERRUPT_CLIENT_MONITORS_CONFIG with crc
14 checksum for the guest to verify a second call hasn't interfered.
15
16 The maximal number of monitors is limited on the QXLRom to 64.
17
18 Signed-off-by: Alon Levy <alevy@redhat.com>
19 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
20 ---
21  configure    |  7 ++++++
22  hw/qxl.c     | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23  trace-events |  6 ++++-
24  3 files changed, 91 insertions(+), 1 deletion(-)
25
26 diff --git a/configure b/configure
27 index f528146..83c478c 100755
28 --- a/configure
29 +++ b/configure
30 @@ -2706,6 +2706,9 @@ EOF
31      if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
32          spice_qxl_io_monitors_config_async="yes"
33      fi
34 +    if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then
35 +        spice_qxl_client_monitors_config="yes"
36 +    fi
37    else
38      if test "$spice" = "yes" ; then
39        feature_not_found "spice"
40 @@ -3453,6 +3456,10 @@ if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
41    echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
42  fi
43  
44 +if test "$spice_qxl_client_monitors_config" = "yes" ; then
45 +  echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak
46 +fi
47 +
48  if test "$smartcard" = "yes" ; then
49    echo "CONFIG_SMARTCARD=y" >> $config_host_mak
50  fi
51 diff --git a/hw/qxl.c b/hw/qxl.c
52 index 1ef117a..0695872 100644
53 --- a/hw/qxl.c
54 +++ b/hw/qxl.c
55 @@ -18,6 +18,8 @@
56   * along with this program; if not, see <http://www.gnu.org/licenses/>.
57   */
58  
59 +#include <zlib.h>
60 +
61  #include "qemu-common.h"
62  #include "qemu-timer.h"
63  #include "qemu-queue.h"
64 @@ -971,6 +973,79 @@ static void interface_set_client_capabilities(QXLInstance *sin,
65  
66  #endif
67  
68 +#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \
69 +    && SPICE_SERVER_VERSION >= 0x000b05
70 +
71 +static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
72 +{
73 +    /*
74 +     * zlib xors the seed with 0xffffffff, and xors the result
75 +     * again with 0xffffffff; Both are not done with linux's crc32,
76 +     * which we want to be compatible with, so undo that.
77 +     */
78 +    return crc32(0xffffffff, p, len) ^ 0xffffffff;
79 +}
80 +
81 +/* called from main context only */
82 +static int interface_client_monitors_config(QXLInstance *sin,
83 +                                        VDAgentMonitorsConfig *monitors_config)
84 +{
85 +    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
86 +    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
87 +    int i;
88 +
89 +    /*
90 +     * Older windows drivers set int_mask to 0 when their ISR is called,
91 +     * then later set it to ~0. So it doesn't relate to the actual interrupts
92 +     * handled. However, they are old, so clearly they don't support this
93 +     * interrupt
94 +     */
95 +    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
96 +        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {
97 +        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
98 +                                                            qxl->ram->int_mask,
99 +                                                            monitors_config);
100 +        return 0;
101 +    }
102 +    if (!monitors_config) {
103 +        return 1;
104 +    }
105 +    memset(&rom->client_monitors_config, 0,
106 +           sizeof(rom->client_monitors_config));
107 +    rom->client_monitors_config.count = monitors_config->num_of_monitors;
108 +    /* monitors_config->flags ignored */
109 +    if (rom->client_monitors_config.count >=
110 +            ARRAY_SIZE(rom->client_monitors_config.heads)) {
111 +        trace_qxl_client_monitors_config_capped(qxl->id,
112 +                                monitors_config->num_of_monitors,
113 +                                ARRAY_SIZE(rom->client_monitors_config.heads));
114 +        rom->client_monitors_config.count =
115 +            ARRAY_SIZE(rom->client_monitors_config.heads);
116 +    }
117 +    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
118 +        VDAgentMonConfig *monitor = &monitors_config->monitors[i];
119 +        QXLURect *rect = &rom->client_monitors_config.heads[i];
120 +        /* monitor->depth ignored */
121 +        rect->left = monitor->x;
122 +        rect->top = monitor->y;
123 +        rect->right = monitor->x + monitor->width;
124 +        rect->bottom = monitor->y + monitor->height;
125 +    }
126 +    rom->client_monitors_config_crc = qxl_crc32(
127 +            (const uint8_t *)&rom->client_monitors_config,
128 +            sizeof(rom->client_monitors_config));
129 +    trace_qxl_client_monitors_config_crc(qxl->id,
130 +            sizeof(rom->client_monitors_config),
131 +            rom->client_monitors_config_crc);
132 +
133 +    trace_qxl_interrupt_client_monitors_config(qxl->id,
134 +                        rom->client_monitors_config.count,
135 +                        rom->client_monitors_config.heads);
136 +    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
137 +    return 1;
138 +}
139 +#endif
140 +
141  static const QXLInterface qxl_interface = {
142      .base.type               = SPICE_INTERFACE_QXL,
143      .base.description        = "qxl gpu",
144 @@ -995,6 +1070,10 @@ static const QXLInterface qxl_interface = {
145  #if SPICE_SERVER_VERSION >= 0x000b04
146      .set_client_capabilities = interface_set_client_capabilities,
147  #endif
148 +#if SPICE_SERVER_VERSION >= 0x000b05 && \
149 +    defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG)
150 +    .client_monitors_config = interface_client_monitors_config,
151 +#endif
152  };
153  
154  static void qxl_enter_vga_mode(PCIQXLDevice *d)
155 diff --git a/trace-events b/trace-events
156 index 80a52d9..07b63f1 100644
157 --- a/trace-events
158 +++ b/trace-events
159 @@ -930,7 +930,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d
160  qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
161  qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
162  qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
163 -qxl_io_log(int qid, const uint8_t *str) "%d %s"
164 +qxl_io_log(int qid, const uint8_t *log_buf) "%d %s"
165  qxl_io_read_unexpected(int qid) "%d"
166  qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
167  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"
168 @@ -974,6 +974,10 @@ qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dir
169  qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
170  qxl_send_events(int qid, uint32_t events) "%d %d"
171  qxl_set_guest_bug(int qid) "%d"
172 +qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p"
173 +qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p"
174 +qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
175 +qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u"
176  
177  # hw/qxl-render.c
178  qxl_render_blit_guest_primary_initialized(void) ""
179 -- 
180 1.7.12.1
181