@@ -0,0 +1,1754 @@
+2007-03-13 Gwenole Beauchesne <gbeauchesne@mandriva.com>
+
+ * Merge Anthony Liguori's QEMU Live Migration (combined) patch +
+ changes from the KVM tree.
+
+================================================================================
+--- qemu-0.9.0/Makefile.target
++++ qemu-0.9.0/Makefile.target
+@@ -320,7 +320,7 @@
+
+ # 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
+--- qemu-0.9.0/audio/wavaudio.c
++++ qemu-0.9.0/audio/wavaudio.c
+@@ -151,7 +151,7 @@
+ le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
+ le_store (hdr + 32, 1 << (bits16 + stereo), 2);
+
+- wav->f = qemu_fopen (conf.wav_path, "wb");
++ wav->f = qemu_fopen_file (conf.wav_path, "wb");
+ if (!wav->f) {
+ dolog ("Failed to open wave file `%s'\nReason: %s\n",
+ conf.wav_path, strerror (errno));
+--- qemu-0.9.0/audio/wavcapture.c
++++ qemu-0.9.0/audio/wavcapture.c
+@@ -132,7 +132,7 @@
+ le_store (hdr + 28, freq << shift, 4);
+ le_store (hdr + 32, 1 << shift, 2);
+
+- wav->f = qemu_fopen (path, "wb");
++ wav->f = qemu_fopen_file (path, "wb");
+ if (!wav->f) {
+ term_printf ("Failed to open wave file `%s'\nReason: %s\n",
+ path, strerror (errno));
+--- qemu-0.9.0/cpu-all.h
++++ qemu-0.9.0/cpu-all.h
+@@ -892,6 +892,7 @@
+
+ #define VGA_DIRTY_FLAG 0x01
+ #define CODE_DIRTY_FLAG 0x02
++#define MIGRATION_DIRTY_FLAG 0x08
+
+ /* read dirty bit (return 0 or 1) */
+ static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
+@@ -914,6 +915,10 @@
+ int dirty_flags);
+ void cpu_tlb_update_dirty(CPUState *env);
+
++int 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, ...));
+
+--- qemu-0.9.0/cutils.c
++++ qemu-0.9.0/cutils.c
+@@ -81,3 +81,43 @@
+ *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;
++}
++
+--- qemu-0.9.0/exec.c
++++ qemu-0.9.0/exec.c
+@@ -82,6 +82,7 @@
+ 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
+@@ -1420,6 +1421,19 @@
+ #endif
+ }
+
++int cpu_physical_memory_set_dirty_tracking(int enable)
++{
++ int r=0;
++
++ in_migration = enable;
++ return r;
++}
++
++int cpu_physical_memory_get_dirty_tracking(void)
++{
++ return in_migration;
++}
++
+ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
+ {
+ ram_addr_t ram_addr;
+@@ -2287,6 +2301,14 @@
+ 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 */
+@@ -2308,9 +2330,21 @@
+ 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, addr1 + 4, 0);
++ /* set dirty bit */
++ phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
++ (0xff & ~CODE_DIRTY_FLAG);
++ }
++ }
+ }
+ }
+
+--- qemu-0.9.0/hw/usb-uhci.c
++++ qemu-0.9.0/hw/usb-uhci.c
+@@ -144,6 +144,58 @@
+ }
+ }
+
++static void uhci_save(QEMUFile *f, void *opaque)
++{
++ UHCIState *s = opaque;
++ uint8_t num_ports = NB_PORTS;
++ int i;
++
++ pci_device_save(&s->dev, f);
++
++ qemu_put_8s(f, &num_ports);
++ for (i = 0; i < num_ports; ++i)
++ qemu_put_be16s(f, &s->ports[i].ctrl);
++ qemu_put_be16s(f, &s->cmd);
++ qemu_put_be16s(f, &s->status);
++ qemu_put_be16s(f, &s->intr);
++ qemu_put_be16s(f, &s->frnum);
++ qemu_put_be32s(f, &s->fl_base_addr);
++ qemu_put_8s(f, &s->sof_timing);
++ qemu_put_8s(f, &s->status2);
|