[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] qxl: use correct rom size for revision < 4
From: |
Alon Levy |
Subject: |
[Qemu-devel] [PATCH] qxl: use correct rom size for revision < 4 |
Date: |
Thu, 6 Dec 2012 17:41:13 +0200 |
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 <address@hidden>
---
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