From 086f90e890fb25e7f12fbe72fe5a8078792398aa Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Apr 2015 12:43:24 +0200 Subject: g364fb: remove pointless call to memory_region_set_coalescing Coalescing work on MMIO, not RAM, thus this call has no effect. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/display/g364fb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'hw/display') diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 46f7b41211..6543f2f4a3 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -489,7 +489,6 @@ static void g364fb_init(DeviceState *dev, G364State *s) memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", s->vram_size, s->vram); vmstate_register_ram(&s->mem_vram, dev); - memory_region_set_coalescing(&s->mem_vram); } #define TYPE_G364 "sysbus-g364" -- cgit 1.4.1 From 74259ae55b15bff4ef7b26faa6431a3ff16d7c9d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Mar 2015 10:47:45 +0100 Subject: display: enable DIRTY_MEMORY_VGA tracking explicitly This will be required soon by the memory core. Tested-by: Aurelien Jarno Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/display/cg3.c | 1 + hw/display/exynos4210_fimd.c | 20 +++++++++++++------- hw/display/g364fb.c | 1 + hw/display/sm501.c | 1 + hw/display/tcx.c | 1 + 5 files changed, 17 insertions(+), 7 deletions(-) (limited to 'hw/display') diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 1e6ff2b546..cbcf518739 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -309,6 +309,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp) memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size, &error_abort); + memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA); vmstate_register_ram_global(&s->vram_mem); sysbus_init_mmio(sbd, &s->vram_mem); diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 45c62afac1..72b3a1d063 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1109,6 +1109,12 @@ static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w) } } +static void exynos4210_fimd_invalidate(void *opaque) +{ + Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; + s->invalidate = true; +} + /* Updates specified window's MemorySection based on values of WINCON, * VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) @@ -1136,7 +1142,11 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) /* TODO: add .exit and unref the region there. Not needed yet since sysbus * does not support hot-unplug. */ - memory_region_unref(w->mem_section.mr); + if (w->mem_section.mr) { + memory_region_set_log(w->mem_section.mr, false, DIRTY_MEMORY_VGA); + memory_region_unref(w->mem_section.mr); + } + w->mem_section = memory_region_find(sysbus_address_space(sbd), fb_start_addr, w->fb_len); assert(w->mem_section.mr); @@ -1162,6 +1172,8 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0); goto error_return; } + memory_region_set_log(w->mem_section.mr, true, DIRTY_MEMORY_VGA); + exynos4210_fimd_invalidate(s); return; error_return: @@ -1224,12 +1236,6 @@ static void exynos4210_fimd_update_irq(Exynos4210fimdState *s) } } -static void exynos4210_fimd_invalidate(void *opaque) -{ - Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - s->invalidate = true; -} - static void exynos4210_update_resolution(Exynos4210fimdState *s) { DisplaySurface *surface = qemu_console_surface(s->console); diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 6543f2f4a3..be62dd6284 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -489,6 +489,7 @@ static void g364fb_init(DeviceState *dev, G364State *s) memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", s->vram_size, s->vram); vmstate_register_ram(&s->mem_vram, dev); + memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA); } #define TYPE_G364 "sysbus-g364" diff --git a/hw/display/sm501.c b/hw/display/sm501.c index c72154b6f1..43f8538f56 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1412,6 +1412,7 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base, memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local", local_mem_bytes, &error_abort); vmstate_register_ram_global(&s->local_mem_region); + memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA); s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); memory_region_add_subregion(address_space_mem, base, &s->local_mem_region); diff --git a/hw/display/tcx.c b/hw/display/tcx.c index a9f9f66d15..58faa96af5 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -1006,6 +1006,7 @@ static void tcx_realizefn(DeviceState *dev, Error **errp) memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram", s->vram_size * (1 + 4 + 4), &error_abort); vmstate_register_ram_global(&s->vram_mem); + memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA); vram_base = memory_region_get_ram_ptr(&s->vram_mem); /* 10/ROM : FCode ROM */ -- cgit 1.4.1 From 5299c0f2cf951c23ec681ff87e455d1cf4ec537b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 22 Apr 2015 13:12:40 +0200 Subject: display: add memory_region_sync_dirty_bitmap calls These are strictly speaking only needed for KVM and Xen, but it's still nice to be consistent. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/display/cg3.c | 1 + hw/display/g364fb.c | 1 + hw/display/sm501.c | 1 + hw/display/tcx.c | 2 ++ 4 files changed, 5 insertions(+) (limited to 'hw/display') diff --git a/hw/display/cg3.c b/hw/display/cg3.c index cbcf518739..b94e5e0d78 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -106,6 +106,7 @@ static void cg3_update_display(void *opaque) pix = memory_region_get_ram_ptr(&s->vram_mem); data = (uint32_t *)surface_data(surface); + memory_region_sync_dirty_bitmap(&s->vram_mem); for (y = 0; y < height; y++) { int update = s->full_update; diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index be62dd6284..52a9733bfd 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -260,6 +260,7 @@ static void g364fb_update_display(void *opaque) qemu_console_resize(s->con, s->width, s->height); } + memory_region_sync_dirty_bitmap(&s->mem_vram); if (s->ctla & CTLA_FORCE_BLANK) { g364fb_draw_blank(s); } else if (s->depth == 8) { diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 43f8538f56..15a5ba8000 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1322,6 +1322,7 @@ static void sm501_draw_crt(SM501State * s) } /* draw each line according to conditions */ + memory_region_sync_dirty_bitmap(&s->local_mem_region); for (y = 0; y < height; y++) { int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0; int update = full_update || update_hwc; diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 58faa96af5..f3faf78bf8 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -353,6 +353,7 @@ static void tcx_update_display(void *opaque) return; } + memory_region_sync_dirty_bitmap(&ts->vram_mem); for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE) { if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE, DIRTY_MEMORY_VGA)) { @@ -446,6 +447,7 @@ static void tcx24_update_display(void *opaque) dd = surface_stride(surface); ds = 1024; + memory_region_sync_dirty_bitmap(&ts->vram_mem); for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE, page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) { if (tcx24_check_dirty(ts, page, page24, cpage)) { -- cgit 1.4.1 From 2d1a35bef0ed96b3f23535e459c552414ccdbafd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Mar 2015 10:50:57 +0100 Subject: memory: differentiate memory_region_is_logging and memory_region_get_dirty_log_mask For now memory regions only track DIRTY_MEMORY_VGA individually, but this will change soon. To support this, split memory_region_is_logging in two functions: one that returns a given bit from dirty_log_mask, and one that returns the entire mask. memory_region_is_logging gets an extra parameter so that the compiler flags misuse. While VGA-specific users (including the Xen listener!) will want to keep checking that bit, KVM and vhost check for "any bit except migration" (because migration is handled via the global start/stop listener callbacks). Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/display/vmware_vga.c | 2 +- hw/virtio/dataplane/vring.c | 2 +- hw/virtio/vhost.c | 3 ++- include/exec/memory.h | 16 ++++++++++++++-- kvm-all.c | 3 ++- memory.c | 7 ++++++- xen-hvm.c | 2 +- 7 files changed, 27 insertions(+), 8 deletions(-) (limited to 'hw/display') diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index c17ddd1fcd..7f397d3c2e 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1124,7 +1124,7 @@ static void vmsvga_update_display(void *opaque) * Is it more efficient to look at vram VGA-dirty bits or wait * for the driver to issue SVGA_CMD_UPDATE? */ - if (memory_region_is_logging(&s->vga.vram)) { + if (memory_region_is_logging(&s->vga.vram, DIRTY_MEMORY_VGA)) { vga_sync_dirty_bitmap(&s->vga); dirty = memory_region_get_dirty(&s->vga.vram, 0, surface_stride(surface) * surface_height(surface), diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 5c7b8c20fa..e37873384f 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -42,7 +42,7 @@ static void *vring_map(MemoryRegion **mr, hwaddr phys, hwaddr len, } /* Ignore regions with dirty logging, we cannot mark them dirty */ - if (memory_region_is_logging(section.mr)) { + if (memory_region_get_dirty_log_mask(section.mr)) { goto out; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 01f1e0490f..53d23d281d 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -416,7 +416,8 @@ static void vhost_set_memory(MemoryListener *listener, memory_listener); hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = int128_get64(section->size); - bool log_dirty = memory_region_is_logging(section->mr); + bool log_dirty = + memory_region_get_dirty_log_mask(section->mr) & ~(1 << DIRTY_MEMORY_MIGRATION); int s = offsetof(struct vhost_memory, regions) + (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; void *ram; diff --git a/include/exec/memory.h b/include/exec/memory.h index 7b0929d54f..156d506063 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -591,11 +591,23 @@ const char *memory_region_name(const MemoryRegion *mr); /** * memory_region_is_logging: return whether a memory region is logging writes * - * Returns %true if the memory region is logging writes + * Returns %true if the memory region is logging writes for the given client * * @mr: the memory region being queried + * @client: the client being queried */ -bool memory_region_is_logging(MemoryRegion *mr); +bool memory_region_is_logging(MemoryRegion *mr, uint8_t client); + +/** + * memory_region_get_dirty_log_mask: return the clients for which a + * memory region is logging writes. + * + * Returns a bitmap of clients, which right now will be either 0 or + * (1 << DIRTY_MEMORY_VGA). + * + * @mr: the memory region being queried + */ +uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr); /** * memory_region_is_rom: check whether a memory region is ROM diff --git a/kvm-all.c b/kvm-all.c index 44a34a52d8..d5416bbd74 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -663,7 +663,8 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) KVMSlot *mem, old; int err; MemoryRegion *mr = section->mr; - bool log_dirty = memory_region_is_logging(mr); + bool log_dirty = + memory_region_get_dirty_log_mask(mr) & ~(1 << DIRTY_MEMORY_MIGRATION); bool writeable = !mr->readonly && !mr->rom_device; bool readonly_flag = mr->readonly || memory_region_is_romd(mr); hwaddr start_addr = section->offset_within_address_space; diff --git a/memory.c b/memory.c index a8f8599079..72e33e853b 100644 --- a/memory.c +++ b/memory.c @@ -1389,11 +1389,16 @@ bool memory_region_is_skip_dump(MemoryRegion *mr) return mr->skip_dump; } -bool memory_region_is_logging(MemoryRegion *mr) +uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) { return mr->dirty_log_mask; } +bool memory_region_is_logging(MemoryRegion *mr, uint8_t client) +{ + return memory_region_get_dirty_log_mask(mr) & (1 << client); +} + bool memory_region_is_rom(MemoryRegion *mr) { return mr->ram && mr->readonly; diff --git a/xen-hvm.c b/xen-hvm.c index 315864ca70..338ab291f8 100644 --- a/xen-hvm.c +++ b/xen-hvm.c @@ -488,7 +488,7 @@ static void xen_set_memory(struct MemoryListener *listener, XenIOState *state = container_of(listener, XenIOState, memory_listener); hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = int128_get64(section->size); - bool log_dirty = memory_region_is_logging(section->mr); + bool log_dirty = memory_region_is_logging(section->mr, DIRTY_MEMORY_VGA); hvmmem_type_t mem_type; if (section->mr == &ram_memory) { -- cgit 1.4.1 From d55d42078bfb507743747b761673507b95a76620 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Mar 2015 10:46:52 +0100 Subject: framebuffer: check memory_region_is_logging framebuffer.c expects DIRTY_MEMORY_VGA logging to be always on, but that will not be the case soon. Because framebuffer.c computes the memory region on the fly for every update (with memory_region_find), it cannot enable/disable logging by itself. Instead, always treat updates as invalidations if dirty logging is not enabled, assuming that the board will enable logging on the RAM region that includes the framebuffer. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/display/framebuffer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'hw/display') diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c index 4546e42654..2cabced208 100644 --- a/hw/display/framebuffer.c +++ b/hw/display/framebuffer.c @@ -63,6 +63,10 @@ void framebuffer_update_display( assert(mem_section.offset_within_address_space == base); memory_region_sync_dirty_bitmap(mem); + if (!memory_region_is_logging(mem, DIRTY_MEMORY_VGA)) { + invalidate = true; + } + src_base = cpu_physical_memory_map(base, &src_len, 0); /* If we can't map the framebuffer then bail. We could try harder, but it's not really worth it as dirty flag tracking will probably -- cgit 1.4.1