[Spice-commits] 45 commits - .gitignore Makefile.target arch_init.c block-migration.c default-configs/pci.mak default-configs/s390x-softmmu.mak docs/xen-save-devices-state.txt error.c error.h exec.c hmp-commands.hx hmp.c hmp.h hw/cirrus_vga.c hw/ds1338.c hw/ioapic.c hw/pci.c hw/qxl-render.c hw/qxl.c hw/scsi-bus.c hw/scsi-disk.c hw/virtio-scsi.c migration-fd.c migration.c migration.h module.c monitor.c pc-bios/bios.bin qapi-schema.json qemu-common.h qerror.c qerror.h qga/channel-win32.c qmp-commands.hx roms/Makefile roms/config.seabios roms/configure-seabios.sh roms/seabios savevm.c sysemu.h trace-events ui/spice-core.c ui/spice-display.c ui/vnc-auth-sasl.c ui/vnc-auth-sasl.h vl.c vmstate.h xen-all.c xen-mapcache.c xen-mapcache.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Thu Mar 22 06:31:05 PDT 2012


 .gitignore                        |    6 +
 Makefile.target                   |    2 
 arch_init.c                       |    2 
 block-migration.c                 |   58 +++++-------
 default-configs/pci.mak           |    1 
 default-configs/s390x-softmmu.mak |    1 
 docs/xen-save-devices-state.txt   |   34 +++++++
 error.c                           |   13 ++
 error.h                           |    5 +
 exec.c                            |   18 ++-
 hmp-commands.hx                   |    3 
 hmp.c                             |   74 +++++++++++++++
 hmp.h                             |    1 
 hw/cirrus_vga.c                   |    4 
 hw/ds1338.c                       |    1 
 hw/ioapic.c                       |    2 
 hw/pci.c                          |    1 
 hw/qxl-render.c                   |   13 --
 hw/qxl.c                          |  176 ++++++++++++++++++--------------------
 hw/scsi-bus.c                     |   18 +++
 hw/scsi-disk.c                    |   49 +++++++---
 hw/virtio-scsi.c                  |    2 
 migration-fd.c                    |    2 
 migration.c                       |   74 ++++-----------
 migration.h                       |    5 -
 module.c                          |    1 
 monitor.c                         |    6 +
 pc-bios/bios.bin                  |binary
 qapi-schema.json                  |   38 ++++++++
 qemu-common.h                     |    1 
 qerror.c                          |    8 +
 qerror.h                          |    6 +
 qga/channel-win32.c               |    4 
 qmp-commands.hx                   |   36 ++++++-
 roms/Makefile                     |   10 ++
 roms/config.seabios               |    1 
 roms/configure-seabios.sh         |    5 +
 roms/seabios                      |    2 
 savevm.c                          |  113 +++++++++++++++++++-----
 sysemu.h                          |   11 +-
 trace-events                      |   66 ++++++++++++++
 ui/spice-core.c                   |   15 +--
 ui/spice-display.c                |   14 ++-
 ui/vnc-auth-sasl.c                |    4 
 ui/vnc-auth-sasl.h                |    4 
 vl.c                              |    7 +
 vmstate.h                         |    3 
 xen-all.c                         |  104 ++++++++++++++++++++++
 xen-mapcache.c                    |   22 ++++
 xen-mapcache.h                    |    9 +
 50 files changed, 769 insertions(+), 286 deletions(-)

New commits:
commit 33cf629a3754b58a1e2dbbe01d91d97e712b7c06
Merge: b85a4ec... c234572...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 13:39:42 2012 -0500

    Merge remote-tracking branch 'sstabellini/saverestore-8' into staging
    
    * sstabellini/saverestore-8:
      xen: do not allocate RAM during INMIGRATE runstate
      xen mapcache: check if memory region has moved.
      xen: record physmap changes to xenstore
      Set runstate to INMIGRATE earlier
      Introduce "xen-save-devices-state"
      cirrus_vga: do not reset videoram
    
    Conflicts:
    	qapi-schema.json
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --cc qapi-schema.json
index 3a962c1,def69a9..0d11d6e
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@@ -1665,22 -1595,20 +1665,39 @@@
    'returns': [ 'ObjectTypeInfo' ] }
  
  ##
 +# @migrate
 +#
 +# Migrates the current running guest to another Virtual Machine.
 +#
 +# @uri: the Uniform Resource Identifier of the destination VM
 +#
 +# @blk: #optional do block migration (full disk copy)
 +#
 +# @inc: #optional incremental disk copy migration
 +#
 +# @detach: this argument exists only for compatibility reasons and
 +#          is ignored by QEMU
 +#
 +# Returns: nothing on success
 +#
 +# Since: 0.14.0
 +##
 +{ 'command': 'migrate',
 +  'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
++
+ # @xen-save-devices-state:
+ #
+ # Save the state of all devices to file. The RAM and the block devices
+ # of the VM are not saved by this command.
+ #
+ # @filename: the file to save the state of the devices to as binary
+ # data. See xen-save-devices-state.txt for a description of the binary
+ # format.
+ #
+ # Returns: Nothing on success
+ #          If @filename cannot be opened, OpenFileFailed
+ #          If an I/O error occurs while writing the file, IOError
+ #
+ # Since: 1.1
+ ##
+ { 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }
 -
diff --cc qmp-commands.hx
index 8b82038,dbb6236..c626ba8
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@@ -444,9 -444,43 +444,36 @@@ Note: inject-nmi is only supported for 
  EQMP
  
      {
+         .name       = "xen-save-devices-state",
+         .args_type  = "filename:F",
+     .mhandler.cmd_new = qmp_marshal_input_xen_save_devices_state,
+     },
+ 
+ SQMP
+ xen-save-devices-state
+ -------
+ 
+ Save the state of all devices to file. The RAM and the block devices
+ of the VM are not saved by this command.
+ 
+ Arguments:
+ 
+ - "filename": the file to save the state of the devices to as binary
+ data. See xen-save-devices-state.txt for a description of the binary
+ format.
+ 
+ Example:
+ 
+ -> { "execute": "xen-save-devices-state",
+      "arguments": { "filename": "/tmp/save" } }
+ <- { "return": {} }
+ 
+ EQMP
+ 
+     {
          .name       = "migrate",
          .args_type  = "detach:-d,blk:-b,inc:-i,uri:s",
 -        .params     = "[-d] [-b] [-i] uri",
 -        .help       = "migrate to URI (using -d to not wait for completion)"
 -		      "\n\t\t\t -b for migration without shared storage with"
 -		      " full copy of disk\n\t\t\t -i for migration without "
 -		      "shared storage with incremental copy of disk "
 -		      "(base image shared between src and destination)",
 -        .user_print = monitor_user_noop,	
 -	.mhandler.cmd_new = do_migrate,
 +        .mhandler.cmd_new = qmp_marshal_input_migrate,
      },
  
  SQMP
commit b85a4ec8a7ce348f3f385a53df4e418f2f54c182
Merge: dfebfcf... b71706d...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 13:37:41 2012 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      qemu-ga: for w32, fix leaked handle ov.hEvent in ga_channel_write()
      ioapic: fix build with DEBUG_IOAPIC
      .gitignore: add qemu-bridge-helper and option rom build products
      cleanup obsolete typedef
      monitor: Remove unused bool field 'qapi' in mon_cmd_t struct
      ds1338: Add missing break statement
      vnc: Fix packed boolean struct members
      Remove type field in ModuleEntry as it's not used

commit dfebfcf02f74ed47b61841037d7eda1baffb4d6e
Merge: 49f5437... ad1be89...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 13:37:23 2012 -0500

    Merge remote-tracking branch 'spice/spice.v50' into staging
    
    * spice/spice.v50:
      spice: fix broken initialization
      hw/qxl.c: Fix compilation failures on 32 bit hosts
      qxl/qxl_render.c: add trace events
      qxl: switch qxl.c to trace-events
      qxl: init_pipe_signaling: exit on failure
      monitor: fix client_migrate_info error handling
      spice: set spice uuid and name

commit 49f54371f22e3e95124e8115050cea29fadde606
Merge: be793eb... baa1bd8...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 13:36:37 2012 -0500

    Merge remote-tracking branch 'bonzini/scsi-next' into staging
    
    * bonzini/scsi-next:
      scsi: add get_dev_path
      virtio-scsi: call unregister_savevm properly
      scsi: copy serial number into VPD page 0x83
      scsi-cd: check ready condition before processing several commands
      get rid of CONFIG_VIRTIO_SCSI

commit be793eb3b9d04ce524cebcffb96e9770d68e57d9
Merge: efeaaf1... 0a1b357...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 13:36:18 2012 -0500

    Merge remote-tracking branch 'qemu-kvm/memory/urgent' into staging
    
    * qemu-kvm/memory/urgent:
      exec: fix guest memory access for Xen

commit c234572ded381423abca9801ebf5a32abd2495ef
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Wed Jan 25 12:36:06 2012 +0000

    xen: do not allocate RAM during INMIGRATE runstate
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-all.c b/xen-all.c
index 972cffd..10d53d1 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -190,6 +190,14 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
     xen_pfn_t *pfn_list;
     int i;
 
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        /* RAM already populated in Xen */
+        fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
+                " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
+                __func__, size, ram_addr); 
+        return;
+    }
+
     if (mr == &ram_memory) {
         return;
     }
commit cd1ba7de230b3a85fb4dba53bb681b7ea626b4eb
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Wed Jan 18 12:21:38 2012 +0000

    xen mapcache: check if memory region has moved.
    
    This patch changes the xen_map_cache behavior. Before trying to map a guest
    addr, mapcache will look into the list of range of address that have been moved
    (physmap/set_memory). There is currently one memory space like this, the vram,
    "moved" from were it's allocated to were the guest will look into.
    
    This help to have a succefull migration.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-all.c b/xen-all.c
index f2cad82..972cffd 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -225,6 +225,22 @@ static XenPhysmap *get_physmapping(XenIOState *state,
     return NULL;
 }
 
+static target_phys_addr_t xen_phys_offset_to_gaddr(target_phys_addr_t start_addr,
+                                                   ram_addr_t size, void *opaque)
+{
+    target_phys_addr_t addr = start_addr & TARGET_PAGE_MASK;
+    XenIOState *xen_io_state = opaque;
+    XenPhysmap *physmap = NULL;
+
+    QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
+        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
+            return physmap->start_addr;
+        }
+    }
+
+    return start_addr;
+}
+
 #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
 static int xen_add_to_physmap(XenIOState *state,
                               target_phys_addr_t start_addr,
@@ -1043,7 +1059,7 @@ int xen_hvm_init(void)
     }
 
     /* Init RAM management */
-    xen_map_cache_init();
+    xen_map_cache_init(xen_phys_offset_to_gaddr, state);
     xen_ram_init(ram_size);
 
     qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
diff --git a/xen-mapcache.c b/xen-mapcache.c
index 585b559..a456479 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -78,6 +78,9 @@ typedef struct MapCache {
     uint8_t *last_address_vaddr;
     unsigned long max_mcache_size;
     unsigned int mcache_bucket_shift;
+
+    phys_offset_to_gaddr_t phys_offset_to_gaddr;
+    void *opaque;
 } MapCache;
 
 static MapCache *mapcache;
@@ -91,13 +94,16 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
         return 0;
 }
 
-void xen_map_cache_init(void)
+void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
 {
     unsigned long size;
     struct rlimit rlimit_as;
 
     mapcache = g_malloc0(sizeof (MapCache));
 
+    mapcache->phys_offset_to_gaddr = f;
+    mapcache->opaque = opaque;
+
     QTAILQ_INIT(&mapcache->locked_entries);
     mapcache->last_address_index = -1;
 
@@ -193,9 +199,14 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
                        uint8_t lock)
 {
     MapCacheEntry *entry, *pentry = NULL;
-    target_phys_addr_t address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
-    target_phys_addr_t address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
+    target_phys_addr_t address_index;
+    target_phys_addr_t address_offset;
     target_phys_addr_t __size = size;
+    bool translated = false;
+
+tryagain:
+    address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
+    address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
 
     trace_xen_map_cache(phys_addr);
 
@@ -237,6 +248,11 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
     if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
         mapcache->last_address_index = -1;
+        if (!translated && mapcache->phys_offset_to_gaddr) {
+            phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
+            translated = true;
+            goto tryagain;
+        }
         trace_xen_map_cache_return(NULL);
         return NULL;
     }
diff --git a/xen-mapcache.h b/xen-mapcache.h
index da874ca..70301a5 100644
--- a/xen-mapcache.h
+++ b/xen-mapcache.h
@@ -11,9 +11,13 @@
 
 #include <stdlib.h>
 
+typedef target_phys_addr_t (*phys_offset_to_gaddr_t)(target_phys_addr_t start_addr,
+                                                     ram_addr_t size,
+                                                     void *opaque);
 #ifdef CONFIG_XEN
 
-void xen_map_cache_init(void);
+void xen_map_cache_init(phys_offset_to_gaddr_t f,
+                        void *opaque);
 uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
                        uint8_t lock);
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
@@ -22,7 +26,8 @@ void xen_invalidate_map_cache(void);
 
 #else
 
-static inline void xen_map_cache_init(void)
+static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
+                                      void *opaque)
 {
 }
 
commit d1814e08c0409d9f352f9ea7fab377bcee1286b8
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Thu Jan 19 15:56:11 2012 +0000

    xen: record physmap changes to xenstore
    
    Write to xenstore any physmap changes so that the hypervisor can be
    aware of them.
    Read physmap changes from xenstore on boot.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-all.c b/xen-all.c
index b0ed1ed..f2cad82 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -65,7 +65,7 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
 typedef struct XenPhysmap {
     target_phys_addr_t start_addr;
     ram_addr_t size;
-    MemoryRegion *mr;
+    char *name;
     target_phys_addr_t phys_offset;
 
     QLIST_ENTRY(XenPhysmap) list;
@@ -237,6 +237,7 @@ static int xen_add_to_physmap(XenIOState *state,
     XenPhysmap *physmap = NULL;
     target_phys_addr_t pfn, start_gpfn;
     target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr);
+    char path[80], value[17];
 
     if (get_physmapping(state, start_addr, size)) {
         return 0;
@@ -275,6 +276,7 @@ go_physmap:
 
     physmap->start_addr = start_addr;
     physmap->size = size;
+    physmap->name = (char *)mr->name;
     physmap->phys_offset = phys_offset;
 
     QLIST_INSERT_HEAD(&state->physmap, physmap, list);
@@ -283,6 +285,30 @@ go_physmap:
                                    start_addr >> TARGET_PAGE_BITS,
                                    (start_addr + size) >> TARGET_PAGE_BITS,
                                    XEN_DOMCTL_MEM_CACHEATTR_WB);
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
+            xen_domid, (uint64_t)phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
+            xen_domid, (uint64_t)phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    if (mr->name) {
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
+                xen_domid, (uint64_t)phys_offset);
+        if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
+            return -1;
+        }
+    }
+
     return 0;
 }
 
@@ -911,6 +937,55 @@ int xen_init(void)
     return 0;
 }
 
+static void xen_read_physmap(XenIOState *state)
+{
+    XenPhysmap *physmap = NULL;
+    unsigned int len, num, i;
+    char path[80], *value = NULL;
+    char **entries = NULL;
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap", xen_domid);
+    entries = xs_directory(state->xenstore, 0, path, &num);
+    if (entries == NULL)
+        return;
+
+    for (i = 0; i < num; i++) {
+        physmap = g_malloc(sizeof (XenPhysmap));
+        physmap->phys_offset = strtoull(entries[i], NULL, 16);
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
+                xen_domid, entries[i]);
+        value = xs_read(state->xenstore, 0, path, &len);
+        if (value == NULL) {
+            free(physmap);
+            continue;
+        }
+        physmap->start_addr = strtoull(value, NULL, 16);
+        free(value);
+
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/size",
+                xen_domid, entries[i]);
+        value = xs_read(state->xenstore, 0, path, &len);
+        if (value == NULL) {
+            free(physmap);
+            continue;
+        }
+        physmap->size = strtoull(value, NULL, 16);
+        free(value);
+
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/name",
+                xen_domid, entries[i]);
+        physmap->name = xs_read(state->xenstore, 0, path, &len);
+
+        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
+    }
+    free(entries);
+    return;
+}
+
 int xen_hvm_init(void)
 {
     int i, rc;
@@ -986,6 +1061,7 @@ int xen_hvm_init(void)
     xen_be_register("console", &xen_console_ops);
     xen_be_register("vkbd", &xen_kbdmouse_ops);
     xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_read_physmap(state);
 
     return 0;
 }
commit 81323a6c16e8042ef74f789a0c8d7188f6d18a14
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Wed Jan 18 12:23:13 2012 +0000

    Set runstate to INMIGRATE earlier
    
    Set runstate to RUN_STATE_INMIGRATE as soon as we can on resume.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/vl.c b/vl.c
index 1d4c350..918177a 100644
--- a/vl.c
+++ b/vl.c
@@ -3099,6 +3099,7 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_incoming:
                 incoming = optarg;
+                runstate_set(RUN_STATE_INMIGRATE);
                 break;
             case QEMU_OPTION_nodefaults:
                 default_serial = 0;
@@ -3596,7 +3597,6 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (incoming) {
-        runstate_set(RUN_STATE_INMIGRATE);
         int ret = qemu_start_incoming_migration(incoming);
         if (ret < 0) {
             fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
commit a7ae8355b4465bb52021451a77615f83872970b0
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Wed Jan 25 12:24:51 2012 +0000

    Introduce "xen-save-devices-state"
    
    - add an "is_ram" flag to SaveStateEntry;
    
    - register_savevm_live sets is_ram for live_savevm devices;
    
    - introduce a "xen-save-devices-state" QAPI command that can be used to save
    the state of all devices, but not the RAM or the block devices of the
    VM.
    
    Changes in v8:
    
    - rename save-devices-state to xen-save-devices-state.
    
    Changes in v7:
    
    - rename save_devices to save-devices-state.
    
    Changes in v6:
    
    - remove the is_ram parameter from register_savevm_live and sets is_ram
    if the device is a live_savevm device;
    
    - introduce save_devices as a QAPI command, write a better description
    for it;
    
    - fix CODING_STYLE;
    
    - introduce a new doc to explain the save format used by save_devices.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt
new file mode 100644
index 0000000..92e08db
--- /dev/null
+++ b/docs/xen-save-devices-state.txt
@@ -0,0 +1,34 @@
+= Save Devices =
+
+QEMU has code to load/save the state of the guest that it is running.
+These are two complementary operations.  Saving the state just does
+that, saves the state for each device that the guest is running.
+
+These operations are normally used with migration (see migration.txt),
+however it is also possible to save the state of all devices to file,
+without saving the RAM or the block devices of the VM.
+
+This operation is called "xen-save-devices-state" (see
+QMP/qmp-commands.txt)
+
+
+The binary format used in the file is the following:
+
+
+-------------------------------------------
+
+32 bit big endian: QEMU_VM_FILE_MAGIC
+32 bit big endian: QEMU_VM_FILE_VERSION
+
+for_each_device
+{
+    8 bit:              QEMU_VM_SECTION_FULL
+    32 bit big endian:  section_id
+    8 bit:              idstr (ID string) length
+    string:             idstr (ID string)
+    32 bit big endian:  instance_id
+    32 bit big endian:  version_id
+    buffer:             device specific data
+}
+
+8 bit: QEMU_VM_EOF
diff --git a/qapi-schema.json b/qapi-schema.json
index d0b6792..def69a9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1593,3 +1593,22 @@
 { 'command': 'qom-list-types',
   'data': { '*implements': 'str', '*abstract': 'bool' },
   'returns': [ 'ObjectTypeInfo' ] }
+
+##
+# @xen-save-devices-state:
+#
+# Save the state of all devices to file. The RAM and the block devices
+# of the VM are not saved by this command.
+#
+# @filename: the file to save the state of the devices to as binary
+# data. See xen-save-devices-state.txt for a description of the binary
+# format.
+#
+# Returns: Nothing on success
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 1.1
+##
+{ 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }
+
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 705f704..dbb6236 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -444,6 +444,33 @@ Note: inject-nmi is only supported for x86 guest currently, it will
 EQMP
 
     {
+        .name       = "xen-save-devices-state",
+        .args_type  = "filename:F",
+    .mhandler.cmd_new = qmp_marshal_input_xen_save_devices_state,
+    },
+
+SQMP
+xen-save-devices-state
+-------
+
+Save the state of all devices to file. The RAM and the block devices
+of the VM are not saved by this command.
+
+Arguments:
+
+- "filename": the file to save the state of the devices to as binary
+data. See xen-save-devices-state.txt for a description of the binary
+format.
+
+Example:
+
+-> { "execute": "xen-save-devices-state",
+     "arguments": { "filename": "/tmp/save" } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "migrate",
         .args_type  = "detach:-d,blk:-b,inc:-i,uri:s",
         .params     = "[-d] [-b] [-i] uri",
diff --git a/savevm.c b/savevm.c
index 80be1ff..0e61eb0 100644
--- a/savevm.c
+++ b/savevm.c
@@ -84,6 +84,7 @@
 #include "qemu-timer.h"
 #include "cpus.h"
 #include "memory.h"
+#include "qmp-commands.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
@@ -1177,6 +1178,7 @@ typedef struct SaveStateEntry {
     void *opaque;
     CompatEntry *compat;
     int no_migrate;
+    int is_ram;
 } SaveStateEntry;
 
 
@@ -1241,6 +1243,10 @@ int register_savevm_live(DeviceState *dev,
     se->opaque = opaque;
     se->vmsd = NULL;
     se->no_migrate = 0;
+    /* if this is a live_savem then set is_ram */
+    if (save_live_state != NULL) {
+        se->is_ram = 1;
+    }
 
     if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
         char *id = dev->parent_bus->info->get_dev_path(dev);
@@ -1728,6 +1734,45 @@ out:
     return ret;
 }
 
+static int qemu_save_device_state(QEMUFile *f)
+{
+    SaveStateEntry *se;
+
+    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
+    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    cpu_synchronize_all_states();
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        int len;
+
+        if (se->is_ram) {
+            continue;
+        }
+        if (se->save_state == NULL && se->vmsd == NULL) {
+            continue;
+        }
+
+        /* Section type */
+        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
+        qemu_put_be32(f, se->section_id);
+
+        /* ID string */
+        len = strlen(se->idstr);
+        qemu_put_byte(f, len);
+        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
+
+        qemu_put_be32(f, se->instance_id);
+        qemu_put_be32(f, se->version_id);
+
+        vmstate_save(f, se);
+    }
+
+    qemu_put_byte(f, QEMU_VM_EOF);
+
+    return qemu_file_get_error(f);
+}
+
 static SaveStateEntry *find_se(const char *idstr, int instance_id)
 {
     SaveStateEntry *se;
@@ -2109,6 +2154,32 @@ void do_savevm(Monitor *mon, const QDict *qdict)
         vm_start();
 }
 
+void qmp_xen_save_devices_state(const char *filename, Error **errp)
+{
+    QEMUFile *f;
+    int saved_vm_running;
+    int ret;
+
+    saved_vm_running = runstate_is_running();
+    vm_stop(RUN_STATE_SAVE_VM);
+
+    f = qemu_fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        goto the_end;
+    }
+    ret = qemu_save_device_state(f);
+    qemu_fclose(f);
+    if (ret < 0) {
+        error_set(errp, QERR_IO_ERROR);
+    }
+
+ the_end:
+    if (saved_vm_running)
+        vm_start();
+    return;
+}
+
 int load_vmstate(const char *name)
 {
     BlockDriverState *bs, *bs_vm_state;
commit 0a1b357f1555ce410d2d0d5f947b5415587ac4d8
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Mon Mar 19 15:54:34 2012 +0000

    exec: fix guest memory access for Xen
    
    In cpu_physical_memory_rw, a change has been introduced and qemu_get_ram_ptr is
    no longuer called with the ram addr we want to access, but only with the
    section address. This patch fixes this. (All other call to qemu_get_ram_ptr are
    already called with the right address.)
    
    This patch fixes Xen guest.
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index a3818ff..265e895 100644
--- a/exec.c
+++ b/exec.c
@@ -3856,8 +3856,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 }
             } else {
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(section->mr->ram_addr)
-                    + section_addr(section, addr);
+                ptr = qemu_get_ram_ptr(section->mr->ram_addr
+                                       + section_addr(section, addr));
                 memcpy(buf, ptr, l);
                 qemu_put_ram_ptr(ptr);
             }
commit efeaaf1ebc0f677dc321845d74b8d6f599eb0927
Merge: b8b3e75... 5bd33de...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 11:37:44 2012 -0500

    Merge remote-tracking branch 'origin/master' into staging
    
    * origin/master:
      tcg: fix sparc host for AREG0 free operation

commit baa1bd8992c22095fa5a483f4b6415eb15180665
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 15:30:40 2012 +0100

    scsi: add get_dev_path
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2cb5a18..8e76c5d 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -7,6 +7,7 @@
 #include "trace.h"
 #include "dma.h"
 
+static char *scsibus_get_dev_path(DeviceState *dev);
 static char *scsibus_get_fw_dev_path(DeviceState *dev);
 static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
 static void scsi_req_dequeue(SCSIRequest *req);
@@ -14,6 +15,7 @@ static void scsi_req_dequeue(SCSIRequest *req);
 static struct BusInfo scsi_bus_info = {
     .name  = "SCSI",
     .size  = sizeof(SCSIBus),
+    .get_dev_path = scsibus_get_dev_path,
     .get_fw_dev_path = scsibus_get_fw_dev_path,
     .props = (Property[]) {
         DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0),
@@ -1423,6 +1425,22 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
     sdev->unit_attention = sense;
 }
 
+static char *scsibus_get_dev_path(DeviceState *dev)
+{
+    SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
+    DeviceState *hba = dev->parent_bus->parent;
+    char *id = NULL;
+
+    if (hba && hba->parent_bus && hba->parent_bus->info->get_dev_path) {
+        id = hba->parent_bus->info->get_dev_path(hba);
+    }
+    if (id) {
+        return g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun);
+    } else {
+        return g_strdup_printf("%d:%d:%d", d->channel, d->id, d->lun);
+    }
+}
+
 static char *scsibus_get_fw_dev_path(DeviceState *dev)
 {
     SCSIDevice *d = SCSI_DEVICE(dev);
commit eb2fa76418402c8b26e1ab4cb53498ee0f4e52ef
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 19 15:21:57 2012 +0100

    virtio-scsi: call unregister_savevm properly
    
    This fixes a use-after-free when migrating after hot-unplug.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index e607edc..45d54fa 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -613,5 +613,7 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 
 void virtio_scsi_exit(VirtIODevice *vdev)
 {
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+    unregister_savevm(s->qdev, "virtio-scsi", s);
     virtio_cleanup(vdev);
 }
commit fd9307912d0a2ffa0310f9e20935d96d5af0a1ca
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 16 19:12:43 2012 +0100

    scsi: copy serial number into VPD page 0x83
    
    Currently QEMU passes the qdev device id to the guest in an ASCII-string
    designator in page 0x83.  While this is fine, it does not match what
    real hardware does; usually the ASCII-string designator there hosts
    another copy of the serial number (there can be other designators,
    for example with a world-wide name).  Do the same for QEMU SCSI
    disks.
    
    ATAPI does not support VPD pages, so it does not matter there.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7846f45..9949786 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -471,8 +471,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
 
         case 0x83: /* Device identification page, mandatory */
         {
-            int max_len = 255 - 8;
-            int id_len = strlen(bdrv_get_device_name(s->qdev.conf.bs));
+            const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
+            int max_len = s->serial ? 20 : 255 - 8;
+            int id_len = strlen(str);
 
             if (id_len > max_len) {
                 id_len = max_len;
@@ -486,7 +487,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             outbuf[buflen++] = 0;   // reserved
             outbuf[buflen++] = id_len; // length of data following
 
-            memcpy(outbuf+buflen, bdrv_get_device_name(s->qdev.conf.bs), id_len);
+            memcpy(outbuf+buflen, str, id_len);
             buflen += id_len;
             break;
         }
commit 9bcaf4fe264c507b59ab2e5fc6b2fa9d36f06d44
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 16 19:11:43 2012 +0100

    scsi-cd: check ready condition before processing several commands
    
    This commit is more or less obvious.  What it caused is less obvious:
    SCSI CD drives failed to eject under Linux, though for example the
    "change" command worked okay.  This happens because of the autoclose
    option in the Linux CD-ROM driver.
    
    The actual chain of events is quite complex and somehow involves
    udev helpers; the actual command that matters is READ TOC, though
    honestly it's not really clear to me how because it should always be
    invoked after autoclose, not before.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index add399e..7846f45 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1152,9 +1152,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
     outbuf = r->iov.iov_base;
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
-        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
-            goto not_ready;
-        }
+        assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
         break;
     case INQUIRY:
         buflen = scsi_disk_emulate_inquiry(req, outbuf);
@@ -1209,7 +1207,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         memset(outbuf, 0, 8);
         bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
         if (!nb_sectors) {
-            goto not_ready;
+            scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
+            return -1;
         }
         if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) {
             goto illegal_request;
@@ -1269,7 +1268,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
             memset(outbuf, 0, req->cmd.xfer);
             bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
             if (!nb_sectors) {
-                goto not_ready;
+                scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
+                return -1;
             }
             if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) {
                 goto illegal_request;
@@ -1314,14 +1314,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
     buflen = MIN(buflen, req->cmd.xfer);
     return buflen;
 
-not_ready:
-    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
-        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
-    } else {
-        scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
-    }
-    return -1;
-
 illegal_request:
     if (r->req.status == -1) {
         scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
@@ -1356,6 +1348,30 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
 #endif
 
     switch (command) {
+    case INQUIRY:
+    case MODE_SENSE:
+    case MODE_SENSE_10:
+    case RESERVE:
+    case RESERVE_10:
+    case RELEASE:
+    case RELEASE_10:
+    case START_STOP:
+    case ALLOW_MEDIUM_REMOVAL:
+    case GET_CONFIGURATION:
+    case GET_EVENT_STATUS_NOTIFICATION:
+    case MECHANISM_STATUS:
+    case REQUEST_SENSE:
+        break;
+
+    default:
+        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+            scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+            return 0;
+        }
+        break;
+    }
+
+    switch (command) {
     case TEST_UNIT_READY:
     case INQUIRY:
     case MODE_SENSE:
commit 7725d14679c4391391b63f933d604b046ef8adf6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 16 19:21:35 2012 +0100

    get rid of CONFIG_VIRTIO_SCSI
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 37fb7ed..63cf769 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -209,7 +209,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
 # need to fix this properly
 obj-$(CONFIG_NO_PCI) += pci-stub.o
 obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
-obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
+obj-$(CONFIG_VIRTIO) += virtio-scsi.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index 21e4ccf..9d3e1db 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -1,6 +1,5 @@
 CONFIG_PCI=y
 CONFIG_VIRTIO_PCI=y
-CONFIG_VIRTIO_SCSI=y
 CONFIG_VIRTIO=y
 CONFIG_USB_UHCI=y
 CONFIG_USB_OHCI=y
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index e588803..3005729 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -1,2 +1 @@
 CONFIG_VIRTIO=y
-CONFIG_VIRTIO_SCSI=y
commit b8b3e75609bd39a085db7612cb7d36a1944eed23
Merge: 5c20f4e... 32b0898...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 08:51:50 2012 -0500

    Merge remote-tracking branch 'qemu-kvm/memory/urgent' into staging
    
    * qemu-kvm/memory/urgent: (42 commits)
      memory: check for watchpoints when getting code ram_addr
      exec: fix write tlb entry misused as iotlb
      Sparc: avoid AREG0 wrappers for memory access helpers
      Sparc: avoid AREG0 for memory access helpers
      TCG: add 5 arg helpers to def-helper.h
      softmmu templates: optionally pass CPUState to memory access functions
      i386: Remove REGPARM
      sparc64: implement PCI and ISA irqs
      sparc: reset CPU state on reset
      apb: use normal PCI device header for PBM device
      w64: Fix data type of next_tb and tcg_qemu_tb_exec
      softfloat: fix for C99
      vmstate: fix varrays with uint32_t indexes
      Fix large memory chunks allocation with tcg_malloc.
      hw/pxa2xx.c: Fix handling of pxa2xx_i2c variable offset within region
      hw/pxa2xx_lcd.c: drop target_phys_addr_t usage in device state
      hw/pxa2xx_dma.c: drop target_phys_addr_t usage in device state
      ARM: Remove unnecessary subpage workarounds
      malta: Fix display for LED array
      malta: Use symbolic hardware addresses
      ...

commit 5c20f4e54a311620861c659dec29d0ee402e8b93
Merge: 46a5801... e1c37d0...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 19 08:51:06 2012 -0500

    Merge remote-tracking branch 'qmp/queue/qmp' into staging
    
    * qmp/queue/qmp:
      qapi: Convert migrate
      Purge migration of (almost) everything to do with monitors
      Error: Introduce error_copy()
      QError: Introduce new errors for the migration command

commit ad1be89948f88e89708b04ccd782456ccec3a6f0
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Mar 14 20:33:37 2012 +0200

    spice: fix broken initialization
    
    Commit 1b71f7c14fab6f00c2680d4489fbee7baf796e4f moved MODULE_INIT_QOM to
    way before MODULE_INIT_MACHINE, thereby breaking assumptions made in
    spice-core.c which registered both a type initializer and a machine
    intializer.
    
    This fix removes the type registration, and replaces it with calling
    qemu_spice_init in vl.c after command line parsing (second pass) is
    done, and after timers are armed, required by spice server.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index 80535b6..a468524 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -554,7 +554,7 @@ void qemu_spice_init(void)
 
     qemu_thread_get_self(&me);
 
-   if (!opts) {
+    if (!opts) {
         return;
     }
     port = qemu_opt_get_number(opts, "port", 0);
@@ -787,10 +787,3 @@ static void spice_register_config(void)
     qemu_add_opts(&qemu_spice_opts);
 }
 machine_init(spice_register_config);
-
-static void spice_register_types(void)
-{
-    qemu_spice_init();
-}
-
-type_init(spice_register_types)
diff --git a/vl.c b/vl.c
index bd95539..eeb634b 100644
--- a/vl.c
+++ b/vl.c
@@ -3369,6 +3369,11 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+#ifdef CONFIG_SPICE
+    /* spice needs the timers to be initialized by this point */
+    qemu_spice_init();
+#endif
+
     if (icount_option && (kvm_enabled() || xen_enabled())) {
         fprintf(stderr, "-icount is not allowed with kvm or xen\n");
         exit(1);
commit 5dba0d453d238c283ac3cd2db810c843f9b822b7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 16 13:50:04 2012 +0000

    hw/qxl.c: Fix compilation failures on 32 bit hosts
    
    Fix compilation failures on 32 bit hosts (cast from pointer to
    integer of different size; %ld expects 'long int' not uint64_t).
    
    Reported-by: Steve Langasek <steve.langasek at canonical.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index d28c1c0..47a162e 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -154,7 +154,7 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
     } else {
         assert(cookie != NULL);
         spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
-                                    clear_dirty_region, (uint64_t)cookie);
+                                    clear_dirty_region, (uintptr_t)cookie);
     }
 }
 
@@ -178,7 +178,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
         cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
                                 QXL_IO_DESTROY_SURFACE_ASYNC);
         cookie->u.surface_id = id;
-        spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
+        spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
     } else {
         qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
     }
@@ -189,8 +189,8 @@ static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
     trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
                                          qxl->num_free_res);
     spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
-        (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                 QXL_IO_FLUSH_SURFACES_ASYNC));
+        (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                  QXL_IO_FLUSH_SURFACES_ASYNC));
 }
 
 void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
@@ -226,8 +226,8 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
     trace_qxl_spice_destroy_surfaces(qxl->id, async);
     if (async) {
         spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
     } else {
         qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
         qxl_spice_destroy_surfaces_complete(qxl);
@@ -764,7 +764,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
     }
     if (cookie && current_async != cookie->io) {
         fprintf(stderr,
-                "qxl: %s: error: current_async = %d != %ld = cookie->io\n",
+                "qxl: %s: error: current_async = %d != %" PRId64 " = cookie->io\n",
                 __func__, current_async, cookie->io);
     }
     switch (current_async) {
@@ -837,7 +837,7 @@ static void interface_update_area_complete(QXLInstance *sin,
 static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
-    QXLCookie *cookie = (QXLCookie *)cookie_token;
+    QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token;
 
     switch (cookie->type) {
     case QXL_COOKIE_TYPE_IO:
commit d53291cf59139ec99425a75b3963f7f9b9a1eebf
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Mar 18 13:46:15 2012 +0100

    qxl/qxl_render.c: add trace events
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 25857f6..28ab182 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -31,11 +31,10 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
         return;
     }
     if (!qxl->guest_primary.data) {
-        dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
+        trace_qxl_render_blit_guest_primary_initialized();
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
     }
-    dprint(qxl, 2, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
-            qxl->guest_primary.qxl_stride,
+    trace_qxl_render_blit(qxl->guest_primary.qxl_stride,
             rect->left, rect->right, rect->top, rect->bottom);
     src = qxl->guest_primary.data;
     if (qxl->guest_primary.qxl_stride < 0) {
@@ -107,8 +106,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
         qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
         qxl->num_dirty_rects = 1;
-        dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
-               __FUNCTION__,
+        trace_qxl_render_guest_primary_resized(
                qxl->guest_primary.surface.width,
                qxl->guest_primary.surface.height,
                qxl->guest_primary.qxl_stride,
@@ -118,8 +116,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
     if (surface->width != qxl->guest_primary.surface.width ||
         surface->height != qxl->guest_primary.surface.height) {
         if (qxl->guest_primary.qxl_stride > 0) {
-            dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
-                   __func__);
             qemu_free_displaysurface(vga->ds);
             qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
                                             qxl->guest_primary.surface.height,
@@ -127,8 +123,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
                                             qxl->guest_primary.abs_stride,
                                             qxl->guest_primary.data);
         } else {
-            dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
-                   __func__);
             qemu_resize_displaysurface(vga->ds,
                     qxl->guest_primary.surface.width,
                     qxl->guest_primary.surface.height);
@@ -187,6 +181,7 @@ void qxl_render_update_area_bh(void *opaque)
 void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
 {
     qemu_mutex_lock(&qxl->ssd.lock);
+    trace_qxl_render_update_area_done(cookie);
     qemu_bh_schedule(qxl->update_area_bh);
     qxl->render_update_cookie_num--;
     qemu_mutex_unlock(&qxl->ssd.lock);
diff --git a/trace-events b/trace-events
index fefd6a0..70f059d 100644
--- a/trace-events
+++ b/trace-events
@@ -781,3 +781,10 @@ qxl_spice_reset_memslots(int qid) "%d"
 qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
 qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
 qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
+qxl_vga_ioport_while_not_in_vga_mode(int qid) "%d (int qid, reset to VGA mode because of VGA io)"
+
+# hw/qxl-render.c
+qxl_render_blit_guest_primary_initialized(void) ""
+qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]"
+qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d"
+qxl_render_update_area_done(void *cookie) "%p"
commit c480bb7da465186b84d8427e068ef7502e47ffbf
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Mar 18 13:46:14 2012 +0100

    qxl: switch qxl.c to trace-events
    
    dprint is still used for qxl_init_common one time prints.
    
    also switched parts of spice-display.c over, mainly all the callbacks to
    spice server.
    
    All qxl device trace events start with the qxl device id.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 26ca893..d28c1c0 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -23,6 +23,7 @@
 #include "qemu-queue.h"
 #include "monitor.h"
 #include "sysemu.h"
+#include "trace.h"
 
 #include "qxl.h"
 
@@ -143,6 +144,10 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
                            uint32_t clear_dirty_region,
                            qxl_async_io async, struct QXLCookie *cookie)
 {
+    trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right,
+                                area->top, area->bottom);
+    trace_qxl_spice_update_area_rest(qxl->id, num_dirty_rects,
+                                     clear_dirty_region);
     if (async == QXL_SYNC) {
         qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
                         dirty_rects, num_dirty_rects, clear_dirty_region);
@@ -156,6 +161,7 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
 static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
                                                     uint32_t id)
 {
+    trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id);
     qemu_mutex_lock(&qxl->track_lock);
     qxl->guest_surfaces.cmds[id] = 0;
     qxl->guest_surfaces.count--;
@@ -167,6 +173,7 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
 {
     QXLCookie *cookie;
 
+    trace_qxl_spice_destroy_surface_wait(qxl->id, id, async);
     if (async) {
         cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
                                 QXL_IO_DESTROY_SURFACE_ASYNC);
@@ -174,12 +181,13 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
         spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
     } else {
         qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
-        qxl_spice_destroy_surface_wait_complete(qxl, id);
     }
 }
 
 static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
 {
+    trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
+                                         qxl->num_free_res);
     spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
         (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
                                  QXL_IO_FLUSH_SURFACES_ASYNC));
@@ -188,21 +196,25 @@ static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
 void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
                                uint32_t count)
 {
+    trace_qxl_spice_loadvm_commands(qxl->id, ext, count);
     qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count);
 }
 
 void qxl_spice_oom(PCIQXLDevice *qxl)
 {
+    trace_qxl_spice_oom(qxl->id);
     qxl->ssd.worker->oom(qxl->ssd.worker);
 }
 
 void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
 {
+    trace_qxl_spice_reset_memslots(qxl->id);
     qxl->ssd.worker->reset_memslots(qxl->ssd.worker);
 }
 
 static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
 {
+    trace_qxl_spice_destroy_surfaces_complete(qxl->id);
     qemu_mutex_lock(&qxl->track_lock);
     memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
     qxl->guest_surfaces.count = 0;
@@ -211,6 +223,7 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
 
 static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
 {
+    trace_qxl_spice_destroy_surfaces(qxl->id, async);
     if (async) {
         spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
                 (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -223,11 +236,13 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
 
 void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
 {
+    trace_qxl_spice_reset_image_cache(qxl->id);
     qxl->ssd.worker->reset_image_cache(qxl->ssd.worker);
 }
 
 void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
 {
+    trace_qxl_spice_reset_cursor(qxl->id);
     qxl->ssd.worker->reset_cursor(qxl->ssd.worker);
     qemu_mutex_lock(&qxl->track_lock);
     qxl->guest_cursor = 0;
@@ -409,7 +424,7 @@ static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
 
-    dprint(qxl, 1, "%s:\n", __FUNCTION__);
+    trace_qxl_interface_attach_worker(qxl->id);
     qxl->ssd.worker = qxl_worker;
 }
 
@@ -417,7 +432,7 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
 
-    dprint(qxl, 1, "%s: %d\n", __FUNCTION__, level);
+    trace_qxl_interface_set_compression_level(qxl->id, level);
     qxl->shadow_rom.compression_level = cpu_to_le32(level);
     qxl->rom->compression_level = cpu_to_le32(level);
     qxl_rom_set_dirty(qxl);
@@ -427,6 +442,7 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
 
+    trace_qxl_interface_set_mm_time(qxl->id, mm_time);
     qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
     qxl->rom->mm_clock = cpu_to_le32(mm_time);
     qxl_rom_set_dirty(qxl);
@@ -436,7 +452,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
 {
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
 
-    dprint(qxl, 1, "%s:\n", __FUNCTION__);
+    trace_qxl_interface_get_init_info(qxl->id);
     info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
     info->memslot_id_bits = MEMSLOT_SLOT_BITS;
     info->num_memslots = NUM_MEMSLOTS;
@@ -505,9 +521,10 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
     QXLCommand *cmd;
     int notify, ret;
 
+    trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode));
+
     switch (qxl->mode) {
     case QXL_MODE_VGA:
-        dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
         ret = false;
         qemu_mutex_lock(&qxl->ssd.lock);
         if (qxl->ssd.update != NULL) {
@@ -518,19 +535,18 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
         }
         qemu_mutex_unlock(&qxl->ssd.lock);
         if (ret) {
-            dprint(qxl, 2, "%s %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
+            trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
             qxl_log_command(qxl, "vga", ext);
         }
         return ret;
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
     case QXL_MODE_UNDEFINED:
-        dprint(qxl, 4, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
         ring = &qxl->ram->cmd_ring;
         if (SPICE_RING_IS_EMPTY(ring)) {
             return false;
         }
-        dprint(qxl, 2, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
+        trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
         SPICE_RING_CONS_ITEM(ring, cmd);
         ext->cmd      = *cmd;
         ext->group_id = MEMSLOT_GROUP_GUEST;
@@ -555,6 +571,7 @@ static int interface_req_cmd_notification(QXLInstance *sin)
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
     int wait = 1;
 
+    trace_qxl_ring_command_req_notification(qxl->id);
     switch (qxl->mode) {
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
@@ -592,10 +609,11 @@ static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
     }
 
     SPICE_RING_PUSH(ring, notify);
-    dprint(d, 2, "free: push %d items, notify %s, ring %d/%d [%d,%d]\n",
-           d->num_free_res, notify ? "yes" : "no",
-           ring->prod - ring->cons, ring->num_items,
-           ring->prod, ring->cons);
+    trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode),
+           d->guest_surfaces.count, d->num_free_res,
+           d->last_release, notify ? "yes" : "no");
+    trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons,
+           ring->num_items, ring->prod, ring->cons);
     if (notify) {
         qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
     }
@@ -642,7 +660,7 @@ static void interface_release_resource(QXLInstance *sin,
     }
     qxl->last_release = ext.info;
     qxl->num_free_res++;
-    dprint(qxl, 3, "%4d\r", qxl->num_free_res);
+    trace_qxl_ring_res_put(qxl->id, qxl->num_free_res);
     qxl_push_free_res(qxl, 0);
 }
 
@@ -654,6 +672,8 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
     QXLCommand *cmd;
     int notify;
 
+    trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode));
+
     switch (qxl->mode) {
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
@@ -677,6 +697,7 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
         if (qxl->id == 0) {
             qxl_render_cursor(qxl, ext);
         }
+        trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode));
         return true;
     default:
         return false;
@@ -689,6 +710,7 @@ static int interface_req_cursor_notification(QXLInstance *sin)
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
     int wait = 1;
 
+    trace_qxl_ring_cursor_req_notification(qxl->id);
     switch (qxl->mode) {
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
@@ -716,7 +738,6 @@ static int interface_flush_resources(QXLInstance *sin)
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
     int ret;
 
-    dprint(qxl, 1, "free: guest flush (have %d)\n", qxl->num_free_res);
     ret = qxl->num_free_res;
     if (ret) {
         qxl_push_free_res(qxl, 1);
@@ -736,7 +757,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
     qxl->current_async = QXL_UNDEFINED_IO;
     qemu_mutex_unlock(&qxl->async_lock);
 
-    dprint(qxl, 2, "async_complete: %d (%p) done\n", current_async, cookie);
+    trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie);
     if (!cookie) {
         fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
         return;
@@ -782,11 +803,15 @@ static void interface_update_area_complete(QXLInstance *sin,
         qemu_mutex_unlock(&qxl->ssd.lock);
         return;
     }
+    trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left,
+            dirty->right, dirty->top, dirty->bottom);
+    trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects);
     if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
         /*
          * overflow - treat this as a full update. Not expected to be common.
          */
-        dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
+        trace_qxl_interface_update_area_complete_overflow(qxl->id,
+                                                          QXL_NUM_DIRTY_RECTS);
         qxl->guest_primary.resized = 1;
     }
     if (qxl->guest_primary.resized) {
@@ -802,8 +827,8 @@ static void interface_update_area_complete(QXLInstance *sin,
         qxl->dirty[qxl_i++] = dirty[i];
     }
     qxl->num_dirty_rects += num_updated_rects;
-    dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
-           __func__, qxl->num_dirty_rects);
+    trace_qxl_interface_update_area_complete_schedule_bh(qxl->id,
+                                                         qxl->num_dirty_rects);
     qemu_bh_schedule(qxl->update_area_bh);
     qemu_mutex_unlock(&qxl->ssd.lock);
 }
@@ -857,7 +882,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
     if (d->mode == QXL_MODE_VGA) {
         return;
     }
-    dprint(d, 1, "%s\n", __FUNCTION__);
+    trace_qxl_enter_vga_mode(d->id);
     qemu_spice_create_host_primary(&d->ssd);
     d->mode = QXL_MODE_VGA;
     memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
@@ -868,7 +893,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d)
     if (d->mode != QXL_MODE_VGA) {
         return;
     }
-    dprint(d, 1, "%s\n", __FUNCTION__);
+    trace_qxl_exit_vga_mode(d->id);
     qxl_destroy_primary(d, QXL_SYNC);
 }
 
@@ -905,7 +930,7 @@ static void qxl_reset_state(PCIQXLDevice *d)
 
 static void qxl_soft_reset(PCIQXLDevice *d)
 {
-    dprint(d, 1, "%s:\n", __FUNCTION__);
+    trace_qxl_soft_reset(d->id);
     qxl_check_state(d);
 
     if (d->id == 0) {
@@ -917,8 +942,7 @@ static void qxl_soft_reset(PCIQXLDevice *d)
 
 static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
 {
-    dprint(d, 1, "%s: start%s\n", __FUNCTION__,
-           loadvm ? " (loadvm)" : "");
+    trace_qxl_hard_reset(d->id, loadvm);
 
     qxl_spice_reset_cursor(d);
     qxl_spice_reset_image_cache(d);
@@ -933,13 +957,12 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
     }
     qemu_spice_create_host_memslot(&d->ssd);
     qxl_soft_reset(d);
-
-    dprint(d, 1, "%s: done\n", __FUNCTION__);
 }
 
 static void qxl_reset_handler(DeviceState *dev)
 {
     PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
+
     qxl_hard_reset(d, 0);
 }
 
@@ -948,8 +971,8 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     VGACommonState *vga = opaque;
     PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
 
+    trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val);
     if (qxl->mode != QXL_MODE_VGA) {
-        dprint(qxl, 1, "%s\n", __FUNCTION__);
         qxl_destroy_primary(qxl, QXL_SYNC);
         qxl_soft_reset(qxl);
     }
@@ -990,9 +1013,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
     guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
     guest_end   = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
 
-    dprint(d, 1, "%s: slot %d: guest phys 0x%" PRIx64 " - 0x%" PRIx64 "\n",
-           __FUNCTION__, slot_id,
-           guest_start, guest_end);
+    trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end);
 
     PANIC_ON(slot_id >= NUM_MEMSLOTS);
     PANIC_ON(guest_start > guest_end);
@@ -1039,10 +1060,6 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
     memslot.generation = d->rom->slot_generation = 0;
     qxl_rom_set_dirty(d);
 
-    dprint(d, 1, "%s: slot %d: host virt 0x%lx - 0x%lx\n",
-           __FUNCTION__, memslot.slot_id,
-           memslot.virt_start, memslot.virt_end);
-
     qemu_spice_add_memslot(&d->ssd, &memslot, async);
     d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
     d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
@@ -1052,21 +1069,19 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
 
 static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
 {
-    dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id);
     qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id);
     d->guest_slots[slot_id].active = 0;
 }
 
 static void qxl_reset_memslots(PCIQXLDevice *d)
 {
-    dprint(d, 1, "%s:\n", __FUNCTION__);
     qxl_spice_reset_memslots(d);
     memset(&d->guest_slots, 0, sizeof(d->guest_slots));
 }
 
 static void qxl_reset_surfaces(PCIQXLDevice *d)
 {
-    dprint(d, 1, "%s:\n", __FUNCTION__);
+    trace_qxl_reset_surfaces(d->id);
     d->mode = QXL_MODE_UNDEFINED;
     qxl_spice_destroy_surfaces(d, QXL_SYNC);
 }
@@ -1108,9 +1123,6 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
     assert(qxl->mode != QXL_MODE_NATIVE);
     qxl_exit_vga_mode(qxl);
 
-    dprint(qxl, 1, "%s: %dx%d\n", __FUNCTION__,
-           le32_to_cpu(sc->width), le32_to_cpu(sc->height));
-
     surface.format     = le32_to_cpu(sc->format);
     surface.height     = le32_to_cpu(sc->height);
     surface.mem        = le64_to_cpu(sc->mem);
@@ -1119,6 +1131,10 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
     surface.width      = le32_to_cpu(sc->width);
     surface.type       = le32_to_cpu(sc->type);
     surface.flags      = le32_to_cpu(sc->flags);
+    trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem,
+                                   sc->format, sc->position);
+    trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type,
+                                        sc->flags);
 
     surface.mouse_mode = true;
     surface.group_id   = MEMSLOT_GROUP_GUEST;
@@ -1142,7 +1158,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
     if (d->mode == QXL_MODE_UNDEFINED) {
         return 0;
     }
-    dprint(d, 1, "%s\n", __FUNCTION__);
+    trace_qxl_destroy_primary(d->id);
     d->mode = QXL_MODE_UNDEFINED;
     qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
     qxl_spice_reset_cursor(d);
@@ -1169,8 +1185,8 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
         .mem        = devmem + d->shadow_rom.draw_area_offset,
     };
 
-    dprint(d, 1, "%s: mode %d  [ %d x %d @ %d bpp devmem 0x%" PRIx64 " ]\n",
-           __func__, modenr, mode->x_res, mode->y_res, mode->bits, devmem);
+    trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits,
+                       devmem);
     if (!loadvm) {
         qxl_hard_reset(d, 0);
     }
@@ -1216,8 +1232,8 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
         if (d->mode != QXL_MODE_VGA) {
             break;
         }
-        dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
-            __func__, io_port, io_port_to_string(io_port));
+        trace_qxl_io_unexpected_vga_mode(d->id,
+            io_port, io_port_to_string(io_port));
         /* be nice to buggy guest drivers */
         if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
             io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
@@ -1259,11 +1275,12 @@ async_common:
         }
         d->current_async = orig_io_port;
         qemu_mutex_unlock(&d->async_lock);
-        dprint(d, 2, "start async %d (%"PRId64")\n", io_port, val);
         break;
     default:
         break;
     }
+    trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode), addr, val, size,
+                       async);
 
     switch (io_port) {
     case QXL_IO_UPDATE_AREA:
@@ -1299,7 +1316,6 @@ async_common:
         d->oom_running = 0;
         break;
     case QXL_IO_SET_MODE:
-        dprint(d, 1, "QXL_SET_MODE %d\n", (int)val);
         qxl_set_mode(d, val, 0);
         break;
     case QXL_IO_LOG:
@@ -1309,7 +1325,6 @@ async_common:
         }
         break;
     case QXL_IO_RESET:
-        dprint(d, 1, "QXL_IO_RESET\n");
         qxl_hard_reset(d, 0);
         break;
     case QXL_IO_MEMSLOT_ADD:
@@ -1337,7 +1352,6 @@ async_common:
                           async);
             goto cancel_async;
         }
-        dprint(d, 1, "QXL_IO_CREATE_PRIMARY async=%d\n", async);
         d->guest_primary.surface = d->ram->create_surface;
         qxl_create_guest_primary(d, 0, async);
         break;
@@ -1347,11 +1361,9 @@ async_common:
                           async);
             goto cancel_async;
         }
-        dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async,
-               qxl_mode_to_string(d->mode));
         if (!qxl_destroy_primary(d, async)) {
-            dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n",
-                    qxl_mode_to_string(d->mode));
+            trace_qxl_io_destroy_primary_ignored(d->id,
+                                                 qxl_mode_to_string(d->mode));
             goto cancel_async;
         }
         break;
@@ -1371,16 +1383,9 @@ async_common:
                 ring->prod, ring->cons);
         }
         qxl_push_free_res(d, 1 /* flush */);
-        dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n",
-            qxl_mode_to_string(d->mode), d->guest_surfaces.count,
-            d->num_free_res, d->last_release);
         break;
     }
     case QXL_IO_FLUSH_SURFACES_ASYNC:
-        dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC"
-                     " (%"PRId64") (%s, s#=%d, res#=%d)\n",
-               val, qxl_mode_to_string(d->mode), d->guest_surfaces.count,
-               d->num_free_res);
         qxl_spice_flush_surfaces_async(d);
         break;
     case QXL_IO_DESTROY_ALL_SURFACES:
@@ -1406,7 +1411,7 @@ static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
 {
     PCIQXLDevice *d = opaque;
 
-    dprint(d, 1, "%s: unexpected\n", __FUNCTION__);
+    trace_qxl_io_read_unexpected(d->id);
     return 0xff;
 }
 
@@ -1557,8 +1562,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
         surface_offset -= vram_start;
         surface_size = cmd->u.surface_create.height *
                        abs(cmd->u.surface_create.stride);
-        dprint(qxl, 3, "%s: dirty surface %d, offset %d, size %d\n", __func__,
-               i, (int)surface_offset, surface_size);
+        trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
         qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
     }
 }
@@ -1792,7 +1796,7 @@ static void qxl_pre_save(void *opaque)
     PCIQXLDevice* d = opaque;
     uint8_t *ram_start = d->vga.vram_ptr;
 
-    dprint(d, 1, "%s:\n", __FUNCTION__);
+    trace_qxl_pre_save(d->id);
     if (d->last_release == NULL) {
         d->last_release_offset = 0;
     } else {
@@ -1805,10 +1809,9 @@ static int qxl_pre_load(void *opaque)
 {
     PCIQXLDevice* d = opaque;
 
-    dprint(d, 1, "%s: start\n", __FUNCTION__);
+    trace_qxl_pre_load(d->id);
     qxl_hard_reset(d, 1);
     qxl_exit_vga_mode(d);
-    dprint(d, 1, "%s: done\n", __FUNCTION__);
     return 0;
 }
 
@@ -1820,7 +1823,6 @@ static void qxl_create_memslots(PCIQXLDevice *d)
         if (!d->guest_slots[i].active) {
             continue;
         }
-        dprint(d, 1, "%s: restoring guest slot %d\n", __func__, i);
         qxl_add_memslot(d, i, 0, QXL_SYNC);
     }
 }
@@ -1832,8 +1834,6 @@ static int qxl_post_load(void *opaque, int version)
     QXLCommandExt *cmds;
     int in, out, newmode;
 
-    dprint(d, 1, "%s: start\n", __FUNCTION__);
-
     assert(d->last_release_offset < d->vga.vram_size);
     if (d->last_release_offset == 0) {
         d->last_release = NULL;
@@ -1843,8 +1843,7 @@ static int qxl_post_load(void *opaque, int version)
 
     d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
 
-    dprint(d, 1, "%s: restore mode (%s)\n", __FUNCTION__,
-        qxl_mode_to_string(d->mode));
+    trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode));
     newmode = d->mode;
     d->mode = QXL_MODE_UNDEFINED;
 
@@ -1886,8 +1885,6 @@ static int qxl_post_load(void *opaque, int version)
         qxl_set_mode(d, d->shadow_rom.mode, 1);
         break;
     }
-    dprint(d, 1, "%s: done\n", __FUNCTION__);
-
     return 0;
 }
 
diff --git a/trace-events b/trace-events
index c8317a0..fefd6a0 100644
--- a/trace-events
+++ b/trace-events
@@ -722,3 +722,62 @@ displaysurface_resize(void *display_state, void *display_surface, int width, int
 
 # vga.c
 ppm_save(const char *filename, void *display_surface) "%s surface=%p"
+
+# hw/qxl.c
+disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
+disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
+qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %dx%d mem=%lx %d,%d"
+qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
+qxl_destroy_primary(int qid) "%d"
+qxl_enter_vga_mode(int qid) "%d"
+qxl_exit_vga_mode(int qid) "%d"
+qxl_hard_reset(int qid, int64_t loadvm) "%d loadvm=%"PRId64""
+qxl_interface_async_complete_io(int qid, uint32_t current_async, void *cookie) "%d current=%d cookie=%p"
+qxl_interface_attach_worker(int qid) "%d"
+qxl_interface_get_init_info(int qid) "%d"
+qxl_interface_set_compression_level(int qid, int64_t level) "%d %"PRId64
+qxl_interface_update_area_complete(int qid, uint32_t surface_id, uint32_t dirty_left, uint32_t dirty_right, uint32_t dirty_top, uint32_t dirty_bottom) "%d surface=%d [%d,%d,%d,%d]"
+qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d #=%d"
+qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
+qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
+qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
+qxl_io_read_unexpected(int qid) "%d"
+qxl_io_unexpected_vga_mode(int qid, uint32_t io_port, const char *desc) "%d 0x%x (%s)"
+qxl_io_write(int qid, const char *mode, uint64_t addr, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " val=%"PRIu64" size=%u async=%d"
+qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64
+qxl_post_load(int qid, const char *mode) "%d %s"
+qxl_pre_load(int qid) "%d"
+qxl_pre_save(int qid) "%d"
+qxl_reset_surfaces(int qid) "%d"
+qxl_ring_command_check(int qid, const char *mode) "%d %s"
+qxl_ring_command_get(int qid, const char *mode) "%d %s"
+qxl_ring_command_req_notification(int qid) "%d"
+qxl_ring_cursor_check(int qid, const char *mode) "%d %s"
+qxl_ring_cursor_get(int qid, const char *mode) "%d %s"
+qxl_ring_cursor_req_notification(int qid) "%d"
+qxl_ring_res_push(int qid, const char *mode, uint32_t surface_count, uint32_t free_res, void *last_release, const char *notify) "%d %s s#=%d res#=%d last=%p notify=%s"
+qxl_ring_res_push_rest(int qid, uint32_t ring_has, uint32_t ring_size, uint32_t prod, uint32_t cons) "%d ring %d/%d [%d,%d]"
+qxl_ring_res_put(int qid, uint32_t free_res) "%d #res=%d"
+qxl_set_mode(int qid, int modenr, uint32_t x_res, uint32_t y_res, uint32_t bits, uint64_t devmem) "%d mode=%d [ x=%d y=%d @ bpp=%d devmem=0x%" PRIx64 " ]"
+qxl_soft_reset(int qid) "%d"
+qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d"
+qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u"
+qemu_spice_create_primary_surface(int qid, uint32_t sid, void *surface, int async) "%d sid=%u surface=%p async=%d"
+qemu_spice_destroy_primary_surface(int qid, uint32_t sid, int async) "%d sid=%u async=%d"
+qemu_spice_wakeup(uint32_t qid) "%d"
+qemu_spice_start(uint32_t qid) "%d"
+qemu_spice_stop(uint32_t qid) "%d"
+qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "lr %d -> %d,  tb -> %d -> %d"
+qxl_spice_destroy_surfaces_complete(int qid) "%d"
+qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
+qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
+qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
+qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
+qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
+qxl_spice_oom(int qid) "%d"
+qxl_spice_reset_cursor(int qid) "%d"
+qxl_spice_reset_image_cache(int qid) "%d"
+qxl_spice_reset_memslots(int qid) "%d"
+qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
+qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
+qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
diff --git a/ui/spice-display.c b/ui/spice-display.c
index ab266ae..28d6d4a 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -22,6 +22,7 @@
 #include "monitor.h"
 #include "console.h"
 #include "sysemu.h"
+#include "trace.h"
 
 #include "spice-display.h"
 
@@ -73,6 +74,10 @@ QXLCookie *qxl_cookie_new(int type, uint64_t io)
 void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
                             qxl_async_io async)
 {
+    trace_qemu_spice_add_memslot(ssd->qxl.id, memslot->slot_id,
+                                memslot->virt_start, memslot->virt_end,
+                                async);
+
     if (async != QXL_SYNC) {
         spice_qxl_add_memslot_async(&ssd->qxl, memslot,
                 (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -84,6 +89,7 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
 
 void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid)
 {
+    trace_qemu_spice_del_memslot(ssd->qxl.id, gid, sid);
     ssd->worker->del_memslot(ssd->worker, gid, sid);
 }
 
@@ -91,6 +97,7 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
                                        QXLDevSurfaceCreate *surface,
                                        qxl_async_io async)
 {
+    trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async);
     if (async != QXL_SYNC) {
         spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
                 (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -100,10 +107,10 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
     }
 }
 
-
 void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
                                         uint32_t id, qxl_async_io async)
 {
+    trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async);
     if (async != QXL_SYNC) {
         spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
                 (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
@@ -115,16 +122,19 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
 
 void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
 {
+    trace_qemu_spice_wakeup(ssd->qxl.id);
     ssd->worker->wakeup(ssd->worker);
 }
 
 void qemu_spice_start(SimpleSpiceDisplay *ssd)
 {
+    trace_qemu_spice_start(ssd->qxl.id);
     ssd->worker->start(ssd->worker);
 }
 
 void qemu_spice_stop(SimpleSpiceDisplay *ssd)
 {
+    trace_qemu_spice_stop(ssd->qxl.id);
     ssd->worker->stop(ssd->worker);
 }
 
@@ -142,7 +152,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
         return NULL;
     };
 
-    dprint(2, "%s: lr %d -> %d,  tb -> %d -> %d\n", __FUNCTION__,
+    trace_qemu_spice_create_update(
            ssd->dirty.left, ssd->dirty.right,
            ssd->dirty.top, ssd->dirty.bottom);
 
commit aa3db4236e3bf1786c8cefab2a95e29a9781caff
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Mar 18 13:46:13 2012 +0100

    qxl: init_pipe_signaling: exit on failure
    
    If pipe creation fails, exit, don't log and continue. Fix indentation at
    the same time.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index e17b0e3..26ca893 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1452,16 +1452,17 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
 
 static void init_pipe_signaling(PCIQXLDevice *d)
 {
-   if (pipe(d->pipe) < 0) {
-       dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
-       return;
-   }
-   fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
-   fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
-   fcntl(d->pipe[0], F_SETOWN, getpid());
-
-   qemu_thread_get_self(&d->main);
-   qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
+    if (pipe(d->pipe) < 0) {
+        fprintf(stderr, "%s:%s: qxl pipe creation failed\n",
+                __FILE__, __func__);
+        exit(1);
+    }
+    fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
+    fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
+    fcntl(d->pipe[0], F_SETOWN, getpid());
+
+    qemu_thread_get_self(&d->main);
+    qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
 }
 
 /* graphics console */
commit 6ec5dae5a49f2933dc9b3925d8054eb380a56d88
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Sun Mar 18 09:42:39 2012 +0200

    monitor: fix client_migrate_info error handling
    
    Report QERR_MISSING_PARAMETER when port is missing. Otherwise
    QERR_UNDEFINED_ERROR will occur.
    
    rhbz #795652
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/monitor.c b/monitor.c
index d57e7bf..8f46031 100644
--- a/monitor.c
+++ b/monitor.c
@@ -880,6 +880,11 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict,
             return -1;
         }
 
+        if (port == -1 && tls_port == -1) {
+            qerror_report(QERR_MISSING_PARAMETER, "port/tls-port");
+            return -1;
+        }
+
         ret = qemu_spice_migrate_info(hostname, port, tls_port, subject,
                                       cb, opaque);
         if (ret != 0) {
commit d0638b185c92a3fa8c82c2ef229312e9dbbd555c
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Mar 5 18:22:26 2012 +0100

    spice: set spice uuid and name
    
    This allows a Spice client to identify a VM
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index c1091e1..80535b6 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -19,6 +19,7 @@
 #include <spice-experimental.h>
 
 #include <netdb.h>
+#include "sysemu.h"
 
 #include "qemu-common.h"
 #include "qemu-spice.h"
@@ -688,6 +689,11 @@ void qemu_spice_init(void)
 
     qemu_opt_foreach(opts, add_channel, &tls_port, 0);
 
+#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */
+    spice_server_set_name(spice_server, qemu_name);
+    spice_server_set_uuid(spice_server, qemu_uuid);
+#endif
+
     if (0 != spice_server_init(spice_server, &core_interface)) {
         error_report("failed to initialize spice server");
         exit(1);
commit b71706d122838d9656e1a6dae80e22401babdf37
Author: Jeff Cody <jcody at redhat.com>
Date:   Thu Mar 15 14:26:18 2012 -0400

    qemu-ga: for w32, fix leaked handle ov.hEvent in ga_channel_write()
    
    In the function ga_channel_write(), the handle ov.hEvent is created
    by the call to CreateEvent(). However, the handle is not closed
    prior to the function return.
    
    This patch closes the handle before the return of the function.
    
    Kudos to Paolo Bonzini for spotting this bug.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Acked-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qga/channel-win32.c b/qga/channel-win32.c
index 190251b..16bf44a 100644
--- a/qga/channel-win32.c
+++ b/qga/channel-win32.c
@@ -259,6 +259,10 @@ static GIOStatus ga_channel_write(GAChannel *c, const char *buf, size_t size,
         *count = written;
     }
 
+    if (ov.hEvent) {
+        CloseHandle(ov.hEvent);
+        ov.hEvent = NULL;
+    }
     return status;
 }
 
commit 0c1f781b7c8ddd79ca15c20b59afa2be69d18295
Author: Jason Wang <jasowang at redhat.com>
Date:   Mon Mar 19 11:19:57 2012 +0800

    ioapic: fix build with DEBUG_IOAPIC
    
    ioapic.c:198: error: format ‘%08x’ expects type ‘unsigned int’, but argument 3 has type ‘uint64_t’
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 3fee011..e2e4796 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -195,7 +195,7 @@ ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
         if (size != 4) {
             break;
         }
-        DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
+        DPRINTF("write: %08x = %08" PRIx64 "\n", s->ioregsel, val);
         switch (s->ioregsel) {
         case IOAPIC_REG_ID:
             s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK;
commit 720f9f582533b2274ee2f1dd0337feb983e2d510
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Mar 19 15:58:45 2012 +1100

    .gitignore: add qemu-bridge-helper and option rom build products
    
    This adds a few previously missing generated files to .gitignore: the
    qemu-bridge-helper binary, and more generated versions of the
    linuxboot, multiboot and kvmvapic roms from pc-bios/optionrom.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/.gitignore b/.gitignore
index 81b1510..9859c7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ qemu-img-cmds.texi
 qemu-img-cmds.h
 qemu-io
 qemu-ga
+qemu-bridge-helper
 qemu-monitor.texi
 QMP/qmp-commands.txt
 test-coroutine
@@ -75,9 +76,14 @@ patches
 pc-bios/bios-pq/status
 pc-bios/vgabios-pq/status
 pc-bios/optionrom/linuxboot.bin
+pc-bios/optionrom/linuxboot.raw
+pc-bios/optionrom/linuxboot.img
 pc-bios/optionrom/multiboot.bin
 pc-bios/optionrom/multiboot.raw
+pc-bios/optionrom/multiboot.img
 pc-bios/optionrom/kvmvapic.bin
+pc-bios/optionrom/kvmvapic.raw
+pc-bios/optionrom/kvmvapic.img
 .stgit-*
 cscope.*
 tags
commit 039f835efcc34a89e1d81a726d751b1718b3791c
Author: Joshua Housh <joshua.housh at calxeda.com>
Date:   Tue Mar 13 13:28:47 2012 -0500

    cleanup obsolete typedef
    
    There are no users of i2c_slave.
    
    Signed-off-by: Joshua Housh <joshua.housh at calxeda.com>
    Signed-off-by: Mark Langsdorf <mark.langsdorf at calxeda.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-common.h b/qemu-common.h
index b0fdf5c..c9e96a8 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -236,7 +236,6 @@ typedef struct MACAddr MACAddr;
 typedef struct VLANState VLANState;
 typedef struct VLANClientState VLANClientState;
 typedef struct i2c_bus i2c_bus;
-typedef struct i2c_slave i2c_slave;
 typedef struct ISABus ISABus;
 typedef struct SMBusDevice SMBusDevice;
 typedef struct PCIHostState PCIHostState;
commit c07c163e0e8cd89ab916774064f26a756eee08e9
Author: Jeff Cody <jcody at redhat.com>
Date:   Mon Mar 12 14:13:57 2012 -0400

    monitor: Remove unused bool field 'qapi' in mon_cmd_t struct
    
    Some minor code cleanup: the 'qapi' bool field in mon_cmd_t is
    unused, and can be removed.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/monitor.c b/monitor.c
index d57e7bf..e71a141 100644
--- a/monitor.c
+++ b/monitor.c
@@ -128,7 +128,6 @@ typedef struct mon_cmd_t {
         int  (*cmd_async)(Monitor *mon, const QDict *params,
                           MonitorCompletion *cb, void *opaque);
     } mhandler;
-    bool qapi;
     int flags;
 } mon_cmd_t;
 
commit fbac6a7d35d119a52606c175aface9bcec805f09
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Feb 25 14:50:25 2012 +0100

    ds1338: Add missing break statement
    
    Without the break statement, case 5 sets month and year from the same
    data. This does not look correct.
    
    The missing break was reported by splint.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ds1338.c b/hw/ds1338.c
index 6397f0a..d590d9c 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -100,6 +100,7 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
             break;
         case 5:
             s->now.tm_mon = from_bcd(data & 0x1f) - 1;
+            break;
         case 6:
             s->now.tm_year = from_bcd(data) + 100;
             break;
commit ee032ca146e932ce616aff7762596a10bf24ecac
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Mar 8 22:58:06 2012 +0100

    vnc: Fix packed boolean struct members
    
    This patch fixes warnings reported by splint:
    
    For variables which are packed in a single bit, a signed data type
    like 'int' does not make much sense.
    
    There is no obvious reason why the two values should be packed,
    so I removed the packing and changed the data type to bool
    because both are used as boolean values.
    
    v2:
    
    Some versions of gcc complain after this modification,
    for example gcc (Debian 4.4.5-8) 4.4.5):
    
    ui/vnc-auth-sasl.c: In function ‘vnc_sasl_client_cleanup’:
    ui/vnc-auth-sasl.c:34: error: suggest parentheses around assignment used as truth value
    
    Obviously, the compiler does not like code which does
    bool = unsigned = bool = 0
    
    Splitting that code in three statements works.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index e2045fc..8fba770 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -31,7 +31,9 @@
 void vnc_sasl_client_cleanup(VncState *vs)
 {
     if (vs->sasl.conn) {
-        vs->sasl.runSSF = vs->sasl.waitWriteSSF = vs->sasl.wantSSF = 0;
+        vs->sasl.runSSF = false;
+        vs->sasl.wantSSF = false;
+        vs->sasl.waitWriteSSF = 0;
         vs->sasl.encodedLength = vs->sasl.encodedOffset = 0;
         vs->sasl.encoded = NULL;
         g_free(vs->sasl.username);
diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h
index fd9b18a..ee243a9 100644
--- a/ui/vnc-auth-sasl.h
+++ b/ui/vnc-auth-sasl.h
@@ -37,9 +37,9 @@ typedef struct VncDisplaySASL VncDisplaySASL;
 struct VncStateSASL {
     sasl_conn_t *conn;
     /* If we want to negotiate an SSF layer with client */
-    int wantSSF :1;
+    bool wantSSF;
     /* If we are now running the SSF layer */
-    int runSSF :1;
+    bool runSSF;
     /*
      * If this is non-zero, then wait for that many bytes
      * to be written plain, before switching to SSF encoding
commit b920df5c79f64fe9617ef070cd6bda1738172f84
Author: Chen Yufei <cyfdecyf at gmail.com>
Date:   Wed Mar 7 23:36:43 2012 +0800

    Remove type field in ModuleEntry as it's not used
    
    Signed-off-by: Chen Yufei <cyfdecyf at gmail.com>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/module.c b/module.c
index 106a969..c3a6da7 100644
--- a/module.c
+++ b/module.c
@@ -19,7 +19,6 @@
 
 typedef struct ModuleEntry
 {
-    module_init_type type;
     void (*init)(void);
     QTAILQ_ENTRY(ModuleEntry) node;
 } ModuleEntry;
commit 32b089808f125470b3563bf4209c2301fa35c58e
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Mar 18 18:31:13 2012 +0200

    memory: check for watchpoints when getting code ram_addr
    
    The code to get the ram_addr from a (tlb entry, vaddr) pair
    checks that the resulting memory is not MMIO, but neglects to
    check whether the region is hidden by a watchpoint page.
    
    Add the missing check.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 3c2b7e5..a3818ff 100644
--- a/exec.c
+++ b/exec.c
@@ -4609,7 +4609,8 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
     pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
     mr = iotlb_to_region(pd);
     if (mr != &io_mem_ram && mr != &io_mem_rom
-        && mr != &io_mem_notdirty && !mr->rom_device) {
+        && mr != &io_mem_notdirty && !mr->rom_device
+        && mr != &io_mem_watch) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
         cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
 #else
commit 7859cc6e39bf86f890bb1c72fd9ba41deb6ce2e7
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Mar 14 16:19:39 2012 +0200

    exec: fix write tlb entry misused as iotlb
    
    A couple of code paths check the lower bits of CPUTLBEntry::addr_write
    against io_mem_ram as a way of looking for a dirty RAM page.  This works
    by accident since the value is zero, which matches all clear bits for
    TLB_INVALID, TLB_MMIO, and TLB_NOTDIRTY (indicating dirty RAM).
    
    Make it work by design by checking for the proper bits.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index be392e2..3c2b7e5 100644
--- a/exec.c
+++ b/exec.c
@@ -2031,14 +2031,19 @@ static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
     cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
 }
 
+static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
+{
+    return (tlbe->addr_write & (TLB_INVALID_MASK|TLB_MMIO|TLB_NOTDIRTY)) == 0;
+}
+
 static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
                                          unsigned long start, unsigned long length)
 {
     unsigned long addr;
-    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
+    if (tlb_is_dirty_ram(tlb_entry)) {
         addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
         if ((addr - start) < length) {
-            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
+            tlb_entry->addr_write |= TLB_NOTDIRTY;
         }
     }
 }
@@ -2091,7 +2096,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
     ram_addr_t ram_addr;
     void *p;
 
-    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
+    if (tlb_is_dirty_ram(tlb_entry)) {
         p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
             + tlb_entry->addend);
         ram_addr = qemu_ram_addr_from_host_nofail(p);
commit 46a5801d0cb5f5ed01a4d31c0e7cc581237ed5ce
Merge: e5ab140... 2ae2bce...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 16 13:18:03 2012 -0500

    Merge remote-tracking branch 'kraxel/seabios-1.6.3.2' into staging
    
    * kraxel/seabios-1.6.3.2:
      Update seabios to 1.6.3.2
      Add seabios build scripts to roms/

commit e5ab1404d014cefe22e9a10fca00d0acf4fe412b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 15 11:29:56 2012 -0500

    pci: fix double free of romfile property
    
    The qdev property release function frees any string properties.  This was
    resulting in a double free during hot unplug.
    
    It manifests in network devices because block devices have a NULL romfile
    property by default.
    
    Cc: Michael Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pci.c b/hw/pci.c
index bf046bf..ed8ec99 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -841,7 +841,6 @@ static int pci_unregister_device(DeviceState *dev)
 
     pci_unregister_io_regions(pci_dev);
     pci_del_option_rom(pci_dev);
-    g_free(pci_dev->romfile);
     do_pci_unregister_device(pci_dev);
     return 0;
 }
commit e1c37d0e94048502f9874e6356ce7136d4b05bdb
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Dec 5 14:48:01 2011 -0200

    qapi: Convert migrate
    
    The migrate command is one of those commands where HMP and QMP completely
    mix up together. This made the conversion to the QAPI (which separates the
    command into QMP and HMP parts) a bit difficult.
    
    The first important change to be noticed is that this commit completes the
    removal of the Monitor object from migration code, started by the previous
    commit.
    
    Another important and tricky change is about supporting the non-detached
    mode. That is, if the user doesn't pass '-d' the migrate command will lock
    the monitor and will only release it when migration is finished.
    
    To support this in the new HMP command (hmp_migrate()), it is necessary
    to create a timer which runs every second and checks if the migration is
    still active. If it is, the timer callback will re-schedule itself to run
    one second in the future. If the migration has already finished, the
    monitor lock is released and the user can use it normally.
    
    All these changes should be transparent to the user.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 6980214..bd35a3e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -806,8 +806,7 @@ ETEXI
 		      " full copy of disk\n\t\t\t -i for migration without "
 		      "shared storage with incremental copy of disk "
 		      "(base image shared between src and destination)",
-        .user_print = monitor_user_noop,	
-	.mhandler.cmd_new = do_migrate,
+        .mhandler.cmd = hmp_migrate,
     },
 
 
diff --git a/hmp.c b/hmp.c
index 290c43d..9cf2d13 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,7 @@
  */
 
 #include "hmp.h"
+#include "qemu-timer.h"
 #include "qmp-commands.h"
 
 static void hmp_handle_error(Monitor *mon, Error **errp)
@@ -860,3 +861,76 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
 
     hmp_handle_error(mon, &error);
 }
+
+typedef struct MigrationStatus
+{
+    QEMUTimer *timer;
+    Monitor *mon;
+    bool is_block_migration;
+} MigrationStatus;
+
+static void hmp_migrate_status_cb(void *opaque)
+{
+    MigrationStatus *status = opaque;
+    MigrationInfo *info;
+
+    info = qmp_query_migrate(NULL);
+    if (!info->has_status || strcmp(info->status, "active") == 0) {
+        if (info->has_disk) {
+            int progress;
+
+            if (info->disk->remaining) {
+                progress = info->disk->transferred * 100 / info->disk->total;
+            } else {
+                progress = 100;
+            }
+
+            monitor_printf(status->mon, "Completed %d %%\r", progress);
+            monitor_flush(status->mon);
+        }
+
+        qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock) + 1000);
+    } else {
+        if (status->is_block_migration) {
+            monitor_printf(status->mon, "\n");
+        }
+        monitor_resume(status->mon);
+        qemu_del_timer(status->timer);
+        g_free(status);
+    }
+
+    qapi_free_MigrationInfo(info);
+}
+
+void hmp_migrate(Monitor *mon, const QDict *qdict)
+{
+    int detach = qdict_get_try_bool(qdict, "detach", 0);
+    int blk = qdict_get_try_bool(qdict, "blk", 0);
+    int inc = qdict_get_try_bool(qdict, "inc", 0);
+    const char *uri = qdict_get_str(qdict, "uri");
+    Error *err = NULL;
+
+    qmp_migrate(uri, !!blk, blk, !!inc, inc, false, false, &err);
+    if (err) {
+        monitor_printf(mon, "migrate: %s\n", error_get_pretty(err));
+        error_free(err);
+        return;
+    }
+
+    if (!detach) {
+        MigrationStatus *status;
+
+        if (monitor_suspend(mon) < 0) {
+            monitor_printf(mon, "terminal does not allow synchronous "
+                           "migration, continuing detached\n");
+            return;
+        }
+
+        status = g_malloc0(sizeof(*status));
+        status->mon = mon;
+        status->is_block_migration = blk || inc;
+        status->timer = qemu_new_timer_ms(rt_clock, hmp_migrate_status_cb,
+                                          status);
+        qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock));
+    }
+}
diff --git a/hmp.h b/hmp.h
index 5409464..8807853 100644
--- a/hmp.h
+++ b/hmp.h
@@ -59,5 +59,6 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
 void hmp_block_stream(Monitor *mon, const QDict *qdict);
 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
+void hmp_migrate(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/migration-fd.c b/migration-fd.c
index 5a068c6..50138ed 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -75,7 +75,7 @@ static int fd_close(MigrationState *s)
 
 int fd_start_outgoing_migration(MigrationState *s, const char *fdname)
 {
-    s->fd = monitor_get_fd(s->mon, fdname);
+    s->fd = monitor_get_fd(cur_mon, fdname);
     if (s->fd == -1) {
         DPRINTF("fd_migration: invalid file descriptor identifier\n");
         goto err_after_get_fd;
diff --git a/migration.c b/migration.c
index b21b2df..8c119ba 100644
--- a/migration.c
+++ b/migration.c
@@ -158,16 +158,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
 
 /* shared migration helpers */
 
-static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
-{
-    if (monitor_suspend(mon) == 0) {
-        DPRINTF("suspending monitor\n");
-    } else {
-        monitor_printf(mon, "terminal does not allow synchronous "
-                       "migration, continuing detached\n");
-    }
-}
-
 static int migrate_fd_cleanup(MigrationState *s)
 {
     int ret = 0;
@@ -178,10 +168,6 @@ static int migrate_fd_cleanup(MigrationState *s)
         DPRINTF("closing file\n");
         ret = qemu_fclose(s->file);
         s->file = NULL;
-    } else {
-        if (s->mon) {
-            monitor_resume(s->mon);
-        }
     }
 
     if (s->fd != -1) {
@@ -321,9 +307,6 @@ static int migrate_fd_close(void *opaque)
 {
     MigrationState *s = opaque;
 
-    if (s->mon) {
-        monitor_resume(s->mon);
-    }
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     return s->close(s);
 }
@@ -376,7 +359,7 @@ void migrate_fd_connect(MigrationState *s)
     migrate_fd_put_ready(s);
 }
 
-static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
+static MigrationState *migrate_init(int blk, int inc)
 {
     MigrationState *s = migrate_get_current();
     int64_t bandwidth_limit = s->bandwidth_limit;
@@ -386,18 +369,9 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
     s->blk = blk;
     s->shared = inc;
 
-    /* s->mon is used for two things:
-       - pass fd in fd migration
-       - suspend/resume monitor for not detached migration
-    */
-    s->mon = mon;
     s->bandwidth_limit = bandwidth_limit;
     s->state = MIG_STATE_SETUP;
 
-    if (!detach) {
-        migrate_fd_monitor_suspend(s, mon);
-    }
-
     return s;
 }
 
@@ -413,32 +387,29 @@ void migrate_del_blocker(Error *reason)
     migration_blockers = g_slist_remove(migration_blockers, reason);
 }
 
-int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate(const char *uri, bool has_blk, bool blk,
+                 bool has_inc, bool inc, bool has_detach, bool detach,
+                 Error **errp)
 {
     MigrationState *s = migrate_get_current();
     const char *p;
-    int detach = qdict_get_try_bool(qdict, "detach", 0);
-    int blk = qdict_get_try_bool(qdict, "blk", 0);
-    int inc = qdict_get_try_bool(qdict, "inc", 0);
-    const char *uri = qdict_get_str(qdict, "uri");
     int ret;
 
     if (s->state == MIG_STATE_ACTIVE) {
-        monitor_printf(mon, "migration already in progress\n");
-        return -1;
+        error_set(errp, QERR_MIGRATION_ACTIVE);
+        return;
     }
 
-    if (qemu_savevm_state_blocked(mon)) {
-        return -1;
+    if (qemu_savevm_state_blocked(errp)) {
+        return;
     }
 
     if (migration_blockers) {
-        Error *err = migration_blockers->data;
-        qerror_report_err(err);
-        return -1;
+        *errp = error_copy(migration_blockers->data);
+        return;
     }
 
-    s = migrate_init(mon, detach, blk, inc);
+    s = migrate_init(blk, inc);
 
     if (strstart(uri, "tcp:", &p)) {
         ret = tcp_start_outgoing_migration(s, p);
@@ -451,21 +422,18 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         ret = fd_start_outgoing_migration(s, p);
 #endif
     } else {
-        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
-        ret  = -EINVAL;
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
+        return;
     }
 
     if (ret < 0) {
-        monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
-        return ret;
-    }
-
-    if (detach) {
-        s->mon = NULL;
+        DPRINTF("migration failed: %s\n", strerror(-ret));
+        /* FIXME: we should return meaningful errors */
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     notifier_list_notify(&migration_state_notifiers, s);
-    return 0;
 }
 
 void qmp_migrate_cancel(Error **errp)
diff --git a/migration.h b/migration.h
index 0e44197..691b367 100644
--- a/migration.h
+++ b/migration.h
@@ -26,7 +26,6 @@ struct MigrationState
     int64_t bandwidth_limit;
     QEMUFile *file;
     int fd;
-    Monitor *mon;
     int state;
     int (*get_error)(MigrationState *s);
     int (*close)(MigrationState *s);
@@ -40,8 +39,6 @@ void process_incoming_migration(QEMUFile *f);
 
 int qemu_start_incoming_migration(const char *uri);
 
-int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 uint64_t migrate_max_downtime(void);
 
 void do_info_migrate_print(Monitor *mon, const QObject *data);
diff --git a/qapi-schema.json b/qapi-schema.json
index 04fa84f..3a962c1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1663,3 +1663,24 @@
 { 'command': 'qom-list-types',
   'data': { '*implements': 'str', '*abstract': 'bool' },
   'returns': [ 'ObjectTypeInfo' ] }
+
+##
+# @migrate
+#
+# Migrates the current running guest to another Virtual Machine.
+#
+# @uri: the Uniform Resource Identifier of the destination VM
+#
+# @blk: #optional do block migration (full disk copy)
+#
+# @inc: #optional incremental disk copy migration
+#
+# @detach: this argument exists only for compatibility reasons and
+#          is ignored by QEMU
+#
+# Returns: nothing on success
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate',
+  'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index dfe8a5b..8b82038 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -446,14 +446,7 @@ EQMP
     {
         .name       = "migrate",
         .args_type  = "detach:-d,blk:-b,inc:-i,uri:s",
-        .params     = "[-d] [-b] [-i] uri",
-        .help       = "migrate to URI (using -d to not wait for completion)"
-		      "\n\t\t\t -b for migration without shared storage with"
-		      " full copy of disk\n\t\t\t -i for migration without "
-		      "shared storage with incremental copy of disk "
-		      "(base image shared between src and destination)",
-        .user_print = monitor_user_noop,	
-	.mhandler.cmd_new = do_migrate,
+        .mhandler.cmd_new = qmp_marshal_input_migrate,
     },
 
 SQMP
diff --git a/savevm.c b/savevm.c
index 70f5c4f..5fdc3e1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1540,14 +1540,13 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
 #define QEMU_VM_SECTION_FULL         0x04
 #define QEMU_VM_SUBSECTION           0x05
 
-bool qemu_savevm_state_blocked(Monitor *mon)
+bool qemu_savevm_state_blocked(Error **errp)
 {
     SaveStateEntry *se;
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->no_migrate) {
-            monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
-                           se->idstr);
+            error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr);
             return true;
         }
     }
@@ -1698,11 +1697,11 @@ void qemu_savevm_state_cancel(QEMUFile *f)
     }
 }
 
-static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
+static int qemu_savevm_state(QEMUFile *f)
 {
     int ret;
 
-    if (qemu_savevm_state_blocked(mon)) {
+    if (qemu_savevm_state_blocked(NULL)) {
         ret = -EINVAL;
         goto out;
     }
@@ -1836,7 +1835,7 @@ int qemu_loadvm_state(QEMUFile *f)
     unsigned int v;
     int ret;
 
-    if (qemu_savevm_state_blocked(default_mon)) {
+    if (qemu_savevm_state_blocked(NULL)) {
         return -EINVAL;
     }
 
@@ -2080,7 +2079,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "Could not open VM state file\n");
         goto the_end;
     }
-    ret = qemu_savevm_state(mon, f);
+    ret = qemu_savevm_state(f);
     vm_state_size = qemu_ftell(f);
     qemu_fclose(f);
     if (ret < 0) {
diff --git a/sysemu.h b/sysemu.h
index 29b0e96..bc2c788 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -76,7 +76,7 @@ void do_info_snapshots(Monitor *mon);
 
 void qemu_announce_self(void);
 
-bool qemu_savevm_state_blocked(Monitor *mon);
+bool qemu_savevm_state_blocked(Error **errp);
 int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared);
 int qemu_savevm_state_iterate(QEMUFile *f);
 int qemu_savevm_state_complete(QEMUFile *f);
commit 539de1246d355d3b8aa33fb7cde732352d8827c7
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Dec 5 14:06:56 2011 -0200

    Purge migration of (almost) everything to do with monitors
    
    The Monitor object is passed back and forth within the migration/savevm
    code so that it can print errors and progress to the user.
    
    However, that approach assumes a HMP monitor, being completely invalid
    in QMP.
    
    This commit drops almost every single usage of the Monitor object, all
    monitor_printf() calls have been converted into DPRINTF() ones.
    
    There are a few remaining Monitor objects, those are going to be dropped
    by the next commit.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index a95ef49..595badf 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -260,7 +260,7 @@ static void sort_ram_list(void)
     g_free(blocks);
 }
 
-int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
+int ram_save_live(QEMUFile *f, int stage, void *opaque)
 {
     ram_addr_t addr;
     uint64_t bytes_transferred_last;
diff --git a/block-migration.c b/block-migration.c
index 4467468..fd2ffff 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -18,7 +18,6 @@
 #include "hw/hw.h"
 #include "qemu-queue.h"
 #include "qemu-timer.h"
-#include "monitor.h"
 #include "block-migration.h"
 #include "migration.h"
 #include "blockdev.h"
@@ -204,8 +203,7 @@ static void blk_mig_read_cb(void *opaque, int ret)
     assert(block_mig_state.submitted >= 0);
 }
 
-static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
-                                BlkMigDevState *bmds)
+static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
 {
     int64_t total_sectors = bmds->total_sectors;
     int64_t cur_sector = bmds->cur_sector;
@@ -272,7 +270,6 @@ static void set_dirty_tracking(int enable)
 
 static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
 {
-    Monitor *mon = opaque;
     BlkMigDevState *bmds;
     int64_t sectors;
 
@@ -295,19 +292,17 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
         block_mig_state.total_sector_sum += sectors;
 
         if (bmds->shared_base) {
-            monitor_printf(mon, "Start migration for %s with shared base "
-                                "image\n",
-                           bs->device_name);
+            DPRINTF("Start migration for %s with shared base image\n",
+                    bs->device_name);
         } else {
-            monitor_printf(mon, "Start full migration for %s\n",
-                           bs->device_name);
+            DPRINTF("Start full migration for %s\n", bs->device_name);
         }
 
         QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
     }
 }
 
-static void init_blk_migration(Monitor *mon, QEMUFile *f)
+static void init_blk_migration(QEMUFile *f)
 {
     block_mig_state.submitted = 0;
     block_mig_state.read_done = 0;
@@ -318,10 +313,10 @@ static void init_blk_migration(Monitor *mon, QEMUFile *f)
     block_mig_state.total_time = 0;
     block_mig_state.reads = 0;
 
-    bdrv_iterate(init_blk_migration_it, mon);
+    bdrv_iterate(init_blk_migration_it, NULL);
 }
 
-static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
+static int blk_mig_save_bulked_block(QEMUFile *f)
 {
     int64_t completed_sector_sum = 0;
     BlkMigDevState *bmds;
@@ -330,7 +325,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
 
     QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
         if (bmds->bulk_completed == 0) {
-            if (mig_save_device_bulk(mon, f, bmds) == 1) {
+            if (mig_save_device_bulk(f, bmds) == 1) {
                 /* completed bulk section for this device */
                 bmds->bulk_completed = 1;
             }
@@ -352,8 +347,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
         block_mig_state.prev_progress = progress;
         qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
                          | BLK_MIG_FLAG_PROGRESS);
-        monitor_printf(mon, "Completed %d %%\r", progress);
-        monitor_flush(mon);
+        DPRINTF("Completed %d %%\r", progress);
     }
 
     return ret;
@@ -368,8 +362,8 @@ static void blk_mig_reset_dirty_cursor(void)
     }
 }
 
-static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
-                                 BlkMigDevState *bmds, int is_async)
+static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
+                                 int is_async)
 {
     BlkMigBlock *blk;
     int64_t total_sectors = bmds->total_sectors;
@@ -428,20 +422,20 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
     return (bmds->cur_dirty >= bmds->total_sectors);
 
 error:
-    monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector);
+    DPRINTF("Error reading sector %" PRId64 "\n", sector);
     qemu_file_set_error(f, ret);
     g_free(blk->buf);
     g_free(blk);
     return 0;
 }
 
-static int blk_mig_save_dirty_block(Monitor *mon, QEMUFile *f, int is_async)
+static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
 {
     BlkMigDevState *bmds;
     int ret = 0;
 
     QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        if (mig_save_device_dirty(mon, f, bmds, is_async) == 0) {
+        if (mig_save_device_dirty(f, bmds, is_async) == 0) {
             ret = 1;
             break;
         }
@@ -520,7 +514,7 @@ static int is_stage2_completed(void)
     return 0;
 }
 
-static void blk_mig_cleanup(Monitor *mon)
+static void blk_mig_cleanup(void)
 {
     BlkMigDevState *bmds;
     BlkMigBlock *blk;
@@ -540,11 +534,9 @@ static void blk_mig_cleanup(Monitor *mon)
         g_free(blk->buf);
         g_free(blk);
     }
-
-    monitor_printf(mon, "\n");
 }
 
-static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
+static int block_save_live(QEMUFile *f, int stage, void *opaque)
 {
     int ret;
 
@@ -552,7 +544,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
             stage, block_mig_state.submitted, block_mig_state.transferred);
 
     if (stage < 0) {
-        blk_mig_cleanup(mon);
+        blk_mig_cleanup();
         return 0;
     }
 
@@ -563,7 +555,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
-        init_blk_migration(mon, f);
+        init_blk_migration(f);
 
         /* start track dirty blocks */
         set_dirty_tracking(1);
@@ -573,7 +565,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     ret = qemu_file_get_error(f);
     if (ret) {
-        blk_mig_cleanup(mon);
+        blk_mig_cleanup();
         return ret;
     }
 
@@ -586,12 +578,12 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
                qemu_file_get_rate_limit(f)) {
             if (block_mig_state.bulk_completed == 0) {
                 /* first finish the bulk phase */
-                if (blk_mig_save_bulked_block(mon, f) == 0) {
+                if (blk_mig_save_bulked_block(f) == 0) {
                     /* finished saving bulk on all devices */
                     block_mig_state.bulk_completed = 1;
                 }
             } else {
-                if (blk_mig_save_dirty_block(mon, f, 1) == 0) {
+                if (blk_mig_save_dirty_block(f, 1) == 0) {
                     /* no more dirty blocks */
                     break;
                 }
@@ -602,7 +594,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
         ret = qemu_file_get_error(f);
         if (ret) {
-            blk_mig_cleanup(mon);
+            blk_mig_cleanup();
             return ret;
         }
     }
@@ -612,8 +604,8 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
            all async read completed */
         assert(block_mig_state.submitted == 0);
 
-        while (blk_mig_save_dirty_block(mon, f, 0) != 0);
-        blk_mig_cleanup(mon);
+        while (blk_mig_save_dirty_block(f, 0) != 0);
+        blk_mig_cleanup();
 
         /* report completion */
         qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
@@ -623,7 +615,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
             return ret;
         }
 
-        monitor_printf(mon, "Block migration completed\n");
+        DPRINTF("Block migration completed\n");
     }
 
     qemu_put_be64(f, BLK_MIG_FLAG_EOS);
diff --git a/migration.c b/migration.c
index 00fa1e3..b21b2df 100644
--- a/migration.c
+++ b/migration.c
@@ -258,7 +258,7 @@ static void migrate_fd_put_ready(void *opaque)
     }
 
     DPRINTF("iterate\n");
-    ret = qemu_savevm_state_iterate(s->mon, s->file);
+    ret = qemu_savevm_state_iterate(s->file);
     if (ret < 0) {
         migrate_fd_error(s);
     } else if (ret == 1) {
@@ -267,7 +267,7 @@ static void migrate_fd_put_ready(void *opaque)
         DPRINTF("done iterating\n");
         vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
 
-        if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
+        if (qemu_savevm_state_complete(s->file) < 0) {
             migrate_fd_error(s);
         } else {
             migrate_fd_completed(s);
@@ -289,7 +289,7 @@ static void migrate_fd_cancel(MigrationState *s)
 
     s->state = MIG_STATE_CANCELLED;
     notifier_list_notify(&migration_state_notifiers, s);
-    qemu_savevm_state_cancel(s->mon, s->file);
+    qemu_savevm_state_cancel(s->file);
 
     migrate_fd_cleanup(s);
 }
@@ -367,7 +367,7 @@ void migrate_fd_connect(MigrationState *s)
                                       migrate_fd_close);
 
     DPRINTF("beginning savevm\n");
-    ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
+    ret = qemu_savevm_state_begin(s->file, s->blk, s->shared);
     if (ret < 0) {
         DPRINTF("failed, %d\n", ret);
         migrate_fd_error(s);
diff --git a/migration.h b/migration.h
index 372b066..0e44197 100644
--- a/migration.h
+++ b/migration.h
@@ -78,7 +78,7 @@ uint64_t ram_bytes_remaining(void);
 uint64_t ram_bytes_transferred(void);
 uint64_t ram_bytes_total(void);
 
-int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
+int ram_save_live(QEMUFile *f, int stage, void *opaque);
 int ram_load(QEMUFile *f, void *opaque, int version_id);
 
 /**
diff --git a/savevm.c b/savevm.c
index 80be1ff..70f5c4f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1554,8 +1554,7 @@ bool qemu_savevm_state_blocked(Monitor *mon)
     return false;
 }
 
-int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
-                            int shared)
+int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared)
 {
     SaveStateEntry *se;
     int ret;
@@ -1588,15 +1587,15 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
         qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);
 
-        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
+        ret = se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
         if (ret < 0) {
-            qemu_savevm_state_cancel(mon, f);
+            qemu_savevm_state_cancel(f);
             return ret;
         }
     }
     ret = qemu_file_get_error(f);
     if (ret != 0) {
-        qemu_savevm_state_cancel(mon, f);
+        qemu_savevm_state_cancel(f);
     }
 
     return ret;
@@ -1609,7 +1608,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
  *   0 : We haven't finished, caller have to go again
  *   1 : We have finished, we can go to complete phase
  */
-int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
+int qemu_savevm_state_iterate(QEMUFile *f)
 {
     SaveStateEntry *se;
     int ret = 1;
@@ -1622,7 +1621,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
         qemu_put_byte(f, QEMU_VM_SECTION_PART);
         qemu_put_be32(f, se->section_id);
 
-        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
+        ret = se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
         if (ret <= 0) {
             /* Do not proceed to the next vmstate before this one reported
                completion of the current stage. This serializes the migration
@@ -1636,12 +1635,12 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
     }
     ret = qemu_file_get_error(f);
     if (ret != 0) {
-        qemu_savevm_state_cancel(mon, f);
+        qemu_savevm_state_cancel(f);
     }
     return ret;
 }
 
-int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
+int qemu_savevm_state_complete(QEMUFile *f)
 {
     SaveStateEntry *se;
     int ret;
@@ -1656,7 +1655,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
         qemu_put_byte(f, QEMU_VM_SECTION_END);
         qemu_put_be32(f, se->section_id);
 
-        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
+        ret = se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
         if (ret < 0) {
             return ret;
         }
@@ -1688,13 +1687,13 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
     return qemu_file_get_error(f);
 }
 
-void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
+void qemu_savevm_state_cancel(QEMUFile *f)
 {
     SaveStateEntry *se;
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->save_live_state) {
-            se->save_live_state(mon, f, -1, se->opaque);
+            se->save_live_state(f, -1, se->opaque);
         }
     }
 }
@@ -1708,17 +1707,17 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
         goto out;
     }
 
-    ret = qemu_savevm_state_begin(mon, f, 0, 0);
+    ret = qemu_savevm_state_begin(f, 0, 0);
     if (ret < 0)
         goto out;
 
     do {
-        ret = qemu_savevm_state_iterate(mon, f);
+        ret = qemu_savevm_state_iterate(f);
         if (ret < 0)
             goto out;
     } while (ret == 0);
 
-    ret = qemu_savevm_state_complete(mon, f);
+    ret = qemu_savevm_state_complete(f);
 
 out:
     if (ret == 0) {
diff --git a/sysemu.h b/sysemu.h
index 98118cc..29b0e96 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -77,11 +77,10 @@ void do_info_snapshots(Monitor *mon);
 void qemu_announce_self(void);
 
 bool qemu_savevm_state_blocked(Monitor *mon);
-int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
-                            int shared);
-int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
-int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
-void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
+int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared);
+int qemu_savevm_state_iterate(QEMUFile *f);
+int qemu_savevm_state_complete(QEMUFile *f);
+void qemu_savevm_state_cancel(QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f);
 
 /* SLIRP */
diff --git a/vmstate.h b/vmstate.h
index 9d3c49c..82d97ae 100644
--- a/vmstate.h
+++ b/vmstate.h
@@ -28,8 +28,7 @@
 
 typedef void SaveSetParamsHandler(int blk_enable, int shared, void * opaque);
 typedef void SaveStateHandler(QEMUFile *f, void *opaque);
-typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
-                                 void *opaque);
+typedef int SaveLiveStateHandler(QEMUFile *f, int stage, void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
 int register_savevm(DeviceState *dev,
commit 79020cfcbb78a85768174bb93ee3b7cfc6ffa353
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Dec 5 16:04:05 2011 -0200

    Error: Introduce error_copy()
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/error.c b/error.c
index 990050f..d3455ab 100644
--- a/error.c
+++ b/error.c
@@ -43,6 +43,19 @@ void error_set(Error **errp, const char *fmt, ...)
     *errp = err;
 }
 
+Error *error_copy(const Error *err)
+{
+    Error *err_new;
+
+    err_new = g_malloc0(sizeof(*err));
+    err_new->msg = g_strdup(err->msg);
+    err_new->fmt = err->fmt;
+    err_new->obj = err->obj;
+    QINCREF(err_new->obj);
+
+    return err_new;
+}
+
 bool error_is_set(Error **errp)
 {
     return (errp && *errp);
diff --git a/error.h b/error.h
index 6361f40..45ff6c1 100644
--- a/error.h
+++ b/error.h
@@ -35,6 +35,11 @@ void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
 bool error_is_set(Error **err);
 
 /**
+ * Returns an exact copy of the error passed as an argument.
+ */
+Error *error_copy(const Error *err);
+
+/**
  * Get a human readable representation of an error object.
  */
 const char *error_get_pretty(Error *err);
commit a4acc064f7054877aeffe0ea27a492b15086b833
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Dec 2 14:58:12 2011 -0200

    QError: Introduce new errors for the migration command
    
    The new errors are QERR_MIGRATION_ACTIVE and QERR_MIGRATION_NOT_SUPPORTED,
    which are going to be used by the QAPI converted migration command.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index f55d435..41c729a 100644
--- a/qerror.c
+++ b/qerror.c
@@ -193,6 +193,14 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Using KVM without %(capability), %(feature) unavailable",
     },
     {
+        .error_fmt = QERR_MIGRATION_ACTIVE,
+        .desc      = "There's a migration process in progress",
+    },
+    {
+        .error_fmt = QERR_MIGRATION_NOT_SUPPORTED,
+        .desc      = "State blocked by non-migratable device '%(device)'",
+    },
+    {
         .error_fmt = QERR_MIGRATION_EXPECTED,
         .desc      = "An incoming migration is expected before this command can be executed",
     },
diff --git a/qerror.h b/qerror.h
index e26c635..e16f9c2 100644
--- a/qerror.h
+++ b/qerror.h
@@ -166,6 +166,12 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_KVM_MISSING_CAP \
     "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
 
+#define QERR_MIGRATION_ACTIVE \
+    "{ 'class': 'MigrationActive', 'data': {} }"
+
+#define QERR_MIGRATION_NOT_SUPPORTED \
+    "{ 'class': 'MigrationNotSupported', 'data': {'device': %s} }"
+
 #define QERR_MIGRATION_EXPECTED \
     "{ 'class': 'MigrationExpected', 'data': {} }"
 
commit 695bb854e88be20756d5e509e02e28f94528b776
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Tue Jan 24 12:04:42 2012 +0000

    cirrus_vga: do not reset videoram
    
    There is no need to set the videoram to 0xff in cirrus_reset, because it
    is the BIOS' job.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Reviewed-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 4edcb94..afedaa4 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2767,10 +2767,6 @@ static void cirrus_reset(void *opaque)
     }
     s->vga.cr[0x27] = s->device_id;
 
-    /* Win2K seems to assume that the pattern buffer is at 0xff
-       initially ! */
-    memset(s->vga.vram_ptr, 0xff, s->real_vram_size);
-
     s->cirrus_hidden_dac_lockindex = 5;
     s->cirrus_hidden_dac_data = 0;
 }
commit 2ae2bce744f1fa1fd9a8d851c57e37c0ac959eb1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 12 14:00:24 2012 +0100

    Update seabios to 1.6.3.2
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 41e2b38..e1f3923 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/roms/seabios b/roms/seabios
index 80d11e8..2e8bd61 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 80d11e8577bf03e98f2eb1b0cb3a281ab2879c9e
+Subproject commit 2e8bd611ce4e1e36b5a80c9ca6e256e23802f095
commit b1c0d031c452bddfdedf33c5fa2ab2cc2b4a5ea0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 9 10:40:31 2012 +0100

    Add seabios build scripts to roms/
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
new file mode 100644
index 0000000..0114e6f
--- /dev/null
+++ b/roms/Makefile
@@ -0,0 +1,10 @@
+
+default:
+	@echo "nothing is build by default"
+	@echo "available build targets:"
+	@echo "  bios           -- update bios.bin (seabios)"
+
+bios: config.seabios
+	sh configure-seabios.sh $<
+	make -C seabios out/bios.bin
+	cp seabios/out/bios.bin ../pc-bios/bios.bin
diff --git a/roms/config.seabios b/roms/config.seabios
new file mode 100644
index 0000000..c373b87
--- /dev/null
+++ b/roms/config.seabios
@@ -0,0 +1 @@
+# empty, default config works for us
diff --git a/roms/configure-seabios.sh b/roms/configure-seabios.sh
new file mode 100755
index 0000000..98f59a2
--- /dev/null
+++ b/roms/configure-seabios.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+config="$1"
+make -C seabios clean distclean
+cp "$config" seabios/.config
+make -C seabios oldnoconfig


More information about the Spice-commits mailing list