From 160c31f78fb4eb747e50d077835dbb70dbdbbb9f Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Thu, 24 May 2012 12:38:11 +0300 Subject: [PATCH 01/10] ui/spice-display.c: add missing initialization for valgrind We can't initialize QXLDevSurfaceCreate field by field because it has a pa hole, and so 4 bytes remain uninitialized when building on x86-64, so just memset. Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/spice-display.c b/ui/spice-display.c index 5418eb3c7c..3e8f0b3ad5 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -244,6 +244,8 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) { QXLDevSurfaceCreate surface; + memset(&surface, 0, sizeof(surface)); + dprint(1, "%s: %dx%d\n", __FUNCTION__, ds_get_width(ssd->ds), ds_get_height(ssd->ds)); From 0a530548a1007dd24a9ea3429af2c9dfae690386 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Thu, 24 May 2012 12:38:12 +0300 Subject: [PATCH 02/10] hw/qxl: s/qxl_guest_bug/qxl_set_guest_bug/ Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 49 +++++++++++++++++++++++++++---------------------- hw/qxl.h | 3 ++- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 3da3399934..8777ba9615 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -30,7 +30,7 @@ /* * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as * such can be changed by the guest, so to avoid a guest trigerrable - * abort we just set qxl_guest_bug and set the return to NULL. Still + * abort we just qxl_set_guest_bug and set the return to NULL. Still * it may happen as a result of emulator bug as well. */ #undef SPICE_RING_PROD_ITEM @@ -40,7 +40,7 @@ uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \ typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \ - qxl_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \ + qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \ "! %p <= %p < %p", (uint8_t *)start, \ (uint8_t *)m_item, (uint8_t *)end); \ ret = NULL; \ @@ -56,7 +56,7 @@ uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \ typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \ - qxl_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \ + qxl_set_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \ "! %p <= %p < %p", (uint8_t *)start, \ (uint8_t *)m_item, (uint8_t *)end); \ ret = NULL; \ @@ -138,7 +138,7 @@ static void qxl_reset_memslots(PCIQXLDevice *d); static void qxl_reset_surfaces(PCIQXLDevice *d); static void qxl_ring_set_dirty(PCIQXLDevice *qxl); -void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) +void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) { qxl_send_events(qxl, QXL_INTERRUPT_ERROR); if (qxl->guestdebug) { @@ -411,7 +411,8 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) uint32_t id = le32_to_cpu(cmd->surface_id); if (id >= NUM_SURFACES) { - qxl_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id, NUM_SURFACES); + qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id, + NUM_SURFACES); return 1; } qemu_mutex_lock(&qxl->track_lock); @@ -1061,12 +1062,12 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end); if (slot_id >= NUM_MEMSLOTS) { - qxl_guest_bug(d, "%s: slot_id >= NUM_MEMSLOTS %d >= %d", __func__, + qxl_set_guest_bug(d, "%s: slot_id >= NUM_MEMSLOTS %d >= %d", __func__, slot_id, NUM_MEMSLOTS); return 1; } if (guest_start > guest_end) { - qxl_guest_bug(d, "%s: guest_start > guest_end 0x%" PRIx64 + qxl_set_guest_bug(d, "%s: guest_start > guest_end 0x%" PRIx64 " > 0x%" PRIx64, __func__, guest_start, guest_end); return 1; } @@ -1091,7 +1092,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, break; } if (i == ARRAY_SIZE(regions)) { - qxl_guest_bug(d, "%s: finished loop without match", __func__); + qxl_set_guest_bug(d, "%s: finished loop without match", __func__); return 1; } @@ -1105,7 +1106,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, break; default: /* should not happen */ - qxl_guest_bug(d, "%s: pci_region = %d", __func__, pci_region); + qxl_set_guest_bug(d, "%s: pci_region = %d", __func__, pci_region); return 1; } @@ -1156,21 +1157,24 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) return (void *)(intptr_t)offset; case MEMSLOT_GROUP_GUEST: if (slot >= NUM_MEMSLOTS) { - qxl_guest_bug(qxl, "slot too large %d >= %d", slot, NUM_MEMSLOTS); + qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, + NUM_MEMSLOTS); return NULL; } if (!qxl->guest_slots[slot].active) { - qxl_guest_bug(qxl, "inactive slot %d\n", slot); + qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); return NULL; } if (offset < qxl->guest_slots[slot].delta) { - qxl_guest_bug(qxl, "slot %d offset %"PRIu64" < delta %"PRIu64"\n", + qxl_set_guest_bug(qxl, + "slot %d offset %"PRIu64" < delta %"PRIu64"\n", slot, offset, qxl->guest_slots[slot].delta); return NULL; } offset -= qxl->guest_slots[slot].delta; if (offset > qxl->guest_slots[slot].size) { - qxl_guest_bug(qxl, "slot %d offset %"PRIu64" > size %"PRIu64"\n", + qxl_set_guest_bug(qxl, + "slot %d offset %"PRIu64" > size %"PRIu64"\n", slot, offset, qxl->guest_slots[slot].size); return NULL; } @@ -1192,7 +1196,7 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, QXLSurfaceCreate *sc = &qxl->guest_primary.surface; if (qxl->mode == QXL_MODE_NATIVE) { - qxl_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE", + qxl_set_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE", __func__); } qxl_exit_vga_mode(qxl); @@ -1342,7 +1346,7 @@ async_common: async = QXL_ASYNC; qemu_mutex_lock(&d->async_lock); if (d->current_async != QXL_UNDEFINED_IO) { - qxl_guest_bug(d, "%d async started before last (%d) complete", + qxl_set_guest_bug(d, "%d async started before last (%d) complete", io_port, d->current_async); qemu_mutex_unlock(&d->async_lock); return; @@ -1403,11 +1407,12 @@ async_common: break; case QXL_IO_MEMSLOT_ADD: if (val >= NUM_MEMSLOTS) { - qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range"); + qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range"); break; } if (d->guest_slots[val].active) { - qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: memory slot already active"); + qxl_set_guest_bug(d, + "QXL_IO_MEMSLOT_ADD: memory slot already active"); break; } d->guest_slots[val].slot = d->ram->mem_slot; @@ -1415,14 +1420,14 @@ async_common: break; case QXL_IO_MEMSLOT_DEL: if (val >= NUM_MEMSLOTS) { - qxl_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range"); + qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range"); break; } qxl_del_memslot(d, val); break; case QXL_IO_CREATE_PRIMARY: if (val != 0) { - qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0", + qxl_set_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0", async); goto cancel_async; } @@ -1431,7 +1436,7 @@ async_common: break; case QXL_IO_DESTROY_PRIMARY: if (val != 0) { - qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", + qxl_set_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", async); goto cancel_async; } @@ -1443,7 +1448,7 @@ async_common: break; case QXL_IO_DESTROY_SURFACE_WAIT: if (val >= NUM_SURFACES) { - qxl_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" + qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" "%" PRIu64 " >= NUM_SURFACES", async, val); goto cancel_async; } @@ -1467,7 +1472,7 @@ async_common: qxl_spice_destroy_surfaces(d, async); break; default: - qxl_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port); + qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port); } return; cancel_async: diff --git a/hw/qxl.h b/hw/qxl.h index 31029503fe..f2d4fdce40 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -127,7 +127,8 @@ typedef struct PCIQXLDevice { /* qxl.c */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); -void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) GCC_FMT_ATTR(2, 3); +void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) + GCC_FMT_ATTR(2, 3); void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, From 0f7bfd8198ffad58a5095ac5d7a46288ea7f5c6e Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Thu, 24 May 2012 19:18:53 +0300 Subject: [PATCH 03/10] qxl: stop dirty loging when not in vga mode Tested with linux guest. Not sure how to check actual performance affect of this. Checked with the previously send traceevent that the kvm ioctl to start/stop dirty logging is being called. (KVM_SET_USER_MEMORY_REGION). Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/qxl.c b/hw/qxl.c index 8777ba9615..5a7be60668 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -932,6 +932,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d) qemu_spice_create_host_primary(&d->ssd); d->mode = QXL_MODE_VGA; memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); + vga_dirty_log_start(&d->vga); } static void qxl_exit_vga_mode(PCIQXLDevice *d) @@ -940,6 +941,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d) return; } trace_qxl_exit_vga_mode(d->id); + vga_dirty_log_stop(&d->vga); qxl_destroy_primary(d, QXL_SYNC); } From 087e6a42ed6ddba524a343563611d2a7b78f15a8 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Thu, 24 May 2012 19:18:54 +0300 Subject: [PATCH 04/10] hw/qxl: ignore guest from guestbug until reset soft_reset is called from any of: * QXL_IO_RESET * vga io * pci reset handler Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 13 ++++++++++++- hw/qxl.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index 5a7be60668..b5e53ce65b 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -141,6 +141,7 @@ static void qxl_ring_set_dirty(PCIQXLDevice *qxl); void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) { qxl_send_events(qxl, QXL_INTERRUPT_ERROR); + qxl->guest_bug = 1; if (qxl->guestdebug) { va_list ap; va_start(ap, msg); @@ -151,6 +152,10 @@ void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) } } +static void qxl_clear_guest_bug(PCIQXLDevice *qxl) +{ + qxl->guest_bug = 0; +} void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, @@ -572,7 +577,7 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) case QXL_MODE_NATIVE: case QXL_MODE_UNDEFINED: ring = &qxl->ram->cmd_ring; - if (SPICE_RING_IS_EMPTY(ring)) { + if (qxl->guest_bug || SPICE_RING_IS_EMPTY(ring)) { return false; } SPICE_RING_CONS_ITEM(qxl, ring, cmd); @@ -980,6 +985,7 @@ static void qxl_soft_reset(PCIQXLDevice *d) { trace_qxl_soft_reset(d->id); qxl_check_state(d); + qxl_clear_guest_bug(d); if (d->id == 0) { qxl_enter_vga_mode(d); @@ -1297,6 +1303,10 @@ static void ioport_write(void *opaque, target_phys_addr_t addr, qxl_async_io async = QXL_SYNC; uint32_t orig_io_port = io_port; + if (d->guest_bug && !io_port == QXL_IO_RESET) { + return; + } + switch (io_port) { case QXL_IO_RESET: case QXL_IO_SET_MODE: @@ -1749,6 +1759,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) qemu_mutex_init(&qxl->track_lock); qemu_mutex_init(&qxl->async_lock); qxl->current_async = QXL_UNDEFINED_IO; + qxl->guest_bug = 0; switch (qxl->revision) { case 1: /* spice 0.4 -- qxl-1 */ diff --git a/hw/qxl.h b/hw/qxl.h index f2d4fdce40..a4ab7cc647 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -31,6 +31,9 @@ typedef struct PCIQXLDevice { uint32_t debug; uint32_t guestdebug; uint32_t cmdlog; + + uint32_t guest_bug; + enum qxl_mode mode; uint32_t cmdflags; int generation; From a5f68c22e76bc4108401046081b058a901555bf4 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 11 Jun 2012 09:24:01 +0300 Subject: [PATCH 05/10] qxl: reset current_async on qxl_soft_reset Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/qxl.c b/hw/qxl.c index b5e53ce65b..4be946288f 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -986,6 +986,7 @@ static void qxl_soft_reset(PCIQXLDevice *d) trace_qxl_soft_reset(d->id); qxl_check_state(d); qxl_clear_guest_bug(d); + d->current_async = QXL_UNDEFINED_IO; if (d->id == 0) { qxl_enter_vga_mode(d); From e9c6149f6ae6873f14a12eea554925b6aa4c4dec Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 24 May 2012 09:16:29 +0200 Subject: [PATCH 06/10] vga: raise xres+yres limits The vgabios will check whenever any given video mode will fit into the given video memory before adding it to the list of available modes, so there is no need to keep xmax * ymax * 32bpp lower than VGA_RAM_SIZE. Lets raise the limits a bit. Should be good for a few years, display sizes are not growing that fast. Signed-off-by: Gerd Hoffmann --- hw/vga_int.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/vga_int.h b/hw/vga_int.h index d244d8ff99..ce33e66744 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -31,8 +31,8 @@ /* bochs VBE support */ #define CONFIG_BOCHS_VBE -#define VBE_DISPI_MAX_XRES 1600 -#define VBE_DISPI_MAX_YRES 1200 +#define VBE_DISPI_MAX_XRES 16000 +#define VBE_DISPI_MAX_YRES 12000 #define VBE_DISPI_MAX_BPP 32 #define VBE_DISPI_INDEX_ID 0x0 From 4a1e244eb65c646bdd938d9d137ace42d76c95a7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 24 May 2012 09:59:44 +0200 Subject: [PATCH 07/10] vga: make vram size configurable Zap the global VGA_RAM_SIZE #define, make the vga ram size configurable for standard vga and vmware vga. cirrus and qxl are left with a fixed size (and private VGA_RAM_SIZE #define) for now. qxl needs some non-trivial adjustments in the mode list handling deal with a runtime-configurable size, which calls for a separate qxl patch. cirrus emulates cards which have 2 MB (isa) and 4 MB (pci), so I guess it would make sense to use these sizes. That change would break migration though, so I left it fixed at 8 MB size. Making it configurabls is pretty pointless for cirrus as we have to match real hardware. Signed-off-by: Gerd Hoffmann --- hw/cirrus_vga.c | 8 ++++++-- hw/qxl.c | 5 ++++- hw/vga-isa-mm.c | 5 ++++- hw/vga-isa.c | 8 +++++++- hw/vga-pci.c | 8 +++++++- hw/vga.c | 13 ++++++++++--- hw/vga_int.h | 4 ++-- hw/vmware_vga.c | 13 ++++++++++--- 8 files changed, 50 insertions(+), 14 deletions(-) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index afedaa43d3..623dd688d9 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -43,6 +43,8 @@ //#define DEBUG_CIRRUS //#define DEBUG_BITBLT +#define VGA_RAM_SIZE (8192 * 1024) + /*************************************** * * definitions @@ -2891,7 +2893,8 @@ static int vga_initfn(ISADevice *dev) ISACirrusVGAState *d = DO_UPCAST(ISACirrusVGAState, dev, dev); VGACommonState *s = &d->cirrus_vga.vga; - vga_common_init(s, VGA_RAM_SIZE); + s->vram_size_mb = VGA_RAM_SIZE >> 20; + vga_common_init(s); cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0, isa_address_space(dev)); s->ds = graphic_console_init(s->update, s->invalidate, @@ -2933,7 +2936,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) int16_t device_id = pc->device_id; /* setup VGA */ - vga_common_init(&s->vga, VGA_RAM_SIZE); + s->vga.vram_size_mb = VGA_RAM_SIZE >> 20; + vga_common_init(&s->vga); cirrus_init_common(s, device_id, 1, pci_address_space(dev)); s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate, s->vga.screen_dump, s->vga.text_update, diff --git a/hw/qxl.c b/hw/qxl.c index 4be946288f..c40cf55e39 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -27,6 +27,8 @@ #include "qxl.h" +#define VGA_RAM_SIZE (8192 * 1024) + /* * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as * such can be changed by the guest, so to avoid a guest trigerrable @@ -1854,7 +1856,8 @@ static int qxl_init_primary(PCIDevice *dev) qxl->id = 0; qxl_init_ramsize(qxl, 32); - vga_common_init(vga, qxl->vga.vram_size); + vga->vram_size_mb = qxl->vga.vram_size >> 20; + vga_common_init(vga); vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false); portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga"); portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0); diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index f8984c62cb..44ae7d92c8 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -28,6 +28,8 @@ #include "pixel_ops.h" #include "qemu-timer.h" +#define VGA_RAM_SIZE (8192 * 1024) + typedef struct ISAVGAMMState { VGACommonState vga; int it_shift; @@ -128,7 +130,8 @@ int isa_vga_mm_init(target_phys_addr_t vram_base, s = g_malloc0(sizeof(*s)); - vga_common_init(&s->vga, VGA_RAM_SIZE); + s->vga.vram_size_mb = VGA_RAM_SIZE >> 20; + vga_common_init(&s->vga); vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate, diff --git a/hw/vga-isa.c b/hw/vga-isa.c index 4bcc4db62f..d2904737bc 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -49,7 +49,7 @@ static int vga_initfn(ISADevice *dev) MemoryRegion *vga_io_memory; const MemoryRegionPortio *vga_ports, *vbe_ports; - vga_common_init(s, VGA_RAM_SIZE); + vga_common_init(s); s->legacy_address_space = isa_address_space(dev); vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports); isa_register_portio_list(dev, 0x3b0, vga_ports, s, "vga"); @@ -69,6 +69,11 @@ static int vga_initfn(ISADevice *dev) return 0; } +static Property vga_isa_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", ISAVGAState, state.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void vga_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -76,6 +81,7 @@ static void vga_class_initfn(ObjectClass *klass, void *data) ic->init = vga_initfn; dc->reset = vga_reset_isa; dc->vmsd = &vmstate_vga_common; + dc->props = vga_isa_properties; } static TypeInfo vga_info = { diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 465b643d21..0848126555 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -53,7 +53,7 @@ static int pci_vga_initfn(PCIDevice *dev) VGACommonState *s = &d->vga; // vga + console init - vga_common_init(s, VGA_RAM_SIZE); + vga_common_init(s); vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); s->ds = graphic_console_init(s->update, s->invalidate, @@ -75,6 +75,11 @@ DeviceState *pci_vga_init(PCIBus *bus) return &pci_create_simple(bus, -1, "VGA")->qdev; } +static Property vga_pci_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void vga_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -87,6 +92,7 @@ static void vga_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_QEMU_VGA; k->class_id = PCI_CLASS_DISPLAY_VGA; dc->vmsd = &vmstate_vga_pci; + dc->props = vga_pci_properties; } static TypeInfo vga_info = { diff --git a/hw/vga.c b/hw/vga.c index d784df7df4..acb3f7d924 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2225,7 +2225,7 @@ const VMStateDescription vmstate_vga_common = { } }; -void vga_common_init(VGACommonState *s, int vga_ram_size) +void vga_common_init(VGACommonState *s) { int i, j, v, b; @@ -2252,16 +2252,23 @@ void vga_common_init(VGACommonState *s, int vga_ram_size) expand4to8[i] = v; } + /* valid range: 1 MB -> 256 MB */ + s->vram_size = 1024 * 1024; + while (s->vram_size < (s->vram_size_mb << 20) && + s->vram_size < (256 << 20)) { + s->vram_size <<= 1; + } + s->vram_size_mb = s->vram_size >> 20; + #ifdef CONFIG_BOCHS_VBE s->is_vbe_vmstate = 1; #else s->is_vbe_vmstate = 0; #endif - memory_region_init_ram(&s->vram, "vga.vram", vga_ram_size); + memory_region_init_ram(&s->vram, "vga.vram", s->vram_size); vmstate_register_ram_global(&s->vram); xen_register_framebuffer(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); - s->vram_size = vga_ram_size; s->get_bpp = vga_get_bpp; s->get_offsets = vga_get_offsets; s->get_resolution = vga_get_resolution; diff --git a/hw/vga_int.h b/hw/vga_int.h index ce33e66744..3b38764a38 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -107,6 +107,7 @@ typedef struct VGACommonState { MemoryRegion vram; MemoryRegion vram_vbe; uint32_t vram_size; + uint32_t vram_size_mb; /* property */ uint32_t latch; MemoryRegion *chain4_alias; uint8_t sr_index; @@ -184,7 +185,7 @@ static inline int c6_to_8(int v) return (v << 2) | (b << 1) | b; } -void vga_common_init(VGACommonState *s, int vga_ram_size); +void vga_common_init(VGACommonState *s); void vga_init(VGACommonState *s, MemoryRegion *address_space, MemoryRegion *address_space_io, bool init_vga_ports); MemoryRegion *vga_init_io(VGACommonState *s, @@ -209,7 +210,6 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; -#define VGA_RAM_SIZE (8192 * 1024) #define VGABIOS_FILENAME "vgabios.bin" #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 142d9f4ea0..f8eb46d0c1 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1078,7 +1078,7 @@ static const VMStateDescription vmstate_vmware_vga = { } }; -static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size, +static void vmsvga_init(struct vmsvga_state_s *s, MemoryRegion *address_space, MemoryRegion *io) { s->scratch_size = SVGA_SCRATCH_SIZE; @@ -1095,7 +1095,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size, vmstate_register_ram_global(&s->fifo_ram); s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram); - vga_common_init(&s->vga, vga_ram_size); + vga_common_init(&s->vga); vga_init(&s->vga, address_space, io, true); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); @@ -1184,7 +1184,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev) "vmsvga-io", 0x10); pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); - vmsvga_init(&s->chip, VGA_RAM_SIZE, pci_address_space(dev), + vmsvga_init(&s->chip, pci_address_space(dev), pci_address_space_io(dev)); pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem); @@ -1199,6 +1199,12 @@ static int pci_vmsvga_initfn(PCIDevice *dev) return 0; } +static Property vga_vmware_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct pci_vmsvga_state_s, + chip.vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void vmsvga_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -1214,6 +1220,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) k->subsystem_id = SVGA_PCI_DEVICE_ID; dc->reset = vmsvga_reset; dc->vmsd = &vmstate_vmware_vga; + dc->props = vga_vmware_properties; } static TypeInfo vmsvga_info = { From 13d1fd44c46629aad672f192abbf02238c6cbf36 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Sun, 10 Jun 2012 18:05:06 +0300 Subject: [PATCH 08/10] qxl: add vgamem_size_mb and vgamem_size In preperation for supporting a larger framebuffer for multiple monitors on a single card, add a property to qxl vgamem_size_mb, and corresponding byte sized vgamem_size, and use instead of VGA_RAM_SIZE. [ kraxel: simplify property handling, add sanity checks ] [ kraxel: fix mode copying ] Signed-off-by: Alon Levy Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 70 +++++++++++++++++++++++++++++++++----------------------- hw/qxl.h | 2 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index c40cf55e39..62eed05e27 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -27,8 +27,6 @@ #include "qxl.h" -#define VGA_RAM_SIZE (8192 * 1024) - /* * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as * such can be changed by the guest, so to avoid a guest trigerrable @@ -116,20 +114,16 @@ static QXLMode qxl_modes[] = { QXL_MODE_EX(1600, 1200), QXL_MODE_EX(1680, 1050), QXL_MODE_EX(1920, 1080), -#if VGA_RAM_SIZE >= (16 * 1024 * 1024) /* these modes need more than 8 MB video memory */ QXL_MODE_EX(1920, 1200), QXL_MODE_EX(1920, 1440), QXL_MODE_EX(2048, 1536), QXL_MODE_EX(2560, 1440), QXL_MODE_EX(2560, 1600), -#endif -#if VGA_RAM_SIZE >= (32 * 1024 * 1024) /* these modes need more than 16 MB video memory */ QXL_MODE_EX(2560, 2048), QXL_MODE_EX(2800, 2100), QXL_MODE_EX(3200, 2400), -#endif }; static PCIQXLDevice *qxl0; @@ -286,6 +280,7 @@ static inline uint32_t msb_mask(uint32_t val) static ram_addr_t qxl_rom_size(void) { uint32_t rom_size = sizeof(QXLRom) + sizeof(QXLModes) + sizeof(qxl_modes); + rom_size = MAX(rom_size, TARGET_PAGE_SIZE); rom_size = msb_mask(rom_size * 2 - 1); return rom_size; @@ -298,8 +293,8 @@ static void init_qxl_rom(PCIQXLDevice *d) uint32_t ram_header_size; uint32_t surface0_area_size; uint32_t num_pages; - uint32_t fb, maxfb = 0; - int i; + uint32_t fb; + int i, n; memset(rom, 0, d->rom_size); @@ -314,26 +309,25 @@ static void init_qxl_rom(PCIQXLDevice *d) rom->slots_end = NUM_MEMSLOTS - 1; rom->n_surfaces = cpu_to_le32(NUM_SURFACES); - modes->n_modes = cpu_to_le32(ARRAY_SIZE(qxl_modes)); - for (i = 0; i < modes->n_modes; i++) { + for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) { fb = qxl_modes[i].y_res * qxl_modes[i].stride; - if (maxfb < fb) { - maxfb = fb; + if (fb > d->vgamem_size) { + continue; } - modes->modes[i].id = cpu_to_le32(i); - modes->modes[i].x_res = cpu_to_le32(qxl_modes[i].x_res); - modes->modes[i].y_res = cpu_to_le32(qxl_modes[i].y_res); - modes->modes[i].bits = cpu_to_le32(qxl_modes[i].bits); - modes->modes[i].stride = cpu_to_le32(qxl_modes[i].stride); - modes->modes[i].x_mili = cpu_to_le32(qxl_modes[i].x_mili); - modes->modes[i].y_mili = cpu_to_le32(qxl_modes[i].y_mili); - modes->modes[i].orientation = cpu_to_le32(qxl_modes[i].orientation); + modes->modes[n].id = cpu_to_le32(i); + modes->modes[n].x_res = cpu_to_le32(qxl_modes[i].x_res); + modes->modes[n].y_res = cpu_to_le32(qxl_modes[i].y_res); + modes->modes[n].bits = cpu_to_le32(qxl_modes[i].bits); + modes->modes[n].stride = cpu_to_le32(qxl_modes[i].stride); + modes->modes[n].x_mili = cpu_to_le32(qxl_modes[i].x_mili); + modes->modes[n].y_mili = cpu_to_le32(qxl_modes[i].y_mili); + modes->modes[n].orientation = cpu_to_le32(qxl_modes[i].orientation); + n++; } - if (maxfb < VGA_RAM_SIZE && d->id == 0) - maxfb = VGA_RAM_SIZE; + modes->n_modes = cpu_to_le32(n); ram_header_size = ALIGN(sizeof(QXLRam), 4096); - surface0_area_size = ALIGN(maxfb, 4096); + surface0_area_size = ALIGN(d->vgamem_size, 4096); num_pages = d->vga.vram_size; num_pages -= ram_header_size; num_pages -= surface0_area_size; @@ -1205,6 +1199,16 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, { QXLDevSurfaceCreate surface; QXLSurfaceCreate *sc = &qxl->guest_primary.surface; + int size; + int requested_height = le32_to_cpu(sc->height); + int requested_stride = le32_to_cpu(sc->stride); + + size = abs(requested_stride) * requested_height; + if (size > qxl->vgamem_size) { + qxl_set_guest_bug(qxl, "%s: requested primary larger then framebuffer" + " size", __func__); + return; + } if (qxl->mode == QXL_MODE_NATIVE) { qxl_set_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE", @@ -1714,14 +1718,20 @@ static DisplayChangeListener display_listener = { .dpy_refresh = display_refresh, }; -static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb) +static void qxl_init_ramsize(PCIQXLDevice *qxl) { - /* vga ram (bar 0) */ + /* vga mode framebuffer / primary surface (bar 0, first part) */ + if (qxl->vgamem_size_mb < 8) { + qxl->vgamem_size_mb = 8; + } + qxl->vgamem_size = qxl->vgamem_size_mb * 1024 * 1024; + + /* vga ram (bar 0, total) */ if (qxl->ram_size_mb != -1) { qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024; } - if (qxl->vga.vram_size < ram_min_mb * 1024 * 1024) { - qxl->vga.vram_size = ram_min_mb * 1024 * 1024; + if (qxl->vga.vram_size < qxl->vgamem_size * 2) { + qxl->vga.vram_size = qxl->vgamem_size * 2; } /* vram32 (surfaces, 32bit, bar 1) */ @@ -1744,6 +1754,7 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb) qxl->vram32_size = 4096; qxl->vram_size = 4096; } + qxl->vgamem_size = msb_mask(qxl->vgamem_size * 2 - 1); qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1); qxl->vram32_size = msb_mask(qxl->vram32_size * 2 - 1); qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1); @@ -1855,7 +1866,7 @@ static int qxl_init_primary(PCIDevice *dev) PortioList *qxl_vga_port_list = g_new(PortioList, 1); qxl->id = 0; - qxl_init_ramsize(qxl, 32); + qxl_init_ramsize(qxl); vga->vram_size_mb = qxl->vga.vram_size >> 20; vga_common_init(vga); vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false); @@ -1878,7 +1889,7 @@ static int qxl_init_secondary(PCIDevice *dev) PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev); qxl->id = device_id++; - qxl_init_ramsize(qxl, 16); + qxl_init_ramsize(qxl); memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size); vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); @@ -2056,6 +2067,7 @@ static Property qxl_properties[] = { DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1), DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1), DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1), + DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 8), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/qxl.h b/hw/qxl.h index a4ab7cc647..172baf6cc2 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -84,6 +84,7 @@ typedef struct PCIQXLDevice { QXLReleaseInfo *last_release; uint32_t last_release_offset; uint32_t oom_running; + uint32_t vgamem_size; /* rom pci bar */ QXLRom shadow_rom; @@ -105,6 +106,7 @@ typedef struct PCIQXLDevice { uint32_t ram_size_mb; uint32_t vram_size_mb; uint32_t vram32_size_mb; + uint32_t vgamem_size_mb; /* qxl_render_update state */ int render_update_cookie_num; From f1dacf1cedbf0f46c13139f3961ef8a976dc71e3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 11 Jun 2012 10:38:22 +0200 Subject: [PATCH 09/10] add pc-1.2 --- hw/pc_piix.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index eae258cefd..2ed9f1afff 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -349,8 +349,8 @@ static void pc_xen_hvm_init(ram_addr_t ram_size, } #endif -static QEMUMachine pc_machine_v1_1 = { - .name = "pc-1.1", +static QEMUMachine pc_machine_v1_2 = { + .name = "pc-1.2", .alias = "pc", .desc = "Standard PC", .init = pc_init_pci, @@ -358,6 +358,13 @@ static QEMUMachine pc_machine_v1_1 = { .is_default = 1, }; +static QEMUMachine pc_machine_v1_1 = { + .name = "pc-1.1", + .desc = "Standard PC", + .init = pc_init_pci, + .max_cpus = 255, +}; + #define PC_COMPAT_1_0 \ {\ .driver = "pc-sysfw",\ @@ -612,6 +619,7 @@ static QEMUMachine xenfv_machine = { static void pc_machine_init(void) { + qemu_register_machine(&pc_machine_v1_2); qemu_register_machine(&pc_machine_v1_1); qemu_register_machine(&pc_machine_v1_0); qemu_register_machine(&pc_machine_v0_15); From 9e56edcf8dd1d4bc7ba2b1efb3641f36c0fad8ba Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 11 Jun 2012 10:42:53 +0200 Subject: [PATCH 10/10] vga: raise default vgamem size Old size: 8 MB (traditional upstream qemu value). New size: 16 MB (traditional qemu-kvm value). Also adds compat properties so old machine types keep the old default values. Signed-off-by: Gerd Hoffmann --- hw/pc_piix.c | 24 ++++++++++++++++++++++++ hw/qxl.c | 2 +- hw/vga-pci.c | 2 +- hw/vmware_vga.c | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 2ed9f1afff..0c0096fd7e 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -358,14 +358,38 @@ static QEMUMachine pc_machine_v1_2 = { .is_default = 1, }; +#define PC_COMPAT_1_1 \ + {\ + .driver = "VGA",\ + .property = "vgamem_mb",\ + .value = stringify(8),\ + },{\ + .driver = "vmware-svga",\ + .property = "vgamem_mb",\ + .value = stringify(8),\ + },{\ + .driver = "qxl-vga",\ + .property = "vgamem_mb",\ + .value = stringify(8),\ + },{\ + .driver = "qxl",\ + .property = "vgamem_mb",\ + .value = stringify(8),\ + } + static QEMUMachine pc_machine_v1_1 = { .name = "pc-1.1", .desc = "Standard PC", .init = pc_init_pci, .max_cpus = 255, + .compat_props = (GlobalProperty[]) { + PC_COMPAT_1_1, + { /* end of list */ } + }, }; #define PC_COMPAT_1_0 \ + PC_COMPAT_1_1,\ {\ .driver = "pc-sysfw",\ .property = "rom_only",\ diff --git a/hw/qxl.c b/hw/qxl.c index 62eed05e27..c2dd3b471b 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -2067,7 +2067,7 @@ static Property qxl_properties[] = { DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1), DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1), DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1), - DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 8), + DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 0848126555..37dc019a61 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -76,7 +76,7 @@ DeviceState *pci_vga_init(PCIBus *bus) } static Property vga_pci_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 8), + DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index f8eb46d0c1..476dc89a0c 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1201,7 +1201,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev) static Property vga_vmware_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", struct pci_vmsvga_state_s, - chip.vga.vram_size_mb, 8), + chip.vga.vram_size_mb, 16), DEFINE_PROP_END_OF_LIST(), };