aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu-all.h2
-rw-r--r--exec.c6
-rw-r--r--hw/cirrus_vga.c65
-rw-r--r--hw/vga.c47
-rw-r--r--hw/vga_int.h9
5 files changed, 129 insertions, 0 deletions
diff --git a/cpu-all.h b/cpu-all.h
index aa4b770fe2..5fa1e69372 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -948,6 +948,8 @@ int cpu_physical_memory_set_dirty_tracking(int enable);
int cpu_physical_memory_get_dirty_tracking(void);
+void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr);
+
void dump_exec_info(FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
diff --git a/exec.c b/exec.c
index 4d39eaaf20..43a1b78f46 100644
--- a/exec.c
+++ b/exec.c
@@ -1887,6 +1887,12 @@ int cpu_physical_memory_get_dirty_tracking(void)
return in_migration;
}
+void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr)
+{
+ if (kvm_enabled())
+ kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+}
+
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
{
ram_addr_t ram_addr;
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 01f3b6a631..e0cf458d76 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -31,6 +31,7 @@
#include "pci.h"
#include "console.h"
#include "vga_int.h"
+#include "kvm.h"
/*
* TODO:
@@ -1228,6 +1229,12 @@ static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
}
if (limit > 0) {
+ /* Thinking about changing bank base? First, drop the dirty bitmap information
+ * on the current location, otherwise we lose this pointer forever */
+ if (s->lfb_vram_mapped) {
+ target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
+ cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
+ }
s->cirrus_bank_base[bank_index] = offset;
s->cirrus_bank_limit[bank_index] = limit;
} else {
@@ -1356,6 +1363,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
break;
case 0x07: // Extended Sequencer Mode
+ cirrus_update_memory_access(s);
case 0x08: // EEPROM Control
case 0x09: // Scratch Register 0
case 0x0a: // Scratch Register 1
@@ -1528,6 +1536,7 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
s->gr[reg_index] = reg_value;
cirrus_update_bank_ptr(s, 0);
cirrus_update_bank_ptr(s, 1);
+ cirrus_update_memory_access(s);
break;
case 0x0B:
s->gr[reg_index] = reg_value;
@@ -2618,6 +2627,52 @@ static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
cirrus_linear_bitblt_writel,
};
+static void map_linear_vram(CirrusVGAState *s)
+{
+
+ if (!s->map_addr && s->lfb_addr && s->lfb_end) {
+ s->map_addr = s->lfb_addr;
+ s->map_end = s->lfb_end;
+ cpu_register_physical_memory(s->map_addr, s->map_end - s->map_addr, s->vram_offset);
+ vga_dirty_log_start((VGAState *)s);
+ }
+
+ if (!s->map_addr)
+ return;
+
+ s->lfb_vram_mapped = 0;
+
+ if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
+ && !((s->sr[0x07] & 0x01) == 0)
+ && !((s->gr[0x0B] & 0x14) == 0x14)
+ && !(s->gr[0x0B] & 0x02)) {
+
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
+ (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
+ cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
+ (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM);
+
+ s->lfb_vram_mapped = 1;
+ vga_dirty_log_start((VGAState *)s);
+ }
+ else {
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, s->vga_io_memory);
+ cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, s->vga_io_memory);
+ }
+
+}
+
+static void unmap_linear_vram(CirrusVGAState *s)
+{
+ if (s->map_addr && s->lfb_addr && s->lfb_end) {
+ vga_dirty_log_stop((VGAState *)s);
+ s->map_addr = s->map_end = 0;
+ }
+
+ cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
+ s->vga_io_memory);
+}
+
/* Compute the memory access functions */
static void cirrus_update_memory_access(CirrusVGAState *s)
{
@@ -2636,11 +2691,13 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
mode = s->gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ map_linear_vram(s);
s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
} else {
generic_io:
+ unmap_linear_vram(s);
s->cirrus_linear_write[0] = cirrus_linear_writeb;
s->cirrus_linear_write[1] = cirrus_linear_writew;
s->cirrus_linear_write[2] = cirrus_linear_writel;
@@ -3102,6 +3159,7 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, &s->hw_cursor_x);
qemu_get_be32s(f, &s->hw_cursor_y);
+ cirrus_update_memory_access(s);
/* force refresh */
s->graphic_mode = -1;
cirrus_update_bank_ptr(s, 0);
@@ -3261,6 +3319,13 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
s->cirrus_linear_io_addr);
cpu_register_physical_memory(addr + 0x1000000, 0x400000,
s->cirrus_linear_bitblt_io_addr);
+
+ s->map_addr = s->map_end = 0;
+ s->lfb_addr = addr & TARGET_PAGE_MASK;
+ s->lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+ /* account for overflow */
+ if (s->lfb_end < addr + VGA_RAM_SIZE)
+ s->lfb_end = addr + VGA_RAM_SIZE;
}
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
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,
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 4fa619accd..b360d3e013 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -102,6 +102,11 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
uint8_t *vram_ptr; \
ram_addr_t vram_offset; \
unsigned int vram_size; \
+ uint32_t lfb_addr; \
+ uint32_t lfb_end; \
+ uint32_t map_addr; \
+ uint32_t map_end; \
+ uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */ \
unsigned long bios_offset; \
unsigned int bios_size; \
target_phys_addr_t base_ctrl; \
@@ -189,6 +194,10 @@ static inline int c6_to_8(int v)
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
ram_addr_t vga_ram_offset, int vga_ram_size);
void vga_init(VGAState *s);
+
+void vga_dirty_log_start(VGAState *s);
+void vga_dirty_log_stop(VGAState *s);
+
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
void vga_invalidate_scanlines(VGAState *s, int y1, int y2);