From patchwork Wed Jul 20 16:49:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avi Kivity X-Patchwork-Id: 992682 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6KGsTtL008490 for ; Wed, 20 Jul 2011 16:54:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752859Ab1GTQyU (ORCPT ); Wed, 20 Jul 2011 12:54:20 -0400 Received: from mx1.redhat.com ([209.132.183.28]:29811 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751564Ab1GTQum (ORCPT ); Wed, 20 Jul 2011 12:50:42 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p6KGoeN2028801 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 20 Jul 2011 12:50:40 -0400 Received: from cleopatra.tlv.redhat.com (cleopatra.tlv.redhat.com [10.35.255.11]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p6KGodq9006695; Wed, 20 Jul 2011 12:50:40 -0400 Received: from s01.tlv.redhat.com (s01.tlv.redhat.com [10.35.255.8]) by cleopatra.tlv.redhat.com (Postfix) with ESMTP id E933D250B35; Wed, 20 Jul 2011 19:50:38 +0300 (IDT) From: Avi Kivity To: qemu-devel@nongnu.org Cc: kvm@vger.kernel.org Subject: [RFC v5 03/86] memory: implement dirty tracking Date: Wed, 20 Jul 2011 19:49:13 +0300 Message-Id: <1311180636-17012-4-git-send-email-avi@redhat.com> In-Reply-To: <1311180636-17012-1-git-send-email-avi@redhat.com> References: <1311180636-17012-1-git-send-email-avi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 20 Jul 2011 16:54:30 +0000 (UTC) Currently dirty tracking is implemented by passing through all calls to the underlying cpu_physical_memory_*() calls. Signed-off-by: Avi Kivity --- memory.c | 39 +++++++++++++++++++++++++++++++-------- memory.h | 1 + 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/memory.c b/memory.c index 10591bf..a569666 100644 --- a/memory.c +++ b/memory.c @@ -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) diff --git a/memory.h b/memory.h index 95270aa..8873f75 100644 --- a/memory.h +++ b/memory.h @@ -86,6 +86,7 @@ struct MemoryRegion { QTAILQ_ENTRY(MemoryRegion) subregions_link; QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced; const char *name; + uint8_t dirty_log_mask; }; /* Initialize a memory region