diff options
author | Avi Kivity <avi@redhat.com> | 2011-07-26 14:26:02 +0300 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-07-29 08:25:42 -0500 |
commit | 5a583347697413f964d886b074860cb888c0e306 (patch) | |
tree | f11cbbb41a0c8ad424ac35f9077e1d396864b842 | |
parent | 093bc2cd885e4e3420509a80a1b9e81848e4b8fe (diff) |
memory: implement dirty tracking
Currently dirty tracking is implemented by passing through
all calls to the underlying cpu_physical_memory_*() calls.
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | memory.c | 39 | ||||
-rw-r--r-- | memory.h | 1 |
2 files changed, 32 insertions, 8 deletions
@@ -69,6 +69,7 @@ struct FlatRange { MemoryRegion *mr; target_phys_addr_t offset_in_region; AddrRange addr; + uint8_t dirty_log_mask; }; /* Flattened global view of current active memory hierarchy. Kept in sorted @@ -177,6 +178,7 @@ static void render_memory_region(FlatView *view, fr.mr = mr; fr.offset_in_region = offset_in_region; fr.addr = addrrange_make(base, now); + fr.dirty_log_mask = mr->dirty_log_mask; flatview_insert(view, i, &fr); ++i; base += now; @@ -194,6 +196,7 @@ static void render_memory_region(FlatView *view, fr.mr = mr; fr.offset_in_region = offset_in_region; fr.addr = addrrange_make(base, remain); + fr.dirty_log_mask = mr->dirty_log_mask; flatview_insert(view, i, &fr); } } @@ -247,9 +250,14 @@ static void memory_region_update_topology(void) } else if (frold && frnew && flatrange_equal(frold, frnew)) { /* In both (logging may have changed) */ + if (frold->dirty_log_mask && !frnew->dirty_log_mask) { + cpu_physical_log_stop(frnew->addr.start, frnew->addr.size); + } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) { + cpu_physical_log_start(frnew->addr.start, frnew->addr.size); + } + ++iold; ++inew; - /* FIXME: dirty logging */ } else { /* In new */ @@ -267,7 +275,7 @@ static void memory_region_update_topology(void) frnew->addr.size, phys_offset, region_offset, - 0); + frnew->dirty_log_mask); ++inew; } } @@ -292,6 +300,7 @@ void memory_region_init(MemoryRegion *mr, memset(&mr->subregions_link, 0, sizeof mr->subregions_link); QTAILQ_INIT(&mr->coalesced); mr->name = qemu_strdup(name); + mr->dirty_log_mask = 0; } static bool memory_region_access_valid(MemoryRegion *mr, @@ -496,24 +505,35 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset) void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) { - /* FIXME */ + uint8_t mask = 1 << client; + + mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask); + memory_region_update_topology(); } bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, unsigned client) { - /* FIXME */ - return true; + assert(mr->has_ram_addr); + return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client); } void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr) { - /* FIXME */ + assert(mr->has_ram_addr); + return cpu_physical_memory_set_dirty(mr->ram_addr + addr); } void memory_region_sync_dirty_bitmap(MemoryRegion *mr) { - /* FIXME */ + FlatRange *fr; + + FOR_EACH_FLAT_RANGE(fr, ¤t_memory_map) { + if (fr->mr == mr) { + cpu_physical_sync_dirty_bitmap(fr->addr.start, + fr->addr.start + fr->addr.size); + } + } } void memory_region_set_readonly(MemoryRegion *mr, bool readonly) @@ -524,7 +544,10 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly) void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr, target_phys_addr_t size, unsigned client) { - /* FIXME */ + assert(mr->has_ram_addr); + cpu_physical_memory_reset_dirty(mr->ram_addr + addr, + mr->ram_addr + addr + size, + 1 << client); } void *memory_region_get_ram_ptr(MemoryRegion *mr) @@ -99,6 +99,7 @@ struct MemoryRegion { QTAILQ_ENTRY(MemoryRegion) subregions_link; QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced; const char *name; + uint8_t dirty_log_mask; }; /** |