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);