Re: [Qemu-devel] [RFC] QEMU Live Migration

2007-01-24 Thread Fabrice Bellard
I looked at your patch and it is OK for me. The 'ssh:' implementation is 
a nice trick. In order to be usable on win32, it is still needed to 
implement a more portable system with a TCP connection.


The dirty flag 0x04 is unfortunately used by kqemu - I should have 
documented it ! You can use 0x08 for the live migration.


Regards,

Fabrice.

Anthony Liguori wrote:

Howdy,

I wanted to post a draft of my QEMU live migration patch.  I think 
there's a lingering memory allocation problem.  I also need to implement 
ARP forwarding and a TCP transport stream.


However, I thought I'd post an initial version in case anyone wants to 
play around with it.


Once you apply the patch, make sure you've got it on both machines.  For 
my setup, I've got a common NFS share mounted in /mnt.  Then I run:


qemu -hda /mnt/win2k.img -monitor telnet:0.0.0.0:1025,server,nowait -vnc :2

Then, I connect to the monitor and execute:

(qemu) migrate ssh://woolly

When the migration completes, the monitor command will finish and then I 
can connect to the machine on woolly:2.


The ssh command will be derived from argc/argv so it's important to 
ensure that the -hda path is valid on both machines.


All three patches are required and should be applied in order of: 
qemu-apic-save-restore.diff qemu-file.diff qemu-migration.diff


Regards,

Anthony Liguori



___
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel


[Qemu-devel] [RFC] QEMU Live Migration

2007-01-21 Thread Anthony Liguori

Howdy,

I wanted to post a draft of my QEMU live migration patch.  I think 
there's a lingering memory allocation problem.  I also need to implement 
ARP forwarding and a TCP transport stream.


However, I thought I'd post an initial version in case anyone wants to 
play around with it.


Once you apply the patch, make sure you've got it on both machines.  For 
my setup, I've got a common NFS share mounted in /mnt.  Then I run:


qemu -hda /mnt/win2k.img -monitor telnet:0.0.0.0:1025,server,nowait -vnc :2

Then, I connect to the monitor and execute:

(qemu) migrate ssh://woolly

When the migration completes, the monitor command will finish and then I 
can connect to the machine on woolly:2.


The ssh command will be derived from argc/argv so it's important to 
ensure that the -hda path is valid on both machines.


All three patches are required and should be applied in order of: 
qemu-apic-save-restore.diff qemu-file.diff qemu-migration.diff


Regards,

Anthony Liguori
diff -r 8ad5450b580b Makefile.target
--- a/Makefile.target	Tue Jan 16 17:04:55 2007 -0600
+++ b/Makefile.target	Tue Jan 16 17:04:56 2007 -0600
@@ -300,7 +300,7 @@ endif
 
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
-VL_OBJS+=cutils.o
+VL_OBJS+=cutils.o migration.o
 VL_OBJS+=block.o block-raw.o
 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
 ifdef CONFIG_WIN32
diff -r 8ad5450b580b cpu-all.h
--- a/cpu-all.h	Tue Jan 16 17:04:55 2007 -0600
+++ b/cpu-all.h	Sun Jan 21 17:39:13 2007 -0600
@@ -884,6 +884,7 @@ int cpu_memory_rw_debug(CPUState *env, t
 
 #define VGA_DIRTY_FLAG  0x01
 #define CODE_DIRTY_FLAG 0x02
+#define MIGRATION_DIRTY_FLAG 0x04
 
 /* read dirty bit (return 0 or 1) */
 static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
@@ -905,6 +906,10 @@ void cpu_physical_memory_reset_dirty(ram
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
  int dirty_flags);
 void cpu_tlb_update_dirty(CPUState *env);
+
+void cpu_physical_memory_set_dirty_tracking(int enable);
+
+int cpu_physical_memory_get_dirty_tracking(void);
 
 void dump_exec_info(FILE *f,
 int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
diff -r 8ad5450b580b cutils.c
--- a/cutils.c	Tue Jan 16 17:04:55 2007 -0600
+++ b/cutils.c	Sun Jan 21 16:58:07 2007 -0600
@@ -81,3 +81,43 @@ int stristart(const char *str, const cha
 *ptr = p;
 return 1;
 }
+
+int hex2bin(char ch)
+{
+if (ch = '0'  ch = '9')
+	return ch - '0';
+else if (ch = 'A'  ch = 'Z')
+	return 10 + ch - 'A';
+else if (ch = 'a'  ch = 'z')
+	return 10 + ch - 'a';
+
+return -1;
+}
+
+char *urldecode(const char *ptr)
+{
+char *ret;
+int i;
+
+ret = qemu_mallocz(strlen(ptr) + 1);
+if (ret == NULL)
+	return NULL;
+
+for (i = 0; *ptr; ptr++, i++) {
+	switch (*ptr) {
+	case '%':
+	if (ptr[1] == 0 || ptr[2] == 0)
+		break;
+	ret[i] = hex2bin(ptr[1])  4 | hex2bin(ptr[2]);
+	ptr += 2;
+	break;
+	default:
+	   ret[i] = *ptr;
+	   break;
+	}
+}
+ret[i] = 0;
+
+return ret;
+}
+
diff -r 8ad5450b580b exec.c
--- a/exec.c	Tue Jan 16 17:04:55 2007 -0600
+++ b/exec.c	Sun Jan 21 17:40:00 2007 -0600
@@ -82,6 +82,7 @@ int phys_ram_fd;
 int phys_ram_fd;
 uint8_t *phys_ram_base;
 uint8_t *phys_ram_dirty;
+static int in_migration;
 
 CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
@@ -1406,6 +1407,16 @@ void cpu_physical_memory_reset_dirty(ram
 }
 }
 #endif
+}
+
+void cpu_physical_memory_set_dirty_tracking(int enable)
+{
+in_migration = enable;
+}
+
+int cpu_physical_memory_get_dirty_tracking(void)
+{
+return in_migration;
 }
 
 static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
@@ -2231,6 +2242,14 @@ uint32_t lduw_phys(target_phys_addr_t ad
 return tswap16(val);
 }
 
+#ifdef __GNUC__
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
+
 /* warning: addr must be aligned. The ram page is not masked as dirty
and the code inside is not invalidated. It is useful if the dirty
bits are used to track modified PTEs */
@@ -2252,9 +2271,21 @@ void stl_phys_notdirty(target_phys_addr_
 io_index = (pd  IO_MEM_SHIFT)  (IO_MEM_NB_ENTRIES - 1);
 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
 } else {
-ptr = phys_ram_base + (pd  TARGET_PAGE_MASK) + 
-(addr  ~TARGET_PAGE_MASK);
+unsigned long addr1;
+addr1 = (pd  TARGET_PAGE_MASK) + (addr  ~TARGET_PAGE_MASK);
+
+ptr = phys_ram_base + addr1;
 stl_p(ptr, val);
+
+	if (unlikely(in_migration)) {
+	if (!cpu_physical_memory_is_dirty(addr1)) {
+		/* invalidate code */
+		tb_invalidate_phys_page_range(addr1,