Skip to content

Commit

Permalink
memory: change dirty getting API to take a size
Browse files Browse the repository at this point in the history
Instead of each device knowing or guessing the guest page size,
just pass the desired size of dirtied memory area.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
  • Loading branch information
blueswirl committed Feb 4, 2012
1 parent cb437e4 commit cd7a45c
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 49 deletions.
7 changes: 4 additions & 3 deletions arch_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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++;
}
Expand Down Expand Up @@ -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);
}
Expand Down
15 changes: 13 additions & 2 deletions exec-obsolete.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,21 @@ 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 = TARGET_PAGE_ALIGN(start + length);
start &= TARGET_PAGE_MASK;
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)
Expand Down
9 changes: 1 addition & 8 deletions hw/framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion hw/g364fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 4 additions & 7 deletions hw/sm501.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
19 changes: 9 additions & 10 deletions hw/tcx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down
17 changes: 5 additions & 12 deletions hw/vga.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 5 additions & 4 deletions memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit cd7a45c

Please sign in to comment.