qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/3] hw/qxl: support client monitor configuration vi


From: Alon Levy
Subject: [Qemu-devel] [PATCH 3/3] hw/qxl: support client monitor configuration via device
Date: Tue, 11 Sep 2012 09:56:10 +0300

Until now we used only the agent to change the monitor count and each
monitor resolution. This patch introduces the qemu part of using the
device as the mediator instead of the agent via virtio-serial.

Spice (>=0.11.5) calls the new QXLInterface::client_monitors_config,
generating an interrupt QXL_INTERRUPT_CLIENT_MONITORS_CONFIG which the
client indicates handling of (after reading from
QXLRom::client_monitors_config) by QXL_IO_CLIENT_MONITORS_CONFIG_DONE.

The maximal number of monitors is limited on the QXLRom to 63.

QXL checks the existance of a QXL_GUEST_CAP_CLIENT_MONITORS_CONFIG_ISR
before issuing the interrupt. (this is in addition to spice checking for
the same capability).

Signed-off-by: Alon Levy <address@hidden>
---
 hw/qxl.c     | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qxl.h     |  2 ++
 trace-events |  5 ++++
 3 files changed, 82 insertions(+)

diff --git a/hw/qxl.c b/hw/qxl.c
index 583a2d9..18c63ff 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -34,6 +34,7 @@
 
 #ifndef CONFIG_QXL_IO_CLIENT_MONITORS_CONFIG
 #define QXL_IO_CAPABILITIES_SET (QXL_IO_FLUSH_RELEASE + 2)
+#define QXL_IO_CLIENT_MONITORS_CONFIG_DONE (QXL_IO_FLUSH_RELEASE + 3)
 #endif
 
 /*
@@ -596,6 +597,8 @@ static const char *io_port_to_string(uint32_t io_port)
         [QXL_IO_FLUSH_RELEASE]          = "QXL_IO_FLUSH_RELEASE",
         [QXL_IO_MONITORS_CONFIG_ASYNC]  = "QXL_IO_MONITORS_CONFIG_ASYNC",
         [QXL_IO_CAPABILITIES_SET]       = "QXL_IO_CAPABILITIES_SET",
+        [QXL_IO_CLIENT_MONITORS_CONFIG_DONE] =
+                                          "QXL_IO_CLIENT_MONITORS_CONFIG_DONE",
     };
 
     if (io_port >= ARRAY_SIZE(io_port_to_string)) {
@@ -986,6 +989,64 @@ static void interface_set_client_capabilities(QXLInstance 
*sin,
 
 #endif
 
+#if defined(CONFIG_QXL_IO_CLIENT_MONITORS_CONFIG) \
+    && SPICE_SERVER_VERSION >= 0x000b05
+static int qxl_test_guest_cap(PCIQXLDevice *qxl, unsigned cap)
+{
+    int ind = cap / 8;
+    uint8_t mask = 1 << (cap & 7);
+
+    if (ind >= sizeof(qxl->ram->guest_capabilities)) {
+        return 0;
+    }
+    return qxl->ram->guest_capabilities[ind] & mask;
+}
+
+/* called from main context only */
+static void interface_client_monitors_config(QXLInstance *sin,
+                                        VDAgentMonitorsConfig *monitors_config)
+{
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
+    int i;
+
+    if (!qxl_test_guest_cap(qxl, QXL_GUEST_CAP_CLIENT_MONITORS_CONFIG_ISR)) {
+        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
+                                                              monitors_config);
+        return;
+    }
+    if (qxl->client_monitors_config_isr_in_progress) {
+        trace_qxl_client_monitors_config_ignored_guest_busy(qxl->id,
+                                                            monitors_config);
+        return;
+    }
+    rom->client_monitors_config.count = monitors_config->num_of_monitors;
+    /* monitors_config->flags ignored */
+    if (rom->client_monitors_config.count >=
+            ARRAY_SIZE(rom->client_monitors_config.heads)) {
+        trace_qxl_client_monitors_config_capped(qxl->id,
+                                monitors_config->num_of_monitors,
+                                ARRAY_SIZE(rom->client_monitors_config.heads));
+        rom->client_monitors_config.count =
+            ARRAY_SIZE(rom->client_monitors_config.heads);
+    }
+    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
+        VDAgentMonConfig *monitor = &monitors_config->monitors[i];
+        QXLURect *rect = &rom->client_monitors_config.heads[i];
+        /* monitor->depth ignored */
+        rect->left = monitor->x;
+        rect->top = monitor->y;
+        rect->right = monitor->x + monitor->width;
+        rect->bottom = monitor->y + monitor->height;
+    }
+    trace_qxl_interrupt_client_monitors_config(qxl->id,
+                        rom->client_monitors_config.count,
+                        rom->client_monitors_config.heads);
+    qxl->client_monitors_config_isr_in_progress = 1;
+    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
+}
+#endif
+
 static const QXLInterface qxl_interface = {
     .base.type               = SPICE_INTERFACE_QXL,
     .base.description        = "qxl gpu",
@@ -1010,6 +1071,10 @@ static const QXLInterface qxl_interface = {
 #if SPICE_SERVER_VERSION >= 0x000b04
     .set_client_capabilities = interface_set_client_capabilities,
 #endif
+#if SPICE_SERVER_VERSION >= 0x000b05 && \
+    defined(CONFIG_QXL_IO_CLIENT_MONITORS_CONFIG)
+    .client_monitors_config = interface_client_monitors_config,
+#endif
 };
 
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -1604,6 +1669,16 @@ async_common:
     case QXL_IO_CAPABILITIES_SET:
         qxl_spice_guest_capabilities_set(d);
         break;
+    case QXL_IO_CLIENT_MONITORS_CONFIG_DONE:
+        trace_qxl_io_client_monitors_config_done(d->id);
+        if (!d->client_monitors_config_isr_in_progress) {
+            qxl_set_guest_bug(d,
+                "%s: unexpected QXL_IO_CLIENT_MONITORS_CONFIG_DONE\n",
+                __func__);
+        } else {
+            d->client_monitors_config_isr_in_progress = 0;
+        }
+        break;
     default:
         qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, 
io_port);
     }
diff --git a/hw/qxl.h b/hw/qxl.h
index 5553824..a1ede3c 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -72,6 +72,8 @@ typedef struct PCIQXLDevice {
 
     QXLPHYSICAL        guest_monitors_config;
 
+    int                client_monitors_config_isr_in_progress;
+
     QemuMutex          track_lock;
 
     /* thread signaling */
diff --git a/trace-events b/trace-events
index 7a35f62..4ea7cdd 100644
--- a/trace-events
+++ b/trace-events
@@ -928,6 +928,7 @@ qxl_io_read_unexpected(int qid) "%d"
 qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char 
*desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
 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"
 qxl_io_capabilities_set(int qid, int caps_size, uint8_t *caps) "%d %d %p"
+qxl_io_client_monitors_config_done(int qid) "%d"
 qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, 
uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64
 qxl_post_load(int qid, const char *mode) "%d %s"
 qxl_pre_load(int qid) "%d"
@@ -968,6 +969,10 @@ qxl_spice_update_area_rest(int qid, uint32_t 
num_dirty_rects, uint32_t clear_dir
 qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d 
offset=%d size=%d"
 qxl_send_events(int qid, uint32_t events) "%d %d"
 qxl_set_guest_bug(int qid) "%d"
+qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d 
%d %p"
+qxl_client_monitors_config_unsupported_by_guest(int qid, void 
*client_monitors_config) "%d %p"
+qxl_client_monitors_config_ignored_guest_busy(int qid, void 
*client_monitors_config) "%d %p"
+qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
 
 # hw/qxl-render.c
 qxl_render_blit_guest_primary_initialized(void) ""
-- 
1.7.12




reply via email to

[Prev in Thread] Current Thread [Next in Thread]