From patchwork Tue Sep 11 06:56:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alon Levy X-Patchwork-Id: 183031 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 882F92C036B for ; Tue, 11 Sep 2012 16:56:55 +1000 (EST) Received: from localhost ([::1]:56986 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBKOz-0006nM-Oe for incoming@patchwork.ozlabs.org; Tue, 11 Sep 2012 02:56:53 -0400 Received: from eggs.gnu.org ([208.118.235.92]:59382) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBKOU-0005Ti-Kt for qemu-devel@nongnu.org; Tue, 11 Sep 2012 02:56:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TBKON-0007J2-Uu for qemu-devel@nongnu.org; Tue, 11 Sep 2012 02:56:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51828) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBKON-0007HY-MC for qemu-devel@nongnu.org; Tue, 11 Sep 2012 02:56:15 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q8B6uFjY028179 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 11 Sep 2012 02:56:15 -0400 Received: from garlic.tlv.redhat.com (spice-ovirt.tlv.redhat.com [10.35.4.71]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q8B6uBdO004025; Tue, 11 Sep 2012 02:56:14 -0400 From: Alon Levy To: qemu-devel@nongnu.org Date: Tue, 11 Sep 2012 09:56:10 +0300 Message-Id: <1347346570-2469-3-git-send-email-alevy@redhat.com> In-Reply-To: <1347346570-2469-1-git-send-email-alevy@redhat.com> References: <1347346570-2469-1-git-send-email-alevy@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: kraxel@redhat.com Subject: [Qemu-devel] [PATCH 3/3] hw/qxl: support client monitor configuration via device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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) ""