qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] qxl: use correct rom size for revision < 4
@ 2012-12-06 15:41 Alon Levy
  2012-12-12 11:46 ` Gerd Hoffmann
  0 siblings, 1 reply; 24+ messages in thread
From: Alon Levy @ 2012-12-06 15:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: kraxel

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 <alevy@redhat.com>
---
 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) ""
-- 
1.8.0.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2013-01-21 12:48 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-06 15:41 [Qemu-devel] [PATCH] qxl: use correct rom size for revision < 4 Alon Levy
2012-12-12 11:46 ` Gerd Hoffmann
2012-12-13 10:40   ` Alon Levy
2012-12-13 14:30     ` Yonit Halperin
2012-12-13 14:43       ` Gerd Hoffmann
2012-12-23 20:33         ` Alon Levy
2013-01-03  7:55           ` Gerd Hoffmann
2012-12-13 11:36   ` [Qemu-devel] [PATCH 1/2] qxl: stop using non revision 4 rom fields " Alon Levy
2012-12-13 11:36     ` [Qemu-devel] [PATCH 2/2] qxl: change rom so that 4096 < size < 8192 Alon Levy
2012-12-13 12:05       ` Gerd Hoffmann
2012-12-23 20:31         ` Alon Levy
2013-01-15 13:34           ` Alon Levy
2013-01-15 15:19             ` Gerd Hoffmann
2013-01-16 17:59               ` [Qemu-devel] [PATCH v2 0/2] fix two revision related errors Alon Levy
2013-01-16 17:59                 ` [Qemu-devel] [PATCH v2 1/2] qxl: stop using non revision 4 rom fields for revision < 4 Alon Levy
2013-01-16 17:59                 ` [Qemu-devel] [PATCH v2 2/2] qxl: change rom size to 8192 Alon Levy
2013-01-17 13:02                 ` [Qemu-devel] [PATCH v2 0/2] fix two revision related errors Gerd Hoffmann
2013-01-17 13:28                   ` Alon Levy
2013-01-17 13:44                     ` Gerd Hoffmann
2013-01-20 16:30                   ` Alon Levy
2013-01-21  6:26                     ` Gerd Hoffmann
2013-01-21 12:47                   ` Alon Levy
2013-01-21 12:48                   ` [Qemu-devel] [PATCH v3 1/2] qxl: stop using non revision 4 rom fields for revision < 4 Alon Levy
2013-01-21 12:48                     ` [Qemu-devel] [PATCH v3 2/2] qxl: change rom size to 8192 Alon Levy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).