aboutsummaryrefslogtreecommitdiff
path: root/hw/vga.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-24 20:21:41 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-24 20:21:41 +0000
commit2bec46dc97571a3c34b18fe4ca198e7bfbdca41f (patch)
treea005e29d9a7346047169901ae046ebe140b9990b /hw/vga.c
parent5832d1f2f51e1a1991c53ea98c535a619cf03001 (diff)
vga optimization (Glauber Costa)
Hypervisors like KVM perform badly while doing mmio on a loop, because it'll generate an exit on each access. This is the case with VGA, which results in very bad performance. In this patch, we map the linear frame buffer as RAM, make sure it has dirty region tracking enabled, and then just let the region to be written. Cleanups suggestions by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Glauber Costa <glommer@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5793 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/vga.c')
-rw-r--r--hw/vga.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/hw/vga.c b/hw/vga.c
index d2b995d5b2..492d3f9ace 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -28,6 +28,7 @@
#include "vga_int.h"
#include "pixel_ops.h"
#include "qemu-timer.h"
+#include "kvm.h"
//#define DEBUG_VGA
//#define DEBUG_VGA_MEM
@@ -1243,6 +1244,8 @@ static void vga_draw_text(VGAState *s, int full_update)
vga_draw_glyph8_func *vga_draw_glyph8;
vga_draw_glyph9_func *vga_draw_glyph9;
+ vga_dirty_log_stop(s);
+
full_update |= update_palette16(s);
palette = s->last_palette;
@@ -1556,6 +1559,18 @@ void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
}
}
+static void vga_sync_dirty_bitmap(VGAState *s)
+{
+ if (s->map_addr)
+ cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
+
+ if (s->lfb_vram_mapped) {
+ cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
+ cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
+ }
+ vga_dirty_log_start(s);
+}
+
/*
* graphic modes
*/
@@ -1570,6 +1585,9 @@ static void vga_draw_graphic(VGAState *s, int full_update)
full_update |= update_basic_params(s);
+ if (!full_update)
+ vga_sync_dirty_bitmap(s);
+
s->get_resolution(s, &width, &height);
disp_width = width;
@@ -1743,6 +1761,8 @@ static void vga_draw_blank(VGAState *s, int full_update)
return;
if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
return;
+ vga_dirty_log_stop(s);
+
if (ds_get_bits_per_pixel(s->ds) == 8)
val = s->rgb_to_pixel(0, 0, 0);
else
@@ -2092,6 +2112,28 @@ typedef struct PCIVGAState {
VGAState vga_state;
} PCIVGAState;
+void vga_dirty_log_start(VGAState *s)
+{
+ if (kvm_enabled() && s->map_addr)
+ kvm_log_start(s->map_addr, s->map_end - s->map_addr);
+
+ if (kvm_enabled() && s->lfb_vram_mapped) {
+ kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
+ kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
+ }
+}
+
+void vga_dirty_log_stop(VGAState *s)
+{
+ if (kvm_enabled() && s->map_addr)
+ kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
+
+ if (kvm_enabled() && s->lfb_vram_mapped) {
+ kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
+ kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
+ }
+}
+
static void vga_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
@@ -2102,6 +2144,11 @@ static void vga_map(PCIDevice *pci_dev, int region_num,
} else {
cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
}
+
+ s->map_addr = addr;
+ s->map_end = addr + VGA_RAM_SIZE;
+
+ vga_dirty_log_start(s);
}
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,