From 8c140f88d10a2220a699e6c2e4df5e290a5546cc Mon Sep 17 00:00:00 2001 Message-Id: From: Blue Swirl Date: Sun, 22 Jan 2012 16:38:21 +0000 Subject: [PATCH 1/3] memory: memory: change dirty getting API to take a size Instead of each target knowing or guessing the guest page size, just pass the desired size of dirtied memory area. Signed-off-by: Blue Swirl --- arch_init.c | 7 ++++--- exec-obsolete.h | 14 ++++++++++++-- hw/framebuffer.c | 9 +-------- hw/g364fb.c | 3 ++- hw/sm501.c | 11 ++++------- hw/tcx.c | 17 ++++++++--------- hw/vga.c | 17 +++++------------ memory.c | 5 +++-- memory.h | 9 +++++---- 9 files changed, 44 insertions(+), 48 deletions(-) diff --git a/arch_init.c b/arch_init.c index 2366511..699bdd1 100644 --- a/arch_init.c +++ b/arch_init.c @@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f) do { mr = block->mr; - if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) { + if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION)) { uint8_t *p; int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0; @@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void) QLIST_FOREACH(block, &ram_list.blocks, next) { ram_addr_t addr; for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { - if (memory_region_get_dirty(block->mr, addr, + if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE, DIRTY_MEMORY_MIGRATION)) { count++; } @@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) /* Make sure all dirty bits are set */ QLIST_FOREACH(block, &ram_list.blocks, next) { for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { - if (!memory_region_get_dirty(block->mr, addr, + if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE, DIRTY_MEMORY_MIGRATION)) { memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE); } diff --git a/exec-obsolete.h b/exec-obsolete.h index 03cf35e..e0ac37b 100644 --- a/exec-obsolete.h +++ b/exec-obsolete.h @@ -59,10 +59,20 @@ static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS]; } -static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, +static inline int cpu_physical_memory_get_dirty(ram_addr_t start, + ram_addr_t length, int dirty_flags) { - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags; + int ret = 0; + uint8_t *p; + ram_addr_t addr, end; + + end = start + length; + p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS); + for (addr = start; addr <= end; addr += TARGET_PAGE_SIZE) { + ret |= *p++ & dirty_flags; + } + return ret; } static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) diff --git a/hw/framebuffer.c b/hw/framebuffer.c index 6bf48dc..ea122fb 100644 --- a/hw/framebuffer.c +++ b/hw/framebuffer.c @@ -87,15 +87,8 @@ void framebuffer_update_display( dest += i * dest_row_pitch; for (; i < rows; i++) { - target_phys_addr_t dirty_offset; - dirty = 0; - dirty_offset = 0; - while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) { - dirty |= memory_region_get_dirty(mem, addr + dirty_offset, + dirty = memory_region_get_dirty(mem, addr, addr + src_width, DIRTY_MEMORY_VGA); - dirty_offset += TARGET_PAGE_SIZE; - } - if (dirty || invalidate) { fn(opaque, dest, src, cols, dest_col_pitch); if (first == -1) diff --git a/hw/g364fb.c b/hw/g364fb.c index 02ec7b5..fd96267 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -62,7 +62,8 @@ typedef struct G364State { static inline int check_dirty(G364State *s, ram_addr_t page) { - return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA); + return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE, + DIRTY_MEMORY_VGA); } static inline void reset_dirty(G364State *s, diff --git a/hw/sm501.c b/hw/sm501.c index 09c5894..94c0abf 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s) 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; - ram_addr_t page0 = offset & TARGET_PAGE_MASK; - ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK; - ram_addr_t page; + ram_addr_t page0 = offset; + ram_addr_t page1 = offset + width * src_bpp - 1; /* check dirty flags for each line */ - for (page = page0; page <= page1; page += TARGET_PAGE_SIZE) - if (memory_region_get_dirty(&s->local_mem_region, page, - DIRTY_MEMORY_VGA)) - update = 1; + update = memory_region_get_dirty(&s->local_mem_region, page0, page1, + DIRTY_MEMORY_VGA); /* draw line and change status */ if (update) { diff --git a/hw/tcx.c b/hw/tcx.c index b6a2753..dc621a8 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24, ram_addr_t cpage) { int ret; - unsigned int off; - - ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA); - for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) { - ret |= memory_region_get_dirty(&s->vram_mem, page24 + off, - DIRTY_MEMORY_VGA); - ret |= memory_region_get_dirty(&s->vram_mem, cpage + off, - DIRTY_MEMORY_VGA); - } + + ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE, + DIRTY_MEMORY_VGA); + ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4, + DIRTY_MEMORY_VGA); + ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4, + DIRTY_MEMORY_VGA); return ret; } @@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque) } for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) { - if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) { + if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE, + DIRTY_MEMORY_VGA)) { if (y_start < 0) y_start = y; if (page < page_min) diff --git a/hw/vga.c b/hw/vga.c index 4dc2610..cf9b39f 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1742,17 +1742,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (!(s->cr[0x17] & 2)) { addr = (addr & ~0x8000) | ((y1 & 2) << 14); } - page0 = addr & TARGET_PAGE_MASK; - page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK; - update = full_update | - memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) | - memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA); - if ((page1 - page0) > TARGET_PAGE_SIZE) { - /* if wide line, can use another page */ - update |= memory_region_get_dirty(&s->vram, - page0 + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - } + page0 = addr; + page1 = addr + bwidth - 1; + update = memory_region_get_dirty(&s->vram, page0, page1, + DIRTY_MEMORY_VGA); /* explicit invalidation for the hardware cursor */ update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; if (update) { @@ -1798,7 +1791,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (page_max >= page_min) { memory_region_reset_dirty(&s->vram, page_min, - page_max + TARGET_PAGE_SIZE - page_min, + page_max - page_min, DIRTY_MEMORY_VGA); } memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); diff --git a/memory.c b/memory.c index ee4c98a..5e77d8a 100644 --- a/memory.c +++ b/memory.c @@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) } bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, - unsigned client) + target_phys_addr_t size, unsigned client) { assert(mr->terminates); - return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client); + return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, + 1 << client); } void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr, diff --git a/memory.h b/memory.h index fa45b99..4cf8d2f 100644 --- a/memory.h +++ b/memory.h @@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset); void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client); /** - * memory_region_get_dirty: Check whether a page is dirty for a specified - * client. + * memory_region_get_dirty: Check whether a range of bytes is dirty + * for a specified client. * - * Checks whether a page has been written to since the last + * Checks whether a range of bytes has been written to since the last * call to memory_region_reset_dirty() with the same @client. Dirty logging * must be enabled. * * @mr: the memory region being queried. * @addr: the address (relative to the start of the region) being queried. + * @size: the size of the range being queried. * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or * %DIRTY_MEMORY_VGA. */ bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, - unsigned client); + target_phys_addr_t size, unsigned client); /** * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region. -- 1.7.2.5