qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCHv3 1/3] qemu: memory notifiers
       [not found] <cover.1264622778.git.mst@redhat.com>
@ 2010-01-27 20:06 ` Michael S. Tsirkin
  2010-02-09 23:27   ` Anthony Liguori
  2010-01-27 20:07 ` [Qemu-devel] [PATCHv3 2/3] kvm: move kvm_set_phys_mem around Michael S. Tsirkin
  2010-01-27 20:07 ` [Qemu-devel] [PATCHv3 3/3] kvm: move kvm to use memory notifiers Michael S. Tsirkin
  2 siblings, 1 reply; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-01-27 20:06 UTC (permalink / raw)
  To: Anthony Liguori, qemu-devel, avi, gleb

This adds notifiers for phys memory changes: a set of callbacks that
vhost can register and update kernel accordingly.  Down the road, kvm
code can be switched to use these as well, instead of calling kvm code
directly from exec.c as is done now.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 cpu-common.h |   19 ++++++++++
 exec.c       |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/cpu-common.h b/cpu-common.h
index 6302372..0ec9b72 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -8,6 +8,7 @@
 #endif
 
 #include "bswap.h"
+#include "qemu-queue.h"
 
 /* address in the RAM (different from a physical address) */
 typedef unsigned long ram_addr_t;
@@ -61,6 +62,24 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
 void cpu_unregister_map_client(void *cookie);
 
+struct CPUPhysMemoryClient;
+typedef struct CPUPhysMemoryClient CPUPhysMemoryClient;
+struct CPUPhysMemoryClient {
+    void (*set_memory)(struct CPUPhysMemoryClient *client,
+                       target_phys_addr_t start_addr,
+                       ram_addr_t size,
+                       ram_addr_t phys_offset);
+    int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
+                             target_phys_addr_t start_addr,
+                             target_phys_addr_t end_addr);
+    int (*migration_log)(struct CPUPhysMemoryClient *client,
+                         int enable);
+    QLIST_ENTRY(CPUPhysMemoryClient) list;
+};
+
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *);
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
+
 uint32_t ldub_phys(target_phys_addr_t addr);
 uint32_t lduw_phys(target_phys_addr_t addr);
 uint32_t ldl_phys(target_phys_addr_t addr);
diff --git a/exec.c b/exec.c
index 76831a1..d713b72 100644
--- a/exec.c
+++ b/exec.c
@@ -1623,6 +1623,101 @@ const CPULogItem cpu_log_items[] = {
     { 0, NULL, NULL },
 };
 
+#ifndef CONFIG_USER_ONLY
+static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
+    = QLIST_HEAD_INITIALIZER(memory_client_list);
+
+static void cpu_notify_set_memory(target_phys_addr_t start_addr,
+				  ram_addr_t size,
+				  ram_addr_t phys_offset)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        client->set_memory(client, start_addr, size, phys_offset);
+    }
+}
+
+static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
+					target_phys_addr_t end)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        int r = client->sync_dirty_bitmap(client, start, end);
+        if (r < 0)
+            return r;
+    }
+    return 0;
+}
+
+static int cpu_notify_migration_log(int enable)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        int r = client->migration_log(client, enable);
+        if (r < 0)
+            return r;
+    }
+    return 0;
+}
+
+static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map,
+                                         CPUPhysMemoryClient *client)
+{
+    PhysPageDesc *pd;
+    int l1, l2;
+
+    for (l1 = 0; l1 < L1_SIZE; ++l1) {
+        pd = phys_map[l1];
+        if (!pd) {
+            continue;
+        }
+        for (l2 = 0; l2 < L2_SIZE; ++l2) {
+            if (pd[l2].phys_offset == IO_MEM_UNASSIGNED) {
+                continue;
+            }
+            client->set_memory(client, pd[l2].region_offset,
+                               TARGET_PAGE_SIZE, pd[l2].phys_offset);
+        }
+    }
+}
+
+static void phys_page_for_each(CPUPhysMemoryClient *client)
+{
+#if TARGET_PHYS_ADDR_SPACE_BITS > 32
+
+#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
+#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
+#endif
+    void **phys_map = (void **)l1_phys_map;
+    int l1;
+    if (!l1_phys_map) {
+        return;
+    }
+    for (l1 = 0; l1 < L1_SIZE; ++l1) {
+        if (phys_map[l1]) {
+            phys_page_for_each_in_l1_map(phys_map[l1], client);
+        }
+    }
+#else
+    if (!l1_phys_map) {
+        return;
+    }
+    phys_page_for_each_in_l1_map(l1_phys_map, client);
+#endif
+}
+
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *client)
+{
+    QLIST_INSERT_HEAD(&memory_client_list, client, list);
+    phys_page_for_each(client);
+}
+
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client)
+{
+    QLIST_REMOVE(client, list);
+}
+#endif
+
 static int cmp1(const char *s1, int n, const char *s2)
 {
     if (strlen(s2) != n)
@@ -1882,11 +1977,16 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 
 int cpu_physical_memory_set_dirty_tracking(int enable)
 {
+    int ret = 0;
     in_migration = enable;
     if (kvm_enabled()) {
-        return kvm_set_migration_log(enable);
+        ret = kvm_set_migration_log(enable);
     }
-    return 0;
+    if (ret < 0) {
+        return ret;
+    }
+    ret = cpu_notify_migration_log(!!enable);
+    return ret;
 }
 
 int cpu_physical_memory_get_dirty_tracking(void)
@@ -1899,8 +1999,13 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
 {
     int ret = 0;
 
-    if (kvm_enabled())
+    if (kvm_enabled()) {
         ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+    }
+    if (ret < 0) {
+        return ret;
+    }
+    ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
     return ret;
 }
 
@@ -2315,6 +2420,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     if (kvm_enabled())
         kvm_set_phys_mem(start_addr, size, phys_offset);
 
+    cpu_notify_set_memory(start_addr, size, phys_offset);
+
     if (phys_offset == IO_MEM_UNASSIGNED) {
         region_offset = start_addr;
     }
-- 
1.6.6.144.g5c3af

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCHv3 2/3] kvm: move kvm_set_phys_mem around
       [not found] <cover.1264622778.git.mst@redhat.com>
  2010-01-27 20:06 ` [Qemu-devel] [PATCHv3 1/3] qemu: memory notifiers Michael S. Tsirkin
@ 2010-01-27 20:07 ` Michael S. Tsirkin
  2010-01-27 20:07 ` [Qemu-devel] [PATCHv3 3/3] kvm: move kvm to use memory notifiers Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-01-27 20:07 UTC (permalink / raw)
  To: Anthony Liguori, qemu-devel, avi, gleb

move kvm_set_phys_mem so that it will
be later available earlier in the file.
needed for next patch using memory notifiers.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Avi Kivity <avi@redhat.com>
---
 kvm-all.c |  276 ++++++++++++++++++++++++++++++------------------------------
 1 files changed, 138 insertions(+), 138 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index 15ec38e..4efb653 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -394,6 +394,144 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
+void kvm_set_phys_mem(target_phys_addr_t start_addr,
+		       ram_addr_t size,
+		       ram_addr_t phys_offset)
+{
+    KVMState *s = kvm_state;
+    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+    KVMSlot *mem, old;
+    int err;
+
+    if (start_addr & ~TARGET_PAGE_MASK) {
+        if (flags >= IO_MEM_UNASSIGNED) {
+            if (!kvm_lookup_overlapping_slot(s, start_addr,
+                                             start_addr + size)) {
+                return;
+            }
+            fprintf(stderr, "Unaligned split of a KVM memory slot\n");
+        } else {
+            fprintf(stderr, "Only page-aligned memory slots supported\n");
+        }
+        abort();
+    }
+
+    /* KVM does not support read-only slots */
+    phys_offset &= ~IO_MEM_ROM;
+
+    while (1) {
+        mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
+        if (!mem) {
+            break;
+        }
+
+        if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
+            (start_addr + size <= mem->start_addr + mem->memory_size) &&
+            (phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
+            /* The new slot fits into the existing one and comes with
+             * identical parameters - nothing to be done. */
+            return;
+        }
+
+        old = *mem;
+
+        /* unregister the overlapping slot */
+        mem->memory_size = 0;
+        err = kvm_set_user_memory_region(s, mem);
+        if (err) {
+            fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
+                    __func__, strerror(-err));
+            abort();
+        }
+
+        /* Workaround for older KVM versions: we can't join slots, even not by
+         * unregistering the previous ones and then registering the larger
+         * slot. We have to maintain the existing fragmentation. Sigh.
+         *
+         * This workaround assumes that the new slot starts at the same
+         * address as the first existing one. If not or if some overlapping
+         * slot comes around later, we will fail (not seen in practice so far)
+         * - and actually require a recent KVM version. */
+        if (s->broken_set_mem_region &&
+            old.start_addr == start_addr && old.memory_size < size &&
+            flags < IO_MEM_UNASSIGNED) {
+            mem = kvm_alloc_slot(s);
+            mem->memory_size = old.memory_size;
+            mem->start_addr = old.start_addr;
+            mem->phys_offset = old.phys_offset;
+            mem->flags = 0;
+
+            err = kvm_set_user_memory_region(s, mem);
+            if (err) {
+                fprintf(stderr, "%s: error updating slot: %s\n", __func__,
+                        strerror(-err));
+                abort();
+            }
+
+            start_addr += old.memory_size;
+            phys_offset += old.memory_size;
+            size -= old.memory_size;
+            continue;
+        }
+
+        /* register prefix slot */
+        if (old.start_addr < start_addr) {
+            mem = kvm_alloc_slot(s);
+            mem->memory_size = start_addr - old.start_addr;
+            mem->start_addr = old.start_addr;
+            mem->phys_offset = old.phys_offset;
+            mem->flags = 0;
+
+            err = kvm_set_user_memory_region(s, mem);
+            if (err) {
+                fprintf(stderr, "%s: error registering prefix slot: %s\n",
+                        __func__, strerror(-err));
+                abort();
+            }
+        }
+
+        /* register suffix slot */
+        if (old.start_addr + old.memory_size > start_addr + size) {
+            ram_addr_t size_delta;
+
+            mem = kvm_alloc_slot(s);
+            mem->start_addr = start_addr + size;
+            size_delta = mem->start_addr - old.start_addr;
+            mem->memory_size = old.memory_size - size_delta;
+            mem->phys_offset = old.phys_offset + size_delta;
+            mem->flags = 0;
+
+            err = kvm_set_user_memory_region(s, mem);
+            if (err) {
+                fprintf(stderr, "%s: error registering suffix slot: %s\n",
+                        __func__, strerror(-err));
+                abort();
+            }
+        }
+    }
+
+    /* in case the KVM bug workaround already "consumed" the new slot */
+    if (!size)
+        return;
+
+    /* KVM does not need to know about this memory */
+    if (flags >= IO_MEM_UNASSIGNED)
+        return;
+
+    mem = kvm_alloc_slot(s);
+    mem->memory_size = size;
+    mem->start_addr = start_addr;
+    mem->phys_offset = phys_offset;
+    mem->flags = 0;
+
+    err = kvm_set_user_memory_region(s, mem);
+    if (err) {
+        fprintf(stderr, "%s: error registering slot: %s\n", __func__,
+                strerror(-err));
+        abort();
+    }
+}
+
 int kvm_init(int smp_cpus)
 {
     static const char upgrade_note[] =
@@ -674,144 +812,6 @@ int kvm_cpu_exec(CPUState *env)
     return ret;
 }
 
-void kvm_set_phys_mem(target_phys_addr_t start_addr,
-                      ram_addr_t size,
-                      ram_addr_t phys_offset)
-{
-    KVMState *s = kvm_state;
-    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
-    KVMSlot *mem, old;
-    int err;
-
-    if (start_addr & ~TARGET_PAGE_MASK) {
-        if (flags >= IO_MEM_UNASSIGNED) {
-            if (!kvm_lookup_overlapping_slot(s, start_addr,
-                                             start_addr + size)) {
-                return;
-            }
-            fprintf(stderr, "Unaligned split of a KVM memory slot\n");
-        } else {
-            fprintf(stderr, "Only page-aligned memory slots supported\n");
-        }
-        abort();
-    }
-
-    /* KVM does not support read-only slots */
-    phys_offset &= ~IO_MEM_ROM;
-
-    while (1) {
-        mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
-        if (!mem) {
-            break;
-        }
-
-        if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
-            (start_addr + size <= mem->start_addr + mem->memory_size) &&
-            (phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
-            /* The new slot fits into the existing one and comes with
-             * identical parameters - nothing to be done. */
-            return;
-        }
-
-        old = *mem;
-
-        /* unregister the overlapping slot */
-        mem->memory_size = 0;
-        err = kvm_set_user_memory_region(s, mem);
-        if (err) {
-            fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
-                    __func__, strerror(-err));
-            abort();
-        }
-
-        /* Workaround for older KVM versions: we can't join slots, even not by
-         * unregistering the previous ones and then registering the larger
-         * slot. We have to maintain the existing fragmentation. Sigh.
-         *
-         * This workaround assumes that the new slot starts at the same
-         * address as the first existing one. If not or if some overlapping
-         * slot comes around later, we will fail (not seen in practice so far)
-         * - and actually require a recent KVM version. */
-        if (s->broken_set_mem_region &&
-            old.start_addr == start_addr && old.memory_size < size &&
-            flags < IO_MEM_UNASSIGNED) {
-            mem = kvm_alloc_slot(s);
-            mem->memory_size = old.memory_size;
-            mem->start_addr = old.start_addr;
-            mem->phys_offset = old.phys_offset;
-            mem->flags = 0;
-
-            err = kvm_set_user_memory_region(s, mem);
-            if (err) {
-                fprintf(stderr, "%s: error updating slot: %s\n", __func__,
-                        strerror(-err));
-                abort();
-            }
-
-            start_addr += old.memory_size;
-            phys_offset += old.memory_size;
-            size -= old.memory_size;
-            continue;
-        }
-
-        /* register prefix slot */
-        if (old.start_addr < start_addr) {
-            mem = kvm_alloc_slot(s);
-            mem->memory_size = start_addr - old.start_addr;
-            mem->start_addr = old.start_addr;
-            mem->phys_offset = old.phys_offset;
-            mem->flags = 0;
-
-            err = kvm_set_user_memory_region(s, mem);
-            if (err) {
-                fprintf(stderr, "%s: error registering prefix slot: %s\n",
-                        __func__, strerror(-err));
-                abort();
-            }
-        }
-
-        /* register suffix slot */
-        if (old.start_addr + old.memory_size > start_addr + size) {
-            ram_addr_t size_delta;
-
-            mem = kvm_alloc_slot(s);
-            mem->start_addr = start_addr + size;
-            size_delta = mem->start_addr - old.start_addr;
-            mem->memory_size = old.memory_size - size_delta;
-            mem->phys_offset = old.phys_offset + size_delta;
-            mem->flags = 0;
-
-            err = kvm_set_user_memory_region(s, mem);
-            if (err) {
-                fprintf(stderr, "%s: error registering suffix slot: %s\n",
-                        __func__, strerror(-err));
-                abort();
-            }
-        }
-    }
-
-    /* in case the KVM bug workaround already "consumed" the new slot */
-    if (!size)
-        return;
-
-    /* KVM does not need to know about this memory */
-    if (flags >= IO_MEM_UNASSIGNED)
-        return;
-
-    mem = kvm_alloc_slot(s);
-    mem->memory_size = size;
-    mem->start_addr = start_addr;
-    mem->phys_offset = phys_offset;
-    mem->flags = 0;
-
-    err = kvm_set_user_memory_region(s, mem);
-    if (err) {
-        fprintf(stderr, "%s: error registering slot: %s\n", __func__,
-                strerror(-err));
-        abort();
-    }
-}
-
 int kvm_ioctl(KVMState *s, int type, ...)
 {
     int ret;
-- 
1.6.6.144.g5c3af

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCHv3 3/3] kvm: move kvm to use memory notifiers
       [not found] <cover.1264622778.git.mst@redhat.com>
  2010-01-27 20:06 ` [Qemu-devel] [PATCHv3 1/3] qemu: memory notifiers Michael S. Tsirkin
  2010-01-27 20:07 ` [Qemu-devel] [PATCHv3 2/3] kvm: move kvm_set_phys_mem around Michael S. Tsirkin
@ 2010-01-27 20:07 ` Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-01-27 20:07 UTC (permalink / raw)
  To: Anthony Liguori, qemu-devel, avi, gleb

remove direct kvm calls from exec.c, make
kvm use memory notifiers framework instead.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Avi Kivity <avi@redhat.com>
---
 exec.c    |   17 +----------------
 kvm-all.c |   40 ++++++++++++++++++++++++++++++++++------
 kvm.h     |    8 --------
 3 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/exec.c b/exec.c
index d713b72..2e7434e 100644
--- a/exec.c
+++ b/exec.c
@@ -1979,12 +1979,6 @@ int cpu_physical_memory_set_dirty_tracking(int enable)
 {
     int ret = 0;
     in_migration = enable;
-    if (kvm_enabled()) {
-        ret = kvm_set_migration_log(enable);
-    }
-    if (ret < 0) {
-        return ret;
-    }
     ret = cpu_notify_migration_log(!!enable);
     return ret;
 }
@@ -1997,14 +1991,8 @@ int cpu_physical_memory_get_dirty_tracking(void)
 int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
                                    target_phys_addr_t end_addr)
 {
-    int ret = 0;
+    int ret;
 
-    if (kvm_enabled()) {
-        ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
-    }
-    if (ret < 0) {
-        return ret;
-    }
     ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
     return ret;
 }
@@ -2417,9 +2405,6 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     ram_addr_t orig_size = size;
     void *subpage;
 
-    if (kvm_enabled())
-        kvm_set_phys_mem(start_addr, size, phys_offset);
-
     cpu_notify_set_memory(start_addr, size, phys_offset);
 
     if (phys_offset == IO_MEM_UNASSIGNED) {
diff --git a/kvm-all.c b/kvm-all.c
index 4efb653..a312654 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -257,7 +257,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
                                           KVM_MEM_LOG_DIRTY_PAGES);
 }
 
-int kvm_set_migration_log(int enable)
+static int kvm_set_migration_log(int enable)
 {
     KVMState *s = kvm_state;
     KVMSlot *mem;
@@ -292,8 +292,8 @@ static int test_le_bit(unsigned long nr, unsigned char *addr)
  * @start_add: start of logged region.
  * @end_addr: end of logged region.
  */
-int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-                                   target_phys_addr_t end_addr)
+static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
+					  target_phys_addr_t end_addr)
 {
     KVMState *s = kvm_state;
     unsigned long size, allocated_size = 0;
@@ -394,9 +394,9 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
-void kvm_set_phys_mem(target_phys_addr_t start_addr,
-		       ram_addr_t size,
-		       ram_addr_t phys_offset)
+static void kvm_set_phys_mem(target_phys_addr_t start_addr,
+			     ram_addr_t size,
+			     ram_addr_t phys_offset)
 {
     KVMState *s = kvm_state;
     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
@@ -532,6 +532,33 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
     }
 }
 
+static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
+				  target_phys_addr_t start_addr,
+				  ram_addr_t size,
+				  ram_addr_t phys_offset)
+{
+	kvm_set_phys_mem(start_addr, size, phys_offset);
+}
+
+static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
+					target_phys_addr_t start_addr,
+					target_phys_addr_t end_addr)
+{
+	return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+}
+
+static int kvm_client_migration_log(struct CPUPhysMemoryClient *client,
+				    int enable)
+{
+	return kvm_set_migration_log(enable);
+}
+
+static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
+	.set_memory = kvm_client_set_memory,
+	.sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
+	.migration_log = kvm_client_migration_log,
+};
+
 int kvm_init(int smp_cpus)
 {
     static const char upgrade_note[] =
@@ -628,6 +655,7 @@ int kvm_init(int smp_cpus)
         goto err;
 
     kvm_state = s;
+    cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
 
     return 0;
 
diff --git a/kvm.h b/kvm.h
index 1c93ac5..672d511 100644
--- a/kvm.h
+++ b/kvm.h
@@ -35,16 +35,8 @@ int kvm_init_vcpu(CPUState *env);
 
 int kvm_cpu_exec(CPUState *env);
 
-void kvm_set_phys_mem(target_phys_addr_t start_addr,
-                      ram_addr_t size,
-                      ram_addr_t phys_offset);
-
-int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-                                   target_phys_addr_t end_addr);
-
 int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size);
 int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
-int kvm_set_migration_log(int enable);
 
 int kvm_has_sync_mmu(void);
 int kvm_has_vcpu_events(void);
-- 
1.6.6.144.g5c3af

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCHv3 1/3] qemu: memory notifiers
  2010-01-27 20:06 ` [Qemu-devel] [PATCHv3 1/3] qemu: memory notifiers Michael S. Tsirkin
@ 2010-02-09 23:27   ` Anthony Liguori
  0 siblings, 0 replies; 4+ messages in thread
From: Anthony Liguori @ 2010-02-09 23:27 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, gleb, avi

On 01/27/2010 02:06 PM, Michael S. Tsirkin wrote:
> This adds notifiers for phys memory changes: a set of callbacks that
> vhost can register and update kernel accordingly.  Down the road, kvm
> code can be switched to use these as well, instead of calling kvm code
> directly from exec.c as is done now.
>
> Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
>    

Applied all.  Thanks.

Regards,

Anthony Liguori

> ---
>   cpu-common.h |   19 ++++++++++
>   exec.c       |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>   2 files changed, 129 insertions(+), 3 deletions(-)
>
> diff --git a/cpu-common.h b/cpu-common.h
> index 6302372..0ec9b72 100644
> --- a/cpu-common.h
> +++ b/cpu-common.h
> @@ -8,6 +8,7 @@
>   #endif
>
>   #include "bswap.h"
> +#include "qemu-queue.h"
>
>   /* address in the RAM (different from a physical address) */
>   typedef unsigned long ram_addr_t;
> @@ -61,6 +62,24 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
>   void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
>   void cpu_unregister_map_client(void *cookie);
>
> +struct CPUPhysMemoryClient;
> +typedef struct CPUPhysMemoryClient CPUPhysMemoryClient;
> +struct CPUPhysMemoryClient {
> +    void (*set_memory)(struct CPUPhysMemoryClient *client,
> +                       target_phys_addr_t start_addr,
> +                       ram_addr_t size,
> +                       ram_addr_t phys_offset);
> +    int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
> +                             target_phys_addr_t start_addr,
> +                             target_phys_addr_t end_addr);
> +    int (*migration_log)(struct CPUPhysMemoryClient *client,
> +                         int enable);
> +    QLIST_ENTRY(CPUPhysMemoryClient) list;
> +};
> +
> +void cpu_register_phys_memory_client(CPUPhysMemoryClient *);
> +void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
> +
>   uint32_t ldub_phys(target_phys_addr_t addr);
>   uint32_t lduw_phys(target_phys_addr_t addr);
>   uint32_t ldl_phys(target_phys_addr_t addr);
> diff --git a/exec.c b/exec.c
> index 76831a1..d713b72 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1623,6 +1623,101 @@ const CPULogItem cpu_log_items[] = {
>       { 0, NULL, NULL },
>   };
>
> +#ifndef CONFIG_USER_ONLY
> +static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
> +    = QLIST_HEAD_INITIALIZER(memory_client_list);
> +
> +static void cpu_notify_set_memory(target_phys_addr_t start_addr,
> +				  ram_addr_t size,
> +				  ram_addr_t phys_offset)
> +{
> +    CPUPhysMemoryClient *client;
> +    QLIST_FOREACH(client,&memory_client_list, list) {
> +        client->set_memory(client, start_addr, size, phys_offset);
> +    }
> +}
> +
> +static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
> +					target_phys_addr_t end)
> +{
> +    CPUPhysMemoryClient *client;
> +    QLIST_FOREACH(client,&memory_client_list, list) {
> +        int r = client->sync_dirty_bitmap(client, start, end);
> +        if (r<  0)
> +            return r;
> +    }
> +    return 0;
> +}
> +
> +static int cpu_notify_migration_log(int enable)
> +{
> +    CPUPhysMemoryClient *client;
> +    QLIST_FOREACH(client,&memory_client_list, list) {
> +        int r = client->migration_log(client, enable);
> +        if (r<  0)
> +            return r;
> +    }
> +    return 0;
> +}
> +
> +static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map,
> +                                         CPUPhysMemoryClient *client)
> +{
> +    PhysPageDesc *pd;
> +    int l1, l2;
> +
> +    for (l1 = 0; l1<  L1_SIZE; ++l1) {
> +        pd = phys_map[l1];
> +        if (!pd) {
> +            continue;
> +        }
> +        for (l2 = 0; l2<  L2_SIZE; ++l2) {
> +            if (pd[l2].phys_offset == IO_MEM_UNASSIGNED) {
> +                continue;
> +            }
> +            client->set_memory(client, pd[l2].region_offset,
> +                               TARGET_PAGE_SIZE, pd[l2].phys_offset);
> +        }
> +    }
> +}
> +
> +static void phys_page_for_each(CPUPhysMemoryClient *client)
> +{
> +#if TARGET_PHYS_ADDR_SPACE_BITS>  32
> +
> +#if TARGET_PHYS_ADDR_SPACE_BITS>  (32 + L1_BITS)
> +#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
> +#endif
> +    void **phys_map = (void **)l1_phys_map;
> +    int l1;
> +    if (!l1_phys_map) {
> +        return;
> +    }
> +    for (l1 = 0; l1<  L1_SIZE; ++l1) {
> +        if (phys_map[l1]) {
> +            phys_page_for_each_in_l1_map(phys_map[l1], client);
> +        }
> +    }
> +#else
> +    if (!l1_phys_map) {
> +        return;
> +    }
> +    phys_page_for_each_in_l1_map(l1_phys_map, client);
> +#endif
> +}
> +
> +void cpu_register_phys_memory_client(CPUPhysMemoryClient *client)
> +{
> +    QLIST_INSERT_HEAD(&memory_client_list, client, list);
> +    phys_page_for_each(client);
> +}
> +
> +void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client)
> +{
> +    QLIST_REMOVE(client, list);
> +}
> +#endif
> +
>   static int cmp1(const char *s1, int n, const char *s2)
>   {
>       if (strlen(s2) != n)
> @@ -1882,11 +1977,16 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
>
>   int cpu_physical_memory_set_dirty_tracking(int enable)
>   {
> +    int ret = 0;
>       in_migration = enable;
>       if (kvm_enabled()) {
> -        return kvm_set_migration_log(enable);
> +        ret = kvm_set_migration_log(enable);
>       }
> -    return 0;
> +    if (ret<  0) {
> +        return ret;
> +    }
> +    ret = cpu_notify_migration_log(!!enable);
> +    return ret;
>   }
>
>   int cpu_physical_memory_get_dirty_tracking(void)
> @@ -1899,8 +1999,13 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
>   {
>       int ret = 0;
>
> -    if (kvm_enabled())
> +    if (kvm_enabled()) {
>           ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
> +    }
> +    if (ret<  0) {
> +        return ret;
> +    }
> +    ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
>       return ret;
>   }
>
> @@ -2315,6 +2420,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
>       if (kvm_enabled())
>           kvm_set_phys_mem(start_addr, size, phys_offset);
>
> +    cpu_notify_set_memory(start_addr, size, phys_offset);
> +
>       if (phys_offset == IO_MEM_UNASSIGNED) {
>           region_offset = start_addr;
>       }
>    

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-02-09 23:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1264622778.git.mst@redhat.com>
2010-01-27 20:06 ` [Qemu-devel] [PATCHv3 1/3] qemu: memory notifiers Michael S. Tsirkin
2010-02-09 23:27   ` Anthony Liguori
2010-01-27 20:07 ` [Qemu-devel] [PATCHv3 2/3] kvm: move kvm_set_phys_mem around Michael S. Tsirkin
2010-01-27 20:07 ` [Qemu-devel] [PATCHv3 3/3] kvm: move kvm to use memory notifiers Michael S. Tsirkin

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).