qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: jasowang@redhat.com, Anthony Liguori <anthony@codemonkey.ws>,
	qemu-devel@nongnu.org, quintela@redhat.com
Subject: [Qemu-devel] [PATCHv2 5/6] migration: stable ram block ordering
Date: Wed, 24 Nov 2010 17:53:09 +0200	[thread overview]
Message-ID: <0bc452a2f9bfd1af031dbe3b5f8793e0b05c52d9.1290613959.git.mst@redhat.com> (raw)
In-Reply-To: <cover.1290613959.git.mst@redhat.com>

This makes ram block ordering under migration stable, ordered by offset.
This is especially useful for migration to exec, for debugging.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Jason Wang <jasowang@redhat.com>
---
 arch_init.c  |   35 +++++++++++++++++++++++++++++++++++
 cpu-common.h |    3 +++
 exec.c       |   24 ++++++++++++++++++++++--
 kvm-all.c    |    2 +-
 4 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 4486925..e32e289 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -23,6 +23,7 @@
  */
 #include <stdint.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #ifndef _WIN32
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -212,6 +213,39 @@ uint64_t ram_bytes_total(void)
     return total;
 }
 
+static int block_compar(const void *a, const void *b)
+{
+    RAMBlock * const *ablock = a;
+    RAMBlock * const *bblock = b;
+    if ((*ablock)->offset < (*bblock)->offset) {
+        return -1;
+    } else if ((*ablock)->offset > (*bblock)->offset) {
+        return 1;
+    }
+    return 0;
+}
+
+static void sort_ram_list(void)
+{
+    RAMBlock *block, *nblock, **blocks;
+    int n;
+    n = 0;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ++n;
+    }
+    blocks = qemu_malloc(n * sizeof *blocks);
+    n = 0;
+    QLIST_FOREACH_SAFE(block, &ram_list.blocks, next, nblock) {
+        blocks[n++] = block;
+        QLIST_REMOVE(block, next);
+    }
+    qsort(blocks, n, sizeof *blocks, block_compar);
+    while (--n >= 0) {
+        QLIST_INSERT_HEAD(&ram_list.blocks, blocks[n], next);
+    }
+    qemu_free(blocks);
+}
+
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 {
     ram_addr_t addr;
@@ -234,6 +268,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         bytes_transferred = 0;
         last_block = NULL;
         last_offset = 0;
+        sort_ram_list();
 
         /* Make sure all dirty bits are set */
         QLIST_FOREACH(block, &ram_list.blocks, next) {
diff --git a/cpu-common.h b/cpu-common.h
index a543b5d..bb6b137 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -46,6 +46,9 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
 void qemu_ram_free(ram_addr_t addr);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
+/* Same but slower, to use for migration, where the order of
+ * RAMBlocks must not change. */
+void *qemu_safe_ram_ptr(ram_addr_t addr);
 /* This should not be used by devices.  */
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
diff --git a/exec.c b/exec.c
index db9ff55..6c8f635 100644
--- a/exec.c
+++ b/exec.c
@@ -2030,10 +2030,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 
     /* we modify the TLB cache so that the dirty bit will be set again
        when accessing the range */
-    start1 = (unsigned long)qemu_get_ram_ptr(start);
+    start1 = (unsigned long)qemu_safe_ram_ptr(start);
     /* Chek that we don't span multiple blocks - this breaks the
        address comparisons below.  */
-    if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
+    if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
             != (end - 1) - start) {
         abort();
     }
@@ -2858,6 +2858,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
     new_block->length = size;
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
+    fprintf(stderr, "alloc ram %s len 0x%x\n", new_block->idstr, (int)new_block->length);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
                                        last_ram_offset() >> TARGET_PAGE_BITS);
@@ -2931,6 +2932,25 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
     return NULL;
 }
 
+/* Return a host pointer to ram allocated with qemu_ram_alloc.
+ * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
+ */
+void *qemu_safe_ram_ptr(ram_addr_t addr)
+{
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (addr - block->offset < block->length) {
+            return block->host + (addr - block->offset);
+        }
+    }
+
+    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
+    abort();
+
+    return NULL;
+}
+
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
 {
     RAMBlock *block;
diff --git a/kvm-all.c b/kvm-all.c
index 37b99c7..cae24bb 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -162,7 +162,7 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
     mem.slot = slot->slot;
     mem.guest_phys_addr = slot->start_addr;
     mem.memory_size = slot->memory_size;
-    mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset);
+    mem.userspace_addr = (unsigned long)qemu_safe_ram_ptr(slot->phys_offset);
     mem.flags = slot->flags;
     if (s->migration_log) {
         mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
-- 
1.7.3.2.91.g446ac

  parent reply	other threads:[~2010-11-24 16:02 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-24 15:52 [Qemu-devel] [PATCHv2 0/6] stable migration image on a stopped vm Michael S. Tsirkin
2010-11-24 15:52 ` [Qemu-devel] [PATCHv2 1/6] virtio-net: don't dma while vm is stopped Michael S. Tsirkin
2010-11-24 15:52 ` [Qemu-devel] [PATCHv2 2/6] cpus: flush all requests on each vm stop Michael S. Tsirkin
2010-11-30 12:45   ` Marcelo Tosatti
2010-11-30 13:14     ` Michael S. Tsirkin
2010-11-30 13:34     ` Michael S. Tsirkin
2010-11-30 13:46       ` Marcelo Tosatti
2010-11-30 14:05         ` Michael S. Tsirkin
2010-12-03 16:30           ` Marcelo Tosatti
2010-11-24 15:53 ` [Qemu-devel] [PATCHv2 3/6] migration/savevm: no need to flush requests Michael S. Tsirkin
2010-11-24 15:53 ` [Qemu-devel] [PATCHv2 4/6] virtio-net: stop/start bh on vm start/stop Michael S. Tsirkin
2010-11-29 15:37   ` [Qemu-devel] [PATCHv3 4/6] virtio-net: stop/start bh when appropriate Michael S. Tsirkin
2010-12-01  5:45     ` Jason Wang
2010-12-01  5:59       ` Michael S. Tsirkin
2010-12-03  8:40         ` Kevin Wolf
2010-12-01  6:02       ` Michael S. Tsirkin
2010-12-01  6:17         ` Jason Wang
2010-12-02 12:56         ` Jason Wang
2010-12-02 13:07           ` Michael S. Tsirkin
2010-12-02 13:08           ` Michael S. Tsirkin
2010-12-02 14:19             ` Jason Wang
2010-12-02 15:38               ` Michael S. Tsirkin
2010-12-03 13:32                 ` Jason Wang
2010-12-02 18:27               ` Michael S. Tsirkin
2010-12-03  8:39                 ` Kevin Wolf
2010-11-24 15:53 ` Michael S. Tsirkin [this message]
2010-11-24 15:53 ` [Qemu-devel] [PATCHv2 6/6] migration: allow rate > 4g Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0bc452a2f9bfd1af031dbe3b5f8793e0b05c52d9.1290613959.git.mst@redhat.com \
    --to=mst@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=jasowang@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).