From patchwork Thu Dec 6 15:41:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alon Levy X-Patchwork-Id: 204283 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 8FBC72C026E for ; Fri, 7 Dec 2012 02:41:54 +1100 (EST) Received: from localhost ([::1]:41453 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TgdaC-0003gP-Fx for incoming@patchwork.ozlabs.org; Thu, 06 Dec 2012 10:41:52 -0500 Received: from eggs.gnu.org ([208.118.235.92]:39579) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TgdZj-0002iv-1x for qemu-devel@nongnu.org; Thu, 06 Dec 2012 10:41:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TgdZg-0005pB-Ox for qemu-devel@nongnu.org; Thu, 06 Dec 2012 10:41:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:26144) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TgdZg-0005ou-Hd for qemu-devel@nongnu.org; Thu, 06 Dec 2012 10:41:20 -0500 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qB6FfICi008946 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 6 Dec 2012 10:41:18 -0500 Received: from Host-001.privatebox (vpn1-6-21.ams2.redhat.com [10.36.6.21]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id qB6FfFRP015766; Thu, 6 Dec 2012 10:41:16 -0500 From: Alon Levy To: qemu-devel@nongnu.org Date: Thu, 6 Dec 2012 17:41:13 +0200 Message-Id: <1354808473-7634-1-git-send-email-alevy@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kraxel@redhat.com Subject: [Qemu-devel] [PATCH] qxl: use correct rom size for revision < 4 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 RHBZ 869981 Before this patch revision < 4 (4 is the default) would result in a wrong qxl_rom size of 16384 instead of 8192 when building with spice-protocol-0.12, due to the addition of fields in the rom for client capabilities and monitors config that were added between spice-protocol 0.10 and 0.12. The solution is a bit involved, since I decided not to change QXLRom which is defined externally in spice-protocol. Instead for revision < 4 we allocate 72 bytes for the QXLRom on the qxl_rom bar (bytes [0,71]) and make sure no fields out of that range are accessed, via checking of the revision and nop-ing. Signed-off-by: Alon Levy --- hw/qxl.c | 37 ++++++++++++++++++++++++++++++++----- hw/qxl.h | 2 ++ trace-events | 2 ++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 3f835b8..4794f13 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -314,10 +314,26 @@ static inline uint32_t msb_mask(uint32_t val) return mask; } -static ram_addr_t qxl_rom_size(void) +static ram_addr_t init_qxl_rom_size(PCIQXLDevice *qxl) { - uint32_t rom_size = sizeof(QXLRom) + sizeof(QXLModes) + sizeof(qxl_modes); + uint32_t rom_size; + switch (qxl->revision) { + case 1: + case 2: + case 3: + /* rom_size ends up in [4096, 8192), so it fits all revisions <= 3 */ + qxl->qxl_rom_size = 72; + break; + case 4: + /* rom_size ends up >= 8192 for spice-protocol >= 12.1 because of added + * client capabilities */ + qxl->qxl_rom_size = sizeof(QXLRom); + break; + default: + abort(); + } + rom_size = qxl->qxl_rom_size + sizeof(QXLModes) + sizeof(qxl_modes); rom_size = MAX(rom_size, TARGET_PAGE_SIZE); rom_size = msb_mask(rom_size * 2 - 1); return rom_size; @@ -326,7 +342,7 @@ static ram_addr_t qxl_rom_size(void) static void init_qxl_rom(PCIQXLDevice *d) { QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar); - QXLModes *modes = (QXLModes *)(rom + 1); + QXLModes *modes = (QXLModes *)((void *)rom + d->qxl_rom_size); uint32_t ram_header_size; uint32_t surface0_area_size; uint32_t num_pages; @@ -338,7 +354,7 @@ static void init_qxl_rom(PCIQXLDevice *d) rom->magic = cpu_to_le32(QXL_ROM_MAGIC); rom->id = cpu_to_le32(d->id); rom->log_level = cpu_to_le32(d->guestdebug); - rom->modes_offset = cpu_to_le32(sizeof(QXLRom)); + rom->modes_offset = cpu_to_le32(d->qxl_rom_size); rom->slot_gen_bits = MEMSLOT_GENERATION_BITS; rom->slot_id_bits = MEMSLOT_SLOT_BITS; @@ -981,6 +997,12 @@ static void interface_set_client_capabilities(QXLInstance *sin, { PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); + if (qxl->revision < 4) { + trace_qxl_set_client_capabilities_unsupported_by_revision(qxl->id, + qxl->revision); + return; + } + if (runstate_check(RUN_STATE_INMIGRATE) || runstate_check(RUN_STATE_POSTMIGRATE)) { return; @@ -1013,6 +1035,11 @@ static int interface_client_monitors_config(QXLInstance *sin, QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar); int i; + if (qxl->revision < 4) { + trace_qxl_client_monitors_config_unsupported_by_device(qxl->id, + qxl->revision); + return 0; + } /* * Older windows drivers set int_mask to 0 when their ISR is called, * then later set it to ~0. So it doesn't relate to the actual interrupts @@ -2031,7 +2058,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); pci_set_byte(&config[PCI_INTERRUPT_PIN], 1); - qxl->rom_size = qxl_rom_size(); + qxl->rom_size = init_qxl_rom_size(qxl); memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size); vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev); init_qxl_rom(qxl); diff --git a/hw/qxl.h b/hw/qxl.h index b3564fb..c9dee70 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -92,6 +92,8 @@ typedef struct PCIQXLDevice { QXLRom shadow_rom; QXLRom *rom; QXLModes *modes; + uint32_t qxl_rom_size; /* size allocated for QXLRom, + <= sizeof(QXLRom) */ uint32_t rom_size; MemoryRegion rom_bar; diff --git a/trace-events b/trace-events index 6c6cbf1..7d9d62d 100644 --- a/trace-events +++ b/trace-events @@ -1006,8 +1006,10 @@ qxl_send_events_vm_stopped(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, uint32_t int_mask, void *client_monitors_config) "%d %X %p" +qxl_client_monitors_config_unsupported_by_device(int qid, int revision) "%d revision=%d" qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d" qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u" +qxl_set_client_capabilities_unsupported_by_revision(int qid, int revision) "%d revision=%d" # hw/qxl-render.c qxl_render_blit_guest_primary_initialized(void) ""