dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame qemu-exec-memory-notifiers.patch

Justin M. Forbes 272dfe
This adds notifiers for phys memory changes: a set of callbacks that
Justin M. Forbes 272dfe
vhost can register and update kernel accordingly.  Down the road, kvm
Justin M. Forbes 272dfe
code can be switched to use these as well, instead of calling kvm code
Justin M. Forbes 272dfe
directly from exec.c as is done now.
Justin M. Forbes 272dfe
Justin M. Forbes 272dfe
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Justin M. Forbes 272dfe
---
Justin M. Forbes 272dfe
 cpu-common.h |   19 ++++++++++
Justin M. Forbes 272dfe
 exec.c       |  114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Justin M. Forbes 272dfe
 2 files changed, 130 insertions(+), 3 deletions(-)
Justin M. Forbes 272dfe
Justin M. Forbes 272dfe
diff --git a/cpu-common.h b/cpu-common.h
Justin M. Forbes 272dfe
index 5e59564..326513d 100644
Justin M. Forbes 272dfe
--- a/cpu-common.h
Justin M. Forbes 272dfe
+++ b/cpu-common.h
Justin M. Forbes 272dfe
@@ -8,6 +8,7 @@
Justin M. Forbes 272dfe
 #endif
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
 #include "bswap.h"
Justin M. Forbes 272dfe
+#include "qemu-queue.h"
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
 /* address in the RAM (different from a physical address) */
Justin M. Forbes 272dfe
 typedef unsigned long ram_addr_t;
Justin M. Forbes 272dfe
@@ -62,6 +63,24 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
Justin M. Forbes 272dfe
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
Justin M. Forbes 272dfe
 void cpu_unregister_map_client(void *cookie);
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
+struct CPUPhysMemoryClient;
Justin M. Forbes 272dfe
+typedef struct CPUPhysMemoryClient CPUPhysMemoryClient;
Justin M. Forbes 272dfe
+struct CPUPhysMemoryClient {
Justin M. Forbes 272dfe
+    void (*set_memory)(struct CPUPhysMemoryClient *client,
Justin M. Forbes 272dfe
+                       target_phys_addr_t start_addr,
Justin M. Forbes 272dfe
+                       ram_addr_t size,
Justin M. Forbes 272dfe
+                       ram_addr_t phys_offset);
Justin M. Forbes 272dfe
+    int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
Justin M. Forbes 272dfe
+                             target_phys_addr_t start_addr,
Justin M. Forbes 272dfe
+                             target_phys_addr_t end_addr);
Justin M. Forbes 272dfe
+    int (*migration_log)(struct CPUPhysMemoryClient *client,
Justin M. Forbes 272dfe
+                         int enable);
Justin M. Forbes 272dfe
+    QLIST_ENTRY(CPUPhysMemoryClient) list;
Justin M. Forbes 272dfe
+};
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *);
Justin M. Forbes 272dfe
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
 uint32_t ldub_phys(target_phys_addr_t addr);
Justin M. Forbes 272dfe
 uint32_t lduw_phys(target_phys_addr_t addr);
Justin M. Forbes 272dfe
 uint32_t ldl_phys(target_phys_addr_t addr);
Justin M. Forbes 272dfe
diff --git a/exec.c b/exec.c
Justin M. Forbes 272dfe
index 8f873ab..cbba15e 100644
Justin M. Forbes 272dfe
--- a/exec.c
Justin M. Forbes 272dfe
+++ b/exec.c
Justin M. Forbes 272dfe
@@ -1640,6 +1640,101 @@ const CPULogItem cpu_log_items[] = {
Justin M. Forbes 272dfe
     { 0, NULL, NULL },
Justin M. Forbes 272dfe
 };
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
+#ifndef CONFIG_USER_ONLY
Justin M. Forbes 272dfe
+static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
Justin M. Forbes 272dfe
+    = QLIST_HEAD_INITIALIZER(memory_client_list);
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+static void cpu_notify_set_memory(target_phys_addr_t start_addr,
Justin M. Forbes 272dfe
+				  ram_addr_t size,
Justin M. Forbes 272dfe
+				  ram_addr_t phys_offset)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+    CPUPhysMemoryClient *client;
Justin M. Forbes 272dfe
+    QLIST_FOREACH(client, &memory_client_list, list) {
Justin M. Forbes 272dfe
+        client->set_memory(client, start_addr, size, phys_offset);
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
Justin M. Forbes 272dfe
+					target_phys_addr_t end)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+    CPUPhysMemoryClient *client;
Justin M. Forbes 272dfe
+    QLIST_FOREACH(client, &memory_client_list, list) {
Justin M. Forbes 272dfe
+        int r = client->sync_dirty_bitmap(client, start, end);
Justin M. Forbes 272dfe
+        if (r < 0)
Justin M. Forbes 272dfe
+            return r;
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    return 0;
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+static int cpu_notify_migration_log(int enable)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+    CPUPhysMemoryClient *client;
Justin M. Forbes 272dfe
+    QLIST_FOREACH(client, &memory_client_list, list) {
Justin M. Forbes 272dfe
+        int r = client->migration_log(client, enable);
Justin M. Forbes 272dfe
+        if (r < 0)
Justin M. Forbes 272dfe
+            return r;
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    return 0;
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map,
Justin M. Forbes 272dfe
+                                         CPUPhysMemoryClient *client)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+    PhysPageDesc *pd;
Justin M. Forbes 272dfe
+    int l1, l2;
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+    for (l1 = 0; l1 < L1_SIZE; ++l1) {
Justin M. Forbes 272dfe
+        pd = phys_map[l1];
Justin M. Forbes 272dfe
+        if (!pd) {
Justin M. Forbes 272dfe
+            continue;
Justin M. Forbes 272dfe
+        }
Justin M. Forbes 272dfe
+        for (l2 = 0; l2 < L2_SIZE; ++l2) {
Justin M. Forbes 272dfe
+            if (pd[l2].phys_offset == IO_MEM_UNASSIGNED) {
Justin M. Forbes 272dfe
+                continue;
Justin M. Forbes 272dfe
+            }
Justin M. Forbes 272dfe
+            client->set_memory(client, pd[l2].region_offset,
Justin M. Forbes 272dfe
+                               TARGET_PAGE_SIZE, pd[l2].phys_offset);
Justin M. Forbes 272dfe
+        }
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+static void phys_page_for_each(CPUPhysMemoryClient *client)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+#if TARGET_PHYS_ADDR_SPACE_BITS > 32
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
Justin M. Forbes 272dfe
+#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
Justin M. Forbes 272dfe
+#endif
Justin M. Forbes 272dfe
+    void **phys_map = (void **)l1_phys_map;
Justin M. Forbes 272dfe
+    int l1;
Justin M. Forbes 272dfe
+    if (!l1_phys_map) {
Justin M. Forbes 272dfe
+        return;
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    for (l1 = 0; l1 < L1_SIZE; ++l1) {
Justin M. Forbes 272dfe
+        if (phys_map[l1]) {
Justin M. Forbes 272dfe
+            phys_page_for_each_in_l1_map(phys_map[l1], client);
Justin M. Forbes 272dfe
+        }
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+#else
Justin M. Forbes 272dfe
+    if (!l1_phys_map) {
Justin M. Forbes 272dfe
+        return;
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    phys_page_for_each_in_l1_map(l1_phys_map, client);
Justin M. Forbes 272dfe
+#endif
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *client)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+    QLIST_INSERT_HEAD(&memory_client_list, client, list);
Justin M. Forbes 272dfe
+    phys_page_for_each(client);
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client)
Justin M. Forbes 272dfe
+{
Justin M. Forbes 272dfe
+    QLIST_REMOVE(client, list);
Justin M. Forbes 272dfe
+}
Justin M. Forbes 272dfe
+#endif
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
 static int cmp1(const char *s1, int n, const char *s2)
Justin M. Forbes 272dfe
 {
Justin M. Forbes 272dfe
     if (strlen(s2) != n)
Justin M. Forbes 272dfe
@@ -1899,10 +1994,16 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
 int cpu_physical_memory_set_dirty_tracking(int enable)
Justin M. Forbes 272dfe
 {
Justin M. Forbes 272dfe
+    int ret = 0;
Justin M. Forbes 272dfe
+    in_migration = enable;
Justin M. Forbes 272dfe
     if (kvm_enabled()) {
Justin M. Forbes 272dfe
-        return kvm_set_migration_log(enable);
Justin M. Forbes 272dfe
+        ret = kvm_set_migration_log(enable);
Justin M. Forbes 272dfe
     }
Justin M. Forbes 272dfe
-    return 0;
Justin M. Forbes 272dfe
+    if (ret < 0) {
Justin M. Forbes 272dfe
+        return ret;
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    ret = cpu_notify_migration_log(!!enable);
Justin M. Forbes 272dfe
+    return ret;
Justin M. Forbes 272dfe
 }
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
 int cpu_physical_memory_get_dirty_tracking(void)
Justin M. Forbes 272dfe
@@ -1915,8 +2016,13 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
Justin M. Forbes 272dfe
 {
Justin M. Forbes 272dfe
     int ret = 0;
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
-    if (kvm_enabled())
Justin M. Forbes 272dfe
+    if (kvm_enabled()) {
Justin M. Forbes 272dfe
         ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    if (ret < 0) {
Justin M. Forbes 272dfe
+        return ret;
Justin M. Forbes 272dfe
+    }
Justin M. Forbes 272dfe
+    ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
Justin M. Forbes 272dfe
     return ret;
Justin M. Forbes 272dfe
 }
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
@@ -2331,6 +2437,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
Justin M. Forbes 272dfe
     if (kvm_enabled())
Justin M. Forbes 272dfe
         kvm_set_phys_mem(start_addr, size, phys_offset);
Justin M. Forbes 272dfe
 
Justin M. Forbes 272dfe
+    cpu_notify_set_memory(start_addr, size, phys_offset);
Justin M. Forbes 272dfe
+
Justin M. Forbes 272dfe
     if (phys_offset == IO_MEM_UNASSIGNED) {
Justin M. Forbes 272dfe
         region_offset = start_addr;
Justin M. Forbes 272dfe
     }
Justin M. Forbes 272dfe
-- 
Justin M. Forbes 272dfe
1.6.6.144.g5c3af