]> xenbits.xensource.com Git - qemu-xen-4.1-testing.git/commitdiff
fix HVM log dirty issue
authorIan Jackson <ian.jackson@eu.citrix.com>
Fri, 4 Sep 2009 15:25:35 +0000 (16:25 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Fri, 4 Sep 2009 17:00:10 +0000 (18:00 +0100)
These patches fix some issues for HVM log dirty in qemu:
* Add necessary logging dirty in qemu to avoid guest error with
intensive disk access when live migration
* Take place of shared memory between qemu and migration tools by new
added hypercall, which is clean and simple

Signed-Off-By: Zhai, Edwin <edwin.zhai@intel.com>
Also revert commit 32710fbdc75e055f73a63d246737ce615b9109e9.
  "[stubdom] fix the crash of HVM live migration with intensive disk access"
 as this is the proper fix.   -iwj

cpu-all.h
i386-dm/exec-dm.c
xen-config-host.h
xenstore.c

index 90231277dbd7dbfcd8bc81888fde6827a4507563..60e0ac370f1f2dfd7d6c1449f4269df3809c86ac 100644 (file)
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -972,20 +972,14 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
     return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
 }
 
+#ifdef CONFIG_DM
+void cpu_physical_memory_set_dirty(ram_addr_t addr);
+#else
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
     phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
-
-#ifndef CONFIG_STUBDOM
-    if (logdirty_bitmap != NULL) {
-        addr >>= TARGET_PAGE_BITS;
-        if (addr / 8 < logdirty_bitmap_size) {
-            logdirty_bitmap[addr / HOST_LONG_BITS]
-                |= 1UL << addr % HOST_LONG_BITS;
-        }
-    }
-#endif
 }
+#endif
 
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
                                      int dirty_flags);
index 4fc26cde96efc58bd9b4be08be106fea958e9422..6ee095efc770961b801bd576b69ed3cd5ce1e9aa 100644 (file)
@@ -359,6 +359,14 @@ void cpu_unregister_io_memory(int io_table_address)
     io_mem_opaque[io_index] = NULL;
 }
 
+void cpu_physical_memory_set_dirty(ram_addr_t addr)
+{
+    phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
+
+    if (xen_logdirty_enable)
+        xc_hvm_modified_memory(xc_handle, domid, addr >> TARGET_PAGE_BITS, 1);
+}
+
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
 {
     return io_mem_write[io_index >> IO_MEM_SHIFT];
@@ -453,8 +461,7 @@ void unregister_iomem(target_phys_addr_t start)
 }
 
 
-unsigned long *logdirty_bitmap;
-unsigned long logdirty_bitmap_size;
+unsigned int xen_logdirty_enable = 0;
 
 /*
  * Replace the standard byte memcpy with a word memcpy for appropriately sized
@@ -557,19 +564,13 @@ void cpu_physical_memory_rw(target_phys_addr_t _addr, uint8_t *buf,
             } else if ((ptr = phys_ram_addr(addr)) != NULL) {
                 /* Writing to RAM */
                 memcpy_words(ptr, buf, l);
-#ifndef CONFIG_STUBDOM
-                if (logdirty_bitmap != NULL) {
-                    /* Record that we have dirtied this frame */
-                    unsigned long pfn = addr >> TARGET_PAGE_BITS;
-                    if (pfn / 8 >= logdirty_bitmap_size) {
-                        fprintf(logfile, "dirtying pfn %lx >= bitmap "
-                                "size %lx\n", pfn, logdirty_bitmap_size * 8);
-                    } else {
-                        logdirty_bitmap[pfn / HOST_LONG_BITS]
-                            |= 1UL << pfn % HOST_LONG_BITS;
-                    }
-                }
-#endif
+
+                if (xen_logdirty_enable)
+                    xc_hvm_modified_memory(xc_handle,
+                        domid,
+                        addr >> TARGET_PAGE_BITS,
+                        ((addr + l + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
+                        - (addr >> TARGET_PAGE_BITS));
 #ifdef __ia64__
                 sync_icache(ptr, l);
 #endif 
@@ -605,13 +606,6 @@ void cpu_physical_memory_rw(target_phys_addr_t _addr, uint8_t *buf,
         addr += l;
     }
 
-#ifdef CONFIG_STUBDOM
-    if (logdirty_bitmap != NULL)
-        xc_hvm_modified_memory(xc_handle, domid, _addr >> TARGET_PAGE_BITS,
-                ((_addr + _len + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
-                    - (_addr >> TARGET_PAGE_BITS));
-#endif
-
     mapcache_unlock();
 }
 #endif
@@ -806,24 +800,11 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     if ((*plen) > l)
         *plen = l;
 #endif
-#ifndef CONFIG_STUBDOM
-    if (logdirty_bitmap != NULL) {
-        /* Record that we have dirtied this frame */
-        unsigned long pfn = addr >> TARGET_PAGE_BITS;
-        do {
-            if (pfn / 8 >= logdirty_bitmap_size) {
-                fprintf(logfile, "dirtying pfn %lx >= bitmap "
-                        "size %lx\n", pfn, logdirty_bitmap_size * 8);
-            } else {
-                logdirty_bitmap[pfn / HOST_LONG_BITS]
-                    |= 1UL << pfn % HOST_LONG_BITS;
-            }
+    if (xen_logdirty_enable)
+        xc_hvm_modified_memory(xc_handle, domid, addr >> TARGET_PAGE_BITS,
+                ((addr + l + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
+                    - (addr >> TARGET_PAGE_BITS));
 
-            pfn++;
-        } while ( (pfn << TARGET_PAGE_BITS) < addr + *plen );
-
-    }
-#endif
     return qemu_map_cache(addr, 1);
 }
 
index f34e76b95284517c528a6805d5a5f4a40b8ae589..3a04df9fe054ecc6f7a4d056e5de33bf36980f96 100644 (file)
@@ -39,8 +39,7 @@ struct CharDriverState;
 void xenstore_store_serial_port_info(int i, struct CharDriverState *chr,
                                     const char *devname);
 
-extern unsigned long *logdirty_bitmap;
-extern unsigned long logdirty_bitmap_size;
+extern unsigned int xen_logdirty_enable;
 
 #ifdef CONFIG_STUBDOM
 #undef HAVE_IOVEC
index bdc25c3d4b40ed0b9b87720b64ec28834882fe66..e091259548d7ce5703d978653410579f7f1e550d 100644 (file)
 
 #include "block_int.h"
 #include <unistd.h>
-#ifndef CONFIG_STUBDOM
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <assert.h>
 
 #include "exec-all.h"
@@ -597,8 +590,8 @@ void xenstore_parse_domain_config(int hvm_domid)
 #endif
 
 
-    /* Set a watch for log-dirty requests from the migration tools */
-    if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
+    /* Set a watch for log-dirty commands from the migration tools */
+    if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/cmd",
                   domid) != -1) {
         xs_watch(xsh, buf, "logdirty");
         fprintf(logfile, "Watching %s\n", buf);
@@ -689,111 +682,44 @@ int xenstore_fd(void)
 static void xenstore_process_logdirty_event(void)
 {
     char *act;
-    static char *active_path = NULL;
-    static char *next_active_path = NULL;
-    static char *seg = NULL;
+    char *ret_path = NULL;
+    char *cmd_path = NULL;
     unsigned int len;
-    int i;
-
-    if (!seg) {
-        char *path = NULL, *key_ascii, key_terminated[17] = {0,};
-        key_t key;
-        int shmid;
-
-        /* Find and map the shared memory segment for log-dirty bitmaps */
-        if (pasprintf(&path, 
-                      "/local/domain/0/device-model/%u/logdirty/key", 
-                      domid) == -1) {
-            fprintf(logfile, "Log-dirty: out of memory\n");
-            exit(1);
-        }
-        
-        key_ascii = xs_read(xsh, XBT_NULL, path, &len);
-        free(path);
-
-        if (!key_ascii) 
-            /* No key yet: wait for the next watch */
-            return;
 
-#ifdef CONFIG_STUBDOM
-        /* We pass the writes to hypervisor */
-        seg = (void*)1;
-#else
-        strncpy(key_terminated, key_ascii, 16);
-        free(key_ascii);
-        key = (key_t) strtoull(key_terminated, NULL, 16);
-
-        /* Figure out how bit the log-dirty bitmaps are */
-        logdirty_bitmap_size = xc_memory_op(xc_handle, 
-                                            XENMEM_maximum_gpfn, &domid) + 1;
-        logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
-                                / HOST_LONG_BITS); /* longs */
-        logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
-
-        /* Map the shared-memory segment */
-        fprintf(logfile, "%s: key=%16.16llx size=%lu\n", __FUNCTION__,
-                (unsigned long long)key, logdirty_bitmap_size);
-        shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
-        if (shmid == -1) {
-            fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
-                    "(%s)\n", (unsigned long long)key, strerror(errno));
-            exit(1);
-        }
-
-        seg = shmat(shmid, NULL, 0);
-        if (seg == (void *)-1) {
-            fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
-                    "(%s)\n", (unsigned long long)key, strerror(errno));
-            exit(1);
-        }
-
-        fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
-
-        /* Double-check that the bitmaps are the size we expect */
-        if (logdirty_bitmap_size != *(uint32_t *)seg) {
-            fprintf(logfile, "Log-dirty: got %u, calc %lu\n", 
-                    *(uint32_t *)seg, logdirty_bitmap_size);
-            /* Stale key: wait for next watch */
-            shmdt(seg);
-            seg = NULL;
-            return;
-        }
-#endif
-
-        /* Remember the paths for the next-active and active entries */
-        if (pasprintf(&active_path, 
-                      "/local/domain/0/device-model/%u/logdirty/active",
-                      domid) == -1) {
-            fprintf(logfile, "Log-dirty: out of memory\n");
-            exit(1);
-        }
-        if (pasprintf(&next_active_path, 
-                      "/local/domain/0/device-model/%u/logdirty/next-active",
-                      domid) == -1) {
-            fprintf(logfile, "Log-dirty: out of memory\n");
-            exit(1);
-        }
+    /* Remember the paths for the command and response entries */
+    if (pasprintf(&ret_path,
+                "/local/domain/0/device-model/%u/logdirty/ret",
+                domid) == -1) {
+        fprintf(logfile, "Log-dirty: out of memory\n");
+        exit(1);
+    }
+    if (pasprintf(&cmd_path,
+                "/local/domain/0/device-model/%u/logdirty/cmd",
+                domid) == -1) {
+        fprintf(logfile, "Log-dirty: out of memory\n");
+        exit(1);
     }
 
-    fprintf(logfile, "Triggered log-dirty buffer switch\n");
     
     /* Read the required active buffer from the store */
-    act = xs_read(xsh, XBT_NULL, next_active_path, &len);
+    act = xs_read(xsh, XBT_NULL, cmd_path, &len);
     if (!act) {
-        fprintf(logfile, "Log-dirty: can't read next-active\n");
-        exit(1);
+        fprintf(logfile, "Log-dirty: no command yet.\n");
+        return;
     }
+    fprintf(logfile, "Log-dirty command %s\n", act);
 
-    /* Switch buffers */
-    i = act[0] - '0';
-    if (i != 0 && i != 1) {
-        fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
+    if (!strcmp(act, "enable")) {
+        xen_logdirty_enable = 1;
+    } else if (!strcmp(act, "disable")) {
+        xen_logdirty_enable = 0;
+    } else {
+        fprintf(logfile, "Log-dirty: bad log-dirty command: %s\n", act);
         exit(1);
     }
-    logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
 
-    /* Ack that we've switched */
-    xs_write(xsh, XBT_NULL, active_path, act, len);
+    /* Ack that we've service the command */
+    xs_write(xsh, XBT_NULL, ret_path, act, len);
     free(act);
 }