All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.