qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/15] Make migration work with hotplug
@ 2010-06-24  4:40 Alex Williamson
  2010-06-24  4:40 ` [Qemu-devel] [PATCH 01/15] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
                   ` (17 more replies)
  0 siblings, 18 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Ok, new approach.  I'm going to attempt to extract myself for the
canonical device path approach, because we're missing too many pieces
to make that work.  Instead, I'll take Anthony's advice and try to
simplify.  We still want a unique name for ramblocks and savevm, but
the hotplug problem today is only for PCI devices.  PCI conveniently
has globally unique, dare I say canonical, addressing in the form of
<domain>:<bus>:<device>.<func>.  To get to this, let's add a new
function on the BusInfo structure called get_dev_path().  For a PCI
device, we can simply traverse up the qdev tree to the BusInfo
structure, look for the function, and call it to return a global PCI
address.

For some buses, these functions could chain up to their parent bus
appending strings together to get a unique path.  An example would be
USB, where the USB port number may not be unique.  If we traverse up
to the PCI device providing USB, and then to the PCI bus, we get a
globally unique PCI path, appended with a USB port number.

To make this work for ramblocks and savevm, we need a DeviceState
pointer when the they are create/registered, and we need a caller
provided context in case there are multiple ramblocks/savevm
associated with a device.  Savevm already provies the context,
and I've attempted to make reasonable guesses at these for the
ramblocks.  Note that most of the ramblocks aren't associated with
a device, so I don't think it makes sense to link savevm and
ramblocks together with the same absolute id string.

Once we have savevm with unique id strings, rather than hotplug
unfriendly instance numbers, we can be sure that the right driver
instance is loading the correct vmstate.  I've also implemented
a compat field for this, so we can still accept incoming migrations
from previous versions.

Once we have ramblocks with a unique id string, we can switch to
using id + offset for migration, which enables a ram_addr_t space
that supports gaps, which enables us to implement qemu_ram_free().  
With that, I think we can finally do migrations reliable after
hotplug!  Note that the target VM still needs to be created to
match the current devices and bus addresses of the source VM.  We
can also still maintain compatibility for migrations here by bumping
the ram migration version and supporting both new and old (just
hope the source hasn't done any hotplugs).

Sound reasonable?  Is get_dev_path the right name?  In the right
place?  The PCI return is currently "dddd:bb:dd.f", should this be
"PCI:dddd:bb:dd.f"?  Something else?  Thanks,

Alex

---

Alex Williamson (15):
      ramblocks: No more being lazy about duplicate names
      pci: Free the space allocated for the option rom on removal
      qemu_ram_free: Implement it
      savevm: Create a new continue flag to avoid resending block name
      savevm: Use RAM blocks for basis of migration
      savevm: Migrate RAM based on name/offset
      ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
      qemu_ram_alloc: Add DeviceState and name parameters
      virtio-net: Incorporate a DeviceState pointer and let savevm track instances
      eepro100: Add a dev field to eeprom new/free functions
      savevm: Make use of DeviceState
      savevm: Add DeviceState param
      pci: Implement BusInfo.get_dev_path()
      qdev: Add a get_dev_path() function to BusInfo
      Remove uses of ram.last_offset (aka last_ram_offset)


 arch_init.c                   |  183 +++++++++++++++++++++++++++++++++++------
 audio/audio.c                 |    2 
 block-migration.c             |    4 -
 cpu-all.h                     |    5 +
 cpu-common.h                  |    2 
 exec.c                        |   96 +++++++++++++++++++---
 hw/adb.c                      |    4 -
 hw/ads7846.c                  |    2 
 hw/an5206.c                   |    4 -
 hw/arm_gic.c                  |    2 
 hw/arm_timer.c                |    4 -
 hw/armv7m.c                   |    9 +-
 hw/armv7m_nvic.c              |    2 
 hw/axis_dev88.c               |    4 -
 hw/cirrus_vga.c               |    2 
 hw/cuda.c                     |    2 
 hw/dma.c                      |    4 -
 hw/dummy_m68k.c               |    2 
 hw/eepro100.c                 |    8 +-
 hw/eeprom93xx.c               |    8 +-
 hw/eeprom93xx.h               |    4 -
 hw/etraxfs.c                  |    6 +
 hw/fw_cfg.c                   |    2 
 hw/g364fb.c                   |    4 -
 hw/grackle_pci.c              |    4 -
 hw/gt64xxx.c                  |    3 -
 hw/gumstix.c                  |    6 +
 hw/heathrow_pic.c             |    2 
 hw/hw.h                       |   18 ++--
 hw/i2c.c                      |    2 
 hw/i8254.c                    |    2 
 hw/i8259.c                    |    2 
 hw/ide/cmd646.c               |    2 
 hw/ide/isa.c                  |    2 
 hw/ide/macio.c                |    2 
 hw/ide/microdrive.c           |    2 
 hw/ide/mmio.c                 |    2 
 hw/ide/piix.c                 |    2 
 hw/integratorcp.c             |    4 -
 hw/m48t59.c                   |    2 
 hw/mac_dbdma.c                |    2 
 hw/mac_nvram.c                |    4 -
 hw/mainstone.c                |    6 +
 hw/max111x.c                  |    3 -
 hw/mcf5208.c                  |    4 -
 hw/mips_jazz.c                |    4 -
 hw/mips_malta.c               |    4 -
 hw/mips_mipssim.c             |    4 -
 hw/mips_r4k.c                 |    6 +
 hw/mipsnet.c                  |    4 -
 hw/mst_fpga.c                 |    3 -
 hw/musicpal.c                 |   11 ++
 hw/nand.c                     |    2 
 hw/omap1.c                    |    6 +
 hw/omap2.c                    |    6 +
 hw/omap_sx1.c                 |   12 ++-
 hw/onenand.c                  |    2 
 hw/openpic.c                  |    5 +
 hw/palm.c                     |    3 -
 hw/pc.c                       |    8 +-
 hw/pci.c                      |   34 +++++++-
 hw/pckbd.c                    |    2 
 hw/petalogix_s3adsp1800_mmu.c |    7 +-
 hw/piix4.c                    |    2 
 hw/pl011.c                    |    2 
 hw/pl022.c                    |    2 
 hw/pl061.c                    |    2 
 hw/ppc405_boards.c            |   18 ++--
 hw/ppc405_uc.c                |    2 
 hw/ppc4xx_devs.c              |    4 +
 hw/ppc4xx_pci.c               |    4 -
 hw/ppc_newworld.c             |    6 +
 hw/ppc_oldworld.c             |    6 +
 hw/ppc_prep.c                 |    4 -
 hw/ppce500_mpc8544ds.c        |    3 -
 hw/ppce500_pci.c              |    4 -
 hw/ps2.c                      |    4 -
 hw/pxa2xx.c                   |   39 +++++----
 hw/pxa2xx_dma.c               |    2 
 hw/pxa2xx_gpio.c              |    2 
 hw/pxa2xx_keypad.c            |    2 
 hw/pxa2xx_lcd.c               |    2 
 hw/pxa2xx_mmci.c              |    2 
 hw/pxa2xx_pic.c               |    3 -
 hw/pxa2xx_timer.c             |    2 
 hw/qdev.c                     |    4 -
 hw/qdev.h                     |    3 +
 hw/r2d.c                      |    4 -
 hw/rc4030.c                   |    2 
 hw/realview.c                 |    6 +
 hw/s390-virtio.c              |    2 
 hw/serial.c                   |    4 -
 hw/sm501.c                    |    2 
 hw/spitz.c                    |   11 +-
 hw/ssd0323.c                  |    3 -
 hw/ssi-sd.c                   |    2 
 hw/stellaris.c                |   11 +-
 hw/stellaris_enet.c           |    4 -
 hw/stellaris_input.c          |    2 
 hw/sun4m.c                    |    8 +-
 hw/sun4u.c                    |    4 -
 hw/syborg.c                   |    2 
 hw/syborg_fb.c                |    2 
 hw/syborg_interrupt.c         |    3 -
 hw/syborg_keyboard.c          |    2 
 hw/syborg_pointer.c           |    2 
 hw/syborg_rtc.c               |    3 -
 hw/syborg_serial.c            |    2 
 hw/syborg_timer.c             |    2 
 hw/tc6393xb.c                 |    2 
 hw/tcx.c                      |    2 
 hw/tosa.c                     |    2 
 hw/tsc2005.c                  |    2 
 hw/tsc210x.c                  |    4 -
 hw/unin_pci.c                 |    6 +
 hw/versatilepb.c              |    2 
 hw/vga-isa-mm.c               |    2 
 hw/vga-isa.c                  |    2 
 hw/vga.c                      |    2 
 hw/virtio-balloon.c           |    3 -
 hw/virtio-blk.c               |    2 
 hw/virtio-net.c               |    7 +-
 hw/virtio-serial-bus.c        |    2 
 hw/vmmouse.c                  |    2 
 hw/vmware_vga.c               |    4 -
 hw/zaurus.c                   |    2 
 qemu-timer.c                  |    2 
 savevm.c                      |  106 +++++++++++++++++++++---
 slirp/slirp.c                 |    5 +
 vl.c                          |    2 
 130 files changed, 648 insertions(+), 286 deletions(-)

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 01/15] Remove uses of ram.last_offset (aka last_ram_offset)
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
@ 2010-06-24  4:40 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 02/15] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

We currently need this either to allocate the next ram_addr_t for a
new block, or for total memory to be migrated.  Both of which we can
calculate without need of this to keep us in a contiguous address space.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   23 ++++++++++++++++-------
 cpu-all.h   |    1 -
 exec.c      |   19 ++++++++++++++-----
 3 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index eb5b67c..109dcef 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -108,9 +108,10 @@ static int ram_save_block(QEMUFile *f)
     static ram_addr_t current_addr = 0;
     ram_addr_t saved_addr = current_addr;
     ram_addr_t addr = 0;
+    uint64_t total_ram = ram_bytes_total();
     int bytes_sent = 0;
 
-    while (addr < ram_list.last_offset) {
+    while (addr < total_ram) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
 
@@ -133,7 +134,7 @@ static int ram_save_block(QEMUFile *f)
             break;
         }
         addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % ram_list.last_offset;
+        current_addr = (saved_addr + addr) % total_ram;
     }
 
     return bytes_sent;
@@ -145,8 +146,9 @@ static ram_addr_t ram_save_remaining(void)
 {
     ram_addr_t addr;
     ram_addr_t count = 0;
+    uint64_t total_ram = ram_bytes_total();
 
-    for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
+    for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
         if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
             count++;
         }
@@ -167,7 +169,13 @@ uint64_t ram_bytes_transferred(void)
 
 uint64_t ram_bytes_total(void)
 {
-    return ram_list.last_offset;
+    RAMBlock *block;
+    uint64_t total = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        total += block->length;
+
+    return total;
 }
 
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
@@ -188,10 +196,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
+        for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
             if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
                 cpu_physical_memory_set_dirty(addr);
             }
@@ -200,7 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, ram_list.last_offset | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -259,7 +268,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != ram_list.last_offset) {
+            if (addr != ram_bytes_total()) {
                 return -EINVAL;
             }
         }
diff --git a/cpu-all.h b/cpu-all.h
index e31c2de..dbb2139 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -870,7 +870,6 @@ typedef struct RAMBlock {
 
 typedef struct RAMList {
     uint8_t *phys_dirty;
-    ram_addr_t last_offset;
     QLIST_HEAD(ram, RAMBlock) blocks;
 } RAMList;
 extern RAMList ram_list;
diff --git a/exec.c b/exec.c
index 7f64384..058b709 100644
--- a/exec.c
+++ b/exec.c
@@ -2765,6 +2765,17 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 }
 #endif
 
+static ram_addr_t find_ram_offset(ram_addr_t size)
+{
+    RAMBlock *block;
+    ram_addr_t last = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        last = MAX(last, block->offset + block->length);
+
+    return last;
+}
+
 ram_addr_t qemu_ram_alloc(ram_addr_t size)
 {
     RAMBlock *new_block;
@@ -2798,18 +2809,16 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
         madvise(new_block->host, size, MADV_MERGEABLE);
 #endif
     }
-    new_block->offset = ram_list.last_offset;
+    new_block->offset = find_ram_offset(size);
     new_block->length = size;
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
-        (ram_list.last_offset + size) >> TARGET_PAGE_BITS);
-    memset(ram_list.phys_dirty + (ram_list.last_offset >> TARGET_PAGE_BITS),
+        (new_block->offset + size) >> TARGET_PAGE_BITS);
+    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0xff, size >> TARGET_PAGE_BITS);
 
-    ram_list.last_offset += size;
-
     if (kvm_enabled())
         kvm_setup_guest_memory(new_block->host, size);
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 02/15] qdev: Add a get_dev_path() function to BusInfo
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
  2010-06-24  4:40 ` [Qemu-devel] [PATCH 01/15] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path() Alex Williamson
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

This function is meant to provide a stable device path for buses
which are able to implement it.  If a bus has a globally unique
addresses scheme, one address level may be sufficient to provide
a path.  Other buses may need to recursively traverse up the
qdev tree.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/qdev.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/qdev.h b/hw/qdev.h
index be5ad67..d64619f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -49,10 +49,13 @@ struct DeviceState {
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
+typedef char *(*bus_get_dev_path)(DeviceState *dev);
+
 struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
+    bus_get_dev_path get_dev_path;
     Property *props;
 };
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path()
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
  2010-06-24  4:40 ` [Qemu-devel] [PATCH 01/15] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 02/15] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  7:39   ` Isaku Yamahata
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 04/15] savevm: Add DeviceState param Alex Williamson
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

This works great for PCI since a <segment>:<bus>:<dev>.<fn> uniquely
describes a global address.  No need to traverse up the qdev tree.
PCI segment support is a placeholder for compatibility once we
support multiple segments.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pci.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7787005..5c9d6b4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -58,11 +58,13 @@ struct PCIBus {
 };
 
 static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static char *pcibus_get_dev_path(DeviceState *dev);
 
 static struct BusInfo pci_bus_info = {
     .name       = "PCI",
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
+    .get_dev_path = pcibus_get_dev_path,
     .props      = (Property[]) {
         DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
         DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
@@ -1853,6 +1855,18 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     }
 }
 
+static char *pcibus_get_dev_path(DeviceState *dev)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    char path[16];
+
+    snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
+             0 /* FIXME for segment support */, d->config[PCI_SECONDARY_BUS],
+             PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+
+    return strdup(path);
+}
+
 static PCIDeviceInfo bridge_info = {
     .qdev.name    = "pci-bridge",
     .qdev.size    = sizeof(PCIBridge),

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 04/15] savevm: Add DeviceState param
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (2 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path() Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 05/15] savevm: Make use of DeviceState Alex Williamson
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

When available, we'd like to be able to access the DeviceState
when registering a savevm.  For buses with a get_dev_path()
function, this will allow us to create more unique savevm
id strings.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 audio/audio.c          |    2 +-
 block-migration.c      |    4 ++--
 exec.c                 |    4 ++--
 hw/adb.c               |    4 ++--
 hw/ads7846.c           |    2 +-
 hw/arm_gic.c           |    2 +-
 hw/arm_timer.c         |    4 ++--
 hw/armv7m_nvic.c       |    2 +-
 hw/cirrus_vga.c        |    2 +-
 hw/cuda.c              |    2 +-
 hw/dma.c               |    4 ++--
 hw/eepro100.c          |    4 ++--
 hw/eeprom93xx.c        |    4 ++--
 hw/fw_cfg.c            |    2 +-
 hw/g364fb.c            |    2 +-
 hw/grackle_pci.c       |    4 ++--
 hw/gt64xxx.c           |    3 ++-
 hw/heathrow_pic.c      |    2 +-
 hw/hw.h                |   18 +++++++++++-------
 hw/i2c.c               |    2 +-
 hw/i8254.c             |    2 +-
 hw/i8259.c             |    2 +-
 hw/ide/cmd646.c        |    2 +-
 hw/ide/isa.c           |    2 +-
 hw/ide/macio.c         |    2 +-
 hw/ide/microdrive.c    |    2 +-
 hw/ide/mmio.c          |    2 +-
 hw/ide/piix.c          |    2 +-
 hw/m48t59.c            |    2 +-
 hw/mac_dbdma.c         |    2 +-
 hw/mac_nvram.c         |    4 ++--
 hw/max111x.c           |    3 ++-
 hw/mipsnet.c           |    4 ++--
 hw/mst_fpga.c          |    3 ++-
 hw/nand.c              |    2 +-
 hw/openpic.c           |    5 +++--
 hw/pci.c               |    2 +-
 hw/pckbd.c             |    2 +-
 hw/piix4.c             |    2 +-
 hw/pl011.c             |    2 +-
 hw/pl022.c             |    2 +-
 hw/pl061.c             |    2 +-
 hw/ppc4xx_pci.c        |    4 ++--
 hw/ppce500_pci.c       |    4 ++--
 hw/ps2.c               |    4 ++--
 hw/pxa2xx.c            |   27 +++++++++++++++------------
 hw/pxa2xx_dma.c        |    2 +-
 hw/pxa2xx_gpio.c       |    2 +-
 hw/pxa2xx_keypad.c     |    2 +-
 hw/pxa2xx_lcd.c        |    2 +-
 hw/pxa2xx_mmci.c       |    2 +-
 hw/pxa2xx_pic.c        |    3 ++-
 hw/pxa2xx_timer.c      |    2 +-
 hw/qdev.c              |    4 ++--
 hw/rc4030.c            |    2 +-
 hw/serial.c            |    4 ++--
 hw/spitz.c             |    9 +++++----
 hw/ssd0323.c           |    3 ++-
 hw/ssi-sd.c            |    2 +-
 hw/stellaris.c         |   11 ++++++-----
 hw/stellaris_enet.c    |    4 ++--
 hw/stellaris_input.c   |    2 +-
 hw/syborg_fb.c         |    2 +-
 hw/syborg_interrupt.c  |    3 ++-
 hw/syborg_keyboard.c   |    2 +-
 hw/syborg_pointer.c    |    2 +-
 hw/syborg_rtc.c        |    3 ++-
 hw/syborg_serial.c     |    2 +-
 hw/syborg_timer.c      |    2 +-
 hw/tsc2005.c           |    2 +-
 hw/tsc210x.c           |    4 ++--
 hw/unin_pci.c          |    6 ++++--
 hw/vga-isa-mm.c        |    2 +-
 hw/vga-isa.c           |    2 +-
 hw/virtio-balloon.c    |    3 ++-
 hw/virtio-blk.c        |    2 +-
 hw/virtio-net.c        |    4 ++--
 hw/virtio-serial-bus.c |    2 +-
 hw/vmmouse.c           |    2 +-
 hw/vmware_vga.c        |    2 +-
 hw/zaurus.c            |    2 +-
 qemu-timer.c           |    2 +-
 savevm.c               |   22 +++++++++++++---------
 slirp/slirp.c          |    5 +++--
 vl.c                   |    2 +-
 85 files changed, 163 insertions(+), 138 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index dbf0b96..ad51077 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1901,7 +1901,7 @@ static void audio_init (void)
     }
 
     QLIST_INIT (&s->card_head);
-    vmstate_register (0, &vmstate_audio, s);
+    vmstate_register (NULL, 0, &vmstate_audio, s);
 }
 
 void AUD_register_card (const char *name, QEMUSoundCard *card)
diff --git a/block-migration.c b/block-migration.c
index 7d04d6d..533564c 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -638,6 +638,6 @@ void blk_mig_init(void)
     QSIMPLEQ_INIT(&block_mig_state.bmds_list);
     QSIMPLEQ_INIT(&block_mig_state.blk_list);
 
-    register_savevm_live("block", 0, 1, block_set_params, block_save_live,
-                         NULL, block_load, &block_mig_state);
+    register_savevm_live(NULL, "block", 0, 1, block_set_params,
+                         block_save_live, NULL, block_load, &block_mig_state);
 }
diff --git a/exec.c b/exec.c
index 058b709..088d665 100644
--- a/exec.c
+++ b/exec.c
@@ -641,8 +641,8 @@ void cpu_exec_init(CPUState *env)
     cpu_list_unlock();
 #endif
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
-    vmstate_register(cpu_index, &vmstate_cpu_common, env);
-    register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
+    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
 #endif
 }
diff --git a/hw/adb.c b/hw/adb.c
index 4fb7a62..99b30f6 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -305,7 +305,7 @@ void adb_kbd_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                             adb_kbd_reset, s);
     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
-    register_savevm("adb_kbd", -1, 1, adb_kbd_save,
+    register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save,
                     adb_kbd_load, s);
 }
 
@@ -475,6 +475,6 @@ void adb_mouse_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                             adb_mouse_reset, s);
     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
-    register_savevm("adb_mouse", -1, 1, adb_mouse_save,
+    register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save,
                     adb_mouse_load, s);
 }
diff --git a/hw/ads7846.c b/hw/ads7846.c
index 184b3dd..b3bbeaf 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -151,7 +151,7 @@ static int ads7846_init(SSISlave *dev)
 
     ads7846_int_update(s);
 
-    register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s);
+    register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s);
     return 0;
 }
 
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index c4afc6a..8286a28 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -744,5 +744,5 @@ static void gic_init(gic_state *s)
     s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
                                           gic_dist_writefn, s);
     gic_reset(s);
-    register_savevm("arm_gic", -1, 1, gic_save, gic_load, s);
+    register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
 }
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9073ffc..f009e9e 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -174,7 +174,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 
     bh = qemu_bh_new(arm_timer_tick, s);
     s->timer = ptimer_init(bh);
-    register_savevm("arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
+    register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
     return s;
 }
 
@@ -271,7 +271,7 @@ static int sp804_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(sp804_readfn,
                                        sp804_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm("sp804", -1, 1, sp804_save, sp804_load, s);
+    register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
     return 0;
 }
 
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 9f09ef4..6c7ce01 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -397,7 +397,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
     gic_init(&s->gic);
     cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
     s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
-    register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+    register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
     return 0;
 }
 
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index ba48289..bbd4b08 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3128,7 +3128,7 @@ void isa_cirrus_vga_init(void)
     s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
                                      s->vga.screen_dump, s->vga.text_update,
                                      &s->vga);
-    vmstate_register(0, &vmstate_cirrus_vga, s);
+    vmstate_register(NULL, 0, &vmstate_cirrus_vga, s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
 }
diff --git a/hw/cuda.c b/hw/cuda.c
index 50950d9..3f238b6 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -763,6 +763,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
 
     s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
     *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s);
-    register_savevm("cuda", -1, 1, cuda_save, cuda_load, s);
+    register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
     qemu_register_reset(cuda_reset, s);
 }
diff --git a/hw/dma.c b/hw/dma.c
index 5b21521..8a7302a 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -548,8 +548,8 @@ void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
               high_page_enable ? 0x480 : -1, cpu_request_exit);
     dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
               high_page_enable ? 0x488 : -1, cpu_request_exit);
-    vmstate_register (0, &vmstate_dma, &dma_controllers[0]);
-    vmstate_register (1, &vmstate_dma, &dma_controllers[1]);
+    vmstate_register (NULL, 0, &vmstate_dma, &dma_controllers[0]);
+    vmstate_register (NULL, 1, &vmstate_dma, &dma_controllers[1]);
 
     dma_bh = qemu_bh_new(DMA_run_bh, NULL);
 }
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 97afa2c..0ddca8b 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1834,7 +1834,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
     cpu_unregister_io_memory(s->mmio_index);
-    vmstate_unregister(s->vmstate, s);
+    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
     eeprom93xx_free(s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
@@ -1893,7 +1893,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
     s->vmstate = qemu_malloc(sizeof(vmstate_eepro100));
     memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
     s->vmstate->name = s->nic->nc.model;
-    vmstate_register(-1, s->vmstate, s);
+    vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
 
     return 0;
 }
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 30a3534..6ba546f 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -316,7 +316,7 @@ eeprom_t *eeprom93xx_new(uint16_t nwords)
     /* Output DO is tristate, read results in 1. */
     eeprom->eedo = 1;
     logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
-    vmstate_register(0, &vmstate_eeprom, eeprom);
+    vmstate_register(NULL, 0, &vmstate_eeprom, eeprom);
     return eeprom;
 }
 
@@ -324,7 +324,7 @@ void eeprom93xx_free(eeprom_t *eeprom)
 {
     /* Destroy EEPROM. */
     logout("eeprom = 0x%p\n", eeprom);
-    vmstate_unregister(&vmstate_eeprom, eeprom);
+    vmstate_unregister(NULL, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 22ebb50..ca8c538 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -352,7 +352,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
 
-    vmstate_register(-1, &vmstate_fw_cfg, s);
+    vmstate_register(NULL, -1, &vmstate_fw_cfg, s);
     qemu_register_reset(fw_cfg_reset, s);
 
     return s;
diff --git a/hw/g364fb.c b/hw/g364fb.c
index d1d2c12..beafd70 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -598,7 +598,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
     s->irq = irq;
 
     qemu_register_reset(g364fb_reset, s);
-    register_savevm("g364fb", 0, 1, g364fb_save, g364fb_load, s);
+    register_savevm(NULL, "g364fb", 0, 1, g364fb_save, g364fb_load, s);
     g364fb_reset(s);
 
     s->ds = graphic_console_init(g364fb_update_display,
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index aa0c51b..0cf29dc 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -113,8 +113,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("grackle", 0, 1, pci_grackle_save, pci_grackle_load,
-                    &s->host_state);
+    register_savevm(&dev->qdev, "grackle", 0, 1, pci_grackle_save,
+                    pci_grackle_load, &s->host_state);
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
 }
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 7691e1d..313c080 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1146,7 +1146,8 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
 
     gt64120_reset(s);
 
-    register_savevm("GT64120 PCI Bus", 0, 1, gt64120_save, gt64120_load, d);
+    register_savevm(&d->qdev, "GT64120 PCI Bus", 0, 1,
+                    gt64120_save, gt64120_load, d);
 
     return s->pci->bus;
 }
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index 5e27021..cd86121 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -224,7 +224,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
     s->irqs = irqs[0];
     *pmem_index = cpu_register_io_memory(pic_read, pic_write, s);
 
-    register_savevm("heathrow_pic", -1, 1, heathrow_pic_save,
+    register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
                     heathrow_pic_load, s);
     qemu_register_reset(heathrow_pic_reset, s);
     return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
diff --git a/hw/hw.h b/hw/hw.h
index a49d866..c2de6fe 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -245,14 +245,16 @@ typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
                                  void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
-int register_savevm(const char *idstr,
+int register_savevm(DeviceState *dev,
+                    const char *idstr,
                     int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
                     void *opaque);
 
-int register_savevm_live(const char *idstr,
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
                          int instance_id,
                          int version_id,
                          SaveSetParamsHandler *set_params,
@@ -261,7 +263,7 @@ int register_savevm_live(const char *idstr,
                          LoadStateHandler *load_state,
                          void *opaque);
 
-void unregister_savevm(const char *idstr, void *opaque);
+void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
 
 typedef void QEMUResetHandler(void *opaque);
 
@@ -765,11 +767,13 @@ extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                               void *opaque, int version_id);
 extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                                void *opaque);
-extern int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                            void *base);
-extern int vmstate_register_with_alias_id(int instance_id,
+extern int vmstate_register(DeviceState *dev, int instance_id,
+                            const VMStateDescription *vmsd, void *base);
+extern int vmstate_register_with_alias_id(DeviceState *dev,
+                                          int instance_id,
                                           const VMStateDescription *vmsd,
                                           void *base, int alias_id,
                                           int required_for_version);
-void vmstate_unregister(const VMStateDescription *vmsd, void *opaque);
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+                        void *opaque);
 #endif
diff --git a/hw/i2c.c b/hw/i2c.c
index bee8e88..f80d12d 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -62,7 +62,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
     i2c_bus *bus;
 
     bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
-    vmstate_register(-1, &vmstate_i2c_bus, bus);
+    vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
     return bus;
 }
 
diff --git a/hw/i8254.c b/hw/i8254.c
index faaa884..06b225c 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -508,7 +508,7 @@ PITState *pit_init(int base, qemu_irq irq)
     s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
     s->irq = irq;
 
-    vmstate_register(base, &vmstate_pit, pit);
+    vmstate_register(NULL, base, &vmstate_pit, pit);
     qemu_register_reset(pit_reset, pit);
     register_ioport_write(base, 4, 1, pit_ioport_write, pit);
     register_ioport_read(base, 3, 1, pit_ioport_read, pit);
diff --git a/hw/i8259.c b/hw/i8259.c
index a995280..a8dbee6 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -483,7 +483,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *s)
         register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
         register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
     }
-    vmstate_register(io_addr, &vmstate_pic, s);
+    vmstate_register(NULL, io_addr, &vmstate_pic, s);
     qemu_register_reset(pic_reset, s);
 }
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 559147f..8b71a13 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -263,7 +263,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     ide_init2(&d->bus[0], irq[0]);
     ide_init2(&d->bus[1], irq[1]);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
     qemu_register_reset(cmd646_reset, d);
     return 0;
 }
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index b6c6347..8c28c08 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -71,7 +71,7 @@ static int isa_ide_initfn(ISADevice *dev)
     ide_init_ioport(&s->bus, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
     ide_init2(&s->bus, s->irq);
-    vmstate_register(0, &vmstate_ide_isa, s);
+    vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s);
     return 0;
 };
 
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index f76c0fa..fd4bdfd 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -321,7 +321,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
 
     pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
                                              pmac_ide_write, d);
-    vmstate_register(0, &vmstate_pmac, d);
+    vmstate_register(NULL, 0, &vmstate_pmac, d);
     qemu_register_reset(pmac_ide_reset, d);
 
     return pmac_ide_memory;
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index a7beac5..8e20e74 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -545,7 +545,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
     md->bus.ifs[0].mdata_size = METADATA_SIZE;
     md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
 
-    vmstate_register(-1, &vmstate_microdrive, md);
+    vmstate_register(NULL, -1, &vmstate_microdrive, md);
 
     return &md->card;
 }
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index e75cccf..9f20e8b 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -133,7 +133,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
     mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s);
     cpu_register_physical_memory(membase, 16 << shift, mem1);
     cpu_register_physical_memory(membase2, 2 << shift, mem2);
-    vmstate_register(0, &vmstate_ide_mmio, s);
+    vmstate_register(NULL, 0, &vmstate_ide_mmio, s);
     qemu_register_reset(mmio_ide_reset, s);
 }
 
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index dad6e86..db27ef6 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -128,7 +128,7 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
 
     pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
     ide_bus_new(&d->bus[0], &d->dev.qdev);
     ide_bus_new(&d->bus[1], &d->dev.qdev);
diff --git a/hw/m48t59.c b/hw/m48t59.c
index c3d7b3a..c7492a6 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -694,7 +694,7 @@ static void m48t59_init_common(M48t59State *s)
     }
     qemu_get_timedate(&s->alarm, 0);
 
-    register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s);
+    register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s);
 }
 
 static int m48t59_init_isa1(ISADevice *dev)
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index e2697d3..03d2d16 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -845,7 +845,7 @@ void* DBDMA_init (int *dbdma_mem_index)
     s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
 
     *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s);
-    register_savevm("dbdma", -1, 1, dbdma_save, dbdma_load, s);
+    register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
     qemu_register_reset(dbdma_reset, s);
 
     dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index f28db6b..ce287c3 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -140,8 +140,8 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
 
     s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s);
     *mem_index = s->mem_index;
-    register_savevm("macio_nvram", -1, 1, macio_nvram_save, macio_nvram_load,
-                    s);
+    register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
+                    macio_nvram_load, s);
     qemu_register_reset(macio_nvram_reset, s);
 
     return s;
diff --git a/hw/max111x.c b/hw/max111x.c
index bd656bb..2844665 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -143,7 +143,8 @@ static int max111x_init(SSISlave *dev, int inputs)
     s->input[7] = 0x80;
     s->com = 0;
 
-    register_savevm("max111x", -1, 0, max111x_save, max111x_load, s);
+    register_savevm(&dev->qdev, "max111x", -1, 0,
+                    max111x_save, max111x_load, s);
     return 0;
 }
 
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index a066f63..a95b3ce 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -239,7 +239,7 @@ static void mipsnet_cleanup(VLANClientState *nc)
 {
     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm("mipsnet", s);
+    unregister_savevm(NULL, "mipsnet", s);
 
     isa_unassign_ioport(s->io_base, 36);
 
@@ -284,5 +284,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
     }
 
     mipsnet_reset(s);
-    register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+    register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
 }
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 1b6cb77..8fc348f 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -234,6 +234,7 @@ qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
 	iomemtype = cpu_register_io_memory(mst_fpga_readfn,
 		mst_fpga_writefn, s);
 	cpu_register_physical_memory(base, 0x00100000, iomemtype);
-	register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
+	register_savevm(NULL, "mainstone_fpga", 0, 0, mst_fpga_save,
+                        mst_fpga_load, s);
 	return qi;
 }
diff --git a/hw/nand.c b/hw/nand.c
index cd7444f..f414aa1 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -502,7 +502,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
        is used.  */
     s->ioaddr = s->io;
 
-    register_savevm("nand", -1, 0, nand_save, nand_load, s);
+    register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
 
     return s;
 }
diff --git a/hw/openpic.c b/hw/openpic.c
index ac21993..2b4cb00 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1234,7 +1234,8 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     opp->irq_out = irq_out;
     opp->need_swap = 1;
 
-    register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp);
+    register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
+                    openpic_save, openpic_load, opp);
     qemu_register_reset(openpic_reset, opp);
 
     opp->irq_raise = openpic_irq_raise;
@@ -1692,7 +1693,7 @@ qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
     mpp->irq_raise = mpic_irq_raise;
     mpp->reset = mpic_reset;
 
-    register_savevm("mpic", 0, 2, openpic_save, openpic_load, mpp);
+    register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
     qemu_register_reset(mpic_reset, mpp);
 
     return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
diff --git a/hw/pci.c b/hw/pci.c
index 5c9d6b4..4092276 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -232,7 +232,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     QLIST_INIT(&bus->child);
     pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
 
-    vmstate_register(-1, &vmstate_pcibus, bus);
+    vmstate_register(NULL, -1, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
 }
 
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 3812284..0533b1d 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -418,7 +418,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
     s->irq_mouse = mouse_irq;
     s->mask = mask;
 
-    vmstate_register(0, &vmstate_kbd, s);
+    vmstate_register(NULL, 0, &vmstate_kbd, s);
     s_io_memory = cpu_register_io_memory(kbd_mm_read, kbd_mm_write, s);
     cpu_register_physical_memory(base, size, s_io_memory);
 
diff --git a/hw/piix4.c b/hw/piix4.c
index f75951b..6f08c5a 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -87,7 +87,7 @@ static int piix4_initfn(PCIDevice *d)
     uint8_t *pci_conf;
 
     isa_bus_new(&d->qdev);
-    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+    register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
 
     pci_conf = d->config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
diff --git a/hw/pl011.c b/hw/pl011.c
index 81de91e..02cf84a 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -306,7 +306,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
         qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
                               pl011_event, s);
     }
-    register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s);
+    register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
     return 0;
 }
 
diff --git a/hw/pl022.c b/hw/pl022.c
index c2e2dda..d7862bc 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -299,7 +299,7 @@ static int pl022_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
-    register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+    register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s);
     return 0;
 }
 
diff --git a/hw/pl061.c b/hw/pl061.c
index 7b1b636..e4505f5 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -303,7 +303,7 @@ static int pl061_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
     pl061_reset(s);
-    register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s);
+    register_savevm(&dev->qdev, "pl061_gpio", -1, 1, pl061_save, pl061_load, s);
     return 0;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index c9e3279..6e437e7 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -392,8 +392,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     qemu_register_reset(ppc4xx_pci_reset, controller);
 
     /* XXX load/save code not tested. */
-    register_savevm("ppc4xx_pci", ppc4xx_pci_id++, 1,
-                    ppc4xx_pci_save, ppc4xx_pci_load, controller);
+    register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
+                    1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
 
     return controller->pci_state.bus;
 
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 336d284..5358f82 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -310,8 +310,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
                                    PCIE500_REG_SIZE, index);
 
     /* XXX load/save code not tested. */
-    register_savevm("ppce500_pci", ppce500_pci_id++, 1,
-                    ppce500_pci_save, ppce500_pci_load, controller);
+    register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++,
+                    1, ppce500_pci_save, ppce500_pci_load, controller);
 
     return controller->pci_state.bus;
 
diff --git a/hw/ps2.c b/hw/ps2.c
index f0b206a..762bb00 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -595,7 +595,7 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
     s->scancode_set = 2;
-    vmstate_register(0, &vmstate_ps2_keyboard, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
     qemu_add_kbd_event_handler(ps2_put_keycode, s);
     qemu_register_reset(ps2_kbd_reset, s);
     return s;
@@ -607,7 +607,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
-    vmstate_register(0, &vmstate_ps2_mouse, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
     qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
     qemu_register_reset(ps2_mouse_reset, s);
     return s;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9095386..4915324 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -860,7 +860,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(pxa2xx_ssp_readfn,
                                        pxa2xx_ssp_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm("pxa2xx_ssp", -1, 0,
+    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
@@ -1515,7 +1515,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
     cpu_register_physical_memory(base & ~region_size,
                     region_size + 1, iomemtype);
 
-    vmstate_register(base, &vmstate_pxa2xx_i2c, s);
+    vmstate_register(NULL, base, &vmstate_pxa2xx_i2c, s);
 
     return s;
 }
@@ -1751,7 +1751,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
                     pxa2xx_i2s_writefn, s);
     cpu_register_physical_memory(base, 0x100000, iomemtype);
 
-    register_savevm("pxa2xx_i2s", base, 0,
+    register_savevm(NULL, "pxa2xx_i2s", base, 0,
                     pxa2xx_i2s_save, pxa2xx_i2s_load, s);
 
     return s;
@@ -2014,7 +2014,8 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
                         pxa2xx_fir_rx, pxa2xx_fir_event, s);
 
-    register_savevm("pxa2xx_fir", 0, 0, pxa2xx_fir_save, pxa2xx_fir_load, s);
+    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                    pxa2xx_fir_load, s);
 
     return s;
 }
@@ -2099,7 +2100,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2110,13 +2111,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     for (i = 0; pxa27x_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2140,7 +2141,8 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
-    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
+    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
+                    pxa2xx_rtc_load, s);
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
@@ -2219,7 +2221,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2230,13 +2232,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     for (i = 0; pxa255_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2260,7 +2262,8 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
-    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
+    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
+                    pxa2xx_rtc_load, s);
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 66c2c30..9c479df 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -507,7 +507,7 @@ static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
                     pxa2xx_dma_writefn, s);
     cpu_register_physical_memory(base, 0x00010000, iomemtype);
 
-    register_savevm("pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
+    register_savevm(NULL, "pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
 
     return s;
 }
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f354f4b..2abcb65 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -312,7 +312,7 @@ PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
                     pxa2xx_gpio_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
-    register_savevm("pxa2xx_gpio", 0, 0,
+    register_savevm(NULL, "pxa2xx_gpio", 0, 0,
                     pxa2xx_gpio_save, pxa2xx_gpio_load, s);
 
     return s;
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 060df58..dfa8945 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -317,7 +317,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
                     pxa2xx_keypad_writefn, s);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
-    register_savevm("pxa2xx_keypad", 0, 0,
+    register_savevm(NULL, "pxa2xx_keypad", 0, 0,
                     pxa2xx_keypad_save, pxa2xx_keypad_load, s);
 
     return s;
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 930299a..111a0dc 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -970,7 +970,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
         exit(1);
     }
 
-    register_savevm("pxa2xx_lcdc", 0, 0,
+    register_savevm(NULL, "pxa2xx_lcdc", 0, 0,
                     pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
 
     return s;
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index a415349..ca98660 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -534,7 +534,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
     /* Instantiate the actual storage */
     s->card = sd_init(bd, 0);
 
-    register_savevm("pxa2xx_mmci", 0, 0,
+    register_savevm(NULL, "pxa2xx_mmci", 0, 0,
                     pxa2xx_mmci_save, pxa2xx_mmci_load, s);
 
     return s;
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 0a98342..4d8944b 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -306,7 +306,8 @@ qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 
-    register_savevm("pxa2xx_pic", 0, 0, pxa2xx_pic_save, pxa2xx_pic_load, s);
+    register_savevm(NULL, "pxa2xx_pic", 0, 0, pxa2xx_pic_save,
+                    pxa2xx_pic_load, s);
 
     return qi;
 }
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index d992cc3..0f0ffd3 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -455,7 +455,7 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
                     pxa2xx_timer_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
-    register_savevm("pxa2xx_timer", 0, 0,
+    register_savevm(NULL, "pxa2xx_timer", 0, 0,
                     pxa2xx_timer_save, pxa2xx_timer_load, s);
 
     return s;
diff --git a/hw/qdev.c b/hw/qdev.c
index 61f999c..952c978 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -280,7 +280,7 @@ int qdev_init(DeviceState *dev)
     }
     qemu_register_reset(qdev_reset, dev);
     if (dev->info->vmsd) {
-        vmstate_register_with_alias_id(-1, dev->info->vmsd, dev,
+        vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
                                        dev->instance_id_alias,
                                        dev->alias_required_for_version);
     }
@@ -342,7 +342,7 @@ void qdev_free(DeviceState *dev)
             qbus_free(bus);
         }
         if (dev->info->vmsd)
-            vmstate_unregister(dev->info->vmsd, dev);
+            vmstate_unregister(dev, dev->info->vmsd, dev);
         if (dev->info->exit)
             dev->info->exit(dev);
         if (dev->opts)
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 2a8233a..2231373 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -813,7 +813,7 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     s->jazz_bus_irq = jazz_bus;
 
     qemu_register_reset(rc4030_reset, s);
-    register_savevm("rc4030", 0, 2, rc4030_save, rc4030_load, s);
+    register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
     s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
diff --git a/hw/serial.c b/hw/serial.c
index c7e4e77..b66d13a 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -813,7 +813,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
     s->chr = chr;
     serial_init_core(s);
 
-    vmstate_register(base, &vmstate_serial, s);
+    vmstate_register(NULL, base, &vmstate_serial, s);
 
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
@@ -948,7 +948,7 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     s->chr = chr;
 
     serial_init_core(s);
-    vmstate_register(base, &vmstate_serial, s);
+    vmstate_register(NULL, base, &vmstate_serial, s);
 
     if (ioregister) {
         if (be) {
diff --git a/hw/spitz.c b/hw/spitz.c
index 4f82e24..943933f 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -178,7 +178,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
                     sl_writefn, s);
     cpu_register_physical_memory(FLASH_BASE, 0x40, iomemtype);
 
-    register_savevm("sl_flash", 0, 0, sl_save, sl_load, s);
+    register_savevm(NULL, "sl_flash", 0, 0, sl_save, sl_load, s);
 }
 
 /* Spitz Keyboard */
@@ -508,7 +508,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
     spitz_keyboard_pre_map(s);
     qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
 
-    register_savevm("spitz_keyboard", 0, 0,
+    register_savevm(NULL, "spitz_keyboard", 0, 0,
                     spitz_keyboard_save, spitz_keyboard_load, s);
 }
 
@@ -613,7 +613,7 @@ static int spitz_lcdtg_init(SSISlave *dev)
     s->bl_power = 0;
     s->bl_intensity = 0x20;
 
-    register_savevm("spitz-lcdtg", -1, 1,
+    register_savevm(&dev->qdev, "spitz-lcdtg", -1, 1,
                     spitz_lcdtg_save, spitz_lcdtg_load, s);
     return 0;
 }
@@ -708,7 +708,8 @@ static int corgi_ssp_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
 
-    register_savevm("spitz_ssp", -1, 1, spitz_ssp_save, spitz_ssp_load, s);
+    register_savevm(&dev->qdev, "spitz_ssp", -1, 1,
+                    spitz_ssp_save, spitz_ssp_load, s);
     return 0;
 }
 
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index b632825..8643961 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -335,7 +335,8 @@ static int ssd0323_init(SSISlave *dev)
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
 
-    register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s);
+    register_savevm(&dev->qdev, "ssd0323_oled", -1, 1,
+                    ssd0323_save, ssd0323_load, s);
     return 0;
 }
 
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 96b33ed..a1a63b2 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -236,7 +236,7 @@ static int ssi_sd_init(SSISlave *dev)
     s->mode = SSI_SD_CMD;
     bs = qdev_init_bdrv(&dev->qdev, IF_SD);
     s->sd = sd_init(bs, 1);
-    register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
+    register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
     return 0;
 }
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5755f8a..ccad134 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -354,7 +354,8 @@ static int stellaris_gptm_init(SysBusDevice *dev)
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
     s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
-    register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s);
+    register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
+                    gptm_save, gptm_load, s);
     return 0;
 }
 
@@ -673,7 +674,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                                        ssys_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
     ssys_reset(s);
-    register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+    register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
     return 0;
 }
 
@@ -887,7 +888,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
-    register_savevm("stellaris_i2c", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_i2c", -1, 1,
                     stellaris_i2c_save, stellaris_i2c_load, s);
     return 0;
 }
@@ -1196,7 +1197,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
-    register_savevm("stellaris_adc", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_adc", -1, 1,
                     stellaris_adc_save, stellaris_adc_load, s);
     return 0;
 }
@@ -1256,7 +1257,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
 
-    register_savevm("stellaris_ssi_bus", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1,
                     stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
     return 0;
 }
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index d1d755e..330a9d6 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -389,7 +389,7 @@ static void stellaris_enet_cleanup(VLANClientState *nc)
 {
     stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm("stellaris_enet", s);
+    unregister_savevm(&s->busdev.qdev, "stellaris_enet", s);
 
     cpu_unregister_io_memory(s->mmio_index);
 
@@ -419,7 +419,7 @@ static int stellaris_enet_init(SysBusDevice *dev)
     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
 
     stellaris_enet_reset(s);
-    register_savevm("stellaris_enet", -1, 1,
+    register_savevm(&s->busdev.qdev, "stellaris_enet", -1, 1,
                     stellaris_enet_save, stellaris_enet_load, s);
     return 0;
 }
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 33395a4..16aae96 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -86,6 +86,6 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
     }
     s->num_buttons = n;
     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
-    register_savevm("stellaris_gamepad", -1, 1,
+    register_savevm(NULL, "stellaris_gamepad", -1, 1,
                     stellaris_gamepad_save, stellaris_gamepad_load, s);
 }
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 7be04a3..ed57203 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -526,7 +526,7 @@ static int syborg_fb_init(SysBusDevice *dev)
     if (!s->rows)
         s->rows = ds_get_height(s->ds);
 
-    register_savevm("syborg_framebuffer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
                     syborg_fb_save, syborg_fb_load, s);
     return 0;
 }
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index f3a1767..30140fb 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -214,7 +214,8 @@ static int syborg_int_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     s->flags = qemu_mallocz(s->num_irqs * sizeof(syborg_int_flags));
 
-    register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
+    register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
+                    syborg_int_load, s);
     return 0;
 }
 
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 4a562f8..7709100 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -220,7 +220,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
 
     qemu_add_kbd_event_handler(syborg_keyboard_event, s);
 
-    register_savevm("syborg_keyboard", -1, 1,
+    register_savevm(&dev->qdev, "syborg_keyboard", -1, 1,
                     syborg_keyboard_save, syborg_keyboard_load, s);
     return 0;
 }
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index 563d730..69b8d96 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -218,7 +218,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
     qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
                                  "Syborg Pointer");
 
-    register_savevm("syborg_pointer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_pointer", -1, 1,
                     syborg_pointer_save, syborg_pointer_load, s);
     return 0;
 }
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index b066213..78d5edb 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -136,7 +136,8 @@ static int syborg_rtc_init(SysBusDevice *dev)
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
 
-    register_savevm("syborg_rtc", -1, 1, syborg_rtc_save, syborg_rtc_load, s);
+    register_savevm(&dev->qdev, "syborg_rtc", -1, 1,
+                    syborg_rtc_save, syborg_rtc_load, s);
     return 0;
 }
 
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index cac00ea..8c42956 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -335,7 +335,7 @@ static int syborg_serial_init(SysBusDevice *dev)
     }
     s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
 
-    register_savevm("syborg_serial", -1, 1,
+    register_savevm(&dev->qdev, "syborg_serial", -1, 1,
                     syborg_serial_save, syborg_serial_load, s);
     return 0;
 }
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 3e4a447..95e07d7 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -221,7 +221,7 @@ static int syborg_timer_init(SysBusDevice *dev)
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
     ptimer_set_freq(s->timer, s->freq);
-    register_savevm("syborg_timer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_timer", -1, 1,
                     syborg_timer_save, syborg_timer_load, s);
     return 0;
 }
diff --git a/hw/tsc2005.c b/hw/tsc2005.c
index b75cc86..a55853c 100644
--- a/hw/tsc2005.c
+++ b/hw/tsc2005.c
@@ -548,7 +548,7 @@ void *tsc2005_init(qemu_irq pintdav)
                     "QEMU TSC2005-driven Touchscreen");
 
     qemu_register_reset((void *) tsc2005_reset, s);
-    register_savevm("tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
+    register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
 
     return s;
 }
diff --git a/hw/tsc210x.c b/hw/tsc210x.c
index e851ca1..fca73f1 100644
--- a/hw/tsc210x.c
+++ b/hw/tsc210x.c
@@ -1143,7 +1143,7 @@ uWireSlave *tsc2102_init(qemu_irq pint)
     AUD_register_card(s->name, &s->card);
 
     qemu_register_reset((void *) tsc210x_reset, s);
-    register_savevm(s->name, -1, 0,
+    register_savevm(NULL, s->name, -1, 0,
                     tsc210x_save, tsc210x_load, s);
 
     return &s->chip;
@@ -1194,7 +1194,7 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
     AUD_register_card(s->name, &s->card);
 
     qemu_register_reset((void *) tsc210x_reset, s);
-    register_savevm(s->name, -1, 0, tsc210x_save, tsc210x_load, s);
+    register_savevm(NULL, s->name, -1, 0, tsc210x_save, tsc210x_load, s);
 
     return &s->chip;
 }
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index f0a773d..362fb77 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -158,7 +158,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
+    register_savevm(&dev->qdev, "uninorth", 0, 1,
+                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
 }
@@ -178,7 +179,8 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
+    register_savevm(&dev->qdev, "uninorth", 0, 1,
+                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
     return 0;
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 8e31e36..680b557 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -100,7 +100,7 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
     s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
     vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
 
-    vmstate_register(0, &vmstate_vga_common, s);
+    vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
     s->vga.bank_offset = 0;
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 7937144..3046054 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -37,7 +37,7 @@ int isa_vga_init(void)
 
     vga_common_init(s, VGA_RAM_SIZE);
     vga_init(s);
-    vmstate_register(0, &vmstate_vga_common, s);
+    vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
     s->ds = graphic_console_init(s->update, s->invalidate,
                                  s->screen_dump, s->text_update, s);
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 152af80..9fe3886 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -270,7 +270,8 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
     reset_stats(s);
     qemu_add_balloon_handler(virtio_balloon_to_target, s);
 
-    register_savevm("virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s);
+    register_savevm(dev, "virtio-balloon", -1, 1,
+                    virtio_balloon_save, virtio_balloon_load, s);
 
     return &s->vdev;
 }
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 0bf929a..a46b758 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -498,7 +498,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
     qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
-    register_savevm("virtio-blk", virtio_blk_id++, 2,
+    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
 
     return &s->vdev;
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 06ba481..e9768e0 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -923,7 +923,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     n->vlans = qemu_mallocz(MAX_VLAN >> 3);
 
-    register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
+    register_savevm(NULL, "virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
@@ -941,7 +941,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-    unregister_savevm("virtio-net", n);
+    unregister_savevm(NULL, "virtio-net", n);
 
     qemu_free(n->mac_table.macs);
     qemu_free(n->vlans);
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 7f9d28f..b5ab3bb 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -790,7 +790,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
      * Register for the savevm section with the virtio-console name
      * to preserve backward compat
      */
-    register_savevm("virtio-console", -1, 2, virtio_serial_save,
+    register_savevm(dev, "virtio-console", -1, 2, virtio_serial_save,
                     virtio_serial_load, vser);
 
     return vdev;
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index afebad9..f359304 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -274,7 +274,7 @@ void *vmmouse_init(void *m)
     vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
-    vmstate_register(0, &vmstate_vmmouse, s);
+    vmstate_register(NULL, 0, &vmstate_vmmouse, s);
 
     return s;
 }
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index bf2a699..359e5d8 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1169,7 +1169,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
     vga_common_init(&s->vga, vga_ram_size);
     vga_init(&s->vga);
-    vmstate_register(0, &vmstate_vga_common, &s->vga);
+    vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
 
     vga_init_vbe(&s->vga);
 
diff --git a/hw/zaurus.c b/hw/zaurus.c
index db6ba75..dd999d7 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -230,7 +230,7 @@ ScoopInfo *scoop_init(PXA2xxState *cpu,
     iomemtype = cpu_register_io_memory(scoop_readfn,
                     scoop_writefn, s);
     cpu_register_physical_memory(target_base, 0x1000, iomemtype);
-    register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
+    register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s);
 
     return s;
 }
diff --git a/qemu-timer.c b/qemu-timer.c
index bdc8206..bc5f207 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -662,7 +662,7 @@ static const VMStateDescription vmstate_timers = {
 
 void configure_icount(const char *option)
 {
-    vmstate_register(0, &vmstate_timers, &timers_state);
+    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
     if (!option)
         return;
 
diff --git a/savevm.c b/savevm.c
index 20354a8..0052406 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1026,7 +1026,8 @@ static int calculate_new_instance_id(const char *idstr)
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
    distinguishing id for all instances of your device class. */
-int register_savevm_live(const char *idstr,
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
                          int instance_id,
                          int version_id,
                          SaveSetParamsHandler *set_params,
@@ -1058,18 +1059,19 @@ int register_savevm_live(const char *idstr,
     return 0;
 }
 
-int register_savevm(const char *idstr,
+int register_savevm(DeviceState *dev,
+                    const char *idstr,
                     int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
                     void *opaque)
 {
-    return register_savevm_live(idstr, instance_id, version_id,
+    return register_savevm_live(dev, idstr, instance_id, version_id,
                                 NULL, NULL, save_state, load_state, opaque);
 }
 
-void unregister_savevm(const char *idstr, void *opaque)
+void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
@@ -1081,7 +1083,7 @@ void unregister_savevm(const char *idstr, void *opaque)
     }
 }
 
-int vmstate_register_with_alias_id(int instance_id,
+int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    const VMStateDescription *vmsd,
                                    void *opaque, int alias_id,
                                    int required_for_version)
@@ -1112,13 +1114,15 @@ int vmstate_register_with_alias_id(int instance_id,
     return 0;
 }
 
-int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                     void *opaque)
+int vmstate_register(DeviceState *dev, int instance_id,
+                     const VMStateDescription *vmsd, void *opaque)
 {
-    return vmstate_register_with_alias_id(instance_id, vmsd, opaque, -1, 0);
+    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
+                                          opaque, -1, 0);
 }
 
-void vmstate_unregister(const VMStateDescription *vmsd, void *opaque)
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+                        void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 3c785cd..82fd9b4 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -232,7 +232,8 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     slirp->opaque = opaque;
 
-    register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
+    register_savevm(NULL, "slirp", 0, 3,
+                    slirp_state_save, slirp_state_load, slirp);
 
     QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
 
@@ -243,7 +244,7 @@ void slirp_cleanup(Slirp *slirp)
 {
     QTAILQ_REMOVE(&slirp_instances, slirp, entry);
 
-    unregister_savevm("slirp", slirp);
+    unregister_savevm(NULL, "slirp", slirp);
 
     qemu_free(slirp->tftp_prefix);
     qemu_free(slirp->bootp_filename);
diff --git a/vl.c b/vl.c
index 920717a..4a1c5f4 100644
--- a/vl.c
+++ b/vl.c
@@ -2794,7 +2794,7 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
-    register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, 
+    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 05/15] savevm: Make use of DeviceState
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (3 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 04/15] savevm: Add DeviceState param Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 06/15] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

For callers that pass a device we can traverse up the qdev tree and
make use of the BusInfo.get_dev_path information for creating unique
savevm id strings.  This avoids needing to rely on the instance number,
which can cause problems with device initialization order and hotplug.

For compatibility, we also store away the old id string and instance
so we can accept migrations from VMs as we add new get_dev_path
implementations.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 savevm.c |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/savevm.c b/savevm.c
index 0052406..e4f50b1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -72,6 +72,7 @@
 
 #include "qemu-common.h"
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "net.h"
 #include "monitor.h"
 #include "sysemu.h"
@@ -988,6 +989,11 @@ const VMStateInfo vmstate_info_unused_buffer = {
     .put  = put_unused_buffer,
 };
 
+typedef struct CompatEntry {
+    char idstr[256];
+    int instance_id;
+} CompatEntry;
+
 typedef struct SaveStateEntry {
     QTAILQ_ENTRY(SaveStateEntry) entry;
     char idstr[256];
@@ -1001,6 +1007,7 @@ typedef struct SaveStateEntry {
     LoadStateHandler *load_state;
     const VMStateDescription *vmsd;
     void *opaque;
+    CompatEntry *compat;
 } SaveStateEntry;
 
 
@@ -1022,6 +1029,23 @@ static int calculate_new_instance_id(const char *idstr)
     return instance_id;
 }
 
+static int calculate_compat_instance_id(const char *idstr)
+{
+    SaveStateEntry *se;
+    int instance_id = 0;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if (!se->compat)
+            continue;
+
+        if (strcmp(idstr, se->compat->idstr) == 0
+            && instance_id <= se->compat->instance_id) {
+            instance_id = se->compat->instance_id + 1;
+        }
+    }
+    return instance_id;
+}
+
 /* TODO: Individual devices generally have very little idea about the rest
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
@@ -1039,7 +1063,6 @@ int register_savevm_live(DeviceState *dev,
     SaveStateEntry *se;
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
     se->version_id = version_id;
     se->section_id = global_section_id++;
     se->set_params = set_params;
@@ -1049,11 +1072,28 @@ int register_savevm_live(DeviceState *dev,
     se->opaque = opaque;
     se->vmsd = NULL;
 
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            pstrcpy(se->idstr, sizeof(se->idstr), id);
+            pstrcat(se->idstr, sizeof(se->idstr), "/");
+            qemu_free(id);
+
+            se->compat = qemu_mallocz(sizeof(CompatEntry));
+            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
+            se->compat->instance_id = instance_id == -1 ?
+                         calculate_compat_instance_id(idstr) : instance_id;
+            instance_id = -1;
+        }
+    }
+    pstrcat(se->idstr, sizeof(se->idstr), idstr);
+
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(idstr);
+        se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
         se->instance_id = instance_id;
     }
+    assert(!se->compat || se->instance_id == 0);
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1074,9 +1114,20 @@ int register_savevm(DeviceState *dev,
 void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
+    char id[256] = "";
+
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *path = dev->parent_bus->info->get_dev_path(dev);
+        if (path) {
+            pstrcpy(id, sizeof(id), path);
+            pstrcat(id, sizeof(id), "/");
+            qemu_free(path);
+        }
+    }
+    pstrcat(id, sizeof(id), idstr);
 
     QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
-        if (strcmp(se->idstr, idstr) == 0 && se->opaque == opaque) {
+        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
             QTAILQ_REMOVE(&savevm_handlers, se, entry);
             qemu_free(se);
         }
@@ -1094,7 +1145,6 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
     se->version_id = vmsd->version_id;
     se->section_id = global_section_id++;
     se->save_live_state = NULL;
@@ -1104,11 +1154,28 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->vmsd = vmsd;
     se->alias_id = alias_id;
 
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            pstrcpy(se->idstr, sizeof(se->idstr), id);
+            pstrcat(se->idstr, sizeof(se->idstr), "/");
+            qemu_free(id);
+
+            se->compat = qemu_mallocz(sizeof(CompatEntry));
+            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
+            se->compat->instance_id = instance_id == -1 ?
+                         calculate_compat_instance_id(vmsd->name) : instance_id;
+            instance_id = -1;
+        }
+    }
+    pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
+
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(vmsd->name);
+        se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
         se->instance_id = instance_id;
     }
+    assert(!se->compat || se->instance_id == 0);
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1454,6 +1521,13 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
             (instance_id == se->instance_id ||
              instance_id == se->alias_id))
             return se;
+        /* Migrating from an older version? */
+        if (strstr(se->idstr, idstr) && se->compat) {
+            if (!strcmp(se->compat->idstr, idstr) &&
+                (instance_id == se->compat->instance_id ||
+                 instance_id == se->alias_id))
+                return se;
+        }
     }
     return NULL;
 }

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 06/15] eepro100: Add a dev field to eeprom new/free functions
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (4 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 05/15] savevm: Make use of DeviceState Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 07/15] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

This allows us to create a more meaningful savevm string.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/eepro100.c   |    4 ++--
 hw/eeprom93xx.c |    8 ++++----
 hw/eeprom93xx.h |    4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 0ddca8b..2b75c8f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1835,7 +1835,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
 
     cpu_unregister_io_memory(s->mmio_index);
     vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
-    eeprom93xx_free(s->eeprom);
+    eeprom93xx_free(&pci_dev->qdev, s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
 }
@@ -1862,7 +1862,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
 
     /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
      * i82559 and later support 64 or 256 word EEPROM. */
-    s->eeprom = eeprom93xx_new(EEPROM_SIZE);
+    s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
 
     /* Handler for memory-mapped I/O */
     s->mmio_index =
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 6ba546f..660b28f 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -289,7 +289,7 @@ void eeprom93xx_reset(eeprom_t *eeprom)
 }
 #endif
 
-eeprom_t *eeprom93xx_new(uint16_t nwords)
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)
 {
     /* Add a new EEPROM (with 16, 64 or 256 words). */
     eeprom_t *eeprom;
@@ -316,15 +316,15 @@ eeprom_t *eeprom93xx_new(uint16_t nwords)
     /* Output DO is tristate, read results in 1. */
     eeprom->eedo = 1;
     logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
-    vmstate_register(NULL, 0, &vmstate_eeprom, eeprom);
+    vmstate_register(dev, 0, &vmstate_eeprom, eeprom);
     return eeprom;
 }
 
-void eeprom93xx_free(eeprom_t *eeprom)
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom)
 {
     /* Destroy EEPROM. */
     logout("eeprom = 0x%p\n", eeprom);
-    vmstate_unregister(NULL, &vmstate_eeprom, eeprom);
+    vmstate_unregister(dev, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/eeprom93xx.h b/hw/eeprom93xx.h
index 47282d3..8ba0e28 100644
--- a/hw/eeprom93xx.h
+++ b/hw/eeprom93xx.h
@@ -23,10 +23,10 @@
 typedef struct _eeprom_t eeprom_t;
 
 /* Create a new EEPROM with (nwords * 2) bytes. */
-eeprom_t *eeprom93xx_new(uint16_t nwords);
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords);
 
 /* Destroy an existing EEPROM. */
-void eeprom93xx_free(eeprom_t *eeprom);
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom);
 
 /* Read from the EEPROM. */
 uint16_t eeprom93xx_read(eeprom_t *eeprom);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 07/15] virtio-net: Incorporate a DeviceState pointer and let savevm track instances
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (5 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 06/15] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 08/15] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Stuff a pointer to the DeviceState into the VirtIONet structure so that
we can easily remove the vmstate entry later.  Also, let vmstate track
the instance number (it should always be zero internally since the
device path should now be unique).

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/virtio-net.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index e9768e0..f41db45 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -60,6 +60,7 @@ typedef struct VirtIONet
         uint8_t *macs;
     } mac_table;
     uint32_t *vlans;
+    DeviceState *qdev;
 } VirtIONet;
 
 /* TODO
@@ -890,7 +891,6 @@ static void virtio_net_vmstate_change(void *opaque, int running, int reason)
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 {
     VirtIONet *n;
-    static int virtio_net_id;
 
     n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
                                         sizeof(struct virtio_net_config),
@@ -923,7 +923,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     n->vlans = qemu_mallocz(MAX_VLAN >> 3);
 
-    register_savevm(NULL, "virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
+    n->qdev = dev;
+    register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
@@ -941,7 +942,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-    unregister_savevm(NULL, "virtio-net", n);
+    unregister_savevm(n->qdev, "virtio-net", n);
 
     qemu_free(n->mac_table.macs);
     qemu_free(n->vlans);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 08/15] qemu_ram_alloc: Add DeviceState and name parameters
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (6 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 07/15] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 09/15] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

These will be used to generate unique id strings for ramblocks.  The name
field is required, the device pointer is optional as most callers don't
have a device.  When there's no device or the device isn't a child of
a bus implementing BusInfo.get_dev_path, the name should be unique for
the platform.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-common.h                  |    2 +-
 exec.c                        |    2 +-
 hw/an5206.c                   |    4 ++--
 hw/armv7m.c                   |    9 ++++++---
 hw/axis_dev88.c               |    4 ++--
 hw/dummy_m68k.c               |    2 +-
 hw/etraxfs.c                  |    6 +++---
 hw/g364fb.c                   |    2 +-
 hw/gumstix.c                  |    6 ++++--
 hw/integratorcp.c             |    4 ++--
 hw/mainstone.c                |    6 ++++--
 hw/mcf5208.c                  |    4 ++--
 hw/mips_jazz.c                |    4 ++--
 hw/mips_malta.c               |    4 ++--
 hw/mips_mipssim.c             |    4 ++--
 hw/mips_r4k.c                 |    6 +++---
 hw/musicpal.c                 |   11 +++++++----
 hw/omap1.c                    |    6 ++++--
 hw/omap2.c                    |    6 ++++--
 hw/omap_sx1.c                 |   12 ++++++++----
 hw/onenand.c                  |    2 +-
 hw/palm.c                     |    3 ++-
 hw/pc.c                       |    8 ++++----
 hw/pci.c                      |    7 ++++++-
 hw/petalogix_s3adsp1800_mmu.c |    7 ++++---
 hw/ppc405_boards.c            |   18 +++++++++---------
 hw/ppc405_uc.c                |    2 +-
 hw/ppc4xx_devs.c              |    4 +++-
 hw/ppc_newworld.c             |    6 +++---
 hw/ppc_oldworld.c             |    6 +++---
 hw/ppc_prep.c                 |    4 ++--
 hw/ppce500_mpc8544ds.c        |    3 ++-
 hw/pxa2xx.c                   |   12 ++++++++----
 hw/r2d.c                      |    4 ++--
 hw/realview.c                 |    6 +++---
 hw/s390-virtio.c              |    2 +-
 hw/sm501.c                    |    2 +-
 hw/spitz.c                    |    2 +-
 hw/sun4m.c                    |    8 ++++----
 hw/sun4u.c                    |    4 ++--
 hw/syborg.c                   |    2 +-
 hw/tc6393xb.c                 |    2 +-
 hw/tcx.c                      |    2 +-
 hw/tosa.c                     |    2 +-
 hw/versatilepb.c              |    2 +-
 hw/vga.c                      |    2 +-
 hw/vmware_vga.c               |    2 +-
 47 files changed, 130 insertions(+), 98 deletions(-)

diff --git a/cpu-common.h b/cpu-common.h
index b24cecc..71e7933 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -40,7 +40,7 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 }
 
 ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
-ram_addr_t qemu_ram_alloc(ram_addr_t);
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
 void qemu_ram_free(ram_addr_t addr);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
diff --git a/exec.c b/exec.c
index 088d665..dc47831 100644
--- a/exec.c
+++ b/exec.c
@@ -2776,7 +2776,7 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
     return last;
 }
 
-ram_addr_t qemu_ram_alloc(ram_addr_t size)
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 {
     RAMBlock *new_block;
 
diff --git a/hw/an5206.c b/hw/an5206.c
index f584d88..b9f19a9 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -54,11 +54,11 @@ static void an5206_init(ram_addr_t ram_size,
 
     /* DRAM at address zero */
     cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "an5206.ram", ram_size) | IO_MEM_RAM);
 
     /* Internal SRAM.  */
     cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512,
-        qemu_ram_alloc(512) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "an5206.sram", 512) | IO_MEM_RAM);
 
     mcf5206_init(AN5206_MBAR_ADDR, env);
 
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 854261d..588ec98 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -200,9 +200,11 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
 
     /* Flash programming is done via the SCU, so pretend it is ROM.  */
     cpu_register_physical_memory(0, flash_size,
-                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "armv7m.flash",
+                                                flash_size) | IO_MEM_ROM);
     cpu_register_physical_memory(0x20000000, sram_size,
-                                 qemu_ram_alloc(sram_size) | IO_MEM_RAM);
+                                 qemu_ram_alloc(NULL, "armv7m.sram",
+                                                sram_size) | IO_MEM_RAM);
     armv7m_bitband_init();
 
     nvic = qdev_create(NULL, "armv7m_nvic");
@@ -236,7 +238,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
        space.  This stops qemu complaining about executing code outside RAM
        when returning from an exception.  */
     cpu_register_physical_memory(0xfffff000, 0x1000,
-                                 qemu_ram_alloc(0x1000) | IO_MEM_RAM);
+                                 qemu_ram_alloc(NULL, "armv7m.hack", 
+                                                0x1000) | IO_MEM_RAM);
 
     qemu_register_reset(armv7m_reset, env);
     return pic;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 3ae4105..f16c76a 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -268,12 +268,12 @@ void axisdev88_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "axisdev88.ram", ram_size);
     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
+    phys_intmem = qemu_ram_alloc(NULL, "axisdev88.chipram", INTMEM_SIZE);
     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
                                  phys_intmem | IO_MEM_RAM);
 
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 9c9e6ff..61efb39 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -39,7 +39,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
 
     /* RAM at address zero */
     cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "dummy_m68k.ram", ram_size) | IO_MEM_RAM);
 
     /* Load kernel.  */
     if (kernel_filename) {
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 01bf929..46e2920 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -68,17 +68,17 @@ void bareetraxfs_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "etraxfs.ram", ram_size);
     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
+    phys_intmem = qemu_ram_alloc(NULL, "etraxfs.chipram", INTMEM_SIZE);
     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
                                  phys_intmem | IO_MEM_RAM);
 
 
-    phys_flash = qemu_ram_alloc(FLASH_SIZE);
+    phys_flash = qemu_ram_alloc(NULL, "etraxfs.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0x0, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
diff --git a/hw/g364fb.c b/hw/g364fb.c
index beafd70..3c8fb98 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -593,7 +593,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
     s = qemu_mallocz(sizeof(G364State));
 
     s->vram_size = 8 * 1024 * 1024;
-    s->vram_offset = qemu_ram_alloc(s->vram_size);
+    s->vram_offset = qemu_ram_alloc(NULL, "g364fb.vram", s->vram_size);
     s->vram = qemu_get_ram_ptr(s->vram_offset);
     s->irq = irq;
 
diff --git a/hw/gumstix.c b/hw/gumstix.c
index b64e04e..c343a16 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -67,7 +67,8 @@ static void connex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(connex_rom),
+    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
+                                                          connex_rom),
                                dinfo->bdrv, sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -105,7 +106,8 @@ static void verdex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(verdex_rom),
+    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
+                                                          verdex_rom),
                                dinfo->bdrv, sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index bee8298..3bf216b 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -253,7 +253,7 @@ static int integratorcm_init(SysBusDevice *dev)
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
-    s->flash_offset = qemu_ram_alloc(0x100000);
+    s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000);
 
     iomemtype = cpu_register_io_memory(integratorcm_readfn,
                                        integratorcm_writefn, s);
@@ -467,7 +467,7 @@ static void integratorcp_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "integrator.ram", ram_size);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero*/
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 54bacfb..cba7e63 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -87,7 +87,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
     /* Setup CPU & memory */
     cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);
     cpu_register_physical_memory(0, MAINSTONE_ROM,
-                    qemu_ram_alloc(MAINSTONE_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "mainstone.rom",
+                                   MAINSTONE_ROM) | IO_MEM_ROM);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
@@ -104,7 +105,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
         }
 
         if (!pflash_cfi01_register(mainstone_flash_base[i],
-                                   qemu_ram_alloc(MAINSTONE_FLASH),
+                                   qemu_ram_alloc(NULL, "mainstone.flash",
+                                                  MAINSTONE_FLASH),
                                    dinfo->bdrv, sector_len,
                                    MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
                                    be)) {
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 5b686c6..38645f7 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -220,11 +220,11 @@ static void mcf5208evb_init(ram_addr_t ram_size,
 
     /* DRAM at 0x40000000 */
     cpu_register_physical_memory(0x40000000, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "mcf5208.ram", ram_size) | IO_MEM_RAM);
 
     /* Internal SRAM.  */
     cpu_register_physical_memory(0x80000000, 16384,
-        qemu_ram_alloc(16384) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "mcf5208.sram", 16384) | IO_MEM_RAM);
 
     /* Internal peripherals.  */
     pic = mcf_intc_init(0xfc048000, env);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 22db7a2..658aba7 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -160,10 +160,10 @@ void mips_jazz_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_jazz.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
-    bios_offset = qemu_ram_alloc(MAGNUM_BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
     cpu_register_physical_memory(0x1fc00000LL,
                                  MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);
     cpu_register_physical_memory(0xfff00000LL,
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 23de7f0..c3f4725 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -833,8 +833,8 @@ void mips_malta_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
 
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 293d99e..111c759 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -144,8 +144,8 @@ mips_mipssim_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate RAM. */
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_mipssim.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_mipssim.bios", BIOS_SIZE);
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 5a96dea..61cd33a 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -198,7 +198,7 @@ void mips_r4k_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_r4k.ram", ram_size);
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
@@ -226,14 +226,14 @@ void mips_r4k_init (ram_addr_t ram_size,
     be = 0;
 #endif
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE);
 	cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
                                      bios_offset | IO_MEM_ROM);
 
         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
-        bios_offset = qemu_ram_alloc(mips_rom);
+        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom);
         if (!pflash_cfi01_register(0x1fc00000, bios_offset,
                                    dinfo->bdrv, sector_len,
                                    mips_rom / sector_len,
diff --git a/hw/musicpal.c b/hw/musicpal.c
index d44c5a0..fa74a81 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1508,9 +1508,10 @@ static void musicpal_init(ram_addr_t ram_size,
 
     /* For now we use a fixed - the original - RAM size */
     cpu_register_physical_memory(0, MP_RAM_DEFAULT_SIZE,
-                                 qemu_ram_alloc(MP_RAM_DEFAULT_SIZE));
+                                 qemu_ram_alloc(NULL, "musicpal.ram",
+                                                MP_RAM_DEFAULT_SIZE));
 
-    sram_off = qemu_ram_alloc(MP_SRAM_SIZE);
+    sram_off = qemu_ram_alloc(NULL, "musicpal.sram", MP_SRAM_SIZE);
     cpu_register_physical_memory(MP_SRAM_BASE, MP_SRAM_SIZE, sram_off);
 
     dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
@@ -1557,14 +1558,16 @@ static void musicpal_init(ram_addr_t ram_size,
          * image is smaller than 32 MB.
          */
 #ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
+                              "musicpal.flash", flash_size),
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
+                              "musicpal.flash", flash_size),
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
diff --git a/hw/omap1.c b/hw/omap1.c
index 8649dbd..e5fa87a 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -4655,9 +4655,11 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
 
     /* Memory-mapped stuff */
     cpu_register_physical_memory(OMAP_EMIFF_BASE, s->sdram_size,
-                    (emiff_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
+                    (emiff_base = qemu_ram_alloc(NULL, "omap1.dram",
+                                                 s->sdram_size)) | IO_MEM_RAM);
     cpu_register_physical_memory(OMAP_IMIF_BASE, s->sram_size,
-                    (imif_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+                    (imif_base = qemu_ram_alloc(NULL, "omap1.sram",
+                                                s->sram_size)) | IO_MEM_RAM);
 
     omap_clkm_init(0xfffece00, 0xe1008000, s);
 
diff --git a/hw/omap2.c b/hw/omap2.c
index 666c15a..b6ccc00 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -4518,9 +4518,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
 
     /* Memory-mapped stuff */
     cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-                    (q2_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
+                    (q2_base = qemu_ram_alloc(NULL, "omap2.dram",
+                                              s->sdram_size)) | IO_MEM_RAM);
     cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-                    (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+                    (sram_base = qemu_ram_alloc(NULL, "omap2.sram",
+                                                s->sram_size)) | IO_MEM_RAM);
 
     s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
 
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 2e9879f..c3f1973 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -139,7 +139,8 @@ static void sx1_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "omap_sx1.flash0-0",
+                                                flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
@@ -157,7 +158,8 @@ static void sx1_init(ram_addr_t ram_size,
 #endif
 
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(flash_size),
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL,
+                                   "omap_sx1.flash0-1", flash_size),
                                    dinfo->bdrv, sector_size,
                                    flash_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
@@ -170,12 +172,14 @@ static void sx1_init(ram_addr_t ram_size,
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
-                                     qemu_ram_alloc(flash1_size) | IO_MEM_ROM);
+                                     qemu_ram_alloc(NULL, "omap_sx1.flash1-0",
+                                                    flash1_size) | IO_MEM_ROM);
         io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
         cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
                         OMAP_CS1_SIZE - flash1_size, io);
 
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(flash1_size),
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL,
+                                   "omap_sx1.flash1-1", flash1_size),
                                    dinfo->bdrv, sector_size,
                                    flash1_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
diff --git a/hw/onenand.c b/hw/onenand.c
index 4118db9..f7afeca 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -638,7 +638,7 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
         s->bdrv = dinfo->bdrv;
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
-    s->ram = qemu_ram_alloc(0xc000 << s->shift);
+    s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
     ram = qemu_get_ram_ptr(s->ram);
     s->boot[0] = ram + (0x0000 << s->shift);
     s->boot[1] = ram + (0x8000 << s->shift);
diff --git a/hw/palm.c b/hw/palm.c
index 8db133d..193aa11 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -213,7 +213,8 @@ static void palmte_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                    qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "palmte.flash",
+                                                flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
diff --git a/hw/pc.c b/hw/pc.c
index 1848151..8c4e307 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -896,7 +896,7 @@ void pc_memory_init(ram_addr_t ram_size,
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(below_4g_mem_size);
+    ram_addr = qemu_ram_alloc(NULL, "pc.lowmem", below_4g_mem_size);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
@@ -907,7 +907,7 @@ void pc_memory_init(ram_addr_t ram_size,
 #if TARGET_PHYS_ADDR_BITS == 32
         hw_error("To much RAM for 32-bit physical address");
 #else
-        ram_addr = qemu_ram_alloc(above_4g_mem_size);
+        ram_addr = qemu_ram_alloc(NULL, "pc.highmem", above_4g_mem_size);
         cpu_register_physical_memory(0x100000000ULL,
                                      above_4g_mem_size,
                                      ram_addr);
@@ -928,7 +928,7 @@ void pc_memory_init(ram_addr_t ram_size,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(bios_size);
+    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size));
     if (ret != 0) {
     bios_error:
@@ -946,7 +946,7 @@ void pc_memory_init(ram_addr_t ram_size,
                                  isa_bios_size,
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
-    option_rom_offset = qemu_ram_alloc(PC_ROM_SIZE);
+    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
     cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
 
     /* map all the bios at the top of memory */
diff --git a/hw/pci.c b/hw/pci.c
index 4092276..7877897 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1713,6 +1713,7 @@ static int pci_add_option_rom(PCIDevice *pdev)
     int size;
     char *path;
     void *ptr;
+    char name[32];
 
     if (!pdev->romfile)
         return 0;
@@ -1748,7 +1749,11 @@ static int pci_add_option_rom(PCIDevice *pdev)
         size = 1 << qemu_fls(size);
     }
 
-    pdev->rom_offset = qemu_ram_alloc(size);
+    if (pdev->qdev.info->vmsd)
+        snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->vmsd->name);
+    else
+        snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name);
+    pdev->rom_offset = qemu_ram_alloc(&pdev->qdev, name, size);
 
     ptr = qemu_get_ram_ptr(pdev->rom_offset);
     load_image(path, ptr);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index cdde991..70b6a36 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -137,14 +137,15 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* Attach emulated BRAM through the LMB.  */
-    phys_lmb_bram = qemu_ram_alloc(LMB_BRAM_SIZE);
+    phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.lmb_bram",
+                                   LMB_BRAM_SIZE);
     cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE,
                                  phys_lmb_bram | IO_MEM_RAM);
 
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size);
     cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
 
-    phys_flash = qemu_ram_alloc(FLASH_SIZE);
+    phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xa0000000, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index 7c7075e..40ff1b3 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -190,7 +190,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* XXX: fix this */
-    ram_bases[0] = qemu_ram_alloc(0x08000000);
+    ram_bases[0] = qemu_ram_alloc(NULL, "ef405ep.ram", 0x08000000);
     ram_sizes[0] = 0x08000000;
     ram_bases[1] = 0x00000000;
     ram_sizes[1] = 0x00000000;
@@ -202,7 +202,7 @@ static void ref405ep_init (ram_addr_t ram_size,
                         kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
-    sram_offset = qemu_ram_alloc(sram_size);
+    sram_offset = qemu_ram_alloc(NULL, "ef405ep.sram", sram_size);
 #ifdef DEBUG_BOARD_INIT
     printf("%s: register SRAM at offset %08lx\n", __func__, sram_offset);
 #endif
@@ -217,7 +217,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
         bios_size = bdrv_getlength(dinfo->bdrv);
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " TARGET_FMT_lx
@@ -236,7 +236,7 @@ static void ref405ep_init (ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -509,9 +509,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
-    ram_bases[0] = qemu_ram_alloc(0x04000000);
+    ram_bases[0] = qemu_ram_alloc(NULL, "taihu_405ep.ram-0", 0x04000000);
     ram_sizes[0] = 0x04000000;
-    ram_bases[1] = qemu_ram_alloc(0x04000000);
+    ram_bases[1] = qemu_ram_alloc(NULL, "taihu_405ep.ram-1", 0x04000000);
     ram_sizes[1] = 0x04000000;
     ram_size = 0x08000000;
 #ifdef DEBUG_BOARD_INIT
@@ -531,7 +531,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size);
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " TARGET_FMT_lx
                " at offset %08lx addr " TARGET_FMT_lx " '%s' %d\n",
@@ -551,7 +551,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 #endif
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
             bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
@@ -580,7 +580,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
                fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
                bdrv_get_device_name(dinfo->bdrv));
 #endif
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size);
         pflash_cfi02_register(0xfc000000, bios_offset,
                               dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index d9bbd93..b884ea5 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -995,7 +995,7 @@ static void ppc405_ocm_init(CPUState *env)
     ppc405_ocm_t *ocm;
 
     ocm = qemu_mallocz(sizeof(ppc405_ocm_t));
-    ocm->offset = qemu_ram_alloc(4096);
+    ocm->offset = qemu_ram_alloc(NULL, "ppc405.ocm", 4096);
     qemu_register_reset(&ocm_reset, ocm);
     ppc_dcr_register(env, OCM0_ISARC,
                      ocm, &dcr_read_ocm, &dcr_write_ocm);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 37a3948..b15db81 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -668,7 +668,9 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
             unsigned int bank_size = sdram_bank_sizes[j];
 
             if (bank_size <= size_left) {
-                ram_bases[i] = qemu_ram_alloc(bank_size);
+                char name[32];
+                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
+                ram_bases[i] = qemu_ram_alloc(NULL, name, bank_size);
                 ram_sizes[i] = bank_size;
                 size_left -= bank_size;
                 break;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index d131aa5..fbba9b6 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -173,11 +173,11 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_core99.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_core99.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -198,7 +198,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate and load VGA BIOS */
-    vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
+    vga_bios_offset = qemu_ram_alloc(NULL, "ppc_core99.vbios", VGA_BIOS_SIZE);
     vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME);
     if (filename) {
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 27ddc01..6b3ab89 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -179,11 +179,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_heathrow.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -203,7 +203,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     }
 
     /* allocate and load VGA BIOS */
-    vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
+    vga_bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.vbios", VGA_BIOS_SIZE);
     vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME);
     if (filename) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index bb9e15f..fc3e17a 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -604,11 +604,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_prep.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_prep.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 0901fa6..1422fad 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -189,7 +189,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
 
     /* Register Memory */
-    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(ram_size));
+    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(NULL,
+                                 "mpc8544ds.ram", ram_size));
 
     /* MPIC */
     irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 4915324..953e9ee 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2054,9 +2054,11 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
-                    sdram_size, qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+                    sdram_size, qemu_ram_alloc(NULL, "pxa270.sdram",
+                                               sdram_size) | IO_MEM_RAM);
     cpu_register_physical_memory(PXA2XX_INTERNAL_BASE,
-                    0x40000, qemu_ram_alloc(0x40000) | IO_MEM_RAM);
+                    0x40000, qemu_ram_alloc(NULL, "pxa270.internal",
+                                            0x40000) | IO_MEM_RAM);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
@@ -2175,9 +2177,11 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size,
-                    qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+                    qemu_ram_alloc(NULL, "pxa255.sdram",
+                                   sdram_size) | IO_MEM_RAM);
     cpu_register_physical_memory(PXA2XX_INTERNAL_BASE, PXA2XX_INTERNAL_SIZE,
-                    qemu_ram_alloc(PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
+                    qemu_ram_alloc(NULL, "pxa255.internal",
+                                   PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
diff --git a/hw/r2d.c b/hw/r2d.c
index 38c4f6a..61414e2 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -242,7 +242,7 @@ static void r2d_init(ram_addr_t ram_size,
     }
 
     /* Allocate memory space */
-    sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
+    sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
     cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
     /* Register peripherals */
     s = sh7750_init(env);
@@ -257,7 +257,7 @@ static void r2d_init(ram_addr_t ram_size,
                   dinfo, NULL);
 
     /* onboard flash memory */
-    pflash_cfi02_register(0x0, qemu_ram_alloc(FLASH_SIZE),
+    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
                           dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                           FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
diff --git a/hw/realview.c b/hw/realview.c
index f786699..70bcdb8 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -196,12 +196,12 @@ static void realview_init(ram_addr_t ram_size,
         /* Core tile RAM.  */
         low_ram_size = ram_size - 0x20000000;
         ram_size = 0x20000000;
-        ram_offset = qemu_ram_alloc(low_ram_size);
+        ram_offset = qemu_ram_alloc(NULL, "realview.lowmem", low_ram_size);
         cpu_register_physical_memory(0x20000000, low_ram_size,
                                      ram_offset | IO_MEM_RAM);
     }
 
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "realview.highmem", ram_size);
     low_ram_size = ram_size;
     if (low_ram_size > 0x10000000)
       low_ram_size = 0x10000000;
@@ -354,7 +354,7 @@ static void realview_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    ram_offset = qemu_ram_alloc(0x1000);
+    ram_offset = qemu_ram_alloc(NULL, "realview.hack", 0x1000);
     cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
                                  ram_offset | IO_MEM_RAM);
 
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 898f442..2fb437b 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -157,7 +157,7 @@ static void s390_init(ram_addr_t ram_size,
     s390_bus = s390_virtio_bus_init(&ram_size);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(ram_size);
+    ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr);
 
     /* init CPUs */
diff --git a/hw/sm501.c b/hw/sm501.c
index b5ec2da..8e6932d 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1371,7 +1371,7 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    s->local_mem_offset = qemu_ram_alloc(local_mem_bytes);
+    s->local_mem_offset = qemu_ram_alloc(NULL, "sm501.local", local_mem_bytes);
     s->local_mem = qemu_get_ram_ptr(s->local_mem_offset);
     cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset);
 
diff --git a/hw/spitz.c b/hw/spitz.c
index 943933f..afda902 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -966,7 +966,7 @@ static void spitz_common_init(ram_addr_t ram_size,
     sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
     cpu_register_physical_memory(0, SPITZ_ROM,
-                    qemu_ram_alloc(SPITZ_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "spitz.rom", SPITZ_ROM) | IO_MEM_ROM);
 
     /* Setup peripherals */
     spitz_keyboard_register(cpu);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index e4ca8f3..208c8a8 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -592,7 +592,7 @@ static int idreg_init1(SysBusDevice *dev)
 {
     ram_addr_t idreg_offset;
 
-    idreg_offset = qemu_ram_alloc(sizeof(idreg_data));
+    idreg_offset = qemu_ram_alloc(NULL, "sun4m.idreg", sizeof(idreg_data));
     sysbus_init_mmio(dev, sizeof(idreg_data), idreg_offset | IO_MEM_ROM);
     return 0;
 }
@@ -627,7 +627,7 @@ static int afx_init1(SysBusDevice *dev)
 {
     ram_addr_t afx_offset;
 
-    afx_offset = qemu_ram_alloc(4);
+    afx_offset = qemu_ram_alloc(NULL, "sun4m.afx", 4);
     sysbus_init_mmio(dev, 4, afx_offset | IO_MEM_RAM);
     return 0;
 }
@@ -690,7 +690,7 @@ static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
-    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
+    prom_offset = qemu_ram_alloc(NULL, "sun4m.prom", PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
     return 0;
 }
@@ -725,7 +725,7 @@ static int ram_init1(SysBusDevice *dev)
 
     RAM_size = d->size;
 
-    ram_offset = qemu_ram_alloc(RAM_size);
+    ram_offset = qemu_ram_alloc(NULL, "sun4m.ram", RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
     return 0;
 }
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 40b5f1f..2234b4e 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -629,7 +629,7 @@ static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
-    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
+    prom_offset = qemu_ram_alloc(NULL, "sun4u.prom", PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
     return 0;
 }
@@ -665,7 +665,7 @@ static int ram_init1(SysBusDevice *dev)
 
     RAM_size = d->size;
 
-    ram_offset = qemu_ram_alloc(RAM_size);
+    ram_offset = qemu_ram_alloc(NULL, "sun4u.ram", RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
     return 0;
 }
diff --git a/hw/syborg.c b/hw/syborg.c
index 2d08cb2..758c69a 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -51,7 +51,7 @@ static void syborg_init(ram_addr_t ram_size,
     }
 
     /* RAM at address zero. */
-    ram_addr = qemu_ram_alloc(ram_size);
+    ram_addr = qemu_ram_alloc(NULL, "syborg.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr | IO_MEM_RAM);
 
     cpu_pic = arm_pic_init_cpu(env);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index e0c5e5f..16db51d 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -593,7 +593,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
                     tc6393xb_writefn, s);
     cpu_register_physical_memory(base, 0x10000, iomemtype);
 
-    s->vram_addr = qemu_ram_alloc(0x100000);
+    s->vram_addr = qemu_ram_alloc(NULL, "tc6393xb.vram", 0x100000);
     s->vram_ptr = qemu_get_ram_ptr(s->vram_addr);
     cpu_register_physical_memory(base + 0x100000, 0x100000, s->vram_addr);
     s->scr_width = 480;
diff --git a/hw/tcx.c b/hw/tcx.c
index beb30ac..6ee65bb 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -510,7 +510,7 @@ static int tcx_init1(SysBusDevice *dev)
     int size;
     uint8_t *vram_base;
 
-    vram_offset = qemu_ram_alloc(s->vram_size * (1 + 4 + 4));
+    vram_offset = qemu_ram_alloc(NULL, "tcx.vram", s->vram_size * (1 + 4 + 4));
     vram_base = qemu_get_ram_ptr(vram_offset);
     s->vram_offset = vram_offset;
 
diff --git a/hw/tosa.c b/hw/tosa.c
index fbe8d8c..ba6d9e7 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -215,7 +215,7 @@ static void tosa_init(ram_addr_t ram_size,
     cpu = pxa255_init(tosa_binfo.ram_size);
 
     cpu_register_physical_memory(0, TOSA_ROM,
-                    qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
 
     tmio = tc6393xb_init(0x10000000,
             pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 391f5b8..1d049f2 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -180,7 +180,7 @@ static void versatile_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "versatile.ram", ram_size);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
diff --git a/hw/vga.c b/hw/vga.c
index 01de1e1..b5c7ee7 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2261,7 +2261,7 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    s->vram_offset = qemu_ram_alloc(vga_ram_size);
+    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
     s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 359e5d8..9e72d2e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1164,7 +1164,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    s->fifo_offset = qemu_ram_alloc(s->fifo_size);
+    s->fifo_offset = qemu_ram_alloc(NULL, "vmsvga.fifo", s->fifo_size);
     s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
 
     vga_common_init(&s->vga, vga_ram_size);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 09/15] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (7 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 08/15] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
@ 2010-06-24  4:41 ` Alex Williamson
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 10/15] savevm: Migrate RAM based on name/offset Alex Williamson
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

With these two pieces in place, we can start naming ramblocks.  When
the device is present and it lives on a bus that provides a device
path, we concatenate the path and the provided name.  Otherwise we
just use name.  The resulting id string must be unique.  For now we
assume an allocation for the same name and size is a device that has
been removed and reinserted and return the same block.  This will go
away once qemu_ram_free() is implemented.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-all.h |    1 +
 exec.c    |   29 +++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index dbb2139..5d8342b 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -865,6 +865,7 @@ typedef struct RAMBlock {
     uint8_t *host;
     ram_addr_t offset;
     ram_addr_t length;
+    char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
 } RAMBlock;
 
diff --git a/exec.c b/exec.c
index dc47831..a136c13 100644
--- a/exec.c
+++ b/exec.c
@@ -36,6 +36,7 @@
 #include "qemu-common.h"
 #include "tcg.h"
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "osdep.h"
 #include "kvm.h"
 #include "qemu-timer.h"
@@ -2778,10 +2779,34 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
 
 ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 {
-    RAMBlock *new_block;
+    RAMBlock *new_block, *block;
 
     size = TARGET_PAGE_ALIGN(size);
-    new_block = qemu_malloc(sizeof(*new_block));
+    new_block = qemu_mallocz(sizeof(*new_block));
+
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
+            qemu_free(id);
+        }
+    }
+    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (!strcmp(block->idstr, new_block->idstr)) {
+            if (block->length == new_block->length) {
+                fprintf(stderr, "RAMBlock \"%s\" exists, assuming lack of"
+                        "free.\n", new_block->idstr);
+                qemu_free(new_block);
+                return block->offset;
+            } else {
+                fprintf(stderr, "RAMBlock \"%s\" already registered with"
+                        "different size, abort\n", new_block->idstr);
+                abort();
+            }
+        }
+    }
 
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 10/15] savevm: Migrate RAM based on name/offset
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (8 preceding siblings ...)
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 09/15] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
@ 2010-06-24  4:42 ` Alex Williamson
  2010-06-24  5:49   ` [Qemu-devel] " Paolo Bonzini
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 11/15] savevm: Use RAM blocks for basis of migration Alex Williamson
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Synchronize RAM blocks with the target and migrate using name/offset
pairs.  This ensures both source and target have the same view of
RAM and that we get the right bits into the right slot.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |  118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 vl.c        |    2 +
 2 files changed, 108 insertions(+), 12 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 109dcef..37aad9d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -113,20 +113,33 @@ static int ram_save_block(QEMUFile *f)
 
     while (addr < total_ram) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
+            RAMBlock *block;
+            ram_addr_t offset;
             uint8_t *p;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
                                             MIGRATION_DIRTY_FLAG);
 
-            p = qemu_get_ram_ptr(current_addr);
+            QLIST_FOREACH(block, &ram_list.blocks, next) {
+                if (current_addr - block->offset < block->length)
+                    break;
+            }
+            offset = current_addr - block->offset;
+            p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
-                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
             } else {
-                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
+                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
@@ -196,6 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        RAMBlock *block;
         uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
@@ -210,6 +224,12 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         cpu_physical_memory_set_dirty_tracking(1);
 
         qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
+
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            qemu_put_byte(f, strlen(block->idstr));
+            qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
+            qemu_put_be64(f, block->length);
+        }
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -257,7 +277,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
     ram_addr_t addr;
     int flags;
 
-    if (version_id != 3) {
+    if (version_id < 3 || version_id > 4) {
         return -EINVAL;
     }
 
@@ -268,23 +288,99 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != ram_bytes_total()) {
-                return -EINVAL;
+            if (version_id == 3) {
+                if (addr != ram_bytes_total()) {
+                    return -EINVAL;
+                }
+            } else {
+                /* Synchronize RAM block list */
+                char id[256];
+                ram_addr_t length;
+                ram_addr_t total_ram_bytes = addr;
+
+                while (total_ram_bytes) {
+                    RAMBlock *block;
+                    uint8_t len;
+
+                    len = qemu_get_byte(f);
+                    qemu_get_buffer(f, (uint8_t *)id, len);
+                    id[len] = 0;
+                    length = qemu_get_be64(f);
+
+                    QLIST_FOREACH(block, &ram_list.blocks, next) {
+                        if (!strncmp(id, block->idstr, sizeof(id))) {
+                            if (block->length != length)
+                                return -EINVAL;
+                            break;
+                        }
+                    }
+
+                    if (!block) {
+                        if (!qemu_ram_alloc(NULL, id, length))
+                            return -ENOMEM;
+                    }
+
+                    total_ram_bytes -= length;
+                }
             }
         }
 
         if (flags & RAM_SAVE_FLAG_COMPRESS) {
-            uint8_t ch = qemu_get_byte(f);
-            memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
+            void *host;
+            uint8_t ch;
+
+            if (version_id == 3) {
+                host = qemu_get_ram_ptr(addr);
+            } else {
+                RAMBlock *block;
+                char id[256];
+                uint8_t len;
+
+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;
+
+                host = block->host + addr;
+            }
+            ch = qemu_get_byte(f);
+            memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
             if (ch == 0 &&
                 (!kvm_enabled() || kvm_has_sync_mmu())) {
-                madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE,
-                        MADV_DONTNEED);
+                madvise(host, TARGET_PAGE_SIZE, MADV_DONTNEED);
             }
 #endif
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
-            qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
+            void *host;
+
+            if (version_id == 3) {
+                host = qemu_get_ram_ptr(addr);
+            } else {
+                RAMBlock *block;
+                char id[256];
+                uint8_t len;
+
+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;
+
+                host = block->host + addr;
+            }
+            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {
             return -EIO;
diff --git a/vl.c b/vl.c
index 4a1c5f4..8a5de9f 100644
--- a/vl.c
+++ b/vl.c
@@ -2794,7 +2794,7 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
-    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
+    register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 11/15] savevm: Use RAM blocks for basis of migration
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (9 preceding siblings ...)
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 10/15] savevm: Migrate RAM based on name/offset Alex Williamson
@ 2010-06-24  4:42 ` Alex Williamson
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name Alex Williamson
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

We don't want to assume a contiguous address space, so migrate based
on RAM blocks instead of a fixed linear address map.  This will allow
us to have holes in the ram_addr_t namespace, so we can implement
qemu_ram_free().

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   67 +++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 37aad9d..186645b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -105,27 +105,26 @@ static int is_dup_page(uint8_t *page, uint8_t ch)
 
 static int ram_save_block(QEMUFile *f)
 {
-    static ram_addr_t current_addr = 0;
-    ram_addr_t saved_addr = current_addr;
-    ram_addr_t addr = 0;
-    uint64_t total_ram = ram_bytes_total();
+    static RAMBlock *last_block = NULL;
+    static ram_addr_t last_offset = 0;
+    RAMBlock *block = last_block;
+    ram_addr_t offset = last_offset;
+    ram_addr_t current_addr;
     int bytes_sent = 0;
 
-    while (addr < total_ram) {
+    if (!block)
+        block = QLIST_FIRST(&ram_list.blocks);
+
+    current_addr = block->offset + offset;
+
+    do {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
-            RAMBlock *block;
-            ram_addr_t offset;
             uint8_t *p;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
                                             MIGRATION_DIRTY_FLAG);
 
-            QLIST_FOREACH(block, &ram_list.blocks, next) {
-                if (current_addr - block->offset < block->length)
-                    break;
-            }
-            offset = current_addr - block->offset;
             p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
@@ -146,9 +145,21 @@ static int ram_save_block(QEMUFile *f)
 
             break;
         }
-        addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % total_ram;
-    }
+
+        offset += TARGET_PAGE_SIZE;
+        if (offset >= block->length) {
+            offset = 0;
+            block = QLIST_NEXT(block, next);
+            if (!block)
+                block = QLIST_FIRST(&ram_list.blocks);
+        }
+
+        current_addr = block->offset + offset;
+
+    } while (current_addr != last_block->offset + last_offset);
+
+    last_block = block;
+    last_offset = offset;
 
     return bytes_sent;
 }
@@ -157,13 +168,16 @@ static uint64_t bytes_transferred;
 
 static ram_addr_t ram_save_remaining(void)
 {
-    ram_addr_t addr;
+    RAMBlock *block;
     ram_addr_t count = 0;
-    uint64_t total_ram = ram_bytes_total();
 
-    for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
-        if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
-            count++;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ram_addr_t addr;
+        for (addr = block->offset; addr < block->offset + block->length;
+             addr += TARGET_PAGE_SIZE) {
+            if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
+                count++;
+            }
         }
     }
 
@@ -210,20 +224,23 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     if (stage == 1) {
         RAMBlock *block;
-        uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
-            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
-                cpu_physical_memory_set_dirty(addr);
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            for (addr = block->offset; addr < block->offset + block->length;
+                 addr += TARGET_PAGE_SIZE) {
+                if (!cpu_physical_memory_get_dirty(addr,
+                                                   MIGRATION_DIRTY_FLAG)) {
+                    cpu_physical_memory_set_dirty(addr);
+                }
             }
         }
 
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
         QLIST_FOREACH(block, &ram_list.blocks, next) {
             qemu_put_byte(f, strlen(block->idstr));

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (10 preceding siblings ...)
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 11/15] savevm: Use RAM blocks for basis of migration Alex Williamson
@ 2010-06-24  4:42 ` Alex Williamson
  2010-06-24  5:51   ` [Qemu-devel] " Paolo Bonzini
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 13/15] qemu_ram_free: Implement it Alex Williamson
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Allows us to compress the protocol a bit by setting a flag on the
offset which indicates we're still working within the same block
as last time.  That way we can avoid sending the block name for
every page.  Suggested by Anthony Liguori.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   94 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 50 insertions(+), 44 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 186645b..2f082f3 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -87,6 +87,7 @@ const uint32_t arch_type = QEMU_ARCH;
 #define RAM_SAVE_FLAG_MEM_SIZE	0x04
 #define RAM_SAVE_FLAG_PAGE	0x08
 #define RAM_SAVE_FLAG_EOS	0x10
+#define RAM_SAVE_FLAG_CONTINUE	0x20
 
 static int is_dup_page(uint8_t *page, uint8_t ch)
 {
@@ -120,6 +121,7 @@ static int ram_save_block(QEMUFile *f)
     do {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
+            int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
@@ -128,17 +130,21 @@ static int ram_save_block(QEMUFile *f)
             p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
-                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, strlen(block->idstr));
-                qemu_put_buffer(f, (uint8_t *)block->idstr,
-                                strlen(block->idstr));
+                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
+                if (!cont) {
+                    qemu_put_byte(f, strlen(block->idstr));
+                    qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                    strlen(block->idstr));
+                }
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
             } else {
-                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
-                qemu_put_byte(f, strlen(block->idstr));
-                qemu_put_buffer(f, (uint8_t *)block->idstr,
-                                strlen(block->idstr));
+                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
+                if (!cont) {
+                    qemu_put_byte(f, strlen(block->idstr));
+                    qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                    strlen(block->idstr));
+                }
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
@@ -289,6 +295,36 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     return (stage == 2) && (expected_time <= migrate_max_downtime());
 }
 
+static inline void *host_from_stream_offset(QEMUFile *f,
+                                            ram_addr_t offset,
+                                            int flags)
+{
+    static RAMBlock *block = NULL;
+    char id[256];
+    uint8_t len;
+
+    if (flags & RAM_SAVE_FLAG_CONTINUE) {
+        if (!block) {
+            fprintf(stderr, "Ack, bad migration stream!\n");
+            return NULL;
+        }
+
+        return block->host + offset;
+    }
+
+    len = qemu_get_byte(f);
+    qemu_get_buffer(f, (uint8_t *)id, len);
+    id[len] = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (!strncmp(id, block->idstr, sizeof(id)))
+            return block->host + offset;
+    }
+
+    fprintf(stderr, "Can't find block %s!\n", id);
+    return NULL;
+}
+
 int ram_load(QEMUFile *f, void *opaque, int version_id)
 {
     ram_addr_t addr;
@@ -346,26 +382,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
             void *host;
             uint8_t ch;
 
-            if (version_id == 3) {
+            if (version_id == 3)
                 host = qemu_get_ram_ptr(addr);
-            } else {
-                RAMBlock *block;
-                char id[256];
-                uint8_t len;
-
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
+            else
+                host = host_from_stream_offset(f, addr, flags);
 
-                QLIST_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id)))
-                        break;
-                }
-                if (!block)
-                    return -EINVAL;
-
-                host = block->host + addr;
-            }
             ch = qemu_get_byte(f);
             memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
@@ -377,26 +398,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
-            if (version_id == 3) {
+            if (version_id == 3)
                 host = qemu_get_ram_ptr(addr);
-            } else {
-                RAMBlock *block;
-                char id[256];
-                uint8_t len;
+            else
+                host = host_from_stream_offset(f, addr, flags);
 
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
-
-                QLIST_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id)))
-                        break;
-                }
-                if (!block)
-                    return -EINVAL;
-
-                host = block->host + addr;
-            }
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 13/15] qemu_ram_free: Implement it
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (11 preceding siblings ...)
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name Alex Williamson
@ 2010-06-24  4:42 ` Alex Williamson
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 14/15] pci: Free the space allocated for the option rom on removal Alex Williamson
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Now that we can support a ram_addr_t space with holes, we can implement
qemu_ram_free().

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-all.h |    3 +++
 exec.c    |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index 5d8342b..224ca40 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -867,6 +867,9 @@ typedef struct RAMBlock {
     ram_addr_t length;
     char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
+#if defined(__linux__) && !defined(TARGET_S390X)
+    int fd;
+#endif
 } RAMBlock;
 
 typedef struct RAMList {
diff --git a/exec.c b/exec.c
index a136c13..e8108d7 100644
--- a/exec.c
+++ b/exec.c
@@ -2699,7 +2699,9 @@ static long gethugepagesize(const char *path)
     return fs.f_bsize;
 }
 
-static void *file_ram_alloc(ram_addr_t memory, const char *path)
+static void *file_ram_alloc(RAMBlock *block,
+                            ram_addr_t memory,
+                            const char *path)
 {
     char *filename;
     void *area;
@@ -2762,19 +2764,35 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 	close(fd);
 	return (NULL);
     }
+    block->fd = fd;
     return area;
 }
 #endif
 
 static ram_addr_t find_ram_offset(ram_addr_t size)
 {
-    RAMBlock *block;
-    ram_addr_t last = 0;
+    RAMBlock *block, *next_block;
+    ram_addr_t offset, mingap = ULONG_MAX;
+
+    if (QLIST_EMPTY(&ram_list.blocks))
+        return 0;
 
-    QLIST_FOREACH(block, &ram_list.blocks, next)
-        last = MAX(last, block->offset + block->length);
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ram_addr_t end, next = ULONG_MAX;
 
-    return last;
+        end = block->offset + block->length;
+
+        QLIST_FOREACH(next_block, &ram_list.blocks, next) {
+            if (next_block->offset >= end) {
+                next = MIN(next, next_block->offset);
+            }
+        }
+        if (next - end >= size && next - end < mingap) {
+            offset =  end;
+            mingap = next - end;
+        }
+    }
+    return offset;
 }
 
 ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
@@ -2810,7 +2828,7 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)
-        new_block->host = file_ram_alloc(size, mem_path);
+        new_block->host = file_ram_alloc(new_block, size, mem_path);
         if (!new_block->host) {
             new_block->host = qemu_vmalloc(size);
 #ifdef MADV_MERGEABLE
@@ -2852,7 +2870,32 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
 void qemu_ram_free(ram_addr_t addr)
 {
-    /* TODO: implement this.  */
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (addr == block->offset) {
+            QLIST_REMOVE(block, next);
+            if (mem_path) {
+#if defined (__linux__) && !defined(TARGET_S390X)
+                if (block->fd) {
+                    munmap(block->host, block->length);
+                    close(block->fd);
+                } else {
+                    qemu_vfree(block->host);
+                }
+#endif
+            } else {
+#if defined(TARGET_S390X) && defined(CONFIG_KVM)
+                munmap(block->host, block->length);
+#else
+                qemu_vfree(block->host);
+#endif
+            }
+            qemu_free(block);
+            return;
+        }
+    }
+
 }
 
 /* Return a host pointer to ram allocated with qemu_ram_alloc.

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 14/15] pci: Free the space allocated for the option rom on removal
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (12 preceding siblings ...)
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 13/15] qemu_ram_free: Implement it Alex Williamson
@ 2010-06-24  4:42 ` Alex Williamson
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 15/15] ramblocks: No more being lazy about duplicate names Alex Williamson
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pci.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7877897..a4f4262 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -76,6 +76,7 @@ static struct BusInfo pci_bus_info = {
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev);
+static void pci_del_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
@@ -709,6 +710,7 @@ static int pci_unregister_device(DeviceState *dev)
         return ret;
 
     pci_unregister_io_regions(pci_dev);
+    pci_del_option_rom(pci_dev);
     do_pci_unregister_device(pci_dev);
     return 0;
 }
@@ -1765,6 +1767,15 @@ static int pci_add_option_rom(PCIDevice *pdev)
     return 0;
 }
 
+static void pci_del_option_rom(PCIDevice *pdev)
+{
+    if (!pdev->rom_offset)
+        return;
+
+    qemu_ram_free(pdev->rom_offset);
+    pdev->rom_offset = 0;
+}
+
 /* Reserve space and add capability to the linked list in pci config space */
 int pci_add_capability_at_offset(PCIDevice *pdev, uint8_t cap_id,
                                  uint8_t offset, uint8_t size)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH 15/15] ramblocks: No more being lazy about duplicate names
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (13 preceding siblings ...)
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 14/15] pci: Free the space allocated for the option rom on removal Alex Williamson
@ 2010-06-24  4:42 ` Alex Williamson
  2010-06-24  6:02 ` [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Yoshiaki Tamura
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24  4:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, armbru, alex.williamson, kraxel, cam, paul

Now that we have a working qemu_ram_free() and the primary runtime
user of it has been updated, don't be lenient about duplicate id strings.
We also shouldn't need to create them ondemand at the target.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |    5 +++--
 exec.c      |   13 +++----------
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 2f082f3..47bb4b2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -369,8 +369,9 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
                     }
 
                     if (!block) {
-                        if (!qemu_ram_alloc(NULL, id, length))
-                            return -ENOMEM;
+                        fprintf(stderr, "Unknown ramblock \"%s\", cannot "
+                                "accept migration\n", id);
+                        return -EINVAL;
                     }
 
                     total_ram_bytes -= length;
diff --git a/exec.c b/exec.c
index e8108d7..ef2a89d 100644
--- a/exec.c
+++ b/exec.c
@@ -2813,16 +2813,9 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (!strcmp(block->idstr, new_block->idstr)) {
-            if (block->length == new_block->length) {
-                fprintf(stderr, "RAMBlock \"%s\" exists, assuming lack of"
-                        "free.\n", new_block->idstr);
-                qemu_free(new_block);
-                return block->offset;
-            } else {
-                fprintf(stderr, "RAMBlock \"%s\" already registered with"
-                        "different size, abort\n", new_block->idstr);
-                abort();
-            }
+            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
+                    new_block->idstr);
+            abort();
         }
     }
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] Re: [PATCH 10/15] savevm: Migrate RAM based on name/offset
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 10/15] savevm: Migrate RAM based on name/offset Alex Williamson
@ 2010-06-24  5:49   ` Paolo Bonzini
  0 siblings, 0 replies; 60+ messages in thread
From: Paolo Bonzini @ 2010-06-24  5:49 UTC (permalink / raw)
  To: Alex Williamson; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On 06/24/2010 06:42 AM, Alex Williamson wrote:
>           if (flags&  RAM_SAVE_FLAG_COMPRESS) {
> -            uint8_t ch = qemu_get_byte(f);
> -            memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
> +            void *host;
> +            uint8_t ch;
> +
> +            if (version_id == 3) {
> +                host = qemu_get_ram_ptr(addr);
> +            } else {
> +                RAMBlock *block;
> +                char id[256];
> +                uint8_t len;
> +
> +                len = qemu_get_byte(f);
> +                qemu_get_buffer(f, (uint8_t *)id, len);
> +                id[len] = 0;

Can you measure the amount of bytes transferred before and now?  It 
seems pretty expensive.  Maybe you could add another flag so that the 
memory name is passed on the wire only if it differs from the previous 
one.  Alternatively (perhaps better) define a new kind of RAM save data 
just for the RAM block, and assume all pages after it are for that 
block.  You can even encode the RAM length in the flags, so that you 
only have to pass "len | RAM_SAVE_FLAG_BLOCK_NAME" followed by the 
length+characters of the name.

Also, code like this:

+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;

is present three times.  It should be split in two functions and these 
functions be called (the first function can also be used elsewhere, I 
think, though this of course can be done in a followup).

Paolo

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [Qemu-devel] Re: [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name Alex Williamson
@ 2010-06-24  5:51   ` Paolo Bonzini
  2010-06-24 15:06     ` Alex Williamson
  0 siblings, 1 reply; 60+ messages in thread
From: Paolo Bonzini @ 2010-06-24  5:51 UTC (permalink / raw)
  To: Alex Williamson; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On 06/24/2010 06:42 AM, Alex Williamson wrote:
> Allows us to compress the protocol a bit by setting a flag on the
> offset which indicates we're still working within the same block
> as last time.  That way we can avoid sending the block name for
> every page.  Suggested by Anthony Liguori.
>
> Signed-off-by: Alex Williamson<alex.williamson@redhat.com>
> ---
>
>   arch_init.c |   94 +++++++++++++++++++++++++++++++----------------------------
>   1 files changed, 50 insertions(+), 44 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index 186645b..2f082f3 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -87,6 +87,7 @@ const uint32_t arch_type = QEMU_ARCH;
>   #define RAM_SAVE_FLAG_MEM_SIZE	0x04
>   #define RAM_SAVE_FLAG_PAGE	0x08
>   #define RAM_SAVE_FLAG_EOS	0x10
> +#define RAM_SAVE_FLAG_CONTINUE	0x20
>
>   static int is_dup_page(uint8_t *page, uint8_t ch)
>   {
> @@ -120,6 +121,7 @@ static int ram_save_block(QEMUFile *f)
>       do {
>           if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
>               uint8_t *p;
> +            int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
>
>               cpu_physical_memory_reset_dirty(current_addr,
>                                               current_addr + TARGET_PAGE_SIZE,
> @@ -128,17 +130,21 @@ static int ram_save_block(QEMUFile *f)
>               p = block->host + offset;
>
>               if (is_dup_page(p, *p)) {
> -                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
> -                qemu_put_byte(f, strlen(block->idstr));
> -                qemu_put_buffer(f, (uint8_t *)block->idstr,
> -                                strlen(block->idstr));
> +                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
> +                if (!cont) {
> +                    qemu_put_byte(f, strlen(block->idstr));
> +                    qemu_put_buffer(f, (uint8_t *)block->idstr,
> +                                    strlen(block->idstr));
> +                }
>                   qemu_put_byte(f, *p);
>                   bytes_sent = 1;
>               } else {
> -                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
> -                qemu_put_byte(f, strlen(block->idstr));
> -                qemu_put_buffer(f, (uint8_t *)block->idstr,
> -                                strlen(block->idstr));
> +                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
> +                if (!cont) {
> +                    qemu_put_byte(f, strlen(block->idstr));
> +                    qemu_put_buffer(f, (uint8_t *)block->idstr,
> +                                    strlen(block->idstr));
> +                }
>                   qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
>                   bytes_sent = TARGET_PAGE_SIZE;
>               }
> @@ -289,6 +295,36 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
>       return (stage == 2)&&  (expected_time<= migrate_max_downtime());
>   }
>
> +static inline void *host_from_stream_offset(QEMUFile *f,
> +                                            ram_addr_t offset,
> +                                            int flags)
> +{
> +    static RAMBlock *block = NULL;
> +    char id[256];
> +    uint8_t len;
> +
> +    if (flags&  RAM_SAVE_FLAG_CONTINUE) {
> +        if (!block) {
> +            fprintf(stderr, "Ack, bad migration stream!\n");
> +            return NULL;
> +        }
> +
> +        return block->host + offset;
> +    }
> +
> +    len = qemu_get_byte(f);
> +    qemu_get_buffer(f, (uint8_t *)id, len);
> +    id[len] = 0;
> +
> +    QLIST_FOREACH(block,&ram_list.blocks, next) {
> +        if (!strncmp(id, block->idstr, sizeof(id)))
> +            return block->host + offset;
> +    }
> +
> +    fprintf(stderr, "Can't find block %s!\n", id);
> +    return NULL;
> +}
> +
>   int ram_load(QEMUFile *f, void *opaque, int version_id)
>   {
>       ram_addr_t addr;
> @@ -346,26 +382,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
>               void *host;
>               uint8_t ch;
>
> -            if (version_id == 3) {
> +            if (version_id == 3)
>                   host = qemu_get_ram_ptr(addr);
> -            } else {
> -                RAMBlock *block;
> -                char id[256];
> -                uint8_t len;
> -
> -                len = qemu_get_byte(f);
> -                qemu_get_buffer(f, (uint8_t *)id, len);
> -                id[len] = 0;
> +            else
> +                host = host_from_stream_offset(f, addr, flags);
>
> -                QLIST_FOREACH(block,&ram_list.blocks, next) {
> -                    if (!strncmp(id, block->idstr, sizeof(id)))
> -                        break;
> -                }
> -                if (!block)
> -                    return -EINVAL;
> -
> -                host = block->host + addr;
> -            }
>               ch = qemu_get_byte(f);
>               memset(host, ch, TARGET_PAGE_SIZE);
>   #ifndef _WIN32
> @@ -377,26 +398,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
>           } else if (flags&  RAM_SAVE_FLAG_PAGE) {
>               void *host;
>
> -            if (version_id == 3) {
> +            if (version_id == 3)
>                   host = qemu_get_ram_ptr(addr);
> -            } else {
> -                RAMBlock *block;
> -                char id[256];
> -                uint8_t len;
> +            else
> +                host = host_from_stream_offset(f, addr, flags);
>
> -                len = qemu_get_byte(f);
> -                qemu_get_buffer(f, (uint8_t *)id, len);
> -                id[len] = 0;
> -
> -                QLIST_FOREACH(block,&ram_list.blocks, next) {
> -                    if (!strncmp(id, block->idstr, sizeof(id)))
> -                        break;
> -                }
> -                if (!block)
> -                    return -EINVAL;
> -
> -                host = block->host + addr;
> -            }
>               qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
>           }
>           if (qemu_file_has_error(f)) {

Gah, sorry. :)

This also takes care of the code duplication, great.

Paolo

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH 00/15] Make migration work with hotplug
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (14 preceding siblings ...)
  2010-06-24  4:42 ` [Qemu-devel] [PATCH 15/15] ramblocks: No more being lazy about duplicate names Alex Williamson
@ 2010-06-24  6:02 ` Yoshiaki Tamura
  2010-06-24 15:04   ` Alex Williamson
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
  17 siblings, 1 reply; 60+ messages in thread
From: Yoshiaki Tamura @ 2010-06-24  6:02 UTC (permalink / raw)
  To: Alex Williamson; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

2010/6/24 Alex Williamson <alex.williamson@redhat.com>:
> Ok, new approach.  I'm going to attempt to extract myself for the
> canonical device path approach, because we're missing too many pieces
> to make that work.  Instead, I'll take Anthony's advice and try to
> simplify.  We still want a unique name for ramblocks and savevm, but
> the hotplug problem today is only for PCI devices.  PCI conveniently
> has globally unique, dare I say canonical, addressing in the form of
> <domain>:<bus>:<device>.<func>.  To get to this, let's add a new
> function on the BusInfo structure called get_dev_path().  For a PCI
> device, we can simply traverse up the qdev tree to the BusInfo
> structure, look for the function, and call it to return a global PCI
> address.
>
> For some buses, these functions could chain up to their parent bus
> appending strings together to get a unique path.  An example would be
> USB, where the USB port number may not be unique.  If we traverse up
> to the PCI device providing USB, and then to the PCI bus, we get a
> globally unique PCI path, appended with a USB port number.
>
> To make this work for ramblocks and savevm, we need a DeviceState
> pointer when the they are create/registered, and we need a caller
> provided context in case there are multiple ramblocks/savevm
> associated with a device.  Savevm already provies the context,
> and I've attempted to make reasonable guesses at these for the
> ramblocks.  Note that most of the ramblocks aren't associated with
> a device, so I don't think it makes sense to link savevm and
> ramblocks together with the same absolute id string.
>
> Once we have savevm with unique id strings, rather than hotplug
> unfriendly instance numbers, we can be sure that the right driver
> instance is loading the correct vmstate.  I've also implemented
> a compat field for this, so we can still accept incoming migrations
> from previous versions.
>
> Once we have ramblocks with a unique id string, we can switch to
> using id + offset for migration, which enables a ram_addr_t space
> that supports gaps, which enables us to implement qemu_ram_free().
> With that, I think we can finally do migrations reliable after
> hotplug!  Note that the target VM still needs to be created to
> match the current devices and bus addresses of the source VM.  We
> can also still maintain compatibility for migrations here by bumping
> the ram migration version and supporting both new and old (just
> hope the source hasn't done any hotplugs).
>
> Sound reasonable?  Is get_dev_path the right name?  In the right
> place?  The PCI return is currently "dddd:bb:dd.f", should this be
> "PCI:dddd:bb:dd.f"?  Something else?  Thanks,

Hi Alex,

Is there additional overhead to save rams introduce by this series?
If so, how much?

Thanks,

Yoshi

>
> Alex
>
> ---
>
> Alex Williamson (15):
>      ramblocks: No more being lazy about duplicate names
>      pci: Free the space allocated for the option rom on removal
>      qemu_ram_free: Implement it
>      savevm: Create a new continue flag to avoid resending block name
>      savevm: Use RAM blocks for basis of migration
>      savevm: Migrate RAM based on name/offset
>      ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
>      qemu_ram_alloc: Add DeviceState and name parameters
>      virtio-net: Incorporate a DeviceState pointer and let savevm track instances
>      eepro100: Add a dev field to eeprom new/free functions
>      savevm: Make use of DeviceState
>      savevm: Add DeviceState param
>      pci: Implement BusInfo.get_dev_path()
>      qdev: Add a get_dev_path() function to BusInfo
>      Remove uses of ram.last_offset (aka last_ram_offset)
>
>
>  arch_init.c                   |  183 +++++++++++++++++++++++++++++++++++------
>  audio/audio.c                 |    2
>  block-migration.c             |    4 -
>  cpu-all.h                     |    5 +
>  cpu-common.h                  |    2
>  exec.c                        |   96 +++++++++++++++++++---
>  hw/adb.c                      |    4 -
>  hw/ads7846.c                  |    2
>  hw/an5206.c                   |    4 -
>  hw/arm_gic.c                  |    2
>  hw/arm_timer.c                |    4 -
>  hw/armv7m.c                   |    9 +-
>  hw/armv7m_nvic.c              |    2
>  hw/axis_dev88.c               |    4 -
>  hw/cirrus_vga.c               |    2
>  hw/cuda.c                     |    2
>  hw/dma.c                      |    4 -
>  hw/dummy_m68k.c               |    2
>  hw/eepro100.c                 |    8 +-
>  hw/eeprom93xx.c               |    8 +-
>  hw/eeprom93xx.h               |    4 -
>  hw/etraxfs.c                  |    6 +
>  hw/fw_cfg.c                   |    2
>  hw/g364fb.c                   |    4 -
>  hw/grackle_pci.c              |    4 -
>  hw/gt64xxx.c                  |    3 -
>  hw/gumstix.c                  |    6 +
>  hw/heathrow_pic.c             |    2
>  hw/hw.h                       |   18 ++--
>  hw/i2c.c                      |    2
>  hw/i8254.c                    |    2
>  hw/i8259.c                    |    2
>  hw/ide/cmd646.c               |    2
>  hw/ide/isa.c                  |    2
>  hw/ide/macio.c                |    2
>  hw/ide/microdrive.c           |    2
>  hw/ide/mmio.c                 |    2
>  hw/ide/piix.c                 |    2
>  hw/integratorcp.c             |    4 -
>  hw/m48t59.c                   |    2
>  hw/mac_dbdma.c                |    2
>  hw/mac_nvram.c                |    4 -
>  hw/mainstone.c                |    6 +
>  hw/max111x.c                  |    3 -
>  hw/mcf5208.c                  |    4 -
>  hw/mips_jazz.c                |    4 -
>  hw/mips_malta.c               |    4 -
>  hw/mips_mipssim.c             |    4 -
>  hw/mips_r4k.c                 |    6 +
>  hw/mipsnet.c                  |    4 -
>  hw/mst_fpga.c                 |    3 -
>  hw/musicpal.c                 |   11 ++
>  hw/nand.c                     |    2
>  hw/omap1.c                    |    6 +
>  hw/omap2.c                    |    6 +
>  hw/omap_sx1.c                 |   12 ++-
>  hw/onenand.c                  |    2
>  hw/openpic.c                  |    5 +
>  hw/palm.c                     |    3 -
>  hw/pc.c                       |    8 +-
>  hw/pci.c                      |   34 +++++++-
>  hw/pckbd.c                    |    2
>  hw/petalogix_s3adsp1800_mmu.c |    7 +-
>  hw/piix4.c                    |    2
>  hw/pl011.c                    |    2
>  hw/pl022.c                    |    2
>  hw/pl061.c                    |    2
>  hw/ppc405_boards.c            |   18 ++--
>  hw/ppc405_uc.c                |    2
>  hw/ppc4xx_devs.c              |    4 +
>  hw/ppc4xx_pci.c               |    4 -
>  hw/ppc_newworld.c             |    6 +
>  hw/ppc_oldworld.c             |    6 +
>  hw/ppc_prep.c                 |    4 -
>  hw/ppce500_mpc8544ds.c        |    3 -
>  hw/ppce500_pci.c              |    4 -
>  hw/ps2.c                      |    4 -
>  hw/pxa2xx.c                   |   39 +++++----
>  hw/pxa2xx_dma.c               |    2
>  hw/pxa2xx_gpio.c              |    2
>  hw/pxa2xx_keypad.c            |    2
>  hw/pxa2xx_lcd.c               |    2
>  hw/pxa2xx_mmci.c              |    2
>  hw/pxa2xx_pic.c               |    3 -
>  hw/pxa2xx_timer.c             |    2
>  hw/qdev.c                     |    4 -
>  hw/qdev.h                     |    3 +
>  hw/r2d.c                      |    4 -
>  hw/rc4030.c                   |    2
>  hw/realview.c                 |    6 +
>  hw/s390-virtio.c              |    2
>  hw/serial.c                   |    4 -
>  hw/sm501.c                    |    2
>  hw/spitz.c                    |   11 +-
>  hw/ssd0323.c                  |    3 -
>  hw/ssi-sd.c                   |    2
>  hw/stellaris.c                |   11 +-
>  hw/stellaris_enet.c           |    4 -
>  hw/stellaris_input.c          |    2
>  hw/sun4m.c                    |    8 +-
>  hw/sun4u.c                    |    4 -
>  hw/syborg.c                   |    2
>  hw/syborg_fb.c                |    2
>  hw/syborg_interrupt.c         |    3 -
>  hw/syborg_keyboard.c          |    2
>  hw/syborg_pointer.c           |    2
>  hw/syborg_rtc.c               |    3 -
>  hw/syborg_serial.c            |    2
>  hw/syborg_timer.c             |    2
>  hw/tc6393xb.c                 |    2
>  hw/tcx.c                      |    2
>  hw/tosa.c                     |    2
>  hw/tsc2005.c                  |    2
>  hw/tsc210x.c                  |    4 -
>  hw/unin_pci.c                 |    6 +
>  hw/versatilepb.c              |    2
>  hw/vga-isa-mm.c               |    2
>  hw/vga-isa.c                  |    2
>  hw/vga.c                      |    2
>  hw/virtio-balloon.c           |    3 -
>  hw/virtio-blk.c               |    2
>  hw/virtio-net.c               |    7 +-
>  hw/virtio-serial-bus.c        |    2
>  hw/vmmouse.c                  |    2
>  hw/vmware_vga.c               |    4 -
>  hw/zaurus.c                   |    2
>  qemu-timer.c                  |    2
>  savevm.c                      |  106 +++++++++++++++++++++---
>  slirp/slirp.c                 |    5 +
>  vl.c                          |    2
>  130 files changed, 648 insertions(+), 286 deletions(-)
>
>
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path()
  2010-06-24  4:41 ` [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path() Alex Williamson
@ 2010-06-24  7:39   ` Isaku Yamahata
  2010-06-24 15:05     ` Alex Williamson
  0 siblings, 1 reply; 60+ messages in thread
From: Isaku Yamahata @ 2010-06-24  7:39 UTC (permalink / raw)
  To: Alex Williamson; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On Wed, Jun 23, 2010 at 10:41:13PM -0600, Alex Williamson wrote:
> This works great for PCI since a <segment>:<bus>:<dev>.<fn> uniquely
> describes a global address.  No need to traverse up the qdev tree.
> PCI segment support is a placeholder for compatibility once we
> support multiple segments.
> 
> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> ---
> 
>  hw/pci.c |   14 ++++++++++++++
>  1 files changed, 14 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 7787005..5c9d6b4 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -58,11 +58,13 @@ struct PCIBus {
>  };
>  
>  static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
> +static char *pcibus_get_dev_path(DeviceState *dev);
>  
>  static struct BusInfo pci_bus_info = {
>      .name       = "PCI",
>      .size       = sizeof(PCIBus),
>      .print_dev  = pcibus_dev_print,
> +    .get_dev_path = pcibus_get_dev_path,
>      .props      = (Property[]) {
>          DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
>          DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
> @@ -1853,6 +1855,18 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
>      }
>  }
>  
> +static char *pcibus_get_dev_path(DeviceState *dev)
> +{
> +    PCIDevice *d = (PCIDevice *)dev;
> +    char path[16];
> +
> +    snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
> +             0 /* FIXME for segment support */, d->config[PCI_SECONDARY_BUS],

pci_find_domain(d->bus)


> +             PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> +
> +    return strdup(path);
> +}
> +
>  static PCIDeviceInfo bridge_info = {
>      .qdev.name    = "pci-bridge",
>      .qdev.size    = sizeof(PCIBridge),
> 
> 

-- 
yamahata

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH 00/15] Make migration work with hotplug
  2010-06-24  6:02 ` [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Yoshiaki Tamura
@ 2010-06-24 15:04   ` Alex Williamson
  2010-06-24 15:23     ` Alex Williamson
  0 siblings, 1 reply; 60+ messages in thread
From: Alex Williamson @ 2010-06-24 15:04 UTC (permalink / raw)
  To: Yoshiaki Tamura; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On Thu, 2010-06-24 at 15:02 +0900, Yoshiaki Tamura wrote:
> 
> Hi Alex,
> 
> Is there additional overhead to save rams introduce by this series?
> If so, how much?

Yes, there is overhead, but it's typically quite small.  If I migrate a
1G VM immediately after I boot to a login prompt (lots of zero pages), I
get an overhead of 0.000076%.  That's only 226 extra bytes over the
297164995 bytes otherwise transferred.  If I build a kernel on the guest
and migrate during the compilation, the overhead is 0.000019%.  The
overhead is tiny largely due to patch 12/15, which avoids sending the
block name if we're working within the same block as sent previously.
If I disable this optimization, the overhead goes up to 0.93% after boot
and 0.26% during a kernel compile.

Note that an x86 VM does a separate qemu_ram_alloc for memory above 4G,
which means in bigger VMs we may end up needing to resend the ramblock
name once in a while as we bounce between above and below 4G.  Worst
case for this could match the 0.26% above, but in my testing during a
kernel compile, this seems to increase the overhead to 0.000026% on a 6G
VM.  I don't see any reason why we couldn't allocate all the ram in a
single qemu_ram_alloc call, so I'll add another patch to make that
change (which will also shorten the name to "pc.ram" for even less
overhead ;).  Thanks,

Alex

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path()
  2010-06-24  7:39   ` Isaku Yamahata
@ 2010-06-24 15:05     ` Alex Williamson
  0 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24 15:05 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On Thu, 2010-06-24 at 16:39 +0900, Isaku Yamahata wrote:
> On Wed, Jun 23, 2010 at 10:41:13PM -0600, Alex Williamson wrote:
> > This works great for PCI since a <segment>:<bus>:<dev>.<fn> uniquely
> > describes a global address.  No need to traverse up the qdev tree.
> > PCI segment support is a placeholder for compatibility once we
> > support multiple segments.
> > 
> > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> > ---
> > 
> >  hw/pci.c |   14 ++++++++++++++
> >  1 files changed, 14 insertions(+), 0 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 7787005..5c9d6b4 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -58,11 +58,13 @@ struct PCIBus {
> >  };
> >  
> >  static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
> > +static char *pcibus_get_dev_path(DeviceState *dev);
> >  
> >  static struct BusInfo pci_bus_info = {
> >      .name       = "PCI",
> >      .size       = sizeof(PCIBus),
> >      .print_dev  = pcibus_dev_print,
> > +    .get_dev_path = pcibus_get_dev_path,
> >      .props      = (Property[]) {
> >          DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
> >          DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
> > @@ -1853,6 +1855,18 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
> >      }
> >  }
> >  
> > +static char *pcibus_get_dev_path(DeviceState *dev)
> > +{
> > +    PCIDevice *d = (PCIDevice *)dev;
> > +    char path[16];
> > +
> > +    snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
> > +             0 /* FIXME for segment support */, d->config[PCI_SECONDARY_BUS],
> 
> pci_find_domain(d->bus)

Thank you Isaku, I'll make the change.

Alex

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [Qemu-devel] Re: [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name
  2010-06-24  5:51   ` [Qemu-devel] " Paolo Bonzini
@ 2010-06-24 15:06     ` Alex Williamson
  0 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-24 15:06 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On Thu, 2010-06-24 at 07:51 +0200, Paolo Bonzini wrote:
> > @@ -377,26 +398,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
> >           } else if (flags&  RAM_SAVE_FLAG_PAGE) {
> >               void *host;
> >
> > -            if (version_id == 3) {
> > +            if (version_id == 3)
> >                   host = qemu_get_ram_ptr(addr);
> > -            } else {
> > -                RAMBlock *block;
> > -                char id[256];
> > -                uint8_t len;
> > +            else
> > +                host = host_from_stream_offset(f, addr, flags);
> >
> > -                len = qemu_get_byte(f);
> > -                qemu_get_buffer(f, (uint8_t *)id, len);
> > -                id[len] = 0;
> > -
> > -                QLIST_FOREACH(block,&ram_list.blocks, next) {
> > -                    if (!strncmp(id, block->idstr, sizeof(id)))
> > -                        break;
> > -                }
> > -                if (!block)
> > -                    return -EINVAL;
> > -
> > -                host = block->host + addr;
> > -            }
> >               qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
> >           }
> >           if (qemu_file_has_error(f)) {
> 
> Gah, sorry. :)
> 
> This also takes care of the code duplication, great.

It was certainly a good thought ;)  See my reply to Yoshi for the
overhead saved.  Thanks,

Alex

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH 00/15] Make migration work with hotplug
  2010-06-24 15:04   ` Alex Williamson
@ 2010-06-24 15:23     ` Alex Williamson
  2010-06-25  2:01       ` Yoshiaki Tamura
  0 siblings, 1 reply; 60+ messages in thread
From: Alex Williamson @ 2010-06-24 15:23 UTC (permalink / raw)
  To: Yoshiaki Tamura; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

On Thu, 2010-06-24 at 09:04 -0600, Alex Williamson wrote:
> On Thu, 2010-06-24 at 15:02 +0900, Yoshiaki Tamura wrote:
> > 
> > Hi Alex,
> > 
> > Is there additional overhead to save rams introduce by this series?
> > If so, how much?
> 
> Yes, there is overhead, but it's typically quite small.  If I migrate a
> 1G VM immediately after I boot to a login prompt (lots of zero pages), I
> get an overhead of 0.000076%.  That's only 226 extra bytes over the
> 297164995 bytes otherwise transferred.  If I build a kernel on the guest
> and migrate during the compilation, the overhead is 0.000019%.  The
> overhead is tiny largely due to patch 12/15, which avoids sending the
> block name if we're working within the same block as sent previously.
> If I disable this optimization, the overhead goes up to 0.93% after boot
> and 0.26% during a kernel compile.
> 
> Note that an x86 VM does a separate qemu_ram_alloc for memory above 4G,
> which means in bigger VMs we may end up needing to resend the ramblock
> name once in a while as we bounce between above and below 4G.  Worst
> case for this could match the 0.26% above, but in my testing during a
> kernel compile, this seems to increase the overhead to 0.000026% on a 6G
> VM.  I don't see any reason why we couldn't allocate all the ram in a
> single qemu_ram_alloc call, so I'll add another patch to make that
> change (which will also shorten the name to "pc.ram" for even less
> overhead ;).  Thanks,

FWIW, with this change, my migration during kernel compile on the 6G VM
seems to be running just at 0.000019%-0.000020%, so that eliminates the
penalty for bigger memory VMs.  Thanks,

Alex

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH 00/15] Make migration work with hotplug
  2010-06-24 15:23     ` Alex Williamson
@ 2010-06-25  2:01       ` Yoshiaki Tamura
  0 siblings, 0 replies; 60+ messages in thread
From: Yoshiaki Tamura @ 2010-06-25  2:01 UTC (permalink / raw)
  To: Alex Williamson; +Cc: jan.kiszka, qemu-devel, armbru, paul, cam, kraxel

Alex Williamson wrote:
> On Thu, 2010-06-24 at 09:04 -0600, Alex Williamson wrote:
>> On Thu, 2010-06-24 at 15:02 +0900, Yoshiaki Tamura wrote:
>>>
>>> Hi Alex,
>>>
>>> Is there additional overhead to save rams introduce by this series?
>>> If so, how much?
>>
>> Yes, there is overhead, but it's typically quite small.  If I migrate a
>> 1G VM immediately after I boot to a login prompt (lots of zero pages), I
>> get an overhead of 0.000076%.  That's only 226 extra bytes over the
>> 297164995 bytes otherwise transferred.  If I build a kernel on the guest
>> and migrate during the compilation, the overhead is 0.000019%.  The
>> overhead is tiny largely due to patch 12/15, which avoids sending the
>> block name if we're working within the same block as sent previously.
>> If I disable this optimization, the overhead goes up to 0.93% after boot
>> and 0.26% during a kernel compile.

Thank your for the detailed numbers and analysis!
If the overhead is at this level, I think it's worth introducing to support 
migration with hot plug devices.

>> Note that an x86 VM does a separate qemu_ram_alloc for memory above 4G,
>> which means in bigger VMs we may end up needing to resend the ramblock
>> name once in a while as we bounce between above and below 4G.  Worst
>> case for this could match the 0.26% above, but in my testing during a
>> kernel compile, this seems to increase the overhead to 0.000026% on a 6G
>> VM.

If we run a program which bounce between the region intentionally, we should get 
a number close to 0.26%, but the overhead is still low enough, and it shouldn't 
be a big problem.

>> I don't see any reason why we couldn't allocate all the ram in a
>> single qemu_ram_alloc call, so I'll add another patch to make that
>> change (which will also shorten the name to "pc.ram" for even less
>> overhead ;).  Thanks,

Hmm.  I didn't know about the qemu_ram_alloc over 4G issue.
If there isn't any reason, how about submitting a patch to fix it besides this 
series?

> FWIW, with this change, my migration during kernel compile on the 6G VM
> seems to be running just at 0.000019%-0.000020%, so that eliminates the
> penalty for bigger memory VMs.  Thanks,

It make sense:-)

Thanks,

Yoshi

>
> Alex
>
>
>
>
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 00/16] Make migration work with hotplug
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (15 preceding siblings ...)
  2010-06-24  6:02 ` [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Yoshiaki Tamura
@ 2010-06-25 17:08 ` Alex Williamson
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
                     ` (15 more replies)
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
  17 siblings, 16 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

v2:

Not too many comments, hope that's because everyone agrees ;)
A couple minor changes.  The 2nd patch is new and provides a
bit of an optimization for large memory pc guets.  The first
two patches stand on their own even if we're undecided about
the rest.  Thanks,

Alex

changes:
  - Use pci_find_domain() for PCI domain, thanks Isaku
  - Convert pc to allocate all ram in one chunk, which avoids
    penalizing large memory VMs bouncing between ramblocks
    during migration.

v1:

Ok, new approach.  I'm going to attempt to extract myself for the
canonical device path approach, because we're missing too many pieces
to make that work.  Instead, I'll take Anthony's advice and try to
simplify.  We still want a unique name for ramblocks and savevm, but
the hotplug problem today is only for PCI devices.  PCI conveniently
has globally unique, dare I say canonical, addressing in the form of
<domain>:<bus>:<device>.<func>.  To get to this, let's add a new
function on the BusInfo structure called get_dev_path().  For a PCI
device, we can simply traverse up the qdev tree to the BusInfo
structure, look for the function, and call it to return a global PCI
address.

For some buses, these functions could chain up to their parent bus
appending strings together to get a unique path.  An example would be
USB, where the USB port number may not be unique.  If we traverse up
to the PCI device providing USB, and then to the PCI bus, we get a
globally unique PCI path, appended with a USB port number.

To make this work for ramblocks and savevm, we need a DeviceState
pointer when the they are create/registered, and we need a caller
provided context in case there are multiple ramblocks/savevm
associated with a device.  Savevm already provies the context,
and I've attempted to make reasonable guesses at these for the
ramblocks.  Note that most of the ramblocks aren't associated with
a device, so I don't think it makes sense to link savevm and
ramblocks together with the same absolute id string.

Once we have savevm with unique id strings, rather than hotplug
unfriendly instance numbers, we can be sure that the right driver
instance is loading the correct vmstate.  I've also implemented
a compat field for this, so we can still accept incoming migrations
from previous versions.

Once we have ramblocks with a unique id string, we can switch to
using id + offset for migration, which enables a ram_addr_t space
that supports gaps, which enables us to implement qemu_ram_free().  
With that, I think we can finally do migrations reliable after
hotplug!  Note that the target VM still needs to be created to
match the current devices and bus addresses of the source VM.  We
can also still maintain compatibility for migrations here by bumping
the ram migration version and supporting both new and old (just
hope the source hasn't done any hotplugs).

Sound reasonable?  Is get_dev_path the right name?  In the right
place?  The PCI return is currently "dddd:bb:dd.f", should this be
"PCI:dddd:bb:dd.f"?  Something else?  Thanks,

Alex

---

Alex Williamson (16):
      ramblocks: No more being lazy about duplicate names
      pci: Free the space allocated for the option rom on removal
      qemu_ram_free: Implement it
      savevm: Create a new continue flag to avoid resending block name
      savevm: Use RAM blocks for basis of migration
      savevm: Migrate RAM based on name/offset
      ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
      qemu_ram_alloc: Add DeviceState and name parameters
      virtio-net: Incorporate a DeviceState pointer and let savevm track instances
      eepro100: Add a dev field to eeprom new/free functions
      savevm: Make use of DeviceState
      savevm: Add DeviceState param
      pci: Implement BusInfo.get_dev_path()
      qdev: Add a get_dev_path() function to BusInfo
      pc: Allocate all ram in a single qemu_ram_alloc()
      Remove uses of ram.last_offset (aka last_ram_offset)


 arch_init.c                   |  183 +++++++++++++++++++++++++++++++++++------
 audio/audio.c                 |    2 
 block-migration.c             |    4 -
 cpu-all.h                     |    5 +
 cpu-common.h                  |    2 
 exec.c                        |   96 +++++++++++++++++++---
 hw/adb.c                      |    4 -
 hw/ads7846.c                  |    2 
 hw/an5206.c                   |    4 -
 hw/arm_gic.c                  |    2 
 hw/arm_timer.c                |    4 -
 hw/armv7m.c                   |    9 +-
 hw/armv7m_nvic.c              |    2 
 hw/axis_dev88.c               |    4 -
 hw/cirrus_vga.c               |    2 
 hw/cuda.c                     |    2 
 hw/dma.c                      |    4 -
 hw/dummy_m68k.c               |    2 
 hw/eepro100.c                 |    8 +-
 hw/eeprom93xx.c               |    8 +-
 hw/eeprom93xx.h               |    4 -
 hw/etraxfs.c                  |    6 +
 hw/fw_cfg.c                   |    2 
 hw/g364fb.c                   |    4 -
 hw/grackle_pci.c              |    4 -
 hw/gt64xxx.c                  |    3 -
 hw/gumstix.c                  |    6 +
 hw/heathrow_pic.c             |    2 
 hw/hw.h                       |   18 ++--
 hw/i2c.c                      |    2 
 hw/i8254.c                    |    2 
 hw/i8259.c                    |    2 
 hw/ide/cmd646.c               |    2 
 hw/ide/isa.c                  |    2 
 hw/ide/macio.c                |    2 
 hw/ide/microdrive.c           |    2 
 hw/ide/mmio.c                 |    2 
 hw/ide/piix.c                 |    2 
 hw/integratorcp.c             |    4 -
 hw/m48t59.c                   |    2 
 hw/mac_dbdma.c                |    2 
 hw/mac_nvram.c                |    4 -
 hw/mainstone.c                |    6 +
 hw/max111x.c                  |    3 -
 hw/mcf5208.c                  |    4 -
 hw/mips_jazz.c                |    4 -
 hw/mips_malta.c               |    4 -
 hw/mips_mipssim.c             |    4 -
 hw/mips_r4k.c                 |    6 +
 hw/mipsnet.c                  |    4 -
 hw/mst_fpga.c                 |    3 -
 hw/musicpal.c                 |   11 ++
 hw/nand.c                     |    2 
 hw/omap1.c                    |    6 +
 hw/omap2.c                    |    6 +
 hw/omap_sx1.c                 |   12 ++-
 hw/onenand.c                  |    2 
 hw/openpic.c                  |    5 +
 hw/palm.c                     |    3 -
 hw/pc.c                       |   27 +++---
 hw/pci.c                      |   34 +++++++-
 hw/pckbd.c                    |    2 
 hw/petalogix_s3adsp1800_mmu.c |    7 +-
 hw/piix4.c                    |    2 
 hw/pl011.c                    |    2 
 hw/pl022.c                    |    2 
 hw/pl061.c                    |    2 
 hw/ppc405_boards.c            |   18 ++--
 hw/ppc405_uc.c                |    2 
 hw/ppc4xx_devs.c              |    4 +
 hw/ppc4xx_pci.c               |    4 -
 hw/ppc_newworld.c             |    6 +
 hw/ppc_oldworld.c             |    6 +
 hw/ppc_prep.c                 |    4 -
 hw/ppce500_mpc8544ds.c        |    3 -
 hw/ppce500_pci.c              |    4 -
 hw/ps2.c                      |    4 -
 hw/pxa2xx.c                   |   39 +++++----
 hw/pxa2xx_dma.c               |    2 
 hw/pxa2xx_gpio.c              |    2 
 hw/pxa2xx_keypad.c            |    2 
 hw/pxa2xx_lcd.c               |    2 
 hw/pxa2xx_mmci.c              |    2 
 hw/pxa2xx_pic.c               |    3 -
 hw/pxa2xx_timer.c             |    2 
 hw/qdev.c                     |    4 -
 hw/qdev.h                     |    3 +
 hw/r2d.c                      |    4 -
 hw/rc4030.c                   |    2 
 hw/realview.c                 |    6 +
 hw/s390-virtio.c              |    2 
 hw/serial.c                   |    4 -
 hw/sm501.c                    |    2 
 hw/spitz.c                    |   11 +-
 hw/ssd0323.c                  |    3 -
 hw/ssi-sd.c                   |    2 
 hw/stellaris.c                |   11 +-
 hw/stellaris_enet.c           |    4 -
 hw/stellaris_input.c          |    2 
 hw/sun4m.c                    |    8 +-
 hw/sun4u.c                    |    4 -
 hw/syborg.c                   |    2 
 hw/syborg_fb.c                |    2 
 hw/syborg_interrupt.c         |    3 -
 hw/syborg_keyboard.c          |    2 
 hw/syborg_pointer.c           |    2 
 hw/syborg_rtc.c               |    3 -
 hw/syborg_serial.c            |    2 
 hw/syborg_timer.c             |    2 
 hw/tc6393xb.c                 |    2 
 hw/tcx.c                      |    2 
 hw/tosa.c                     |    2 
 hw/tsc2005.c                  |    2 
 hw/tsc210x.c                  |    4 -
 hw/unin_pci.c                 |    6 +
 hw/versatilepb.c              |    2 
 hw/vga-isa-mm.c               |    2 
 hw/vga-isa.c                  |    2 
 hw/vga.c                      |    2 
 hw/virtio-balloon.c           |    3 -
 hw/virtio-blk.c               |    2 
 hw/virtio-net.c               |    7 +-
 hw/virtio-serial-bus.c        |    2 
 hw/vmmouse.c                  |    2 
 hw/vmware_vga.c               |    4 -
 hw/zaurus.c                   |    2 
 qemu-timer.c                  |    2 
 savevm.c                      |  106 +++++++++++++++++++++---
 slirp/slirp.c                 |    5 +
 vl.c                          |    2 
 130 files changed, 656 insertions(+), 297 deletions(-)

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset)
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
@ 2010-06-25 17:08   ` Alex Williamson
  2010-07-06 15:45     ` Anthony Liguori
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 02/16] pc: Allocate all ram in a single qemu_ram_alloc() Alex Williamson
                     ` (14 subsequent siblings)
  15 siblings, 1 reply; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

We currently need this either to allocate the next ram_addr_t for a
new block, or for total memory to be migrated.  Both of which we can
calculate without need of this to keep us in a contiguous address space.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   23 ++++++++++++++++-------
 cpu-all.h   |    1 -
 exec.c      |   19 ++++++++++++++-----
 3 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index eb5b67c..109dcef 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -108,9 +108,10 @@ static int ram_save_block(QEMUFile *f)
     static ram_addr_t current_addr = 0;
     ram_addr_t saved_addr = current_addr;
     ram_addr_t addr = 0;
+    uint64_t total_ram = ram_bytes_total();
     int bytes_sent = 0;
 
-    while (addr < ram_list.last_offset) {
+    while (addr < total_ram) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
 
@@ -133,7 +134,7 @@ static int ram_save_block(QEMUFile *f)
             break;
         }
         addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % ram_list.last_offset;
+        current_addr = (saved_addr + addr) % total_ram;
     }
 
     return bytes_sent;
@@ -145,8 +146,9 @@ static ram_addr_t ram_save_remaining(void)
 {
     ram_addr_t addr;
     ram_addr_t count = 0;
+    uint64_t total_ram = ram_bytes_total();
 
-    for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
+    for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
         if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
             count++;
         }
@@ -167,7 +169,13 @@ uint64_t ram_bytes_transferred(void)
 
 uint64_t ram_bytes_total(void)
 {
-    return ram_list.last_offset;
+    RAMBlock *block;
+    uint64_t total = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        total += block->length;
+
+    return total;
 }
 
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
@@ -188,10 +196,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
+        for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
             if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
                 cpu_physical_memory_set_dirty(addr);
             }
@@ -200,7 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, ram_list.last_offset | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -259,7 +268,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != ram_list.last_offset) {
+            if (addr != ram_bytes_total()) {
                 return -EINVAL;
             }
         }
diff --git a/cpu-all.h b/cpu-all.h
index e31c2de..dbb2139 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -870,7 +870,6 @@ typedef struct RAMBlock {
 
 typedef struct RAMList {
     uint8_t *phys_dirty;
-    ram_addr_t last_offset;
     QLIST_HEAD(ram, RAMBlock) blocks;
 } RAMList;
 extern RAMList ram_list;
diff --git a/exec.c b/exec.c
index 7f64384..058b709 100644
--- a/exec.c
+++ b/exec.c
@@ -2765,6 +2765,17 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 }
 #endif
 
+static ram_addr_t find_ram_offset(ram_addr_t size)
+{
+    RAMBlock *block;
+    ram_addr_t last = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        last = MAX(last, block->offset + block->length);
+
+    return last;
+}
+
 ram_addr_t qemu_ram_alloc(ram_addr_t size)
 {
     RAMBlock *new_block;
@@ -2798,18 +2809,16 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
         madvise(new_block->host, size, MADV_MERGEABLE);
 #endif
     }
-    new_block->offset = ram_list.last_offset;
+    new_block->offset = find_ram_offset(size);
     new_block->length = size;
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
-        (ram_list.last_offset + size) >> TARGET_PAGE_BITS);
-    memset(ram_list.phys_dirty + (ram_list.last_offset >> TARGET_PAGE_BITS),
+        (new_block->offset + size) >> TARGET_PAGE_BITS);
+    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0xff, size >> TARGET_PAGE_BITS);
 
-    ram_list.last_offset += size;
-
     if (kvm_enabled())
         kvm_setup_guest_memory(new_block->host, size);
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 02/16] pc: Allocate all ram in a single qemu_ram_alloc()
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
@ 2010-06-25 17:08   ` Alex Williamson
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 03/16] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
                     ` (13 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This will benefit us when we migrate based on ramblock name since
we won't be bouncing between separate blocks.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pc.c |   22 +++++++++-------------
 1 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 1848151..d6f3aa4 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -893,27 +893,23 @@ void pc_memory_init(ram_addr_t ram_size,
     *above_4g_mem_size_p = above_4g_mem_size;
     *below_4g_mem_size_p = below_4g_mem_size;
 
+#if TARGET_PHYS_ADDR_BITS == 32
+    if (above_4g_mem_size > 0) {
+        hw_error("To much RAM for 32-bit physical address");
+    }
+#endif
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(below_4g_mem_size);
+    ram_addr = qemu_ram_alloc(below_4g_mem_size + above_4g_mem_size);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
                  ram_addr + 0x100000);
-
-    /* above 4giga memory allocation */
-    if (above_4g_mem_size > 0) {
-#if TARGET_PHYS_ADDR_BITS == 32
-        hw_error("To much RAM for 32-bit physical address");
-#else
-        ram_addr = qemu_ram_alloc(above_4g_mem_size);
-        cpu_register_physical_memory(0x100000000ULL,
-                                     above_4g_mem_size,
-                                     ram_addr);
+#if TARGET_PHYS_ADDR_BITS > 32
+    cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
+                                 ram_addr + below_4g_mem_size);
 #endif
-    }
-
 
     /* BIOS load */
     if (bios_name == NULL)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 03/16] qdev: Add a get_dev_path() function to BusInfo
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 02/16] pc: Allocate all ram in a single qemu_ram_alloc() Alex Williamson
@ 2010-06-25 17:08   ` Alex Williamson
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 04/16] pci: Implement BusInfo.get_dev_path() Alex Williamson
                     ` (12 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This function is meant to provide a stable device path for buses
which are able to implement it.  If a bus has a globally unique
addresses scheme, one address level may be sufficient to provide
a path.  Other buses may need to recursively traverse up the
qdev tree.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/qdev.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/qdev.h b/hw/qdev.h
index be5ad67..d64619f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -49,10 +49,13 @@ struct DeviceState {
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
+typedef char *(*bus_get_dev_path)(DeviceState *dev);
+
 struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
+    bus_get_dev_path get_dev_path;
     Property *props;
 };
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 04/16] pci: Implement BusInfo.get_dev_path()
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (2 preceding siblings ...)
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 03/16] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
@ 2010-06-25 17:08   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 05/16] savevm: Add DeviceState param Alex Williamson
                     ` (11 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This works great for PCI since a <segment>:<bus>:<dev>.<fn> uniquely
describes a global address.  No need to traverse up the qdev tree.
PCI segment support is a placeholder for compatibility once we
support multiple segments.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pci.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7787005..1e77ae6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -58,11 +58,13 @@ struct PCIBus {
 };
 
 static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static char *pcibus_get_dev_path(DeviceState *dev);
 
 static struct BusInfo pci_bus_info = {
     .name       = "PCI",
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
+    .get_dev_path = pcibus_get_dev_path,
     .props      = (Property[]) {
         DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
         DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
@@ -1853,6 +1855,18 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     }
 }
 
+static char *pcibus_get_dev_path(DeviceState *dev)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    char path[16];
+
+    snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
+             pci_find_domain(d->bus), d->config[PCI_SECONDARY_BUS],
+             PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+
+    return strdup(path);
+}
+
 static PCIDeviceInfo bridge_info = {
     .qdev.name    = "pci-bridge",
     .qdev.size    = sizeof(PCIBridge),

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 05/16] savevm: Add DeviceState param
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (3 preceding siblings ...)
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 04/16] pci: Implement BusInfo.get_dev_path() Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 06/16] savevm: Make use of DeviceState Alex Williamson
                     ` (10 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

When available, we'd like to be able to access the DeviceState
when registering a savevm.  For buses with a get_dev_path()
function, this will allow us to create more unique savevm
id strings.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 audio/audio.c          |    2 +-
 block-migration.c      |    4 ++--
 exec.c                 |    4 ++--
 hw/adb.c               |    4 ++--
 hw/ads7846.c           |    2 +-
 hw/arm_gic.c           |    2 +-
 hw/arm_timer.c         |    4 ++--
 hw/armv7m_nvic.c       |    2 +-
 hw/cirrus_vga.c        |    2 +-
 hw/cuda.c              |    2 +-
 hw/dma.c               |    4 ++--
 hw/eepro100.c          |    4 ++--
 hw/eeprom93xx.c        |    4 ++--
 hw/fw_cfg.c            |    2 +-
 hw/g364fb.c            |    2 +-
 hw/grackle_pci.c       |    4 ++--
 hw/gt64xxx.c           |    3 ++-
 hw/heathrow_pic.c      |    2 +-
 hw/hw.h                |   18 +++++++++++-------
 hw/i2c.c               |    2 +-
 hw/i8254.c             |    2 +-
 hw/i8259.c             |    2 +-
 hw/ide/cmd646.c        |    2 +-
 hw/ide/isa.c           |    2 +-
 hw/ide/macio.c         |    2 +-
 hw/ide/microdrive.c    |    2 +-
 hw/ide/mmio.c          |    2 +-
 hw/ide/piix.c          |    2 +-
 hw/m48t59.c            |    2 +-
 hw/mac_dbdma.c         |    2 +-
 hw/mac_nvram.c         |    4 ++--
 hw/max111x.c           |    3 ++-
 hw/mipsnet.c           |    4 ++--
 hw/mst_fpga.c          |    3 ++-
 hw/nand.c              |    2 +-
 hw/openpic.c           |    5 +++--
 hw/pci.c               |    2 +-
 hw/pckbd.c             |    2 +-
 hw/piix4.c             |    2 +-
 hw/pl011.c             |    2 +-
 hw/pl022.c             |    2 +-
 hw/pl061.c             |    2 +-
 hw/ppc4xx_pci.c        |    4 ++--
 hw/ppce500_pci.c       |    4 ++--
 hw/ps2.c               |    4 ++--
 hw/pxa2xx.c            |   27 +++++++++++++++------------
 hw/pxa2xx_dma.c        |    2 +-
 hw/pxa2xx_gpio.c       |    2 +-
 hw/pxa2xx_keypad.c     |    2 +-
 hw/pxa2xx_lcd.c        |    2 +-
 hw/pxa2xx_mmci.c       |    2 +-
 hw/pxa2xx_pic.c        |    3 ++-
 hw/pxa2xx_timer.c      |    2 +-
 hw/qdev.c              |    4 ++--
 hw/rc4030.c            |    2 +-
 hw/serial.c            |    4 ++--
 hw/spitz.c             |    9 +++++----
 hw/ssd0323.c           |    3 ++-
 hw/ssi-sd.c            |    2 +-
 hw/stellaris.c         |   11 ++++++-----
 hw/stellaris_enet.c    |    4 ++--
 hw/stellaris_input.c   |    2 +-
 hw/syborg_fb.c         |    2 +-
 hw/syborg_interrupt.c  |    3 ++-
 hw/syborg_keyboard.c   |    2 +-
 hw/syborg_pointer.c    |    2 +-
 hw/syborg_rtc.c        |    3 ++-
 hw/syborg_serial.c     |    2 +-
 hw/syborg_timer.c      |    2 +-
 hw/tsc2005.c           |    2 +-
 hw/tsc210x.c           |    4 ++--
 hw/unin_pci.c          |    6 ++++--
 hw/vga-isa-mm.c        |    2 +-
 hw/vga-isa.c           |    2 +-
 hw/virtio-balloon.c    |    3 ++-
 hw/virtio-blk.c        |    2 +-
 hw/virtio-net.c        |    4 ++--
 hw/virtio-serial-bus.c |    2 +-
 hw/vmmouse.c           |    2 +-
 hw/vmware_vga.c        |    2 +-
 hw/zaurus.c            |    2 +-
 qemu-timer.c           |    2 +-
 savevm.c               |   22 +++++++++++++---------
 slirp/slirp.c          |    5 +++--
 vl.c                   |    2 +-
 85 files changed, 163 insertions(+), 138 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index dbf0b96..ad51077 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1901,7 +1901,7 @@ static void audio_init (void)
     }
 
     QLIST_INIT (&s->card_head);
-    vmstate_register (0, &vmstate_audio, s);
+    vmstate_register (NULL, 0, &vmstate_audio, s);
 }
 
 void AUD_register_card (const char *name, QEMUSoundCard *card)
diff --git a/block-migration.c b/block-migration.c
index 7d04d6d..533564c 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -638,6 +638,6 @@ void blk_mig_init(void)
     QSIMPLEQ_INIT(&block_mig_state.bmds_list);
     QSIMPLEQ_INIT(&block_mig_state.blk_list);
 
-    register_savevm_live("block", 0, 1, block_set_params, block_save_live,
-                         NULL, block_load, &block_mig_state);
+    register_savevm_live(NULL, "block", 0, 1, block_set_params,
+                         block_save_live, NULL, block_load, &block_mig_state);
 }
diff --git a/exec.c b/exec.c
index 058b709..088d665 100644
--- a/exec.c
+++ b/exec.c
@@ -641,8 +641,8 @@ void cpu_exec_init(CPUState *env)
     cpu_list_unlock();
 #endif
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
-    vmstate_register(cpu_index, &vmstate_cpu_common, env);
-    register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
+    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
 #endif
 }
diff --git a/hw/adb.c b/hw/adb.c
index 4fb7a62..99b30f6 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -305,7 +305,7 @@ void adb_kbd_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                             adb_kbd_reset, s);
     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
-    register_savevm("adb_kbd", -1, 1, adb_kbd_save,
+    register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save,
                     adb_kbd_load, s);
 }
 
@@ -475,6 +475,6 @@ void adb_mouse_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                             adb_mouse_reset, s);
     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
-    register_savevm("adb_mouse", -1, 1, adb_mouse_save,
+    register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save,
                     adb_mouse_load, s);
 }
diff --git a/hw/ads7846.c b/hw/ads7846.c
index 184b3dd..b3bbeaf 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -151,7 +151,7 @@ static int ads7846_init(SSISlave *dev)
 
     ads7846_int_update(s);
 
-    register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s);
+    register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s);
     return 0;
 }
 
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index c4afc6a..8286a28 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -744,5 +744,5 @@ static void gic_init(gic_state *s)
     s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
                                           gic_dist_writefn, s);
     gic_reset(s);
-    register_savevm("arm_gic", -1, 1, gic_save, gic_load, s);
+    register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
 }
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9073ffc..f009e9e 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -174,7 +174,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 
     bh = qemu_bh_new(arm_timer_tick, s);
     s->timer = ptimer_init(bh);
-    register_savevm("arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
+    register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
     return s;
 }
 
@@ -271,7 +271,7 @@ static int sp804_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(sp804_readfn,
                                        sp804_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm("sp804", -1, 1, sp804_save, sp804_load, s);
+    register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
     return 0;
 }
 
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 9f09ef4..6c7ce01 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -397,7 +397,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
     gic_init(&s->gic);
     cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
     s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
-    register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+    register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
     return 0;
 }
 
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index ba48289..bbd4b08 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3128,7 +3128,7 @@ void isa_cirrus_vga_init(void)
     s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
                                      s->vga.screen_dump, s->vga.text_update,
                                      &s->vga);
-    vmstate_register(0, &vmstate_cirrus_vga, s);
+    vmstate_register(NULL, 0, &vmstate_cirrus_vga, s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
 }
diff --git a/hw/cuda.c b/hw/cuda.c
index 50950d9..3f238b6 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -763,6 +763,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
 
     s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
     *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s);
-    register_savevm("cuda", -1, 1, cuda_save, cuda_load, s);
+    register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
     qemu_register_reset(cuda_reset, s);
 }
diff --git a/hw/dma.c b/hw/dma.c
index 5b21521..8a7302a 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -548,8 +548,8 @@ void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
               high_page_enable ? 0x480 : -1, cpu_request_exit);
     dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
               high_page_enable ? 0x488 : -1, cpu_request_exit);
-    vmstate_register (0, &vmstate_dma, &dma_controllers[0]);
-    vmstate_register (1, &vmstate_dma, &dma_controllers[1]);
+    vmstate_register (NULL, 0, &vmstate_dma, &dma_controllers[0]);
+    vmstate_register (NULL, 1, &vmstate_dma, &dma_controllers[1]);
 
     dma_bh = qemu_bh_new(DMA_run_bh, NULL);
 }
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 97afa2c..0ddca8b 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1834,7 +1834,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
     cpu_unregister_io_memory(s->mmio_index);
-    vmstate_unregister(s->vmstate, s);
+    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
     eeprom93xx_free(s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
@@ -1893,7 +1893,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
     s->vmstate = qemu_malloc(sizeof(vmstate_eepro100));
     memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
     s->vmstate->name = s->nic->nc.model;
-    vmstate_register(-1, s->vmstate, s);
+    vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
 
     return 0;
 }
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 30a3534..6ba546f 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -316,7 +316,7 @@ eeprom_t *eeprom93xx_new(uint16_t nwords)
     /* Output DO is tristate, read results in 1. */
     eeprom->eedo = 1;
     logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
-    vmstate_register(0, &vmstate_eeprom, eeprom);
+    vmstate_register(NULL, 0, &vmstate_eeprom, eeprom);
     return eeprom;
 }
 
@@ -324,7 +324,7 @@ void eeprom93xx_free(eeprom_t *eeprom)
 {
     /* Destroy EEPROM. */
     logout("eeprom = 0x%p\n", eeprom);
-    vmstate_unregister(&vmstate_eeprom, eeprom);
+    vmstate_unregister(NULL, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 22ebb50..ca8c538 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -352,7 +352,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
 
-    vmstate_register(-1, &vmstate_fw_cfg, s);
+    vmstate_register(NULL, -1, &vmstate_fw_cfg, s);
     qemu_register_reset(fw_cfg_reset, s);
 
     return s;
diff --git a/hw/g364fb.c b/hw/g364fb.c
index d1d2c12..beafd70 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -598,7 +598,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
     s->irq = irq;
 
     qemu_register_reset(g364fb_reset, s);
-    register_savevm("g364fb", 0, 1, g364fb_save, g364fb_load, s);
+    register_savevm(NULL, "g364fb", 0, 1, g364fb_save, g364fb_load, s);
     g364fb_reset(s);
 
     s->ds = graphic_console_init(g364fb_update_display,
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index aa0c51b..0cf29dc 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -113,8 +113,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("grackle", 0, 1, pci_grackle_save, pci_grackle_load,
-                    &s->host_state);
+    register_savevm(&dev->qdev, "grackle", 0, 1, pci_grackle_save,
+                    pci_grackle_load, &s->host_state);
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
 }
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 7691e1d..313c080 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1146,7 +1146,8 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
 
     gt64120_reset(s);
 
-    register_savevm("GT64120 PCI Bus", 0, 1, gt64120_save, gt64120_load, d);
+    register_savevm(&d->qdev, "GT64120 PCI Bus", 0, 1,
+                    gt64120_save, gt64120_load, d);
 
     return s->pci->bus;
 }
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index 5e27021..cd86121 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -224,7 +224,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
     s->irqs = irqs[0];
     *pmem_index = cpu_register_io_memory(pic_read, pic_write, s);
 
-    register_savevm("heathrow_pic", -1, 1, heathrow_pic_save,
+    register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
                     heathrow_pic_load, s);
     qemu_register_reset(heathrow_pic_reset, s);
     return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
diff --git a/hw/hw.h b/hw/hw.h
index a49d866..c2de6fe 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -245,14 +245,16 @@ typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
                                  void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
-int register_savevm(const char *idstr,
+int register_savevm(DeviceState *dev,
+                    const char *idstr,
                     int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
                     void *opaque);
 
-int register_savevm_live(const char *idstr,
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
                          int instance_id,
                          int version_id,
                          SaveSetParamsHandler *set_params,
@@ -261,7 +263,7 @@ int register_savevm_live(const char *idstr,
                          LoadStateHandler *load_state,
                          void *opaque);
 
-void unregister_savevm(const char *idstr, void *opaque);
+void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
 
 typedef void QEMUResetHandler(void *opaque);
 
@@ -765,11 +767,13 @@ extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                               void *opaque, int version_id);
 extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                                void *opaque);
-extern int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                            void *base);
-extern int vmstate_register_with_alias_id(int instance_id,
+extern int vmstate_register(DeviceState *dev, int instance_id,
+                            const VMStateDescription *vmsd, void *base);
+extern int vmstate_register_with_alias_id(DeviceState *dev,
+                                          int instance_id,
                                           const VMStateDescription *vmsd,
                                           void *base, int alias_id,
                                           int required_for_version);
-void vmstate_unregister(const VMStateDescription *vmsd, void *opaque);
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+                        void *opaque);
 #endif
diff --git a/hw/i2c.c b/hw/i2c.c
index bee8e88..f80d12d 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -62,7 +62,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
     i2c_bus *bus;
 
     bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
-    vmstate_register(-1, &vmstate_i2c_bus, bus);
+    vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
     return bus;
 }
 
diff --git a/hw/i8254.c b/hw/i8254.c
index faaa884..06b225c 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -508,7 +508,7 @@ PITState *pit_init(int base, qemu_irq irq)
     s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
     s->irq = irq;
 
-    vmstate_register(base, &vmstate_pit, pit);
+    vmstate_register(NULL, base, &vmstate_pit, pit);
     qemu_register_reset(pit_reset, pit);
     register_ioport_write(base, 4, 1, pit_ioport_write, pit);
     register_ioport_read(base, 3, 1, pit_ioport_read, pit);
diff --git a/hw/i8259.c b/hw/i8259.c
index a995280..a8dbee6 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -483,7 +483,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *s)
         register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
         register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
     }
-    vmstate_register(io_addr, &vmstate_pic, s);
+    vmstate_register(NULL, io_addr, &vmstate_pic, s);
     qemu_register_reset(pic_reset, s);
 }
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 559147f..8b71a13 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -263,7 +263,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     ide_init2(&d->bus[0], irq[0]);
     ide_init2(&d->bus[1], irq[1]);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
     qemu_register_reset(cmd646_reset, d);
     return 0;
 }
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index b6c6347..8c28c08 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -71,7 +71,7 @@ static int isa_ide_initfn(ISADevice *dev)
     ide_init_ioport(&s->bus, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
     ide_init2(&s->bus, s->irq);
-    vmstate_register(0, &vmstate_ide_isa, s);
+    vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s);
     return 0;
 };
 
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index f76c0fa..fd4bdfd 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -321,7 +321,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
 
     pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
                                              pmac_ide_write, d);
-    vmstate_register(0, &vmstate_pmac, d);
+    vmstate_register(NULL, 0, &vmstate_pmac, d);
     qemu_register_reset(pmac_ide_reset, d);
 
     return pmac_ide_memory;
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index a7beac5..8e20e74 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -545,7 +545,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
     md->bus.ifs[0].mdata_size = METADATA_SIZE;
     md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
 
-    vmstate_register(-1, &vmstate_microdrive, md);
+    vmstate_register(NULL, -1, &vmstate_microdrive, md);
 
     return &md->card;
 }
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index e75cccf..9f20e8b 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -133,7 +133,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
     mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s);
     cpu_register_physical_memory(membase, 16 << shift, mem1);
     cpu_register_physical_memory(membase2, 2 << shift, mem2);
-    vmstate_register(0, &vmstate_ide_mmio, s);
+    vmstate_register(NULL, 0, &vmstate_ide_mmio, s);
     qemu_register_reset(mmio_ide_reset, s);
 }
 
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index dad6e86..db27ef6 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -128,7 +128,7 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
 
     pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
     ide_bus_new(&d->bus[0], &d->dev.qdev);
     ide_bus_new(&d->bus[1], &d->dev.qdev);
diff --git a/hw/m48t59.c b/hw/m48t59.c
index c3d7b3a..c7492a6 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -694,7 +694,7 @@ static void m48t59_init_common(M48t59State *s)
     }
     qemu_get_timedate(&s->alarm, 0);
 
-    register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s);
+    register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s);
 }
 
 static int m48t59_init_isa1(ISADevice *dev)
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index e2697d3..03d2d16 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -845,7 +845,7 @@ void* DBDMA_init (int *dbdma_mem_index)
     s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
 
     *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s);
-    register_savevm("dbdma", -1, 1, dbdma_save, dbdma_load, s);
+    register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
     qemu_register_reset(dbdma_reset, s);
 
     dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index f28db6b..ce287c3 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -140,8 +140,8 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
 
     s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s);
     *mem_index = s->mem_index;
-    register_savevm("macio_nvram", -1, 1, macio_nvram_save, macio_nvram_load,
-                    s);
+    register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
+                    macio_nvram_load, s);
     qemu_register_reset(macio_nvram_reset, s);
 
     return s;
diff --git a/hw/max111x.c b/hw/max111x.c
index bd656bb..2844665 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -143,7 +143,8 @@ static int max111x_init(SSISlave *dev, int inputs)
     s->input[7] = 0x80;
     s->com = 0;
 
-    register_savevm("max111x", -1, 0, max111x_save, max111x_load, s);
+    register_savevm(&dev->qdev, "max111x", -1, 0,
+                    max111x_save, max111x_load, s);
     return 0;
 }
 
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index a066f63..a95b3ce 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -239,7 +239,7 @@ static void mipsnet_cleanup(VLANClientState *nc)
 {
     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm("mipsnet", s);
+    unregister_savevm(NULL, "mipsnet", s);
 
     isa_unassign_ioport(s->io_base, 36);
 
@@ -284,5 +284,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
     }
 
     mipsnet_reset(s);
-    register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+    register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
 }
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 1b6cb77..8fc348f 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -234,6 +234,7 @@ qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
 	iomemtype = cpu_register_io_memory(mst_fpga_readfn,
 		mst_fpga_writefn, s);
 	cpu_register_physical_memory(base, 0x00100000, iomemtype);
-	register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
+	register_savevm(NULL, "mainstone_fpga", 0, 0, mst_fpga_save,
+                        mst_fpga_load, s);
 	return qi;
 }
diff --git a/hw/nand.c b/hw/nand.c
index cd7444f..f414aa1 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -502,7 +502,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
        is used.  */
     s->ioaddr = s->io;
 
-    register_savevm("nand", -1, 0, nand_save, nand_load, s);
+    register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
 
     return s;
 }
diff --git a/hw/openpic.c b/hw/openpic.c
index ac21993..2b4cb00 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1234,7 +1234,8 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     opp->irq_out = irq_out;
     opp->need_swap = 1;
 
-    register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp);
+    register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
+                    openpic_save, openpic_load, opp);
     qemu_register_reset(openpic_reset, opp);
 
     opp->irq_raise = openpic_irq_raise;
@@ -1692,7 +1693,7 @@ qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
     mpp->irq_raise = mpic_irq_raise;
     mpp->reset = mpic_reset;
 
-    register_savevm("mpic", 0, 2, openpic_save, openpic_load, mpp);
+    register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
     qemu_register_reset(mpic_reset, mpp);
 
     return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
diff --git a/hw/pci.c b/hw/pci.c
index 1e77ae6..79f1f11 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -232,7 +232,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     QLIST_INIT(&bus->child);
     pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
 
-    vmstate_register(-1, &vmstate_pcibus, bus);
+    vmstate_register(NULL, -1, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
 }
 
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 3812284..0533b1d 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -418,7 +418,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
     s->irq_mouse = mouse_irq;
     s->mask = mask;
 
-    vmstate_register(0, &vmstate_kbd, s);
+    vmstate_register(NULL, 0, &vmstate_kbd, s);
     s_io_memory = cpu_register_io_memory(kbd_mm_read, kbd_mm_write, s);
     cpu_register_physical_memory(base, size, s_io_memory);
 
diff --git a/hw/piix4.c b/hw/piix4.c
index f75951b..6f08c5a 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -87,7 +87,7 @@ static int piix4_initfn(PCIDevice *d)
     uint8_t *pci_conf;
 
     isa_bus_new(&d->qdev);
-    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+    register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
 
     pci_conf = d->config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
diff --git a/hw/pl011.c b/hw/pl011.c
index 81de91e..02cf84a 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -306,7 +306,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
         qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
                               pl011_event, s);
     }
-    register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s);
+    register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
     return 0;
 }
 
diff --git a/hw/pl022.c b/hw/pl022.c
index c2e2dda..d7862bc 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -299,7 +299,7 @@ static int pl022_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
-    register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+    register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s);
     return 0;
 }
 
diff --git a/hw/pl061.c b/hw/pl061.c
index 7b1b636..e4505f5 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -303,7 +303,7 @@ static int pl061_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
     pl061_reset(s);
-    register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s);
+    register_savevm(&dev->qdev, "pl061_gpio", -1, 1, pl061_save, pl061_load, s);
     return 0;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index c9e3279..6e437e7 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -392,8 +392,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     qemu_register_reset(ppc4xx_pci_reset, controller);
 
     /* XXX load/save code not tested. */
-    register_savevm("ppc4xx_pci", ppc4xx_pci_id++, 1,
-                    ppc4xx_pci_save, ppc4xx_pci_load, controller);
+    register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
+                    1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
 
     return controller->pci_state.bus;
 
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 336d284..5358f82 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -310,8 +310,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
                                    PCIE500_REG_SIZE, index);
 
     /* XXX load/save code not tested. */
-    register_savevm("ppce500_pci", ppce500_pci_id++, 1,
-                    ppce500_pci_save, ppce500_pci_load, controller);
+    register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++,
+                    1, ppce500_pci_save, ppce500_pci_load, controller);
 
     return controller->pci_state.bus;
 
diff --git a/hw/ps2.c b/hw/ps2.c
index f0b206a..762bb00 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -595,7 +595,7 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
     s->scancode_set = 2;
-    vmstate_register(0, &vmstate_ps2_keyboard, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
     qemu_add_kbd_event_handler(ps2_put_keycode, s);
     qemu_register_reset(ps2_kbd_reset, s);
     return s;
@@ -607,7 +607,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
-    vmstate_register(0, &vmstate_ps2_mouse, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
     qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
     qemu_register_reset(ps2_mouse_reset, s);
     return s;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9095386..4915324 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -860,7 +860,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(pxa2xx_ssp_readfn,
                                        pxa2xx_ssp_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm("pxa2xx_ssp", -1, 0,
+    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
@@ -1515,7 +1515,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
     cpu_register_physical_memory(base & ~region_size,
                     region_size + 1, iomemtype);
 
-    vmstate_register(base, &vmstate_pxa2xx_i2c, s);
+    vmstate_register(NULL, base, &vmstate_pxa2xx_i2c, s);
 
     return s;
 }
@@ -1751,7 +1751,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
                     pxa2xx_i2s_writefn, s);
     cpu_register_physical_memory(base, 0x100000, iomemtype);
 
-    register_savevm("pxa2xx_i2s", base, 0,
+    register_savevm(NULL, "pxa2xx_i2s", base, 0,
                     pxa2xx_i2s_save, pxa2xx_i2s_load, s);
 
     return s;
@@ -2014,7 +2014,8 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
                         pxa2xx_fir_rx, pxa2xx_fir_event, s);
 
-    register_savevm("pxa2xx_fir", 0, 0, pxa2xx_fir_save, pxa2xx_fir_load, s);
+    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                    pxa2xx_fir_load, s);
 
     return s;
 }
@@ -2099,7 +2100,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2110,13 +2111,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     for (i = 0; pxa27x_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2140,7 +2141,8 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
-    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
+    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
+                    pxa2xx_rtc_load, s);
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
@@ -2219,7 +2221,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2230,13 +2232,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     for (i = 0; pxa255_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2260,7 +2262,8 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
-    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
+    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
+                    pxa2xx_rtc_load, s);
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 66c2c30..9c479df 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -507,7 +507,7 @@ static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
                     pxa2xx_dma_writefn, s);
     cpu_register_physical_memory(base, 0x00010000, iomemtype);
 
-    register_savevm("pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
+    register_savevm(NULL, "pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
 
     return s;
 }
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f354f4b..2abcb65 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -312,7 +312,7 @@ PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
                     pxa2xx_gpio_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
-    register_savevm("pxa2xx_gpio", 0, 0,
+    register_savevm(NULL, "pxa2xx_gpio", 0, 0,
                     pxa2xx_gpio_save, pxa2xx_gpio_load, s);
 
     return s;
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 060df58..dfa8945 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -317,7 +317,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
                     pxa2xx_keypad_writefn, s);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
-    register_savevm("pxa2xx_keypad", 0, 0,
+    register_savevm(NULL, "pxa2xx_keypad", 0, 0,
                     pxa2xx_keypad_save, pxa2xx_keypad_load, s);
 
     return s;
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 930299a..111a0dc 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -970,7 +970,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
         exit(1);
     }
 
-    register_savevm("pxa2xx_lcdc", 0, 0,
+    register_savevm(NULL, "pxa2xx_lcdc", 0, 0,
                     pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
 
     return s;
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index a415349..ca98660 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -534,7 +534,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
     /* Instantiate the actual storage */
     s->card = sd_init(bd, 0);
 
-    register_savevm("pxa2xx_mmci", 0, 0,
+    register_savevm(NULL, "pxa2xx_mmci", 0, 0,
                     pxa2xx_mmci_save, pxa2xx_mmci_load, s);
 
     return s;
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 0a98342..4d8944b 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -306,7 +306,8 @@ qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 
-    register_savevm("pxa2xx_pic", 0, 0, pxa2xx_pic_save, pxa2xx_pic_load, s);
+    register_savevm(NULL, "pxa2xx_pic", 0, 0, pxa2xx_pic_save,
+                    pxa2xx_pic_load, s);
 
     return qi;
 }
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index d992cc3..0f0ffd3 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -455,7 +455,7 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
                     pxa2xx_timer_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
-    register_savevm("pxa2xx_timer", 0, 0,
+    register_savevm(NULL, "pxa2xx_timer", 0, 0,
                     pxa2xx_timer_save, pxa2xx_timer_load, s);
 
     return s;
diff --git a/hw/qdev.c b/hw/qdev.c
index 61f999c..952c978 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -280,7 +280,7 @@ int qdev_init(DeviceState *dev)
     }
     qemu_register_reset(qdev_reset, dev);
     if (dev->info->vmsd) {
-        vmstate_register_with_alias_id(-1, dev->info->vmsd, dev,
+        vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
                                        dev->instance_id_alias,
                                        dev->alias_required_for_version);
     }
@@ -342,7 +342,7 @@ void qdev_free(DeviceState *dev)
             qbus_free(bus);
         }
         if (dev->info->vmsd)
-            vmstate_unregister(dev->info->vmsd, dev);
+            vmstate_unregister(dev, dev->info->vmsd, dev);
         if (dev->info->exit)
             dev->info->exit(dev);
         if (dev->opts)
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 2a8233a..2231373 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -813,7 +813,7 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     s->jazz_bus_irq = jazz_bus;
 
     qemu_register_reset(rc4030_reset, s);
-    register_savevm("rc4030", 0, 2, rc4030_save, rc4030_load, s);
+    register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
     s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
diff --git a/hw/serial.c b/hw/serial.c
index c7e4e77..b66d13a 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -813,7 +813,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
     s->chr = chr;
     serial_init_core(s);
 
-    vmstate_register(base, &vmstate_serial, s);
+    vmstate_register(NULL, base, &vmstate_serial, s);
 
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
@@ -948,7 +948,7 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     s->chr = chr;
 
     serial_init_core(s);
-    vmstate_register(base, &vmstate_serial, s);
+    vmstate_register(NULL, base, &vmstate_serial, s);
 
     if (ioregister) {
         if (be) {
diff --git a/hw/spitz.c b/hw/spitz.c
index 4f82e24..943933f 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -178,7 +178,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
                     sl_writefn, s);
     cpu_register_physical_memory(FLASH_BASE, 0x40, iomemtype);
 
-    register_savevm("sl_flash", 0, 0, sl_save, sl_load, s);
+    register_savevm(NULL, "sl_flash", 0, 0, sl_save, sl_load, s);
 }
 
 /* Spitz Keyboard */
@@ -508,7 +508,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
     spitz_keyboard_pre_map(s);
     qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
 
-    register_savevm("spitz_keyboard", 0, 0,
+    register_savevm(NULL, "spitz_keyboard", 0, 0,
                     spitz_keyboard_save, spitz_keyboard_load, s);
 }
 
@@ -613,7 +613,7 @@ static int spitz_lcdtg_init(SSISlave *dev)
     s->bl_power = 0;
     s->bl_intensity = 0x20;
 
-    register_savevm("spitz-lcdtg", -1, 1,
+    register_savevm(&dev->qdev, "spitz-lcdtg", -1, 1,
                     spitz_lcdtg_save, spitz_lcdtg_load, s);
     return 0;
 }
@@ -708,7 +708,8 @@ static int corgi_ssp_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
 
-    register_savevm("spitz_ssp", -1, 1, spitz_ssp_save, spitz_ssp_load, s);
+    register_savevm(&dev->qdev, "spitz_ssp", -1, 1,
+                    spitz_ssp_save, spitz_ssp_load, s);
     return 0;
 }
 
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index b632825..8643961 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -335,7 +335,8 @@ static int ssd0323_init(SSISlave *dev)
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
 
-    register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s);
+    register_savevm(&dev->qdev, "ssd0323_oled", -1, 1,
+                    ssd0323_save, ssd0323_load, s);
     return 0;
 }
 
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 96b33ed..a1a63b2 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -236,7 +236,7 @@ static int ssi_sd_init(SSISlave *dev)
     s->mode = SSI_SD_CMD;
     bs = qdev_init_bdrv(&dev->qdev, IF_SD);
     s->sd = sd_init(bs, 1);
-    register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
+    register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
     return 0;
 }
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5755f8a..ccad134 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -354,7 +354,8 @@ static int stellaris_gptm_init(SysBusDevice *dev)
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
     s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
-    register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s);
+    register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
+                    gptm_save, gptm_load, s);
     return 0;
 }
 
@@ -673,7 +674,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                                        ssys_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
     ssys_reset(s);
-    register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+    register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
     return 0;
 }
 
@@ -887,7 +888,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
-    register_savevm("stellaris_i2c", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_i2c", -1, 1,
                     stellaris_i2c_save, stellaris_i2c_load, s);
     return 0;
 }
@@ -1196,7 +1197,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
-    register_savevm("stellaris_adc", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_adc", -1, 1,
                     stellaris_adc_save, stellaris_adc_load, s);
     return 0;
 }
@@ -1256,7 +1257,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
 
-    register_savevm("stellaris_ssi_bus", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1,
                     stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
     return 0;
 }
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index d1d755e..330a9d6 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -389,7 +389,7 @@ static void stellaris_enet_cleanup(VLANClientState *nc)
 {
     stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm("stellaris_enet", s);
+    unregister_savevm(&s->busdev.qdev, "stellaris_enet", s);
 
     cpu_unregister_io_memory(s->mmio_index);
 
@@ -419,7 +419,7 @@ static int stellaris_enet_init(SysBusDevice *dev)
     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
 
     stellaris_enet_reset(s);
-    register_savevm("stellaris_enet", -1, 1,
+    register_savevm(&s->busdev.qdev, "stellaris_enet", -1, 1,
                     stellaris_enet_save, stellaris_enet_load, s);
     return 0;
 }
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 33395a4..16aae96 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -86,6 +86,6 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
     }
     s->num_buttons = n;
     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
-    register_savevm("stellaris_gamepad", -1, 1,
+    register_savevm(NULL, "stellaris_gamepad", -1, 1,
                     stellaris_gamepad_save, stellaris_gamepad_load, s);
 }
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 7be04a3..ed57203 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -526,7 +526,7 @@ static int syborg_fb_init(SysBusDevice *dev)
     if (!s->rows)
         s->rows = ds_get_height(s->ds);
 
-    register_savevm("syborg_framebuffer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
                     syborg_fb_save, syborg_fb_load, s);
     return 0;
 }
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index f3a1767..30140fb 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -214,7 +214,8 @@ static int syborg_int_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     s->flags = qemu_mallocz(s->num_irqs * sizeof(syborg_int_flags));
 
-    register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
+    register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
+                    syborg_int_load, s);
     return 0;
 }
 
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 4a562f8..7709100 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -220,7 +220,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
 
     qemu_add_kbd_event_handler(syborg_keyboard_event, s);
 
-    register_savevm("syborg_keyboard", -1, 1,
+    register_savevm(&dev->qdev, "syborg_keyboard", -1, 1,
                     syborg_keyboard_save, syborg_keyboard_load, s);
     return 0;
 }
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index 563d730..69b8d96 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -218,7 +218,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
     qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
                                  "Syborg Pointer");
 
-    register_savevm("syborg_pointer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_pointer", -1, 1,
                     syborg_pointer_save, syborg_pointer_load, s);
     return 0;
 }
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index b066213..78d5edb 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -136,7 +136,8 @@ static int syborg_rtc_init(SysBusDevice *dev)
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
 
-    register_savevm("syborg_rtc", -1, 1, syborg_rtc_save, syborg_rtc_load, s);
+    register_savevm(&dev->qdev, "syborg_rtc", -1, 1,
+                    syborg_rtc_save, syborg_rtc_load, s);
     return 0;
 }
 
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index cac00ea..8c42956 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -335,7 +335,7 @@ static int syborg_serial_init(SysBusDevice *dev)
     }
     s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
 
-    register_savevm("syborg_serial", -1, 1,
+    register_savevm(&dev->qdev, "syborg_serial", -1, 1,
                     syborg_serial_save, syborg_serial_load, s);
     return 0;
 }
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 3e4a447..95e07d7 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -221,7 +221,7 @@ static int syborg_timer_init(SysBusDevice *dev)
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
     ptimer_set_freq(s->timer, s->freq);
-    register_savevm("syborg_timer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_timer", -1, 1,
                     syborg_timer_save, syborg_timer_load, s);
     return 0;
 }
diff --git a/hw/tsc2005.c b/hw/tsc2005.c
index b75cc86..a55853c 100644
--- a/hw/tsc2005.c
+++ b/hw/tsc2005.c
@@ -548,7 +548,7 @@ void *tsc2005_init(qemu_irq pintdav)
                     "QEMU TSC2005-driven Touchscreen");
 
     qemu_register_reset((void *) tsc2005_reset, s);
-    register_savevm("tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
+    register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
 
     return s;
 }
diff --git a/hw/tsc210x.c b/hw/tsc210x.c
index e851ca1..fca73f1 100644
--- a/hw/tsc210x.c
+++ b/hw/tsc210x.c
@@ -1143,7 +1143,7 @@ uWireSlave *tsc2102_init(qemu_irq pint)
     AUD_register_card(s->name, &s->card);
 
     qemu_register_reset((void *) tsc210x_reset, s);
-    register_savevm(s->name, -1, 0,
+    register_savevm(NULL, s->name, -1, 0,
                     tsc210x_save, tsc210x_load, s);
 
     return &s->chip;
@@ -1194,7 +1194,7 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
     AUD_register_card(s->name, &s->card);
 
     qemu_register_reset((void *) tsc210x_reset, s);
-    register_savevm(s->name, -1, 0, tsc210x_save, tsc210x_load, s);
+    register_savevm(NULL, s->name, -1, 0, tsc210x_save, tsc210x_load, s);
 
     return &s->chip;
 }
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index f0a773d..362fb77 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -158,7 +158,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
+    register_savevm(&dev->qdev, "uninorth", 0, 1,
+                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
 }
@@ -178,7 +179,8 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
+    register_savevm(&dev->qdev, "uninorth", 0, 1,
+                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
     return 0;
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 8e31e36..680b557 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -100,7 +100,7 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
     s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
     vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
 
-    vmstate_register(0, &vmstate_vga_common, s);
+    vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
     s->vga.bank_offset = 0;
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 7937144..3046054 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -37,7 +37,7 @@ int isa_vga_init(void)
 
     vga_common_init(s, VGA_RAM_SIZE);
     vga_init(s);
-    vmstate_register(0, &vmstate_vga_common, s);
+    vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
     s->ds = graphic_console_init(s->update, s->invalidate,
                                  s->screen_dump, s->text_update, s);
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 152af80..9fe3886 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -270,7 +270,8 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
     reset_stats(s);
     qemu_add_balloon_handler(virtio_balloon_to_target, s);
 
-    register_savevm("virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s);
+    register_savevm(dev, "virtio-balloon", -1, 1,
+                    virtio_balloon_save, virtio_balloon_load, s);
 
     return &s->vdev;
 }
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 0bf929a..a46b758 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -498,7 +498,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
     qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
-    register_savevm("virtio-blk", virtio_blk_id++, 2,
+    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
 
     return &s->vdev;
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 06ba481..e9768e0 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -923,7 +923,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     n->vlans = qemu_mallocz(MAX_VLAN >> 3);
 
-    register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
+    register_savevm(NULL, "virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
@@ -941,7 +941,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-    unregister_savevm("virtio-net", n);
+    unregister_savevm(NULL, "virtio-net", n);
 
     qemu_free(n->mac_table.macs);
     qemu_free(n->vlans);
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 7f9d28f..b5ab3bb 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -790,7 +790,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
      * Register for the savevm section with the virtio-console name
      * to preserve backward compat
      */
-    register_savevm("virtio-console", -1, 2, virtio_serial_save,
+    register_savevm(dev, "virtio-console", -1, 2, virtio_serial_save,
                     virtio_serial_load, vser);
 
     return vdev;
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index afebad9..f359304 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -274,7 +274,7 @@ void *vmmouse_init(void *m)
     vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
-    vmstate_register(0, &vmstate_vmmouse, s);
+    vmstate_register(NULL, 0, &vmstate_vmmouse, s);
 
     return s;
 }
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index bf2a699..359e5d8 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1169,7 +1169,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
     vga_common_init(&s->vga, vga_ram_size);
     vga_init(&s->vga);
-    vmstate_register(0, &vmstate_vga_common, &s->vga);
+    vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
 
     vga_init_vbe(&s->vga);
 
diff --git a/hw/zaurus.c b/hw/zaurus.c
index db6ba75..dd999d7 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -230,7 +230,7 @@ ScoopInfo *scoop_init(PXA2xxState *cpu,
     iomemtype = cpu_register_io_memory(scoop_readfn,
                     scoop_writefn, s);
     cpu_register_physical_memory(target_base, 0x1000, iomemtype);
-    register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
+    register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s);
 
     return s;
 }
diff --git a/qemu-timer.c b/qemu-timer.c
index bdc8206..bc5f207 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -662,7 +662,7 @@ static const VMStateDescription vmstate_timers = {
 
 void configure_icount(const char *option)
 {
-    vmstate_register(0, &vmstate_timers, &timers_state);
+    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
     if (!option)
         return;
 
diff --git a/savevm.c b/savevm.c
index 20354a8..0052406 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1026,7 +1026,8 @@ static int calculate_new_instance_id(const char *idstr)
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
    distinguishing id for all instances of your device class. */
-int register_savevm_live(const char *idstr,
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
                          int instance_id,
                          int version_id,
                          SaveSetParamsHandler *set_params,
@@ -1058,18 +1059,19 @@ int register_savevm_live(const char *idstr,
     return 0;
 }
 
-int register_savevm(const char *idstr,
+int register_savevm(DeviceState *dev,
+                    const char *idstr,
                     int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
                     void *opaque)
 {
-    return register_savevm_live(idstr, instance_id, version_id,
+    return register_savevm_live(dev, idstr, instance_id, version_id,
                                 NULL, NULL, save_state, load_state, opaque);
 }
 
-void unregister_savevm(const char *idstr, void *opaque)
+void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
@@ -1081,7 +1083,7 @@ void unregister_savevm(const char *idstr, void *opaque)
     }
 }
 
-int vmstate_register_with_alias_id(int instance_id,
+int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    const VMStateDescription *vmsd,
                                    void *opaque, int alias_id,
                                    int required_for_version)
@@ -1112,13 +1114,15 @@ int vmstate_register_with_alias_id(int instance_id,
     return 0;
 }
 
-int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                     void *opaque)
+int vmstate_register(DeviceState *dev, int instance_id,
+                     const VMStateDescription *vmsd, void *opaque)
 {
-    return vmstate_register_with_alias_id(instance_id, vmsd, opaque, -1, 0);
+    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
+                                          opaque, -1, 0);
 }
 
-void vmstate_unregister(const VMStateDescription *vmsd, void *opaque)
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+                        void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 3c785cd..82fd9b4 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -232,7 +232,8 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     slirp->opaque = opaque;
 
-    register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
+    register_savevm(NULL, "slirp", 0, 3,
+                    slirp_state_save, slirp_state_load, slirp);
 
     QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
 
@@ -243,7 +244,7 @@ void slirp_cleanup(Slirp *slirp)
 {
     QTAILQ_REMOVE(&slirp_instances, slirp, entry);
 
-    unregister_savevm("slirp", slirp);
+    unregister_savevm(NULL, "slirp", slirp);
 
     qemu_free(slirp->tftp_prefix);
     qemu_free(slirp->bootp_filename);
diff --git a/vl.c b/vl.c
index 920717a..4a1c5f4 100644
--- a/vl.c
+++ b/vl.c
@@ -2794,7 +2794,7 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
-    register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, 
+    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 06/16] savevm: Make use of DeviceState
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (4 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 05/16] savevm: Add DeviceState param Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 07/16] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
                     ` (9 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

For callers that pass a device we can traverse up the qdev tree and
make use of the BusInfo.get_dev_path information for creating unique
savevm id strings.  This avoids needing to rely on the instance number,
which can cause problems with device initialization order and hotplug.

For compatibility, we also store away the old id string and instance
so we can accept migrations from VMs as we add new get_dev_path
implementations.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 savevm.c |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/savevm.c b/savevm.c
index 0052406..e4f50b1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -72,6 +72,7 @@
 
 #include "qemu-common.h"
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "net.h"
 #include "monitor.h"
 #include "sysemu.h"
@@ -988,6 +989,11 @@ const VMStateInfo vmstate_info_unused_buffer = {
     .put  = put_unused_buffer,
 };
 
+typedef struct CompatEntry {
+    char idstr[256];
+    int instance_id;
+} CompatEntry;
+
 typedef struct SaveStateEntry {
     QTAILQ_ENTRY(SaveStateEntry) entry;
     char idstr[256];
@@ -1001,6 +1007,7 @@ typedef struct SaveStateEntry {
     LoadStateHandler *load_state;
     const VMStateDescription *vmsd;
     void *opaque;
+    CompatEntry *compat;
 } SaveStateEntry;
 
 
@@ -1022,6 +1029,23 @@ static int calculate_new_instance_id(const char *idstr)
     return instance_id;
 }
 
+static int calculate_compat_instance_id(const char *idstr)
+{
+    SaveStateEntry *se;
+    int instance_id = 0;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if (!se->compat)
+            continue;
+
+        if (strcmp(idstr, se->compat->idstr) == 0
+            && instance_id <= se->compat->instance_id) {
+            instance_id = se->compat->instance_id + 1;
+        }
+    }
+    return instance_id;
+}
+
 /* TODO: Individual devices generally have very little idea about the rest
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
@@ -1039,7 +1063,6 @@ int register_savevm_live(DeviceState *dev,
     SaveStateEntry *se;
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
     se->version_id = version_id;
     se->section_id = global_section_id++;
     se->set_params = set_params;
@@ -1049,11 +1072,28 @@ int register_savevm_live(DeviceState *dev,
     se->opaque = opaque;
     se->vmsd = NULL;
 
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            pstrcpy(se->idstr, sizeof(se->idstr), id);
+            pstrcat(se->idstr, sizeof(se->idstr), "/");
+            qemu_free(id);
+
+            se->compat = qemu_mallocz(sizeof(CompatEntry));
+            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
+            se->compat->instance_id = instance_id == -1 ?
+                         calculate_compat_instance_id(idstr) : instance_id;
+            instance_id = -1;
+        }
+    }
+    pstrcat(se->idstr, sizeof(se->idstr), idstr);
+
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(idstr);
+        se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
         se->instance_id = instance_id;
     }
+    assert(!se->compat || se->instance_id == 0);
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1074,9 +1114,20 @@ int register_savevm(DeviceState *dev,
 void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
+    char id[256] = "";
+
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *path = dev->parent_bus->info->get_dev_path(dev);
+        if (path) {
+            pstrcpy(id, sizeof(id), path);
+            pstrcat(id, sizeof(id), "/");
+            qemu_free(path);
+        }
+    }
+    pstrcat(id, sizeof(id), idstr);
 
     QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
-        if (strcmp(se->idstr, idstr) == 0 && se->opaque == opaque) {
+        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
             QTAILQ_REMOVE(&savevm_handlers, se, entry);
             qemu_free(se);
         }
@@ -1094,7 +1145,6 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
     se->version_id = vmsd->version_id;
     se->section_id = global_section_id++;
     se->save_live_state = NULL;
@@ -1104,11 +1154,28 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->vmsd = vmsd;
     se->alias_id = alias_id;
 
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            pstrcpy(se->idstr, sizeof(se->idstr), id);
+            pstrcat(se->idstr, sizeof(se->idstr), "/");
+            qemu_free(id);
+
+            se->compat = qemu_mallocz(sizeof(CompatEntry));
+            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
+            se->compat->instance_id = instance_id == -1 ?
+                         calculate_compat_instance_id(vmsd->name) : instance_id;
+            instance_id = -1;
+        }
+    }
+    pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
+
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(vmsd->name);
+        se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
         se->instance_id = instance_id;
     }
+    assert(!se->compat || se->instance_id == 0);
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1454,6 +1521,13 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
             (instance_id == se->instance_id ||
              instance_id == se->alias_id))
             return se;
+        /* Migrating from an older version? */
+        if (strstr(se->idstr, idstr) && se->compat) {
+            if (!strcmp(se->compat->idstr, idstr) &&
+                (instance_id == se->compat->instance_id ||
+                 instance_id == se->alias_id))
+                return se;
+        }
     }
     return NULL;
 }

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 07/16] eepro100: Add a dev field to eeprom new/free functions
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (5 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 06/16] savevm: Make use of DeviceState Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
                     ` (8 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This allows us to create a more meaningful savevm string.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/eepro100.c   |    4 ++--
 hw/eeprom93xx.c |    8 ++++----
 hw/eeprom93xx.h |    4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 0ddca8b..2b75c8f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1835,7 +1835,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
 
     cpu_unregister_io_memory(s->mmio_index);
     vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
-    eeprom93xx_free(s->eeprom);
+    eeprom93xx_free(&pci_dev->qdev, s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
 }
@@ -1862,7 +1862,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
 
     /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
      * i82559 and later support 64 or 256 word EEPROM. */
-    s->eeprom = eeprom93xx_new(EEPROM_SIZE);
+    s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
 
     /* Handler for memory-mapped I/O */
     s->mmio_index =
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 6ba546f..660b28f 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -289,7 +289,7 @@ void eeprom93xx_reset(eeprom_t *eeprom)
 }
 #endif
 
-eeprom_t *eeprom93xx_new(uint16_t nwords)
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)
 {
     /* Add a new EEPROM (with 16, 64 or 256 words). */
     eeprom_t *eeprom;
@@ -316,15 +316,15 @@ eeprom_t *eeprom93xx_new(uint16_t nwords)
     /* Output DO is tristate, read results in 1. */
     eeprom->eedo = 1;
     logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
-    vmstate_register(NULL, 0, &vmstate_eeprom, eeprom);
+    vmstate_register(dev, 0, &vmstate_eeprom, eeprom);
     return eeprom;
 }
 
-void eeprom93xx_free(eeprom_t *eeprom)
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom)
 {
     /* Destroy EEPROM. */
     logout("eeprom = 0x%p\n", eeprom);
-    vmstate_unregister(NULL, &vmstate_eeprom, eeprom);
+    vmstate_unregister(dev, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/eeprom93xx.h b/hw/eeprom93xx.h
index 47282d3..8ba0e28 100644
--- a/hw/eeprom93xx.h
+++ b/hw/eeprom93xx.h
@@ -23,10 +23,10 @@
 typedef struct _eeprom_t eeprom_t;
 
 /* Create a new EEPROM with (nwords * 2) bytes. */
-eeprom_t *eeprom93xx_new(uint16_t nwords);
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords);
 
 /* Destroy an existing EEPROM. */
-void eeprom93xx_free(eeprom_t *eeprom);
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom);
 
 /* Read from the EEPROM. */
 uint16_t eeprom93xx_read(eeprom_t *eeprom);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (6 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 07/16] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 09/16] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
                     ` (7 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Stuff a pointer to the DeviceState into the VirtIONet structure so that
we can easily remove the vmstate entry later.  Also, let vmstate track
the instance number (it should always be zero internally since the
device path should now be unique).

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/virtio-net.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index e9768e0..f41db45 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -60,6 +60,7 @@ typedef struct VirtIONet
         uint8_t *macs;
     } mac_table;
     uint32_t *vlans;
+    DeviceState *qdev;
 } VirtIONet;
 
 /* TODO
@@ -890,7 +891,6 @@ static void virtio_net_vmstate_change(void *opaque, int running, int reason)
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 {
     VirtIONet *n;
-    static int virtio_net_id;
 
     n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
                                         sizeof(struct virtio_net_config),
@@ -923,7 +923,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     n->vlans = qemu_mallocz(MAX_VLAN >> 3);
 
-    register_savevm(NULL, "virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
+    n->qdev = dev;
+    register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
@@ -941,7 +942,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-    unregister_savevm(NULL, "virtio-net", n);
+    unregister_savevm(n->qdev, "virtio-net", n);
 
     qemu_free(n->mac_table.macs);
     qemu_free(n->vlans);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 09/16] qemu_ram_alloc: Add DeviceState and name parameters
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (7 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
                     ` (6 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

These will be used to generate unique id strings for ramblocks.  The name
field is required, the device pointer is optional as most callers don't
have a device.  When there's no device or the device isn't a child of
a bus implementing BusInfo.get_dev_path, the name should be unique for
the platform.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-common.h                  |    2 +-
 exec.c                        |    2 +-
 hw/an5206.c                   |    4 ++--
 hw/armv7m.c                   |    9 ++++++---
 hw/axis_dev88.c               |    4 ++--
 hw/dummy_m68k.c               |    2 +-
 hw/etraxfs.c                  |    6 +++---
 hw/g364fb.c                   |    2 +-
 hw/gumstix.c                  |    6 ++++--
 hw/integratorcp.c             |    4 ++--
 hw/mainstone.c                |    6 ++++--
 hw/mcf5208.c                  |    4 ++--
 hw/mips_jazz.c                |    4 ++--
 hw/mips_malta.c               |    4 ++--
 hw/mips_mipssim.c             |    4 ++--
 hw/mips_r4k.c                 |    6 +++---
 hw/musicpal.c                 |   11 +++++++----
 hw/omap1.c                    |    6 ++++--
 hw/omap2.c                    |    6 ++++--
 hw/omap_sx1.c                 |   12 ++++++++----
 hw/onenand.c                  |    2 +-
 hw/palm.c                     |    3 ++-
 hw/pc.c                       |    7 ++++---
 hw/pci.c                      |    7 ++++++-
 hw/petalogix_s3adsp1800_mmu.c |    7 ++++---
 hw/ppc405_boards.c            |   18 +++++++++---------
 hw/ppc405_uc.c                |    2 +-
 hw/ppc4xx_devs.c              |    4 +++-
 hw/ppc_newworld.c             |    6 +++---
 hw/ppc_oldworld.c             |    6 +++---
 hw/ppc_prep.c                 |    4 ++--
 hw/ppce500_mpc8544ds.c        |    3 ++-
 hw/pxa2xx.c                   |   12 ++++++++----
 hw/r2d.c                      |    4 ++--
 hw/realview.c                 |    6 +++---
 hw/s390-virtio.c              |    2 +-
 hw/sm501.c                    |    2 +-
 hw/spitz.c                    |    2 +-
 hw/sun4m.c                    |    8 ++++----
 hw/sun4u.c                    |    4 ++--
 hw/syborg.c                   |    2 +-
 hw/tc6393xb.c                 |    2 +-
 hw/tcx.c                      |    2 +-
 hw/tosa.c                     |    2 +-
 hw/versatilepb.c              |    2 +-
 hw/vga.c                      |    2 +-
 hw/vmware_vga.c               |    2 +-
 47 files changed, 130 insertions(+), 97 deletions(-)

diff --git a/cpu-common.h b/cpu-common.h
index b24cecc..71e7933 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -40,7 +40,7 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 }
 
 ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
-ram_addr_t qemu_ram_alloc(ram_addr_t);
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
 void qemu_ram_free(ram_addr_t addr);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
diff --git a/exec.c b/exec.c
index 088d665..dc47831 100644
--- a/exec.c
+++ b/exec.c
@@ -2776,7 +2776,7 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
     return last;
 }
 
-ram_addr_t qemu_ram_alloc(ram_addr_t size)
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 {
     RAMBlock *new_block;
 
diff --git a/hw/an5206.c b/hw/an5206.c
index f584d88..b9f19a9 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -54,11 +54,11 @@ static void an5206_init(ram_addr_t ram_size,
 
     /* DRAM at address zero */
     cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "an5206.ram", ram_size) | IO_MEM_RAM);
 
     /* Internal SRAM.  */
     cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512,
-        qemu_ram_alloc(512) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "an5206.sram", 512) | IO_MEM_RAM);
 
     mcf5206_init(AN5206_MBAR_ADDR, env);
 
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 854261d..588ec98 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -200,9 +200,11 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
 
     /* Flash programming is done via the SCU, so pretend it is ROM.  */
     cpu_register_physical_memory(0, flash_size,
-                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "armv7m.flash",
+                                                flash_size) | IO_MEM_ROM);
     cpu_register_physical_memory(0x20000000, sram_size,
-                                 qemu_ram_alloc(sram_size) | IO_MEM_RAM);
+                                 qemu_ram_alloc(NULL, "armv7m.sram",
+                                                sram_size) | IO_MEM_RAM);
     armv7m_bitband_init();
 
     nvic = qdev_create(NULL, "armv7m_nvic");
@@ -236,7 +238,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
        space.  This stops qemu complaining about executing code outside RAM
        when returning from an exception.  */
     cpu_register_physical_memory(0xfffff000, 0x1000,
-                                 qemu_ram_alloc(0x1000) | IO_MEM_RAM);
+                                 qemu_ram_alloc(NULL, "armv7m.hack", 
+                                                0x1000) | IO_MEM_RAM);
 
     qemu_register_reset(armv7m_reset, env);
     return pic;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 3ae4105..f16c76a 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -268,12 +268,12 @@ void axisdev88_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "axisdev88.ram", ram_size);
     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
+    phys_intmem = qemu_ram_alloc(NULL, "axisdev88.chipram", INTMEM_SIZE);
     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
                                  phys_intmem | IO_MEM_RAM);
 
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 9c9e6ff..61efb39 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -39,7 +39,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
 
     /* RAM at address zero */
     cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "dummy_m68k.ram", ram_size) | IO_MEM_RAM);
 
     /* Load kernel.  */
     if (kernel_filename) {
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 01bf929..46e2920 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -68,17 +68,17 @@ void bareetraxfs_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "etraxfs.ram", ram_size);
     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
+    phys_intmem = qemu_ram_alloc(NULL, "etraxfs.chipram", INTMEM_SIZE);
     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
                                  phys_intmem | IO_MEM_RAM);
 
 
-    phys_flash = qemu_ram_alloc(FLASH_SIZE);
+    phys_flash = qemu_ram_alloc(NULL, "etraxfs.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0x0, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
diff --git a/hw/g364fb.c b/hw/g364fb.c
index beafd70..3c8fb98 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -593,7 +593,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
     s = qemu_mallocz(sizeof(G364State));
 
     s->vram_size = 8 * 1024 * 1024;
-    s->vram_offset = qemu_ram_alloc(s->vram_size);
+    s->vram_offset = qemu_ram_alloc(NULL, "g364fb.vram", s->vram_size);
     s->vram = qemu_get_ram_ptr(s->vram_offset);
     s->irq = irq;
 
diff --git a/hw/gumstix.c b/hw/gumstix.c
index b64e04e..c343a16 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -67,7 +67,8 @@ static void connex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(connex_rom),
+    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
+                                                          connex_rom),
                                dinfo->bdrv, sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -105,7 +106,8 @@ static void verdex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(verdex_rom),
+    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
+                                                          verdex_rom),
                                dinfo->bdrv, sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index bee8298..3bf216b 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -253,7 +253,7 @@ static int integratorcm_init(SysBusDevice *dev)
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
-    s->flash_offset = qemu_ram_alloc(0x100000);
+    s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000);
 
     iomemtype = cpu_register_io_memory(integratorcm_readfn,
                                        integratorcm_writefn, s);
@@ -467,7 +467,7 @@ static void integratorcp_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "integrator.ram", ram_size);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero*/
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 54bacfb..cba7e63 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -87,7 +87,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
     /* Setup CPU & memory */
     cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);
     cpu_register_physical_memory(0, MAINSTONE_ROM,
-                    qemu_ram_alloc(MAINSTONE_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "mainstone.rom",
+                                   MAINSTONE_ROM) | IO_MEM_ROM);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
@@ -104,7 +105,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
         }
 
         if (!pflash_cfi01_register(mainstone_flash_base[i],
-                                   qemu_ram_alloc(MAINSTONE_FLASH),
+                                   qemu_ram_alloc(NULL, "mainstone.flash",
+                                                  MAINSTONE_FLASH),
                                    dinfo->bdrv, sector_len,
                                    MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
                                    be)) {
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 5b686c6..38645f7 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -220,11 +220,11 @@ static void mcf5208evb_init(ram_addr_t ram_size,
 
     /* DRAM at 0x40000000 */
     cpu_register_physical_memory(0x40000000, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "mcf5208.ram", ram_size) | IO_MEM_RAM);
 
     /* Internal SRAM.  */
     cpu_register_physical_memory(0x80000000, 16384,
-        qemu_ram_alloc(16384) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "mcf5208.sram", 16384) | IO_MEM_RAM);
 
     /* Internal peripherals.  */
     pic = mcf_intc_init(0xfc048000, env);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 22db7a2..658aba7 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -160,10 +160,10 @@ void mips_jazz_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_jazz.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
-    bios_offset = qemu_ram_alloc(MAGNUM_BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
     cpu_register_physical_memory(0x1fc00000LL,
                                  MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);
     cpu_register_physical_memory(0xfff00000LL,
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 23de7f0..c3f4725 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -833,8 +833,8 @@ void mips_malta_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
 
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 293d99e..111c759 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -144,8 +144,8 @@ mips_mipssim_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate RAM. */
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_mipssim.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_mipssim.bios", BIOS_SIZE);
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 5a96dea..61cd33a 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -198,7 +198,7 @@ void mips_r4k_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_r4k.ram", ram_size);
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
@@ -226,14 +226,14 @@ void mips_r4k_init (ram_addr_t ram_size,
     be = 0;
 #endif
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE);
 	cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
                                      bios_offset | IO_MEM_ROM);
 
         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
-        bios_offset = qemu_ram_alloc(mips_rom);
+        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom);
         if (!pflash_cfi01_register(0x1fc00000, bios_offset,
                                    dinfo->bdrv, sector_len,
                                    mips_rom / sector_len,
diff --git a/hw/musicpal.c b/hw/musicpal.c
index d44c5a0..fa74a81 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1508,9 +1508,10 @@ static void musicpal_init(ram_addr_t ram_size,
 
     /* For now we use a fixed - the original - RAM size */
     cpu_register_physical_memory(0, MP_RAM_DEFAULT_SIZE,
-                                 qemu_ram_alloc(MP_RAM_DEFAULT_SIZE));
+                                 qemu_ram_alloc(NULL, "musicpal.ram",
+                                                MP_RAM_DEFAULT_SIZE));
 
-    sram_off = qemu_ram_alloc(MP_SRAM_SIZE);
+    sram_off = qemu_ram_alloc(NULL, "musicpal.sram", MP_SRAM_SIZE);
     cpu_register_physical_memory(MP_SRAM_BASE, MP_SRAM_SIZE, sram_off);
 
     dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
@@ -1557,14 +1558,16 @@ static void musicpal_init(ram_addr_t ram_size,
          * image is smaller than 32 MB.
          */
 #ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
+                              "musicpal.flash", flash_size),
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
+                              "musicpal.flash", flash_size),
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
diff --git a/hw/omap1.c b/hw/omap1.c
index 8649dbd..e5fa87a 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -4655,9 +4655,11 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
 
     /* Memory-mapped stuff */
     cpu_register_physical_memory(OMAP_EMIFF_BASE, s->sdram_size,
-                    (emiff_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
+                    (emiff_base = qemu_ram_alloc(NULL, "omap1.dram",
+                                                 s->sdram_size)) | IO_MEM_RAM);
     cpu_register_physical_memory(OMAP_IMIF_BASE, s->sram_size,
-                    (imif_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+                    (imif_base = qemu_ram_alloc(NULL, "omap1.sram",
+                                                s->sram_size)) | IO_MEM_RAM);
 
     omap_clkm_init(0xfffece00, 0xe1008000, s);
 
diff --git a/hw/omap2.c b/hw/omap2.c
index 666c15a..b6ccc00 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -4518,9 +4518,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
 
     /* Memory-mapped stuff */
     cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-                    (q2_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
+                    (q2_base = qemu_ram_alloc(NULL, "omap2.dram",
+                                              s->sdram_size)) | IO_MEM_RAM);
     cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-                    (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+                    (sram_base = qemu_ram_alloc(NULL, "omap2.sram",
+                                                s->sram_size)) | IO_MEM_RAM);
 
     s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
 
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 2e9879f..c3f1973 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -139,7 +139,8 @@ static void sx1_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "omap_sx1.flash0-0",
+                                                flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
@@ -157,7 +158,8 @@ static void sx1_init(ram_addr_t ram_size,
 #endif
 
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(flash_size),
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL,
+                                   "omap_sx1.flash0-1", flash_size),
                                    dinfo->bdrv, sector_size,
                                    flash_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
@@ -170,12 +172,14 @@ static void sx1_init(ram_addr_t ram_size,
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
-                                     qemu_ram_alloc(flash1_size) | IO_MEM_ROM);
+                                     qemu_ram_alloc(NULL, "omap_sx1.flash1-0",
+                                                    flash1_size) | IO_MEM_ROM);
         io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
         cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
                         OMAP_CS1_SIZE - flash1_size, io);
 
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(flash1_size),
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL,
+                                   "omap_sx1.flash1-1", flash1_size),
                                    dinfo->bdrv, sector_size,
                                    flash1_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
diff --git a/hw/onenand.c b/hw/onenand.c
index 4118db9..f7afeca 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -638,7 +638,7 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
         s->bdrv = dinfo->bdrv;
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
-    s->ram = qemu_ram_alloc(0xc000 << s->shift);
+    s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
     ram = qemu_get_ram_ptr(s->ram);
     s->boot[0] = ram + (0x0000 << s->shift);
     s->boot[1] = ram + (0x8000 << s->shift);
diff --git a/hw/palm.c b/hw/palm.c
index 8db133d..193aa11 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -213,7 +213,8 @@ static void palmte_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                    qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "palmte.flash",
+                                                flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
diff --git a/hw/pc.c b/hw/pc.c
index d6f3aa4..644cb36 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -901,7 +901,8 @@ void pc_memory_init(ram_addr_t ram_size,
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(below_4g_mem_size + above_4g_mem_size);
+    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
+                              below_4g_mem_size + above_4g_mem_size);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
@@ -924,7 +925,7 @@ void pc_memory_init(ram_addr_t ram_size,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(bios_size);
+    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size));
     if (ret != 0) {
     bios_error:
@@ -942,7 +943,7 @@ void pc_memory_init(ram_addr_t ram_size,
                                  isa_bios_size,
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
-    option_rom_offset = qemu_ram_alloc(PC_ROM_SIZE);
+    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
     cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
 
     /* map all the bios at the top of memory */
diff --git a/hw/pci.c b/hw/pci.c
index 79f1f11..fe7c5c3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1713,6 +1713,7 @@ static int pci_add_option_rom(PCIDevice *pdev)
     int size;
     char *path;
     void *ptr;
+    char name[32];
 
     if (!pdev->romfile)
         return 0;
@@ -1748,7 +1749,11 @@ static int pci_add_option_rom(PCIDevice *pdev)
         size = 1 << qemu_fls(size);
     }
 
-    pdev->rom_offset = qemu_ram_alloc(size);
+    if (pdev->qdev.info->vmsd)
+        snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->vmsd->name);
+    else
+        snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name);
+    pdev->rom_offset = qemu_ram_alloc(&pdev->qdev, name, size);
 
     ptr = qemu_get_ram_ptr(pdev->rom_offset);
     load_image(path, ptr);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index cdde991..70b6a36 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -137,14 +137,15 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* Attach emulated BRAM through the LMB.  */
-    phys_lmb_bram = qemu_ram_alloc(LMB_BRAM_SIZE);
+    phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.lmb_bram",
+                                   LMB_BRAM_SIZE);
     cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE,
                                  phys_lmb_bram | IO_MEM_RAM);
 
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size);
     cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
 
-    phys_flash = qemu_ram_alloc(FLASH_SIZE);
+    phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xa0000000, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index 7c7075e..40ff1b3 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -190,7 +190,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* XXX: fix this */
-    ram_bases[0] = qemu_ram_alloc(0x08000000);
+    ram_bases[0] = qemu_ram_alloc(NULL, "ef405ep.ram", 0x08000000);
     ram_sizes[0] = 0x08000000;
     ram_bases[1] = 0x00000000;
     ram_sizes[1] = 0x00000000;
@@ -202,7 +202,7 @@ static void ref405ep_init (ram_addr_t ram_size,
                         kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
-    sram_offset = qemu_ram_alloc(sram_size);
+    sram_offset = qemu_ram_alloc(NULL, "ef405ep.sram", sram_size);
 #ifdef DEBUG_BOARD_INIT
     printf("%s: register SRAM at offset %08lx\n", __func__, sram_offset);
 #endif
@@ -217,7 +217,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
         bios_size = bdrv_getlength(dinfo->bdrv);
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " TARGET_FMT_lx
@@ -236,7 +236,7 @@ static void ref405ep_init (ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -509,9 +509,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
-    ram_bases[0] = qemu_ram_alloc(0x04000000);
+    ram_bases[0] = qemu_ram_alloc(NULL, "taihu_405ep.ram-0", 0x04000000);
     ram_sizes[0] = 0x04000000;
-    ram_bases[1] = qemu_ram_alloc(0x04000000);
+    ram_bases[1] = qemu_ram_alloc(NULL, "taihu_405ep.ram-1", 0x04000000);
     ram_sizes[1] = 0x04000000;
     ram_size = 0x08000000;
 #ifdef DEBUG_BOARD_INIT
@@ -531,7 +531,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size);
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " TARGET_FMT_lx
                " at offset %08lx addr " TARGET_FMT_lx " '%s' %d\n",
@@ -551,7 +551,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 #endif
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
             bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
@@ -580,7 +580,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
                fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
                bdrv_get_device_name(dinfo->bdrv));
 #endif
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size);
         pflash_cfi02_register(0xfc000000, bios_offset,
                               dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index d9bbd93..b884ea5 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -995,7 +995,7 @@ static void ppc405_ocm_init(CPUState *env)
     ppc405_ocm_t *ocm;
 
     ocm = qemu_mallocz(sizeof(ppc405_ocm_t));
-    ocm->offset = qemu_ram_alloc(4096);
+    ocm->offset = qemu_ram_alloc(NULL, "ppc405.ocm", 4096);
     qemu_register_reset(&ocm_reset, ocm);
     ppc_dcr_register(env, OCM0_ISARC,
                      ocm, &dcr_read_ocm, &dcr_write_ocm);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 37a3948..b15db81 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -668,7 +668,9 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
             unsigned int bank_size = sdram_bank_sizes[j];
 
             if (bank_size <= size_left) {
-                ram_bases[i] = qemu_ram_alloc(bank_size);
+                char name[32];
+                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
+                ram_bases[i] = qemu_ram_alloc(NULL, name, bank_size);
                 ram_sizes[i] = bank_size;
                 size_left -= bank_size;
                 break;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index d131aa5..fbba9b6 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -173,11 +173,11 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_core99.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_core99.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -198,7 +198,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate and load VGA BIOS */
-    vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
+    vga_bios_offset = qemu_ram_alloc(NULL, "ppc_core99.vbios", VGA_BIOS_SIZE);
     vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME);
     if (filename) {
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 27ddc01..6b3ab89 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -179,11 +179,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_heathrow.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -203,7 +203,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     }
 
     /* allocate and load VGA BIOS */
-    vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
+    vga_bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.vbios", VGA_BIOS_SIZE);
     vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME);
     if (filename) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index bb9e15f..fc3e17a 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -604,11 +604,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_prep.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_prep.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 0901fa6..1422fad 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -189,7 +189,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
 
     /* Register Memory */
-    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(ram_size));
+    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(NULL,
+                                 "mpc8544ds.ram", ram_size));
 
     /* MPIC */
     irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 4915324..953e9ee 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2054,9 +2054,11 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
-                    sdram_size, qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+                    sdram_size, qemu_ram_alloc(NULL, "pxa270.sdram",
+                                               sdram_size) | IO_MEM_RAM);
     cpu_register_physical_memory(PXA2XX_INTERNAL_BASE,
-                    0x40000, qemu_ram_alloc(0x40000) | IO_MEM_RAM);
+                    0x40000, qemu_ram_alloc(NULL, "pxa270.internal",
+                                            0x40000) | IO_MEM_RAM);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
@@ -2175,9 +2177,11 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size,
-                    qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+                    qemu_ram_alloc(NULL, "pxa255.sdram",
+                                   sdram_size) | IO_MEM_RAM);
     cpu_register_physical_memory(PXA2XX_INTERNAL_BASE, PXA2XX_INTERNAL_SIZE,
-                    qemu_ram_alloc(PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
+                    qemu_ram_alloc(NULL, "pxa255.internal",
+                                   PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
diff --git a/hw/r2d.c b/hw/r2d.c
index 38c4f6a..61414e2 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -242,7 +242,7 @@ static void r2d_init(ram_addr_t ram_size,
     }
 
     /* Allocate memory space */
-    sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
+    sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
     cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
     /* Register peripherals */
     s = sh7750_init(env);
@@ -257,7 +257,7 @@ static void r2d_init(ram_addr_t ram_size,
                   dinfo, NULL);
 
     /* onboard flash memory */
-    pflash_cfi02_register(0x0, qemu_ram_alloc(FLASH_SIZE),
+    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
                           dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                           FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
diff --git a/hw/realview.c b/hw/realview.c
index f786699..70bcdb8 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -196,12 +196,12 @@ static void realview_init(ram_addr_t ram_size,
         /* Core tile RAM.  */
         low_ram_size = ram_size - 0x20000000;
         ram_size = 0x20000000;
-        ram_offset = qemu_ram_alloc(low_ram_size);
+        ram_offset = qemu_ram_alloc(NULL, "realview.lowmem", low_ram_size);
         cpu_register_physical_memory(0x20000000, low_ram_size,
                                      ram_offset | IO_MEM_RAM);
     }
 
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "realview.highmem", ram_size);
     low_ram_size = ram_size;
     if (low_ram_size > 0x10000000)
       low_ram_size = 0x10000000;
@@ -354,7 +354,7 @@ static void realview_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    ram_offset = qemu_ram_alloc(0x1000);
+    ram_offset = qemu_ram_alloc(NULL, "realview.hack", 0x1000);
     cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
                                  ram_offset | IO_MEM_RAM);
 
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 898f442..2fb437b 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -157,7 +157,7 @@ static void s390_init(ram_addr_t ram_size,
     s390_bus = s390_virtio_bus_init(&ram_size);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(ram_size);
+    ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr);
 
     /* init CPUs */
diff --git a/hw/sm501.c b/hw/sm501.c
index b5ec2da..8e6932d 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1371,7 +1371,7 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    s->local_mem_offset = qemu_ram_alloc(local_mem_bytes);
+    s->local_mem_offset = qemu_ram_alloc(NULL, "sm501.local", local_mem_bytes);
     s->local_mem = qemu_get_ram_ptr(s->local_mem_offset);
     cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset);
 
diff --git a/hw/spitz.c b/hw/spitz.c
index 943933f..afda902 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -966,7 +966,7 @@ static void spitz_common_init(ram_addr_t ram_size,
     sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
     cpu_register_physical_memory(0, SPITZ_ROM,
-                    qemu_ram_alloc(SPITZ_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "spitz.rom", SPITZ_ROM) | IO_MEM_ROM);
 
     /* Setup peripherals */
     spitz_keyboard_register(cpu);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index e4ca8f3..208c8a8 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -592,7 +592,7 @@ static int idreg_init1(SysBusDevice *dev)
 {
     ram_addr_t idreg_offset;
 
-    idreg_offset = qemu_ram_alloc(sizeof(idreg_data));
+    idreg_offset = qemu_ram_alloc(NULL, "sun4m.idreg", sizeof(idreg_data));
     sysbus_init_mmio(dev, sizeof(idreg_data), idreg_offset | IO_MEM_ROM);
     return 0;
 }
@@ -627,7 +627,7 @@ static int afx_init1(SysBusDevice *dev)
 {
     ram_addr_t afx_offset;
 
-    afx_offset = qemu_ram_alloc(4);
+    afx_offset = qemu_ram_alloc(NULL, "sun4m.afx", 4);
     sysbus_init_mmio(dev, 4, afx_offset | IO_MEM_RAM);
     return 0;
 }
@@ -690,7 +690,7 @@ static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
-    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
+    prom_offset = qemu_ram_alloc(NULL, "sun4m.prom", PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
     return 0;
 }
@@ -725,7 +725,7 @@ static int ram_init1(SysBusDevice *dev)
 
     RAM_size = d->size;
 
-    ram_offset = qemu_ram_alloc(RAM_size);
+    ram_offset = qemu_ram_alloc(NULL, "sun4m.ram", RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
     return 0;
 }
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 40b5f1f..2234b4e 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -629,7 +629,7 @@ static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
-    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
+    prom_offset = qemu_ram_alloc(NULL, "sun4u.prom", PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
     return 0;
 }
@@ -665,7 +665,7 @@ static int ram_init1(SysBusDevice *dev)
 
     RAM_size = d->size;
 
-    ram_offset = qemu_ram_alloc(RAM_size);
+    ram_offset = qemu_ram_alloc(NULL, "sun4u.ram", RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
     return 0;
 }
diff --git a/hw/syborg.c b/hw/syborg.c
index 2d08cb2..758c69a 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -51,7 +51,7 @@ static void syborg_init(ram_addr_t ram_size,
     }
 
     /* RAM at address zero. */
-    ram_addr = qemu_ram_alloc(ram_size);
+    ram_addr = qemu_ram_alloc(NULL, "syborg.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr | IO_MEM_RAM);
 
     cpu_pic = arm_pic_init_cpu(env);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index e0c5e5f..16db51d 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -593,7 +593,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
                     tc6393xb_writefn, s);
     cpu_register_physical_memory(base, 0x10000, iomemtype);
 
-    s->vram_addr = qemu_ram_alloc(0x100000);
+    s->vram_addr = qemu_ram_alloc(NULL, "tc6393xb.vram", 0x100000);
     s->vram_ptr = qemu_get_ram_ptr(s->vram_addr);
     cpu_register_physical_memory(base + 0x100000, 0x100000, s->vram_addr);
     s->scr_width = 480;
diff --git a/hw/tcx.c b/hw/tcx.c
index beb30ac..6ee65bb 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -510,7 +510,7 @@ static int tcx_init1(SysBusDevice *dev)
     int size;
     uint8_t *vram_base;
 
-    vram_offset = qemu_ram_alloc(s->vram_size * (1 + 4 + 4));
+    vram_offset = qemu_ram_alloc(NULL, "tcx.vram", s->vram_size * (1 + 4 + 4));
     vram_base = qemu_get_ram_ptr(vram_offset);
     s->vram_offset = vram_offset;
 
diff --git a/hw/tosa.c b/hw/tosa.c
index fbe8d8c..ba6d9e7 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -215,7 +215,7 @@ static void tosa_init(ram_addr_t ram_size,
     cpu = pxa255_init(tosa_binfo.ram_size);
 
     cpu_register_physical_memory(0, TOSA_ROM,
-                    qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
 
     tmio = tc6393xb_init(0x10000000,
             pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 391f5b8..1d049f2 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -180,7 +180,7 @@ static void versatile_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "versatile.ram", ram_size);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
diff --git a/hw/vga.c b/hw/vga.c
index 01de1e1..b5c7ee7 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2261,7 +2261,7 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    s->vram_offset = qemu_ram_alloc(vga_ram_size);
+    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
     s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 359e5d8..9e72d2e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1164,7 +1164,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    s->fifo_offset = qemu_ram_alloc(s->fifo_size);
+    s->fifo_offset = qemu_ram_alloc(NULL, "vmsvga.fifo", s->fifo_size);
     s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
 
     vga_common_init(&s->vga, vga_ram_size);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (8 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 09/16] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 11/16] savevm: Migrate RAM based on name/offset Alex Williamson
                     ` (5 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

With these two pieces in place, we can start naming ramblocks.  When
the device is present and it lives on a bus that provides a device
path, we concatenate the path and the provided name.  Otherwise we
just use name.  The resulting id string must be unique.  For now we
assume an allocation for the same name and size is a device that has
been removed and reinserted and return the same block.  This will go
away once qemu_ram_free() is implemented.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-all.h |    1 +
 exec.c    |   29 +++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index dbb2139..5d8342b 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -865,6 +865,7 @@ typedef struct RAMBlock {
     uint8_t *host;
     ram_addr_t offset;
     ram_addr_t length;
+    char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
 } RAMBlock;
 
diff --git a/exec.c b/exec.c
index dc47831..a136c13 100644
--- a/exec.c
+++ b/exec.c
@@ -36,6 +36,7 @@
 #include "qemu-common.h"
 #include "tcg.h"
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "osdep.h"
 #include "kvm.h"
 #include "qemu-timer.h"
@@ -2778,10 +2779,34 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
 
 ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 {
-    RAMBlock *new_block;
+    RAMBlock *new_block, *block;
 
     size = TARGET_PAGE_ALIGN(size);
-    new_block = qemu_malloc(sizeof(*new_block));
+    new_block = qemu_mallocz(sizeof(*new_block));
+
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
+            qemu_free(id);
+        }
+    }
+    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (!strcmp(block->idstr, new_block->idstr)) {
+            if (block->length == new_block->length) {
+                fprintf(stderr, "RAMBlock \"%s\" exists, assuming lack of"
+                        "free.\n", new_block->idstr);
+                qemu_free(new_block);
+                return block->offset;
+            } else {
+                fprintf(stderr, "RAMBlock \"%s\" already registered with"
+                        "different size, abort\n", new_block->idstr);
+                abort();
+            }
+        }
+    }
 
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 11/16] savevm: Migrate RAM based on name/offset
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (9 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migration Alex Williamson
                     ` (4 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Synchronize RAM blocks with the target and migrate using name/offset
pairs.  This ensures both source and target have the same view of
RAM and that we get the right bits into the right slot.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |  118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 vl.c        |    2 +
 2 files changed, 108 insertions(+), 12 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 109dcef..37aad9d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -113,20 +113,33 @@ static int ram_save_block(QEMUFile *f)
 
     while (addr < total_ram) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
+            RAMBlock *block;
+            ram_addr_t offset;
             uint8_t *p;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
                                             MIGRATION_DIRTY_FLAG);
 
-            p = qemu_get_ram_ptr(current_addr);
+            QLIST_FOREACH(block, &ram_list.blocks, next) {
+                if (current_addr - block->offset < block->length)
+                    break;
+            }
+            offset = current_addr - block->offset;
+            p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
-                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
             } else {
-                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
+                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
@@ -196,6 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        RAMBlock *block;
         uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
@@ -210,6 +224,12 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         cpu_physical_memory_set_dirty_tracking(1);
 
         qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
+
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            qemu_put_byte(f, strlen(block->idstr));
+            qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
+            qemu_put_be64(f, block->length);
+        }
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -257,7 +277,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
     ram_addr_t addr;
     int flags;
 
-    if (version_id != 3) {
+    if (version_id < 3 || version_id > 4) {
         return -EINVAL;
     }
 
@@ -268,23 +288,99 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != ram_bytes_total()) {
-                return -EINVAL;
+            if (version_id == 3) {
+                if (addr != ram_bytes_total()) {
+                    return -EINVAL;
+                }
+            } else {
+                /* Synchronize RAM block list */
+                char id[256];
+                ram_addr_t length;
+                ram_addr_t total_ram_bytes = addr;
+
+                while (total_ram_bytes) {
+                    RAMBlock *block;
+                    uint8_t len;
+
+                    len = qemu_get_byte(f);
+                    qemu_get_buffer(f, (uint8_t *)id, len);
+                    id[len] = 0;
+                    length = qemu_get_be64(f);
+
+                    QLIST_FOREACH(block, &ram_list.blocks, next) {
+                        if (!strncmp(id, block->idstr, sizeof(id))) {
+                            if (block->length != length)
+                                return -EINVAL;
+                            break;
+                        }
+                    }
+
+                    if (!block) {
+                        if (!qemu_ram_alloc(NULL, id, length))
+                            return -ENOMEM;
+                    }
+
+                    total_ram_bytes -= length;
+                }
             }
         }
 
         if (flags & RAM_SAVE_FLAG_COMPRESS) {
-            uint8_t ch = qemu_get_byte(f);
-            memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
+            void *host;
+            uint8_t ch;
+
+            if (version_id == 3) {
+                host = qemu_get_ram_ptr(addr);
+            } else {
+                RAMBlock *block;
+                char id[256];
+                uint8_t len;
+
+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;
+
+                host = block->host + addr;
+            }
+            ch = qemu_get_byte(f);
+            memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
             if (ch == 0 &&
                 (!kvm_enabled() || kvm_has_sync_mmu())) {
-                madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE,
-                        MADV_DONTNEED);
+                madvise(host, TARGET_PAGE_SIZE, MADV_DONTNEED);
             }
 #endif
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
-            qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
+            void *host;
+
+            if (version_id == 3) {
+                host = qemu_get_ram_ptr(addr);
+            } else {
+                RAMBlock *block;
+                char id[256];
+                uint8_t len;
+
+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;
+
+                host = block->host + addr;
+            }
+            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {
             return -EIO;
diff --git a/vl.c b/vl.c
index 4a1c5f4..8a5de9f 100644
--- a/vl.c
+++ b/vl.c
@@ -2794,7 +2794,7 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
-    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
+    register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migration
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (10 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 11/16] savevm: Migrate RAM based on name/offset Alex Williamson
@ 2010-06-25 17:09   ` Alex Williamson
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 13/16] savevm: Create a new continue flag to avoid resending block name Alex Williamson
                     ` (3 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

We don't want to assume a contiguous address space, so migrate based
on RAM blocks instead of a fixed linear address map.  This will allow
us to have holes in the ram_addr_t namespace, so we can implement
qemu_ram_free().

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   67 +++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 37aad9d..186645b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -105,27 +105,26 @@ static int is_dup_page(uint8_t *page, uint8_t ch)
 
 static int ram_save_block(QEMUFile *f)
 {
-    static ram_addr_t current_addr = 0;
-    ram_addr_t saved_addr = current_addr;
-    ram_addr_t addr = 0;
-    uint64_t total_ram = ram_bytes_total();
+    static RAMBlock *last_block = NULL;
+    static ram_addr_t last_offset = 0;
+    RAMBlock *block = last_block;
+    ram_addr_t offset = last_offset;
+    ram_addr_t current_addr;
     int bytes_sent = 0;
 
-    while (addr < total_ram) {
+    if (!block)
+        block = QLIST_FIRST(&ram_list.blocks);
+
+    current_addr = block->offset + offset;
+
+    do {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
-            RAMBlock *block;
-            ram_addr_t offset;
             uint8_t *p;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
                                             MIGRATION_DIRTY_FLAG);
 
-            QLIST_FOREACH(block, &ram_list.blocks, next) {
-                if (current_addr - block->offset < block->length)
-                    break;
-            }
-            offset = current_addr - block->offset;
             p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
@@ -146,9 +145,21 @@ static int ram_save_block(QEMUFile *f)
 
             break;
         }
-        addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % total_ram;
-    }
+
+        offset += TARGET_PAGE_SIZE;
+        if (offset >= block->length) {
+            offset = 0;
+            block = QLIST_NEXT(block, next);
+            if (!block)
+                block = QLIST_FIRST(&ram_list.blocks);
+        }
+
+        current_addr = block->offset + offset;
+
+    } while (current_addr != last_block->offset + last_offset);
+
+    last_block = block;
+    last_offset = offset;
 
     return bytes_sent;
 }
@@ -157,13 +168,16 @@ static uint64_t bytes_transferred;
 
 static ram_addr_t ram_save_remaining(void)
 {
-    ram_addr_t addr;
+    RAMBlock *block;
     ram_addr_t count = 0;
-    uint64_t total_ram = ram_bytes_total();
 
-    for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
-        if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
-            count++;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ram_addr_t addr;
+        for (addr = block->offset; addr < block->offset + block->length;
+             addr += TARGET_PAGE_SIZE) {
+            if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
+                count++;
+            }
         }
     }
 
@@ -210,20 +224,23 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     if (stage == 1) {
         RAMBlock *block;
-        uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
-            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
-                cpu_physical_memory_set_dirty(addr);
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            for (addr = block->offset; addr < block->offset + block->length;
+                 addr += TARGET_PAGE_SIZE) {
+                if (!cpu_physical_memory_get_dirty(addr,
+                                                   MIGRATION_DIRTY_FLAG)) {
+                    cpu_physical_memory_set_dirty(addr);
+                }
             }
         }
 
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
         QLIST_FOREACH(block, &ram_list.blocks, next) {
             qemu_put_byte(f, strlen(block->idstr));

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 13/16] savevm: Create a new continue flag to avoid resending block name
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (11 preceding siblings ...)
  2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migration Alex Williamson
@ 2010-06-25 17:10   ` Alex Williamson
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 14/16] qemu_ram_free: Implement it Alex Williamson
                     ` (2 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Allows us to compress the protocol a bit by setting a flag on the
offset which indicates we're still working within the same block
as last time.  That way we can avoid sending the block name for
every page.  Suggested by Anthony Liguori.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   94 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 50 insertions(+), 44 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 186645b..2f082f3 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -87,6 +87,7 @@ const uint32_t arch_type = QEMU_ARCH;
 #define RAM_SAVE_FLAG_MEM_SIZE	0x04
 #define RAM_SAVE_FLAG_PAGE	0x08
 #define RAM_SAVE_FLAG_EOS	0x10
+#define RAM_SAVE_FLAG_CONTINUE	0x20
 
 static int is_dup_page(uint8_t *page, uint8_t ch)
 {
@@ -120,6 +121,7 @@ static int ram_save_block(QEMUFile *f)
     do {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
+            int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
@@ -128,17 +130,21 @@ static int ram_save_block(QEMUFile *f)
             p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
-                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, strlen(block->idstr));
-                qemu_put_buffer(f, (uint8_t *)block->idstr,
-                                strlen(block->idstr));
+                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
+                if (!cont) {
+                    qemu_put_byte(f, strlen(block->idstr));
+                    qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                    strlen(block->idstr));
+                }
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
             } else {
-                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
-                qemu_put_byte(f, strlen(block->idstr));
-                qemu_put_buffer(f, (uint8_t *)block->idstr,
-                                strlen(block->idstr));
+                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
+                if (!cont) {
+                    qemu_put_byte(f, strlen(block->idstr));
+                    qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                    strlen(block->idstr));
+                }
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
@@ -289,6 +295,36 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     return (stage == 2) && (expected_time <= migrate_max_downtime());
 }
 
+static inline void *host_from_stream_offset(QEMUFile *f,
+                                            ram_addr_t offset,
+                                            int flags)
+{
+    static RAMBlock *block = NULL;
+    char id[256];
+    uint8_t len;
+
+    if (flags & RAM_SAVE_FLAG_CONTINUE) {
+        if (!block) {
+            fprintf(stderr, "Ack, bad migration stream!\n");
+            return NULL;
+        }
+
+        return block->host + offset;
+    }
+
+    len = qemu_get_byte(f);
+    qemu_get_buffer(f, (uint8_t *)id, len);
+    id[len] = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (!strncmp(id, block->idstr, sizeof(id)))
+            return block->host + offset;
+    }
+
+    fprintf(stderr, "Can't find block %s!\n", id);
+    return NULL;
+}
+
 int ram_load(QEMUFile *f, void *opaque, int version_id)
 {
     ram_addr_t addr;
@@ -346,26 +382,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
             void *host;
             uint8_t ch;
 
-            if (version_id == 3) {
+            if (version_id == 3)
                 host = qemu_get_ram_ptr(addr);
-            } else {
-                RAMBlock *block;
-                char id[256];
-                uint8_t len;
-
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
+            else
+                host = host_from_stream_offset(f, addr, flags);
 
-                QLIST_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id)))
-                        break;
-                }
-                if (!block)
-                    return -EINVAL;
-
-                host = block->host + addr;
-            }
             ch = qemu_get_byte(f);
             memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
@@ -377,26 +398,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
-            if (version_id == 3) {
+            if (version_id == 3)
                 host = qemu_get_ram_ptr(addr);
-            } else {
-                RAMBlock *block;
-                char id[256];
-                uint8_t len;
+            else
+                host = host_from_stream_offset(f, addr, flags);
 
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
-
-                QLIST_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id)))
-                        break;
-                }
-                if (!block)
-                    return -EINVAL;
-
-                host = block->host + addr;
-            }
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 14/16] qemu_ram_free: Implement it
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (12 preceding siblings ...)
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 13/16] savevm: Create a new continue flag to avoid resending block name Alex Williamson
@ 2010-06-25 17:10   ` Alex Williamson
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 15/16] pci: Free the space allocated for the option rom on removal Alex Williamson
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 16/16] ramblocks: No more being lazy about duplicate names Alex Williamson
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Now that we can support a ram_addr_t space with holes, we can implement
qemu_ram_free().

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-all.h |    3 +++
 exec.c    |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index 5d8342b..224ca40 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -867,6 +867,9 @@ typedef struct RAMBlock {
     ram_addr_t length;
     char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
+#if defined(__linux__) && !defined(TARGET_S390X)
+    int fd;
+#endif
 } RAMBlock;
 
 typedef struct RAMList {
diff --git a/exec.c b/exec.c
index a136c13..e8108d7 100644
--- a/exec.c
+++ b/exec.c
@@ -2699,7 +2699,9 @@ static long gethugepagesize(const char *path)
     return fs.f_bsize;
 }
 
-static void *file_ram_alloc(ram_addr_t memory, const char *path)
+static void *file_ram_alloc(RAMBlock *block,
+                            ram_addr_t memory,
+                            const char *path)
 {
     char *filename;
     void *area;
@@ -2762,19 +2764,35 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 	close(fd);
 	return (NULL);
     }
+    block->fd = fd;
     return area;
 }
 #endif
 
 static ram_addr_t find_ram_offset(ram_addr_t size)
 {
-    RAMBlock *block;
-    ram_addr_t last = 0;
+    RAMBlock *block, *next_block;
+    ram_addr_t offset, mingap = ULONG_MAX;
+
+    if (QLIST_EMPTY(&ram_list.blocks))
+        return 0;
 
-    QLIST_FOREACH(block, &ram_list.blocks, next)
-        last = MAX(last, block->offset + block->length);
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ram_addr_t end, next = ULONG_MAX;
 
-    return last;
+        end = block->offset + block->length;
+
+        QLIST_FOREACH(next_block, &ram_list.blocks, next) {
+            if (next_block->offset >= end) {
+                next = MIN(next, next_block->offset);
+            }
+        }
+        if (next - end >= size && next - end < mingap) {
+            offset =  end;
+            mingap = next - end;
+        }
+    }
+    return offset;
 }
 
 ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
@@ -2810,7 +2828,7 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)
-        new_block->host = file_ram_alloc(size, mem_path);
+        new_block->host = file_ram_alloc(new_block, size, mem_path);
         if (!new_block->host) {
             new_block->host = qemu_vmalloc(size);
 #ifdef MADV_MERGEABLE
@@ -2852,7 +2870,32 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
 void qemu_ram_free(ram_addr_t addr)
 {
-    /* TODO: implement this.  */
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (addr == block->offset) {
+            QLIST_REMOVE(block, next);
+            if (mem_path) {
+#if defined (__linux__) && !defined(TARGET_S390X)
+                if (block->fd) {
+                    munmap(block->host, block->length);
+                    close(block->fd);
+                } else {
+                    qemu_vfree(block->host);
+                }
+#endif
+            } else {
+#if defined(TARGET_S390X) && defined(CONFIG_KVM)
+                munmap(block->host, block->length);
+#else
+                qemu_vfree(block->host);
+#endif
+            }
+            qemu_free(block);
+            return;
+        }
+    }
+
 }
 
 /* Return a host pointer to ram allocated with qemu_ram_alloc.

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 15/16] pci: Free the space allocated for the option rom on removal
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (13 preceding siblings ...)
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 14/16] qemu_ram_free: Implement it Alex Williamson
@ 2010-06-25 17:10   ` Alex Williamson
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 16/16] ramblocks: No more being lazy about duplicate names Alex Williamson
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pci.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index fe7c5c3..a7ff566 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -76,6 +76,7 @@ static struct BusInfo pci_bus_info = {
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev);
+static void pci_del_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
@@ -709,6 +710,7 @@ static int pci_unregister_device(DeviceState *dev)
         return ret;
 
     pci_unregister_io_regions(pci_dev);
+    pci_del_option_rom(pci_dev);
     do_pci_unregister_device(pci_dev);
     return 0;
 }
@@ -1765,6 +1767,15 @@ static int pci_add_option_rom(PCIDevice *pdev)
     return 0;
 }
 
+static void pci_del_option_rom(PCIDevice *pdev)
+{
+    if (!pdev->rom_offset)
+        return;
+
+    qemu_ram_free(pdev->rom_offset);
+    pdev->rom_offset = 0;
+}
+
 /* Reserve space and add capability to the linked list in pci config space */
 int pci_add_capability_at_offset(PCIDevice *pdev, uint8_t cap_id,
                                  uint8_t offset, uint8_t size)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v2 16/16] ramblocks: No more being lazy about duplicate names
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
                     ` (14 preceding siblings ...)
  2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 15/16] pci: Free the space allocated for the option rom on removal Alex Williamson
@ 2010-06-25 17:10   ` Alex Williamson
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-06-25 17:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Now that we have a working qemu_ram_free() and the primary runtime
user of it has been updated, don't be lenient about duplicate id strings.
We also shouldn't need to create them ondemand at the target.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |    5 +++--
 exec.c      |   13 +++----------
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 2f082f3..47bb4b2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -369,8 +369,9 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
                     }
 
                     if (!block) {
-                        if (!qemu_ram_alloc(NULL, id, length))
-                            return -ENOMEM;
+                        fprintf(stderr, "Unknown ramblock \"%s\", cannot "
+                                "accept migration\n", id);
+                        return -EINVAL;
                     }
 
                     total_ram_bytes -= length;
diff --git a/exec.c b/exec.c
index e8108d7..ef2a89d 100644
--- a/exec.c
+++ b/exec.c
@@ -2813,16 +2813,9 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (!strcmp(block->idstr, new_block->idstr)) {
-            if (block->length == new_block->length) {
-                fprintf(stderr, "RAMBlock \"%s\" exists, assuming lack of"
-                        "free.\n", new_block->idstr);
-                qemu_free(new_block);
-                return block->offset;
-            } else {
-                fprintf(stderr, "RAMBlock \"%s\" already registered with"
-                        "different size, abort\n", new_block->idstr);
-                abort();
-            }
+            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
+                    new_block->idstr);
+            abort();
         }
     }
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug
  2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
                   ` (16 preceding siblings ...)
  2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
@ 2010-07-02 17:11 ` Alex Williamson
  2010-07-02 17:11   ` [Qemu-devel] [PATCH v3 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
                     ` (15 more replies)
  17 siblings, 16 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

v3:

Still looking for comments...

changes:
  - Rebase to latest upstream to pickup a few more callers
  - Fix a bug in patch introducing qemu_ram_free().  Since we now
    try to place blocks into existing holes in the address space,
    the end of the current block isn't necessarily the top
    ram_addr_t for realloc'ing the dirty bitmap.

v2:

Not too many comments, hope that's because everyone agrees ;)
A couple minor changes.  The 2nd patch is new and provides a
bit of an optimization for large memory pc guets.  The first
two patches stand on their own even if we're undecided about
the rest.  Thanks,

Alex

changes:
  - Use pci_find_domain() for PCI domain, thanks Isaku
  - Convert pc to allocate all ram in one chunk, which avoids
    penalizing large memory VMs bouncing between ramblocks
    during migration.

v1:

Ok, new approach.  I'm going to attempt to extract myself for the
canonical device path approach, because we're missing too many pieces
to make that work.  Instead, I'll take Anthony's advice and try to
simplify.  We still want a unique name for ramblocks and savevm, but
the hotplug problem today is only for PCI devices.  PCI conveniently
has globally unique, dare I say canonical, addressing in the form of
<domain>:<bus>:<device>.<func>.  To get to this, let's add a new
function on the BusInfo structure called get_dev_path().  For a PCI
device, we can simply traverse up the qdev tree to the BusInfo
structure, look for the function, and call it to return a global PCI
address.

For some buses, these functions could chain up to their parent bus
appending strings together to get a unique path.  An example would be
USB, where the USB port number may not be unique.  If we traverse up
to the PCI device providing USB, and then to the PCI bus, we get a
globally unique PCI path, appended with a USB port number.

To make this work for ramblocks and savevm, we need a DeviceState
pointer when the they are create/registered, and we need a caller
provided context in case there are multiple ramblocks/savevm
associated with a device.  Savevm already provies the context,
and I've attempted to make reasonable guesses at these for the
ramblocks.  Note that most of the ramblocks aren't associated with
a device, so I don't think it makes sense to link savevm and
ramblocks together with the same absolute id string.

Once we have savevm with unique id strings, rather than hotplug
unfriendly instance numbers, we can be sure that the right driver
instance is loading the correct vmstate.  I've also implemented
a compat field for this, so we can still accept incoming migrations
from previous versions.

Once we have ramblocks with a unique id string, we can switch to
using id + offset for migration, which enables a ram_addr_t space
that supports gaps, which enables us to implement qemu_ram_free().  
With that, I think we can finally do migrations reliable after
hotplug!  Note that the target VM still needs to be created to
match the current devices and bus addresses of the source VM.  We
can also still maintain compatibility for migrations here by bumping
the ram migration version and supporting both new and old (just
hope the source hasn't done any hotplugs).

Sound reasonable?  Is get_dev_path the right name?  In the right
place?  The PCI return is currently "dddd:bb:dd.f", should this be
"PCI:dddd:bb:dd.f"?  Something else?  Thanks,

Alex

---

Alex Williamson (16):
      ramblocks: No more being lazy about duplicate names
      pci: Free the space allocated for the option rom on removal
      qemu_ram_free: Implement it
      savevm: Create a new continue flag to avoid resending block name
      savevm: Use RAM blocks for basis of migration
      savevm: Migrate RAM based on name/offset
      ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
      qemu_ram_alloc: Add DeviceState and name parameters
      virtio-net: Incorporate a DeviceState pointer and let savevm track instances
      eepro100: Add a dev field to eeprom new/free functions
      savevm: Make use of DeviceState
      savevm: Add DeviceState param
      pci: Implement BusInfo.get_dev_path()
      qdev: Add a get_dev_path() function to BusInfo
      pc: Allocate all ram in a single qemu_ram_alloc()
      Remove uses of ram.last_offset (aka last_ram_offset)


 arch_init.c                   |  183 +++++++++++++++++++++++++++++++++++------
 audio/audio.c                 |    2 
 block-migration.c             |    4 -
 cpu-all.h                     |    5 +
 cpu-common.h                  |    2 
 exec.c                        |  107 +++++++++++++++++++++---
 hw/adb.c                      |    4 -
 hw/ads7846.c                  |    2 
 hw/an5206.c                   |    4 -
 hw/arm_gic.c                  |    2 
 hw/arm_timer.c                |    4 -
 hw/armv7m.c                   |    9 +-
 hw/armv7m_nvic.c              |    2 
 hw/axis_dev88.c               |    4 -
 hw/cirrus_vga.c               |    2 
 hw/cuda.c                     |    2 
 hw/dma.c                      |    4 -
 hw/dummy_m68k.c               |    2 
 hw/eepro100.c                 |    8 +-
 hw/eeprom93xx.c               |    8 +-
 hw/eeprom93xx.h               |    4 -
 hw/etraxfs.c                  |    6 +
 hw/g364fb.c                   |    4 -
 hw/grackle_pci.c              |    4 -
 hw/gt64xxx.c                  |    3 -
 hw/gumstix.c                  |    6 +
 hw/heathrow_pic.c             |    2 
 hw/hw.h                       |   18 ++--
 hw/i2c.c                      |    2 
 hw/i8254.c                    |    2 
 hw/i8259.c                    |    2 
 hw/ide/cmd646.c               |    2 
 hw/ide/isa.c                  |    2 
 hw/ide/macio.c                |    2 
 hw/ide/microdrive.c           |    2 
 hw/ide/mmio.c                 |    2 
 hw/ide/piix.c                 |    2 
 hw/ide/via.c                  |    2 
 hw/integratorcp.c             |    4 -
 hw/m48t59.c                   |    2 
 hw/mac_dbdma.c                |    2 
 hw/mac_nvram.c                |    4 -
 hw/mainstone.c                |    6 +
 hw/max111x.c                  |    3 -
 hw/mcf5208.c                  |    4 -
 hw/mips_fulong2e.c            |    6 +
 hw/mips_jazz.c                |    4 -
 hw/mips_malta.c               |    4 -
 hw/mips_mipssim.c             |    4 -
 hw/mips_r4k.c                 |    6 +
 hw/mipsnet.c                  |    4 -
 hw/mst_fpga.c                 |    3 -
 hw/musicpal.c                 |   11 ++
 hw/nand.c                     |    2 
 hw/omap1.c                    |    6 +
 hw/omap2.c                    |    6 +
 hw/omap_sx1.c                 |   12 ++-
 hw/onenand.c                  |    2 
 hw/openpic.c                  |    5 +
 hw/palm.c                     |    3 -
 hw/pc.c                       |   27 +++---
 hw/pci.c                      |   34 +++++++-
 hw/pckbd.c                    |    2 
 hw/petalogix_s3adsp1800_mmu.c |    7 +-
 hw/piix4.c                    |    2 
 hw/pl011.c                    |    2 
 hw/pl022.c                    |    2 
 hw/pl061.c                    |    2 
 hw/ppc405_boards.c            |   18 ++--
 hw/ppc405_uc.c                |    2 
 hw/ppc4xx_devs.c              |    4 +
 hw/ppc4xx_pci.c               |    4 -
 hw/ppc_newworld.c             |    6 +
 hw/ppc_oldworld.c             |    6 +
 hw/ppc_prep.c                 |    4 -
 hw/ppce500_mpc8544ds.c        |    3 -
 hw/ppce500_pci.c              |    4 -
 hw/ps2.c                      |    4 -
 hw/pxa2xx.c                   |   39 +++++----
 hw/pxa2xx_dma.c               |    2 
 hw/pxa2xx_gpio.c              |    2 
 hw/pxa2xx_keypad.c            |    2 
 hw/pxa2xx_lcd.c               |    2 
 hw/pxa2xx_mmci.c              |    2 
 hw/pxa2xx_pic.c               |    3 -
 hw/pxa2xx_timer.c             |    2 
 hw/qdev.c                     |    4 -
 hw/qdev.h                     |    3 +
 hw/r2d.c                      |    4 -
 hw/rc4030.c                   |    2 
 hw/realview.c                 |    6 +
 hw/s390-virtio.c              |    2 
 hw/serial.c                   |    4 -
 hw/sm501.c                    |    2 
 hw/spitz.c                    |   11 +-
 hw/ssd0323.c                  |    3 -
 hw/ssi-sd.c                   |    2 
 hw/stellaris.c                |   11 +-
 hw/stellaris_enet.c           |    4 -
 hw/stellaris_input.c          |    2 
 hw/sun4m.c                    |    8 +-
 hw/sun4u.c                    |    4 -
 hw/syborg.c                   |    2 
 hw/syborg_fb.c                |    2 
 hw/syborg_interrupt.c         |    3 -
 hw/syborg_keyboard.c          |    2 
 hw/syborg_pointer.c           |    2 
 hw/syborg_rtc.c               |    3 -
 hw/syborg_serial.c            |    2 
 hw/syborg_timer.c             |    2 
 hw/tc6393xb.c                 |    2 
 hw/tcx.c                      |    2 
 hw/tosa.c                     |    2 
 hw/tsc2005.c                  |    2 
 hw/tsc210x.c                  |    4 -
 hw/unin_pci.c                 |    6 +
 hw/versatilepb.c              |    2 
 hw/vga-isa-mm.c               |    2 
 hw/vga-isa.c                  |    2 
 hw/vga.c                      |    2 
 hw/virtio-balloon.c           |    3 -
 hw/virtio-blk.c               |    2 
 hw/virtio-net.c               |    7 +-
 hw/virtio-serial-bus.c        |    2 
 hw/vmmouse.c                  |    2 
 hw/vmware_vga.c               |    4 -
 hw/zaurus.c                   |    2 
 qemu-timer.c                  |    2 
 savevm.c                      |  106 +++++++++++++++++++++---
 slirp/slirp.c                 |    5 +
 vl.c                          |    2 
 131 files changed, 670 insertions(+), 300 deletions(-)

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 01/16] Remove uses of ram.last_offset (aka last_ram_offset)
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
@ 2010-07-02 17:11   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 02/16] pc: Allocate all ram in a single qemu_ram_alloc() Alex Williamson
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

We currently need this either to allocate the next ram_addr_t for a
new block, or for total memory to be migrated.  Both of which we can
calculate without need of this to keep us in a contiguous address space.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   23 ++++++++++++++++-------
 cpu-all.h   |    1 -
 exec.c      |   19 ++++++++++++++-----
 3 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index eb5b67c..109dcef 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -108,9 +108,10 @@ static int ram_save_block(QEMUFile *f)
     static ram_addr_t current_addr = 0;
     ram_addr_t saved_addr = current_addr;
     ram_addr_t addr = 0;
+    uint64_t total_ram = ram_bytes_total();
     int bytes_sent = 0;
 
-    while (addr < ram_list.last_offset) {
+    while (addr < total_ram) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
 
@@ -133,7 +134,7 @@ static int ram_save_block(QEMUFile *f)
             break;
         }
         addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % ram_list.last_offset;
+        current_addr = (saved_addr + addr) % total_ram;
     }
 
     return bytes_sent;
@@ -145,8 +146,9 @@ static ram_addr_t ram_save_remaining(void)
 {
     ram_addr_t addr;
     ram_addr_t count = 0;
+    uint64_t total_ram = ram_bytes_total();
 
-    for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
+    for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
         if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
             count++;
         }
@@ -167,7 +169,13 @@ uint64_t ram_bytes_transferred(void)
 
 uint64_t ram_bytes_total(void)
 {
-    return ram_list.last_offset;
+    RAMBlock *block;
+    uint64_t total = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        total += block->length;
+
+    return total;
 }
 
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
@@ -188,10 +196,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
+        for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
             if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
                 cpu_physical_memory_set_dirty(addr);
             }
@@ -200,7 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, ram_list.last_offset | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -259,7 +268,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != ram_list.last_offset) {
+            if (addr != ram_bytes_total()) {
                 return -EINVAL;
             }
         }
diff --git a/cpu-all.h b/cpu-all.h
index e31c2de..dbb2139 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -870,7 +870,6 @@ typedef struct RAMBlock {
 
 typedef struct RAMList {
     uint8_t *phys_dirty;
-    ram_addr_t last_offset;
     QLIST_HEAD(ram, RAMBlock) blocks;
 } RAMList;
 extern RAMList ram_list;
diff --git a/exec.c b/exec.c
index 137175c..a6b3f21 100644
--- a/exec.c
+++ b/exec.c
@@ -2767,6 +2767,17 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 }
 #endif
 
+static ram_addr_t find_ram_offset(ram_addr_t size)
+{
+    RAMBlock *block;
+    ram_addr_t last = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        last = MAX(last, block->offset + block->length);
+
+    return last;
+}
+
 ram_addr_t qemu_ram_alloc(ram_addr_t size)
 {
     RAMBlock *new_block;
@@ -2800,18 +2811,16 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
         madvise(new_block->host, size, MADV_MERGEABLE);
 #endif
     }
-    new_block->offset = ram_list.last_offset;
+    new_block->offset = find_ram_offset(size);
     new_block->length = size;
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
-        (ram_list.last_offset + size) >> TARGET_PAGE_BITS);
-    memset(ram_list.phys_dirty + (ram_list.last_offset >> TARGET_PAGE_BITS),
+        (new_block->offset + size) >> TARGET_PAGE_BITS);
+    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0xff, size >> TARGET_PAGE_BITS);
 
-    ram_list.last_offset += size;
-
     if (kvm_enabled())
         kvm_setup_guest_memory(new_block->host, size);
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 02/16] pc: Allocate all ram in a single qemu_ram_alloc()
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
  2010-07-02 17:11   ` [Qemu-devel] [PATCH v3 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 03/16] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
                     ` (13 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This will benefit us when we migrate based on ramblock name since
we won't be bouncing between separate blocks.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pc.c |   22 +++++++++-------------
 1 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 25ebafa..de60686 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -877,27 +877,23 @@ void pc_memory_init(ram_addr_t ram_size,
     *above_4g_mem_size_p = above_4g_mem_size;
     *below_4g_mem_size_p = below_4g_mem_size;
 
+#if TARGET_PHYS_ADDR_BITS == 32
+    if (above_4g_mem_size > 0) {
+        hw_error("To much RAM for 32-bit physical address");
+    }
+#endif
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(below_4g_mem_size);
+    ram_addr = qemu_ram_alloc(below_4g_mem_size + above_4g_mem_size);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
                  ram_addr + 0x100000);
-
-    /* above 4giga memory allocation */
-    if (above_4g_mem_size > 0) {
-#if TARGET_PHYS_ADDR_BITS == 32
-        hw_error("To much RAM for 32-bit physical address");
-#else
-        ram_addr = qemu_ram_alloc(above_4g_mem_size);
-        cpu_register_physical_memory(0x100000000ULL,
-                                     above_4g_mem_size,
-                                     ram_addr);
+#if TARGET_PHYS_ADDR_BITS > 32
+    cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
+                                 ram_addr + below_4g_mem_size);
 #endif
-    }
-
 
     /* BIOS load */
     if (bios_name == NULL)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 03/16] qdev: Add a get_dev_path() function to BusInfo
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
  2010-07-02 17:11   ` [Qemu-devel] [PATCH v3 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 02/16] pc: Allocate all ram in a single qemu_ram_alloc() Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 04/16] pci: Implement BusInfo.get_dev_path() Alex Williamson
                     ` (12 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This function is meant to provide a stable device path for buses
which are able to implement it.  If a bus has a globally unique
addresses scheme, one address level may be sufficient to provide
a path.  Other buses may need to recursively traverse up the
qdev tree.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/qdev.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/qdev.h b/hw/qdev.h
index be5ad67..d64619f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -49,10 +49,13 @@ struct DeviceState {
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
+typedef char *(*bus_get_dev_path)(DeviceState *dev);
+
 struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
+    bus_get_dev_path get_dev_path;
     Property *props;
 };
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 04/16] pci: Implement BusInfo.get_dev_path()
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (2 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 03/16] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 05/16] savevm: Add DeviceState param Alex Williamson
                     ` (11 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This works great for PCI since a <segment>:<bus>:<dev>.<fn> uniquely
describes a global address.  No need to traverse up the qdev tree.
PCI segment support is a placeholder for compatibility once we
support multiple segments.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pci.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7787005..1e77ae6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -58,11 +58,13 @@ struct PCIBus {
 };
 
 static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static char *pcibus_get_dev_path(DeviceState *dev);
 
 static struct BusInfo pci_bus_info = {
     .name       = "PCI",
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
+    .get_dev_path = pcibus_get_dev_path,
     .props      = (Property[]) {
         DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
         DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
@@ -1853,6 +1855,18 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     }
 }
 
+static char *pcibus_get_dev_path(DeviceState *dev)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    char path[16];
+
+    snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
+             pci_find_domain(d->bus), d->config[PCI_SECONDARY_BUS],
+             PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+
+    return strdup(path);
+}
+
 static PCIDeviceInfo bridge_info = {
     .qdev.name    = "pci-bridge",
     .qdev.size    = sizeof(PCIBridge),

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 05/16] savevm: Add DeviceState param
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (3 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 04/16] pci: Implement BusInfo.get_dev_path() Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 06/16] savevm: Make use of DeviceState Alex Williamson
                     ` (10 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

When available, we'd like to be able to access the DeviceState
when registering a savevm.  For buses with a get_dev_path()
function, this will allow us to create more unique savevm
id strings.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 audio/audio.c          |    2 +-
 block-migration.c      |    4 ++--
 exec.c                 |    4 ++--
 hw/adb.c               |    4 ++--
 hw/ads7846.c           |    2 +-
 hw/arm_gic.c           |    2 +-
 hw/arm_timer.c         |    4 ++--
 hw/armv7m_nvic.c       |    2 +-
 hw/cirrus_vga.c        |    2 +-
 hw/cuda.c              |    2 +-
 hw/dma.c               |    4 ++--
 hw/eepro100.c          |    4 ++--
 hw/eeprom93xx.c        |    4 ++--
 hw/g364fb.c            |    2 +-
 hw/grackle_pci.c       |    4 ++--
 hw/gt64xxx.c           |    3 ++-
 hw/heathrow_pic.c      |    2 +-
 hw/hw.h                |   18 +++++++++++-------
 hw/i2c.c               |    2 +-
 hw/i8254.c             |    2 +-
 hw/i8259.c             |    2 +-
 hw/ide/cmd646.c        |    2 +-
 hw/ide/isa.c           |    2 +-
 hw/ide/macio.c         |    2 +-
 hw/ide/microdrive.c    |    2 +-
 hw/ide/mmio.c          |    2 +-
 hw/ide/piix.c          |    2 +-
 hw/ide/via.c           |    2 +-
 hw/m48t59.c            |    2 +-
 hw/mac_dbdma.c         |    2 +-
 hw/mac_nvram.c         |    4 ++--
 hw/max111x.c           |    3 ++-
 hw/mips_fulong2e.c     |    2 +-
 hw/mipsnet.c           |    4 ++--
 hw/mst_fpga.c          |    3 ++-
 hw/nand.c              |    2 +-
 hw/openpic.c           |    5 +++--
 hw/pci.c               |    2 +-
 hw/pckbd.c             |    2 +-
 hw/piix4.c             |    2 +-
 hw/pl011.c             |    2 +-
 hw/pl022.c             |    2 +-
 hw/pl061.c             |    2 +-
 hw/ppc4xx_pci.c        |    4 ++--
 hw/ppce500_pci.c       |    4 ++--
 hw/ps2.c               |    4 ++--
 hw/pxa2xx.c            |   27 +++++++++++++++------------
 hw/pxa2xx_dma.c        |    2 +-
 hw/pxa2xx_gpio.c       |    2 +-
 hw/pxa2xx_keypad.c     |    2 +-
 hw/pxa2xx_lcd.c        |    2 +-
 hw/pxa2xx_mmci.c       |    2 +-
 hw/pxa2xx_pic.c        |    3 ++-
 hw/pxa2xx_timer.c      |    2 +-
 hw/qdev.c              |    4 ++--
 hw/rc4030.c            |    2 +-
 hw/serial.c            |    4 ++--
 hw/spitz.c             |    9 +++++----
 hw/ssd0323.c           |    3 ++-
 hw/ssi-sd.c            |    2 +-
 hw/stellaris.c         |   11 ++++++-----
 hw/stellaris_enet.c    |    4 ++--
 hw/stellaris_input.c   |    2 +-
 hw/syborg_fb.c         |    2 +-
 hw/syborg_interrupt.c  |    3 ++-
 hw/syborg_keyboard.c   |    2 +-
 hw/syborg_pointer.c    |    2 +-
 hw/syborg_rtc.c        |    3 ++-
 hw/syborg_serial.c     |    2 +-
 hw/syborg_timer.c      |    2 +-
 hw/tsc2005.c           |    2 +-
 hw/tsc210x.c           |    4 ++--
 hw/unin_pci.c          |    6 ++++--
 hw/vga-isa-mm.c        |    2 +-
 hw/vga-isa.c           |    2 +-
 hw/virtio-balloon.c    |    3 ++-
 hw/virtio-blk.c        |    2 +-
 hw/virtio-net.c        |    4 ++--
 hw/virtio-serial-bus.c |    2 +-
 hw/vmmouse.c           |    2 +-
 hw/vmware_vga.c        |    2 +-
 hw/zaurus.c            |    2 +-
 qemu-timer.c           |    2 +-
 savevm.c               |   22 +++++++++++++---------
 slirp/slirp.c          |    5 +++--
 vl.c                   |    2 +-
 86 files changed, 164 insertions(+), 139 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index dbf0b96..ad51077 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1901,7 +1901,7 @@ static void audio_init (void)
     }
 
     QLIST_INIT (&s->card_head);
-    vmstate_register (0, &vmstate_audio, s);
+    vmstate_register (NULL, 0, &vmstate_audio, s);
 }
 
 void AUD_register_card (const char *name, QEMUSoundCard *card)
diff --git a/block-migration.c b/block-migration.c
index 7d04d6d..533564c 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -638,6 +638,6 @@ void blk_mig_init(void)
     QSIMPLEQ_INIT(&block_mig_state.bmds_list);
     QSIMPLEQ_INIT(&block_mig_state.blk_list);
 
-    register_savevm_live("block", 0, 1, block_set_params, block_save_live,
-                         NULL, block_load, &block_mig_state);
+    register_savevm_live(NULL, "block", 0, 1, block_set_params,
+                         block_save_live, NULL, block_load, &block_mig_state);
 }
diff --git a/exec.c b/exec.c
index a6b3f21..c8be508 100644
--- a/exec.c
+++ b/exec.c
@@ -641,8 +641,8 @@ void cpu_exec_init(CPUState *env)
     cpu_list_unlock();
 #endif
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
-    vmstate_register(cpu_index, &vmstate_cpu_common, env);
-    register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
+    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
 #endif
 }
diff --git a/hw/adb.c b/hw/adb.c
index 4fb7a62..99b30f6 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -305,7 +305,7 @@ void adb_kbd_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                             adb_kbd_reset, s);
     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
-    register_savevm("adb_kbd", -1, 1, adb_kbd_save,
+    register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save,
                     adb_kbd_load, s);
 }
 
@@ -475,6 +475,6 @@ void adb_mouse_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                             adb_mouse_reset, s);
     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
-    register_savevm("adb_mouse", -1, 1, adb_mouse_save,
+    register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save,
                     adb_mouse_load, s);
 }
diff --git a/hw/ads7846.c b/hw/ads7846.c
index 184b3dd..b3bbeaf 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -151,7 +151,7 @@ static int ads7846_init(SSISlave *dev)
 
     ads7846_int_update(s);
 
-    register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s);
+    register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s);
     return 0;
 }
 
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index c4afc6a..8286a28 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -744,5 +744,5 @@ static void gic_init(gic_state *s)
     s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
                                           gic_dist_writefn, s);
     gic_reset(s);
-    register_savevm("arm_gic", -1, 1, gic_save, gic_load, s);
+    register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
 }
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9073ffc..f009e9e 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -174,7 +174,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 
     bh = qemu_bh_new(arm_timer_tick, s);
     s->timer = ptimer_init(bh);
-    register_savevm("arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
+    register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
     return s;
 }
 
@@ -271,7 +271,7 @@ static int sp804_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(sp804_readfn,
                                        sp804_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm("sp804", -1, 1, sp804_save, sp804_load, s);
+    register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
     return 0;
 }
 
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 9f09ef4..6c7ce01 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -397,7 +397,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
     gic_init(&s->gic);
     cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
     s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
-    register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+    register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
     return 0;
 }
 
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index ba48289..bbd4b08 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3128,7 +3128,7 @@ void isa_cirrus_vga_init(void)
     s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
                                      s->vga.screen_dump, s->vga.text_update,
                                      &s->vga);
-    vmstate_register(0, &vmstate_cirrus_vga, s);
+    vmstate_register(NULL, 0, &vmstate_cirrus_vga, s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
 }
diff --git a/hw/cuda.c b/hw/cuda.c
index 50950d9..3f238b6 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -763,6 +763,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
 
     s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
     *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s);
-    register_savevm("cuda", -1, 1, cuda_save, cuda_load, s);
+    register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
     qemu_register_reset(cuda_reset, s);
 }
diff --git a/hw/dma.c b/hw/dma.c
index 5b21521..8a7302a 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -548,8 +548,8 @@ void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
               high_page_enable ? 0x480 : -1, cpu_request_exit);
     dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
               high_page_enable ? 0x488 : -1, cpu_request_exit);
-    vmstate_register (0, &vmstate_dma, &dma_controllers[0]);
-    vmstate_register (1, &vmstate_dma, &dma_controllers[1]);
+    vmstate_register (NULL, 0, &vmstate_dma, &dma_controllers[0]);
+    vmstate_register (NULL, 1, &vmstate_dma, &dma_controllers[1]);
 
     dma_bh = qemu_bh_new(DMA_run_bh, NULL);
 }
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 97afa2c..0ddca8b 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1834,7 +1834,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
     cpu_unregister_io_memory(s->mmio_index);
-    vmstate_unregister(s->vmstate, s);
+    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
     eeprom93xx_free(s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
@@ -1893,7 +1893,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
     s->vmstate = qemu_malloc(sizeof(vmstate_eepro100));
     memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
     s->vmstate->name = s->nic->nc.model;
-    vmstate_register(-1, s->vmstate, s);
+    vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
 
     return 0;
 }
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 30a3534..6ba546f 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -316,7 +316,7 @@ eeprom_t *eeprom93xx_new(uint16_t nwords)
     /* Output DO is tristate, read results in 1. */
     eeprom->eedo = 1;
     logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
-    vmstate_register(0, &vmstate_eeprom, eeprom);
+    vmstate_register(NULL, 0, &vmstate_eeprom, eeprom);
     return eeprom;
 }
 
@@ -324,7 +324,7 @@ void eeprom93xx_free(eeprom_t *eeprom)
 {
     /* Destroy EEPROM. */
     logout("eeprom = 0x%p\n", eeprom);
-    vmstate_unregister(&vmstate_eeprom, eeprom);
+    vmstate_unregister(NULL, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/g364fb.c b/hw/g364fb.c
index d1d2c12..beafd70 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -598,7 +598,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
     s->irq = irq;
 
     qemu_register_reset(g364fb_reset, s);
-    register_savevm("g364fb", 0, 1, g364fb_save, g364fb_load, s);
+    register_savevm(NULL, "g364fb", 0, 1, g364fb_save, g364fb_load, s);
     g364fb_reset(s);
 
     s->ds = graphic_console_init(g364fb_update_display,
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index aa0c51b..0cf29dc 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -113,8 +113,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("grackle", 0, 1, pci_grackle_save, pci_grackle_load,
-                    &s->host_state);
+    register_savevm(&dev->qdev, "grackle", 0, 1, pci_grackle_save,
+                    pci_grackle_load, &s->host_state);
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
 }
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 7691e1d..313c080 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1146,7 +1146,8 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
 
     gt64120_reset(s);
 
-    register_savevm("GT64120 PCI Bus", 0, 1, gt64120_save, gt64120_load, d);
+    register_savevm(&d->qdev, "GT64120 PCI Bus", 0, 1,
+                    gt64120_save, gt64120_load, d);
 
     return s->pci->bus;
 }
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index 5e27021..cd86121 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -224,7 +224,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
     s->irqs = irqs[0];
     *pmem_index = cpu_register_io_memory(pic_read, pic_write, s);
 
-    register_savevm("heathrow_pic", -1, 1, heathrow_pic_save,
+    register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
                     heathrow_pic_load, s);
     qemu_register_reset(heathrow_pic_reset, s);
     return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
diff --git a/hw/hw.h b/hw/hw.h
index a49d866..c2de6fe 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -245,14 +245,16 @@ typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
                                  void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
-int register_savevm(const char *idstr,
+int register_savevm(DeviceState *dev,
+                    const char *idstr,
                     int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
                     void *opaque);
 
-int register_savevm_live(const char *idstr,
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
                          int instance_id,
                          int version_id,
                          SaveSetParamsHandler *set_params,
@@ -261,7 +263,7 @@ int register_savevm_live(const char *idstr,
                          LoadStateHandler *load_state,
                          void *opaque);
 
-void unregister_savevm(const char *idstr, void *opaque);
+void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
 
 typedef void QEMUResetHandler(void *opaque);
 
@@ -765,11 +767,13 @@ extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                               void *opaque, int version_id);
 extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                                void *opaque);
-extern int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                            void *base);
-extern int vmstate_register_with_alias_id(int instance_id,
+extern int vmstate_register(DeviceState *dev, int instance_id,
+                            const VMStateDescription *vmsd, void *base);
+extern int vmstate_register_with_alias_id(DeviceState *dev,
+                                          int instance_id,
                                           const VMStateDescription *vmsd,
                                           void *base, int alias_id,
                                           int required_for_version);
-void vmstate_unregister(const VMStateDescription *vmsd, void *opaque);
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+                        void *opaque);
 #endif
diff --git a/hw/i2c.c b/hw/i2c.c
index bee8e88..f80d12d 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -62,7 +62,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
     i2c_bus *bus;
 
     bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name));
-    vmstate_register(-1, &vmstate_i2c_bus, bus);
+    vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
     return bus;
 }
 
diff --git a/hw/i8254.c b/hw/i8254.c
index faaa884..06b225c 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -508,7 +508,7 @@ PITState *pit_init(int base, qemu_irq irq)
     s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
     s->irq = irq;
 
-    vmstate_register(base, &vmstate_pit, pit);
+    vmstate_register(NULL, base, &vmstate_pit, pit);
     qemu_register_reset(pit_reset, pit);
     register_ioport_write(base, 4, 1, pit_ioport_write, pit);
     register_ioport_read(base, 3, 1, pit_ioport_read, pit);
diff --git a/hw/i8259.c b/hw/i8259.c
index a995280..a8dbee6 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -483,7 +483,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *s)
         register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
         register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
     }
-    vmstate_register(io_addr, &vmstate_pic, s);
+    vmstate_register(NULL, io_addr, &vmstate_pic, s);
     qemu_register_reset(pic_reset, s);
 }
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 559147f..8b71a13 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -263,7 +263,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     ide_init2(&d->bus[0], irq[0]);
     ide_init2(&d->bus[1], irq[1]);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
     qemu_register_reset(cmd646_reset, d);
     return 0;
 }
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index b6c6347..8c28c08 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -71,7 +71,7 @@ static int isa_ide_initfn(ISADevice *dev)
     ide_init_ioport(&s->bus, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
     ide_init2(&s->bus, s->irq);
-    vmstate_register(0, &vmstate_ide_isa, s);
+    vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s);
     return 0;
 };
 
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index f76c0fa..fd4bdfd 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -321,7 +321,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
 
     pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
                                              pmac_ide_write, d);
-    vmstate_register(0, &vmstate_pmac, d);
+    vmstate_register(NULL, 0, &vmstate_pmac, d);
     qemu_register_reset(pmac_ide_reset, d);
 
     return pmac_ide_memory;
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index a7beac5..8e20e74 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -545,7 +545,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
     md->bus.ifs[0].mdata_size = METADATA_SIZE;
     md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
 
-    vmstate_register(-1, &vmstate_microdrive, md);
+    vmstate_register(NULL, -1, &vmstate_microdrive, md);
 
     return &md->card;
 }
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index e75cccf..9f20e8b 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -133,7 +133,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
     mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s);
     cpu_register_physical_memory(membase, 16 << shift, mem1);
     cpu_register_physical_memory(membase2, 2 << shift, mem2);
-    vmstate_register(0, &vmstate_ide_mmio, s);
+    vmstate_register(NULL, 0, &vmstate_ide_mmio, s);
     qemu_register_reset(mmio_ide_reset, s);
 }
 
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index dad6e86..db27ef6 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -128,7 +128,7 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
 
     pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
     ide_bus_new(&d->bus[0], &d->dev.qdev);
     ide_bus_new(&d->bus[1], &d->dev.qdev);
diff --git a/hw/ide/via.c b/hw/ide/via.c
index d933caf..c9b814e 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -157,7 +157,7 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
     pci_register_bar((PCIDevice *)d, 4, 0x10,
                            PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
-    vmstate_register(0, &vmstate_ide_pci, d);
+    vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
     ide_bus_new(&d->bus[0], &d->dev.qdev);
     ide_bus_new(&d->bus[1], &d->dev.qdev);
diff --git a/hw/m48t59.c b/hw/m48t59.c
index c3d7b3a..c7492a6 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -694,7 +694,7 @@ static void m48t59_init_common(M48t59State *s)
     }
     qemu_get_timedate(&s->alarm, 0);
 
-    register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s);
+    register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s);
 }
 
 static int m48t59_init_isa1(ISADevice *dev)
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index e2697d3..03d2d16 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -845,7 +845,7 @@ void* DBDMA_init (int *dbdma_mem_index)
     s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
 
     *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s);
-    register_savevm("dbdma", -1, 1, dbdma_save, dbdma_load, s);
+    register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
     qemu_register_reset(dbdma_reset, s);
 
     dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index f28db6b..ce287c3 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -140,8 +140,8 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
 
     s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s);
     *mem_index = s->mem_index;
-    register_savevm("macio_nvram", -1, 1, macio_nvram_save, macio_nvram_load,
-                    s);
+    register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
+                    macio_nvram_load, s);
     qemu_register_reset(macio_nvram_reset, s);
 
     return s;
diff --git a/hw/max111x.c b/hw/max111x.c
index bd656bb..2844665 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -143,7 +143,8 @@ static int max111x_init(SSISlave *dev, int inputs)
     s->input[7] = 0x80;
     s->com = 0;
 
-    register_savevm("max111x", -1, 0, max111x_save, max111x_load, s);
+    register_savevm(&dev->qdev, "max111x", -1, 0,
+                    max111x_save, max111x_load, s);
     return 0;
 }
 
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index d85240a..7b1da0d 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -282,7 +282,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
         exit(1);
     }
 
-    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    register_savevm(NULL, "cpu", 0, 3, cpu_save, cpu_load, env);
     qemu_register_reset(main_cpu_reset, env);
 
     /* fulong 2e has 256M ram. */
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index a066f63..a95b3ce 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -239,7 +239,7 @@ static void mipsnet_cleanup(VLANClientState *nc)
 {
     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm("mipsnet", s);
+    unregister_savevm(NULL, "mipsnet", s);
 
     isa_unassign_ioport(s->io_base, 36);
 
@@ -284,5 +284,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
     }
 
     mipsnet_reset(s);
-    register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+    register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
 }
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 1b6cb77..8fc348f 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -234,6 +234,7 @@ qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
 	iomemtype = cpu_register_io_memory(mst_fpga_readfn,
 		mst_fpga_writefn, s);
 	cpu_register_physical_memory(base, 0x00100000, iomemtype);
-	register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
+	register_savevm(NULL, "mainstone_fpga", 0, 0, mst_fpga_save,
+                        mst_fpga_load, s);
 	return qi;
 }
diff --git a/hw/nand.c b/hw/nand.c
index cd7444f..f414aa1 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -502,7 +502,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
        is used.  */
     s->ioaddr = s->io;
 
-    register_savevm("nand", -1, 0, nand_save, nand_load, s);
+    register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
 
     return s;
 }
diff --git a/hw/openpic.c b/hw/openpic.c
index ac21993..2b4cb00 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1234,7 +1234,8 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     opp->irq_out = irq_out;
     opp->need_swap = 1;
 
-    register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp);
+    register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
+                    openpic_save, openpic_load, opp);
     qemu_register_reset(openpic_reset, opp);
 
     opp->irq_raise = openpic_irq_raise;
@@ -1692,7 +1693,7 @@ qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
     mpp->irq_raise = mpic_irq_raise;
     mpp->reset = mpic_reset;
 
-    register_savevm("mpic", 0, 2, openpic_save, openpic_load, mpp);
+    register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
     qemu_register_reset(mpic_reset, mpp);
 
     return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
diff --git a/hw/pci.c b/hw/pci.c
index 1e77ae6..79f1f11 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -232,7 +232,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     QLIST_INIT(&bus->child);
     pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
 
-    vmstate_register(-1, &vmstate_pcibus, bus);
+    vmstate_register(NULL, -1, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
 }
 
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 3812284..0533b1d 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -418,7 +418,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
     s->irq_mouse = mouse_irq;
     s->mask = mask;
 
-    vmstate_register(0, &vmstate_kbd, s);
+    vmstate_register(NULL, 0, &vmstate_kbd, s);
     s_io_memory = cpu_register_io_memory(kbd_mm_read, kbd_mm_write, s);
     cpu_register_physical_memory(base, size, s_io_memory);
 
diff --git a/hw/piix4.c b/hw/piix4.c
index f75951b..6f08c5a 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -87,7 +87,7 @@ static int piix4_initfn(PCIDevice *d)
     uint8_t *pci_conf;
 
     isa_bus_new(&d->qdev);
-    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+    register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
 
     pci_conf = d->config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
diff --git a/hw/pl011.c b/hw/pl011.c
index 81de91e..02cf84a 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -306,7 +306,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
         qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
                               pl011_event, s);
     }
-    register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s);
+    register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
     return 0;
 }
 
diff --git a/hw/pl022.c b/hw/pl022.c
index c2e2dda..d7862bc 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -299,7 +299,7 @@ static int pl022_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
-    register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+    register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s);
     return 0;
 }
 
diff --git a/hw/pl061.c b/hw/pl061.c
index 7b1b636..e4505f5 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -303,7 +303,7 @@ static int pl061_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
     pl061_reset(s);
-    register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s);
+    register_savevm(&dev->qdev, "pl061_gpio", -1, 1, pl061_save, pl061_load, s);
     return 0;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index c9e3279..6e437e7 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -392,8 +392,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     qemu_register_reset(ppc4xx_pci_reset, controller);
 
     /* XXX load/save code not tested. */
-    register_savevm("ppc4xx_pci", ppc4xx_pci_id++, 1,
-                    ppc4xx_pci_save, ppc4xx_pci_load, controller);
+    register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
+                    1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
 
     return controller->pci_state.bus;
 
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 336d284..5358f82 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -310,8 +310,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
                                    PCIE500_REG_SIZE, index);
 
     /* XXX load/save code not tested. */
-    register_savevm("ppce500_pci", ppce500_pci_id++, 1,
-                    ppce500_pci_save, ppce500_pci_load, controller);
+    register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++,
+                    1, ppce500_pci_save, ppce500_pci_load, controller);
 
     return controller->pci_state.bus;
 
diff --git a/hw/ps2.c b/hw/ps2.c
index f0b206a..762bb00 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -595,7 +595,7 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
     s->scancode_set = 2;
-    vmstate_register(0, &vmstate_ps2_keyboard, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
     qemu_add_kbd_event_handler(ps2_put_keycode, s);
     qemu_register_reset(ps2_kbd_reset, s);
     return s;
@@ -607,7 +607,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 
     s->common.update_irq = update_irq;
     s->common.update_arg = update_arg;
-    vmstate_register(0, &vmstate_ps2_mouse, s);
+    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
     qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
     qemu_register_reset(ps2_mouse_reset, s);
     return s;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9095386..4915324 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -860,7 +860,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(pxa2xx_ssp_readfn,
                                        pxa2xx_ssp_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm("pxa2xx_ssp", -1, 0,
+    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
@@ -1515,7 +1515,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
     cpu_register_physical_memory(base & ~region_size,
                     region_size + 1, iomemtype);
 
-    vmstate_register(base, &vmstate_pxa2xx_i2c, s);
+    vmstate_register(NULL, base, &vmstate_pxa2xx_i2c, s);
 
     return s;
 }
@@ -1751,7 +1751,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
                     pxa2xx_i2s_writefn, s);
     cpu_register_physical_memory(base, 0x100000, iomemtype);
 
-    register_savevm("pxa2xx_i2s", base, 0,
+    register_savevm(NULL, "pxa2xx_i2s", base, 0,
                     pxa2xx_i2s_save, pxa2xx_i2s_load, s);
 
     return s;
@@ -2014,7 +2014,8 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
                         pxa2xx_fir_rx, pxa2xx_fir_event, s);
 
-    register_savevm("pxa2xx_fir", 0, 0, pxa2xx_fir_save, pxa2xx_fir_load, s);
+    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                    pxa2xx_fir_load, s);
 
     return s;
 }
@@ -2099,7 +2100,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2110,13 +2111,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     for (i = 0; pxa27x_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2140,7 +2141,8 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
-    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
+    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
+                    pxa2xx_rtc_load, s);
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
@@ -2219,7 +2221,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2230,13 +2232,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     for (i = 0; pxa255_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2260,7 +2262,8 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
-    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
+    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
+                    pxa2xx_rtc_load, s);
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 66c2c30..9c479df 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -507,7 +507,7 @@ static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
                     pxa2xx_dma_writefn, s);
     cpu_register_physical_memory(base, 0x00010000, iomemtype);
 
-    register_savevm("pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
+    register_savevm(NULL, "pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
 
     return s;
 }
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f354f4b..2abcb65 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -312,7 +312,7 @@ PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
                     pxa2xx_gpio_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
-    register_savevm("pxa2xx_gpio", 0, 0,
+    register_savevm(NULL, "pxa2xx_gpio", 0, 0,
                     pxa2xx_gpio_save, pxa2xx_gpio_load, s);
 
     return s;
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 060df58..dfa8945 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -317,7 +317,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
                     pxa2xx_keypad_writefn, s);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
-    register_savevm("pxa2xx_keypad", 0, 0,
+    register_savevm(NULL, "pxa2xx_keypad", 0, 0,
                     pxa2xx_keypad_save, pxa2xx_keypad_load, s);
 
     return s;
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 930299a..111a0dc 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -970,7 +970,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
         exit(1);
     }
 
-    register_savevm("pxa2xx_lcdc", 0, 0,
+    register_savevm(NULL, "pxa2xx_lcdc", 0, 0,
                     pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
 
     return s;
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index a415349..ca98660 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -534,7 +534,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
     /* Instantiate the actual storage */
     s->card = sd_init(bd, 0);
 
-    register_savevm("pxa2xx_mmci", 0, 0,
+    register_savevm(NULL, "pxa2xx_mmci", 0, 0,
                     pxa2xx_mmci_save, pxa2xx_mmci_load, s);
 
     return s;
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 0a98342..4d8944b 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -306,7 +306,8 @@ qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 
-    register_savevm("pxa2xx_pic", 0, 0, pxa2xx_pic_save, pxa2xx_pic_load, s);
+    register_savevm(NULL, "pxa2xx_pic", 0, 0, pxa2xx_pic_save,
+                    pxa2xx_pic_load, s);
 
     return qi;
 }
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index d992cc3..0f0ffd3 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -455,7 +455,7 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
                     pxa2xx_timer_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
-    register_savevm("pxa2xx_timer", 0, 0,
+    register_savevm(NULL, "pxa2xx_timer", 0, 0,
                     pxa2xx_timer_save, pxa2xx_timer_load, s);
 
     return s;
diff --git a/hw/qdev.c b/hw/qdev.c
index 61f999c..952c978 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -280,7 +280,7 @@ int qdev_init(DeviceState *dev)
     }
     qemu_register_reset(qdev_reset, dev);
     if (dev->info->vmsd) {
-        vmstate_register_with_alias_id(-1, dev->info->vmsd, dev,
+        vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
                                        dev->instance_id_alias,
                                        dev->alias_required_for_version);
     }
@@ -342,7 +342,7 @@ void qdev_free(DeviceState *dev)
             qbus_free(bus);
         }
         if (dev->info->vmsd)
-            vmstate_unregister(dev->info->vmsd, dev);
+            vmstate_unregister(dev, dev->info->vmsd, dev);
         if (dev->info->exit)
             dev->info->exit(dev);
         if (dev->opts)
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 2a8233a..2231373 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -813,7 +813,7 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     s->jazz_bus_irq = jazz_bus;
 
     qemu_register_reset(rc4030_reset, s);
-    register_savevm("rc4030", 0, 2, rc4030_save, rc4030_load, s);
+    register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
     s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
diff --git a/hw/serial.c b/hw/serial.c
index c7e4e77..b66d13a 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -813,7 +813,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
     s->chr = chr;
     serial_init_core(s);
 
-    vmstate_register(base, &vmstate_serial, s);
+    vmstate_register(NULL, base, &vmstate_serial, s);
 
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
@@ -948,7 +948,7 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     s->chr = chr;
 
     serial_init_core(s);
-    vmstate_register(base, &vmstate_serial, s);
+    vmstate_register(NULL, base, &vmstate_serial, s);
 
     if (ioregister) {
         if (be) {
diff --git a/hw/spitz.c b/hw/spitz.c
index b3e5318..89ea085 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -178,7 +178,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
                     sl_writefn, s);
     cpu_register_physical_memory(FLASH_BASE, 0x40, iomemtype);
 
-    register_savevm("sl_flash", 0, 0, sl_save, sl_load, s);
+    register_savevm(NULL, "sl_flash", 0, 0, sl_save, sl_load, s);
 }
 
 /* Spitz Keyboard */
@@ -508,7 +508,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
     spitz_keyboard_pre_map(s);
     qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
 
-    register_savevm("spitz_keyboard", 0, 0,
+    register_savevm(NULL, "spitz_keyboard", 0, 0,
                     spitz_keyboard_save, spitz_keyboard_load, s);
 }
 
@@ -613,7 +613,7 @@ static int spitz_lcdtg_init(SSISlave *dev)
     s->bl_power = 0;
     s->bl_intensity = 0x20;
 
-    register_savevm("spitz-lcdtg", -1, 1,
+    register_savevm(&dev->qdev, "spitz-lcdtg", -1, 1,
                     spitz_lcdtg_save, spitz_lcdtg_load, s);
     return 0;
 }
@@ -708,7 +708,8 @@ static int corgi_ssp_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
 
-    register_savevm("spitz_ssp", -1, 1, spitz_ssp_save, spitz_ssp_load, s);
+    register_savevm(&dev->qdev, "spitz_ssp", -1, 1,
+                    spitz_ssp_save, spitz_ssp_load, s);
     return 0;
 }
 
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index b632825..8643961 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -335,7 +335,8 @@ static int ssd0323_init(SSISlave *dev)
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
 
-    register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s);
+    register_savevm(&dev->qdev, "ssd0323_oled", -1, 1,
+                    ssd0323_save, ssd0323_load, s);
     return 0;
 }
 
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 96b33ed..a1a63b2 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -236,7 +236,7 @@ static int ssi_sd_init(SSISlave *dev)
     s->mode = SSI_SD_CMD;
     bs = qdev_init_bdrv(&dev->qdev, IF_SD);
     s->sd = sd_init(bs, 1);
-    register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
+    register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
     return 0;
 }
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5755f8a..ccad134 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -354,7 +354,8 @@ static int stellaris_gptm_init(SysBusDevice *dev)
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
     s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
-    register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s);
+    register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
+                    gptm_save, gptm_load, s);
     return 0;
 }
 
@@ -673,7 +674,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                                        ssys_writefn, s);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
     ssys_reset(s);
-    register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+    register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
     return 0;
 }
 
@@ -887,7 +888,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
-    register_savevm("stellaris_i2c", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_i2c", -1, 1,
                     stellaris_i2c_save, stellaris_i2c_load, s);
     return 0;
 }
@@ -1196,7 +1197,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
-    register_savevm("stellaris_adc", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_adc", -1, 1,
                     stellaris_adc_save, stellaris_adc_load, s);
     return 0;
 }
@@ -1256,7 +1257,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
 
-    register_savevm("stellaris_ssi_bus", -1, 1,
+    register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1,
                     stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
     return 0;
 }
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index d1d755e..330a9d6 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -389,7 +389,7 @@ static void stellaris_enet_cleanup(VLANClientState *nc)
 {
     stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm("stellaris_enet", s);
+    unregister_savevm(&s->busdev.qdev, "stellaris_enet", s);
 
     cpu_unregister_io_memory(s->mmio_index);
 
@@ -419,7 +419,7 @@ static int stellaris_enet_init(SysBusDevice *dev)
     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
 
     stellaris_enet_reset(s);
-    register_savevm("stellaris_enet", -1, 1,
+    register_savevm(&s->busdev.qdev, "stellaris_enet", -1, 1,
                     stellaris_enet_save, stellaris_enet_load, s);
     return 0;
 }
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 33395a4..16aae96 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -86,6 +86,6 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
     }
     s->num_buttons = n;
     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
-    register_savevm("stellaris_gamepad", -1, 1,
+    register_savevm(NULL, "stellaris_gamepad", -1, 1,
                     stellaris_gamepad_save, stellaris_gamepad_load, s);
 }
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 7be04a3..ed57203 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -526,7 +526,7 @@ static int syborg_fb_init(SysBusDevice *dev)
     if (!s->rows)
         s->rows = ds_get_height(s->ds);
 
-    register_savevm("syborg_framebuffer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1,
                     syborg_fb_save, syborg_fb_load, s);
     return 0;
 }
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index f3a1767..30140fb 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -214,7 +214,8 @@ static int syborg_int_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     s->flags = qemu_mallocz(s->num_irqs * sizeof(syborg_int_flags));
 
-    register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
+    register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save,
+                    syborg_int_load, s);
     return 0;
 }
 
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 4a562f8..7709100 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -220,7 +220,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
 
     qemu_add_kbd_event_handler(syborg_keyboard_event, s);
 
-    register_savevm("syborg_keyboard", -1, 1,
+    register_savevm(&dev->qdev, "syborg_keyboard", -1, 1,
                     syborg_keyboard_save, syborg_keyboard_load, s);
     return 0;
 }
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index 563d730..69b8d96 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -218,7 +218,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
     qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
                                  "Syborg Pointer");
 
-    register_savevm("syborg_pointer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_pointer", -1, 1,
                     syborg_pointer_save, syborg_pointer_load, s);
     return 0;
 }
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index b066213..78d5edb 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -136,7 +136,8 @@ static int syborg_rtc_init(SysBusDevice *dev)
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
 
-    register_savevm("syborg_rtc", -1, 1, syborg_rtc_save, syborg_rtc_load, s);
+    register_savevm(&dev->qdev, "syborg_rtc", -1, 1,
+                    syborg_rtc_save, syborg_rtc_load, s);
     return 0;
 }
 
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index cac00ea..8c42956 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -335,7 +335,7 @@ static int syborg_serial_init(SysBusDevice *dev)
     }
     s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
 
-    register_savevm("syborg_serial", -1, 1,
+    register_savevm(&dev->qdev, "syborg_serial", -1, 1,
                     syborg_serial_save, syborg_serial_load, s);
     return 0;
 }
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 3e4a447..95e07d7 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -221,7 +221,7 @@ static int syborg_timer_init(SysBusDevice *dev)
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
     ptimer_set_freq(s->timer, s->freq);
-    register_savevm("syborg_timer", -1, 1,
+    register_savevm(&dev->qdev, "syborg_timer", -1, 1,
                     syborg_timer_save, syborg_timer_load, s);
     return 0;
 }
diff --git a/hw/tsc2005.c b/hw/tsc2005.c
index b75cc86..a55853c 100644
--- a/hw/tsc2005.c
+++ b/hw/tsc2005.c
@@ -548,7 +548,7 @@ void *tsc2005_init(qemu_irq pintdav)
                     "QEMU TSC2005-driven Touchscreen");
 
     qemu_register_reset((void *) tsc2005_reset, s);
-    register_savevm("tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
+    register_savevm(NULL, "tsc2005", -1, 0, tsc2005_save, tsc2005_load, s);
 
     return s;
 }
diff --git a/hw/tsc210x.c b/hw/tsc210x.c
index e851ca1..fca73f1 100644
--- a/hw/tsc210x.c
+++ b/hw/tsc210x.c
@@ -1143,7 +1143,7 @@ uWireSlave *tsc2102_init(qemu_irq pint)
     AUD_register_card(s->name, &s->card);
 
     qemu_register_reset((void *) tsc210x_reset, s);
-    register_savevm(s->name, -1, 0,
+    register_savevm(NULL, s->name, -1, 0,
                     tsc210x_save, tsc210x_load, s);
 
     return &s->chip;
@@ -1194,7 +1194,7 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
     AUD_register_card(s->name, &s->card);
 
     qemu_register_reset((void *) tsc210x_reset, s);
-    register_savevm(s->name, -1, 0, tsc210x_save, tsc210x_load, s);
+    register_savevm(NULL, s->name, -1, 0, tsc210x_save, tsc210x_load, s);
 
     return &s->chip;
 }
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index f0a773d..362fb77 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -158,7 +158,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
+    register_savevm(&dev->qdev, "uninorth", 0, 1,
+                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
 }
@@ -178,7 +179,8 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
+    register_savevm(&dev->qdev, "uninorth", 0, 1,
+                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
     return 0;
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 8e31e36..680b557 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -100,7 +100,7 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
     s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
     vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
 
-    vmstate_register(0, &vmstate_vga_common, s);
+    vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
     s->vga.bank_offset = 0;
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 7937144..3046054 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -37,7 +37,7 @@ int isa_vga_init(void)
 
     vga_common_init(s, VGA_RAM_SIZE);
     vga_init(s);
-    vmstate_register(0, &vmstate_vga_common, s);
+    vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
     s->ds = graphic_console_init(s->update, s->invalidate,
                                  s->screen_dump, s->text_update, s);
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 152af80..9fe3886 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -270,7 +270,8 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
     reset_stats(s);
     qemu_add_balloon_handler(virtio_balloon_to_target, s);
 
-    register_savevm("virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s);
+    register_savevm(dev, "virtio-balloon", -1, 1,
+                    virtio_balloon_save, virtio_balloon_load, s);
 
     return &s->vdev;
 }
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 0bf929a..a46b758 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -498,7 +498,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
     qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
-    register_savevm("virtio-blk", virtio_blk_id++, 2,
+    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
 
     return &s->vdev;
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 06ba481..e9768e0 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -923,7 +923,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     n->vlans = qemu_mallocz(MAX_VLAN >> 3);
 
-    register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
+    register_savevm(NULL, "virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
@@ -941,7 +941,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-    unregister_savevm("virtio-net", n);
+    unregister_savevm(NULL, "virtio-net", n);
 
     qemu_free(n->mac_table.macs);
     qemu_free(n->vlans);
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index fa5283c..26d5841 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -784,7 +784,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
      * Register for the savevm section with the virtio-console name
      * to preserve backward compat
      */
-    register_savevm("virtio-console", -1, 2, virtio_serial_save,
+    register_savevm(dev, "virtio-console", -1, 2, virtio_serial_save,
                     virtio_serial_load, vser);
 
     return vdev;
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index afebad9..f359304 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -274,7 +274,7 @@ void *vmmouse_init(void *m)
     vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
-    vmstate_register(0, &vmstate_vmmouse, s);
+    vmstate_register(NULL, 0, &vmstate_vmmouse, s);
 
     return s;
 }
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index bf2a699..359e5d8 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1169,7 +1169,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
     vga_common_init(&s->vga, vga_ram_size);
     vga_init(&s->vga);
-    vmstate_register(0, &vmstate_vga_common, &s->vga);
+    vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
 
     vga_init_vbe(&s->vga);
 
diff --git a/hw/zaurus.c b/hw/zaurus.c
index db6ba75..dd999d7 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -230,7 +230,7 @@ ScoopInfo *scoop_init(PXA2xxState *cpu,
     iomemtype = cpu_register_io_memory(scoop_readfn,
                     scoop_writefn, s);
     cpu_register_physical_memory(target_base, 0x1000, iomemtype);
-    register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
+    register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s);
 
     return s;
 }
diff --git a/qemu-timer.c b/qemu-timer.c
index bdc8206..bc5f207 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -662,7 +662,7 @@ static const VMStateDescription vmstate_timers = {
 
 void configure_icount(const char *option)
 {
-    vmstate_register(0, &vmstate_timers, &timers_state);
+    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
     if (!option)
         return;
 
diff --git a/savevm.c b/savevm.c
index 20354a8..0052406 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1026,7 +1026,8 @@ static int calculate_new_instance_id(const char *idstr)
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
    distinguishing id for all instances of your device class. */
-int register_savevm_live(const char *idstr,
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
                          int instance_id,
                          int version_id,
                          SaveSetParamsHandler *set_params,
@@ -1058,18 +1059,19 @@ int register_savevm_live(const char *idstr,
     return 0;
 }
 
-int register_savevm(const char *idstr,
+int register_savevm(DeviceState *dev,
+                    const char *idstr,
                     int instance_id,
                     int version_id,
                     SaveStateHandler *save_state,
                     LoadStateHandler *load_state,
                     void *opaque)
 {
-    return register_savevm_live(idstr, instance_id, version_id,
+    return register_savevm_live(dev, idstr, instance_id, version_id,
                                 NULL, NULL, save_state, load_state, opaque);
 }
 
-void unregister_savevm(const char *idstr, void *opaque)
+void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
@@ -1081,7 +1083,7 @@ void unregister_savevm(const char *idstr, void *opaque)
     }
 }
 
-int vmstate_register_with_alias_id(int instance_id,
+int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    const VMStateDescription *vmsd,
                                    void *opaque, int alias_id,
                                    int required_for_version)
@@ -1112,13 +1114,15 @@ int vmstate_register_with_alias_id(int instance_id,
     return 0;
 }
 
-int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                     void *opaque)
+int vmstate_register(DeviceState *dev, int instance_id,
+                     const VMStateDescription *vmsd, void *opaque)
 {
-    return vmstate_register_with_alias_id(instance_id, vmsd, opaque, -1, 0);
+    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
+                                          opaque, -1, 0);
 }
 
-void vmstate_unregister(const VMStateDescription *vmsd, void *opaque)
+void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+                        void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 3c785cd..82fd9b4 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -232,7 +232,8 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     slirp->opaque = opaque;
 
-    register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
+    register_savevm(NULL, "slirp", 0, 3,
+                    slirp_state_save, slirp_state_load, slirp);
 
     QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
 
@@ -243,7 +244,7 @@ void slirp_cleanup(Slirp *slirp)
 {
     QTAILQ_REMOVE(&slirp_instances, slirp, entry);
 
-    unregister_savevm("slirp", slirp);
+    unregister_savevm(NULL, "slirp", slirp);
 
     qemu_free(slirp->tftp_prefix);
     qemu_free(slirp->bootp_filename);
diff --git a/vl.c b/vl.c
index 920717a..4a1c5f4 100644
--- a/vl.c
+++ b/vl.c
@@ -2794,7 +2794,7 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
-    register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, 
+    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 06/16] savevm: Make use of DeviceState
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (4 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 05/16] savevm: Add DeviceState param Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 07/16] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
                     ` (9 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

For callers that pass a device we can traverse up the qdev tree and
make use of the BusInfo.get_dev_path information for creating unique
savevm id strings.  This avoids needing to rely on the instance number,
which can cause problems with device initialization order and hotplug.

For compatibility, we also store away the old id string and instance
so we can accept migrations from VMs as we add new get_dev_path
implementations.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 savevm.c |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/savevm.c b/savevm.c
index 0052406..e4f50b1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -72,6 +72,7 @@
 
 #include "qemu-common.h"
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "net.h"
 #include "monitor.h"
 #include "sysemu.h"
@@ -988,6 +989,11 @@ const VMStateInfo vmstate_info_unused_buffer = {
     .put  = put_unused_buffer,
 };
 
+typedef struct CompatEntry {
+    char idstr[256];
+    int instance_id;
+} CompatEntry;
+
 typedef struct SaveStateEntry {
     QTAILQ_ENTRY(SaveStateEntry) entry;
     char idstr[256];
@@ -1001,6 +1007,7 @@ typedef struct SaveStateEntry {
     LoadStateHandler *load_state;
     const VMStateDescription *vmsd;
     void *opaque;
+    CompatEntry *compat;
 } SaveStateEntry;
 
 
@@ -1022,6 +1029,23 @@ static int calculate_new_instance_id(const char *idstr)
     return instance_id;
 }
 
+static int calculate_compat_instance_id(const char *idstr)
+{
+    SaveStateEntry *se;
+    int instance_id = 0;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if (!se->compat)
+            continue;
+
+        if (strcmp(idstr, se->compat->idstr) == 0
+            && instance_id <= se->compat->instance_id) {
+            instance_id = se->compat->instance_id + 1;
+        }
+    }
+    return instance_id;
+}
+
 /* TODO: Individual devices generally have very little idea about the rest
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
@@ -1039,7 +1063,6 @@ int register_savevm_live(DeviceState *dev,
     SaveStateEntry *se;
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
     se->version_id = version_id;
     se->section_id = global_section_id++;
     se->set_params = set_params;
@@ -1049,11 +1072,28 @@ int register_savevm_live(DeviceState *dev,
     se->opaque = opaque;
     se->vmsd = NULL;
 
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            pstrcpy(se->idstr, sizeof(se->idstr), id);
+            pstrcat(se->idstr, sizeof(se->idstr), "/");
+            qemu_free(id);
+
+            se->compat = qemu_mallocz(sizeof(CompatEntry));
+            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
+            se->compat->instance_id = instance_id == -1 ?
+                         calculate_compat_instance_id(idstr) : instance_id;
+            instance_id = -1;
+        }
+    }
+    pstrcat(se->idstr, sizeof(se->idstr), idstr);
+
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(idstr);
+        se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
         se->instance_id = instance_id;
     }
+    assert(!se->compat || se->instance_id == 0);
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1074,9 +1114,20 @@ int register_savevm(DeviceState *dev,
 void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
+    char id[256] = "";
+
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *path = dev->parent_bus->info->get_dev_path(dev);
+        if (path) {
+            pstrcpy(id, sizeof(id), path);
+            pstrcat(id, sizeof(id), "/");
+            qemu_free(path);
+        }
+    }
+    pstrcat(id, sizeof(id), idstr);
 
     QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
-        if (strcmp(se->idstr, idstr) == 0 && se->opaque == opaque) {
+        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
             QTAILQ_REMOVE(&savevm_handlers, se, entry);
             qemu_free(se);
         }
@@ -1094,7 +1145,6 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
     se->version_id = vmsd->version_id;
     se->section_id = global_section_id++;
     se->save_live_state = NULL;
@@ -1104,11 +1154,28 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->vmsd = vmsd;
     se->alias_id = alias_id;
 
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            pstrcpy(se->idstr, sizeof(se->idstr), id);
+            pstrcat(se->idstr, sizeof(se->idstr), "/");
+            qemu_free(id);
+
+            se->compat = qemu_mallocz(sizeof(CompatEntry));
+            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
+            se->compat->instance_id = instance_id == -1 ?
+                         calculate_compat_instance_id(vmsd->name) : instance_id;
+            instance_id = -1;
+        }
+    }
+    pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
+
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(vmsd->name);
+        se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
         se->instance_id = instance_id;
     }
+    assert(!se->compat || se->instance_id == 0);
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1454,6 +1521,13 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
             (instance_id == se->instance_id ||
              instance_id == se->alias_id))
             return se;
+        /* Migrating from an older version? */
+        if (strstr(se->idstr, idstr) && se->compat) {
+            if (!strcmp(se->compat->idstr, idstr) &&
+                (instance_id == se->compat->instance_id ||
+                 instance_id == se->alias_id))
+                return se;
+        }
     }
     return NULL;
 }

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 07/16] eepro100: Add a dev field to eeprom new/free functions
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (5 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 06/16] savevm: Make use of DeviceState Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
                     ` (8 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

This allows us to create a more meaningful savevm string.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/eepro100.c   |    4 ++--
 hw/eeprom93xx.c |    8 ++++----
 hw/eeprom93xx.h |    4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 0ddca8b..2b75c8f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1835,7 +1835,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev)
 
     cpu_unregister_io_memory(s->mmio_index);
     vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
-    eeprom93xx_free(s->eeprom);
+    eeprom93xx_free(&pci_dev->qdev, s->eeprom);
     qemu_del_vlan_client(&s->nic->nc);
     return 0;
 }
@@ -1862,7 +1862,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
 
     /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
      * i82559 and later support 64 or 256 word EEPROM. */
-    s->eeprom = eeprom93xx_new(EEPROM_SIZE);
+    s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
 
     /* Handler for memory-mapped I/O */
     s->mmio_index =
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 6ba546f..660b28f 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -289,7 +289,7 @@ void eeprom93xx_reset(eeprom_t *eeprom)
 }
 #endif
 
-eeprom_t *eeprom93xx_new(uint16_t nwords)
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)
 {
     /* Add a new EEPROM (with 16, 64 or 256 words). */
     eeprom_t *eeprom;
@@ -316,15 +316,15 @@ eeprom_t *eeprom93xx_new(uint16_t nwords)
     /* Output DO is tristate, read results in 1. */
     eeprom->eedo = 1;
     logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
-    vmstate_register(NULL, 0, &vmstate_eeprom, eeprom);
+    vmstate_register(dev, 0, &vmstate_eeprom, eeprom);
     return eeprom;
 }
 
-void eeprom93xx_free(eeprom_t *eeprom)
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom)
 {
     /* Destroy EEPROM. */
     logout("eeprom = 0x%p\n", eeprom);
-    vmstate_unregister(NULL, &vmstate_eeprom, eeprom);
+    vmstate_unregister(dev, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/eeprom93xx.h b/hw/eeprom93xx.h
index 47282d3..8ba0e28 100644
--- a/hw/eeprom93xx.h
+++ b/hw/eeprom93xx.h
@@ -23,10 +23,10 @@
 typedef struct _eeprom_t eeprom_t;
 
 /* Create a new EEPROM with (nwords * 2) bytes. */
-eeprom_t *eeprom93xx_new(uint16_t nwords);
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords);
 
 /* Destroy an existing EEPROM. */
-void eeprom93xx_free(eeprom_t *eeprom);
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom);
 
 /* Read from the EEPROM. */
 uint16_t eeprom93xx_read(eeprom_t *eeprom);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (6 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 07/16] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 09/16] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
                     ` (7 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Stuff a pointer to the DeviceState into the VirtIONet structure so that
we can easily remove the vmstate entry later.  Also, let vmstate track
the instance number (it should always be zero internally since the
device path should now be unique).

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/virtio-net.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index e9768e0..f41db45 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -60,6 +60,7 @@ typedef struct VirtIONet
         uint8_t *macs;
     } mac_table;
     uint32_t *vlans;
+    DeviceState *qdev;
 } VirtIONet;
 
 /* TODO
@@ -890,7 +891,6 @@ static void virtio_net_vmstate_change(void *opaque, int running, int reason)
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 {
     VirtIONet *n;
-    static int virtio_net_id;
 
     n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
                                         sizeof(struct virtio_net_config),
@@ -923,7 +923,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
 
     n->vlans = qemu_mallocz(MAX_VLAN >> 3);
 
-    register_savevm(NULL, "virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
+    n->qdev = dev;
+    register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
@@ -941,7 +942,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     qemu_purge_queued_packets(&n->nic->nc);
 
-    unregister_savevm(NULL, "virtio-net", n);
+    unregister_savevm(n->qdev, "virtio-net", n);
 
     qemu_free(n->mac_table.macs);
     qemu_free(n->vlans);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 09/16] qemu_ram_alloc: Add DeviceState and name parameters
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (7 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
                     ` (6 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

These will be used to generate unique id strings for ramblocks.  The name
field is required, the device pointer is optional as most callers don't
have a device.  When there's no device or the device isn't a child of
a bus implementing BusInfo.get_dev_path, the name should be unique for
the platform.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-common.h                  |    2 +-
 exec.c                        |    2 +-
 hw/an5206.c                   |    4 ++--
 hw/armv7m.c                   |    9 ++++++---
 hw/axis_dev88.c               |    4 ++--
 hw/dummy_m68k.c               |    2 +-
 hw/etraxfs.c                  |    6 +++---
 hw/g364fb.c                   |    2 +-
 hw/gumstix.c                  |    6 ++++--
 hw/integratorcp.c             |    4 ++--
 hw/mainstone.c                |    6 ++++--
 hw/mcf5208.c                  |    4 ++--
 hw/mips_fulong2e.c            |    4 ++--
 hw/mips_jazz.c                |    4 ++--
 hw/mips_malta.c               |    4 ++--
 hw/mips_mipssim.c             |    4 ++--
 hw/mips_r4k.c                 |    6 +++---
 hw/musicpal.c                 |   11 +++++++----
 hw/omap1.c                    |    6 ++++--
 hw/omap2.c                    |    6 ++++--
 hw/omap_sx1.c                 |   12 ++++++++----
 hw/onenand.c                  |    2 +-
 hw/palm.c                     |    3 ++-
 hw/pc.c                       |    7 ++++---
 hw/pci.c                      |    7 ++++++-
 hw/petalogix_s3adsp1800_mmu.c |    7 ++++---
 hw/ppc405_boards.c            |   18 +++++++++---------
 hw/ppc405_uc.c                |    2 +-
 hw/ppc4xx_devs.c              |    4 +++-
 hw/ppc_newworld.c             |    6 +++---
 hw/ppc_oldworld.c             |    6 +++---
 hw/ppc_prep.c                 |    4 ++--
 hw/ppce500_mpc8544ds.c        |    3 ++-
 hw/pxa2xx.c                   |   12 ++++++++----
 hw/r2d.c                      |    4 ++--
 hw/realview.c                 |    6 +++---
 hw/s390-virtio.c              |    2 +-
 hw/sm501.c                    |    2 +-
 hw/spitz.c                    |    2 +-
 hw/sun4m.c                    |    8 ++++----
 hw/sun4u.c                    |    4 ++--
 hw/syborg.c                   |    2 +-
 hw/tc6393xb.c                 |    2 +-
 hw/tcx.c                      |    2 +-
 hw/tosa.c                     |    2 +-
 hw/versatilepb.c              |    2 +-
 hw/vga.c                      |    2 +-
 hw/vmware_vga.c               |    2 +-
 48 files changed, 132 insertions(+), 99 deletions(-)

diff --git a/cpu-common.h b/cpu-common.h
index b24cecc..71e7933 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -40,7 +40,7 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
 }
 
 ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
-ram_addr_t qemu_ram_alloc(ram_addr_t);
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
 void qemu_ram_free(ram_addr_t addr);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
diff --git a/exec.c b/exec.c
index c8be508..164ba16 100644
--- a/exec.c
+++ b/exec.c
@@ -2778,7 +2778,7 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
     return last;
 }
 
-ram_addr_t qemu_ram_alloc(ram_addr_t size)
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 {
     RAMBlock *new_block;
 
diff --git a/hw/an5206.c b/hw/an5206.c
index f584d88..b9f19a9 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -54,11 +54,11 @@ static void an5206_init(ram_addr_t ram_size,
 
     /* DRAM at address zero */
     cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "an5206.ram", ram_size) | IO_MEM_RAM);
 
     /* Internal SRAM.  */
     cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512,
-        qemu_ram_alloc(512) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "an5206.sram", 512) | IO_MEM_RAM);
 
     mcf5206_init(AN5206_MBAR_ADDR, env);
 
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 854261d..588ec98 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -200,9 +200,11 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
 
     /* Flash programming is done via the SCU, so pretend it is ROM.  */
     cpu_register_physical_memory(0, flash_size,
-                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "armv7m.flash",
+                                                flash_size) | IO_MEM_ROM);
     cpu_register_physical_memory(0x20000000, sram_size,
-                                 qemu_ram_alloc(sram_size) | IO_MEM_RAM);
+                                 qemu_ram_alloc(NULL, "armv7m.sram",
+                                                sram_size) | IO_MEM_RAM);
     armv7m_bitband_init();
 
     nvic = qdev_create(NULL, "armv7m_nvic");
@@ -236,7 +238,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
        space.  This stops qemu complaining about executing code outside RAM
        when returning from an exception.  */
     cpu_register_physical_memory(0xfffff000, 0x1000,
-                                 qemu_ram_alloc(0x1000) | IO_MEM_RAM);
+                                 qemu_ram_alloc(NULL, "armv7m.hack", 
+                                                0x1000) | IO_MEM_RAM);
 
     qemu_register_reset(armv7m_reset, env);
     return pic;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 3ae4105..f16c76a 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -268,12 +268,12 @@ void axisdev88_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "axisdev88.ram", ram_size);
     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
+    phys_intmem = qemu_ram_alloc(NULL, "axisdev88.chipram", INTMEM_SIZE);
     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
                                  phys_intmem | IO_MEM_RAM);
 
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 9c9e6ff..61efb39 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -39,7 +39,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
 
     /* RAM at address zero */
     cpu_register_physical_memory(0, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "dummy_m68k.ram", ram_size) | IO_MEM_RAM);
 
     /* Load kernel.  */
     if (kernel_filename) {
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 01bf929..46e2920 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -68,17 +68,17 @@ void bareetraxfs_init (ram_addr_t ram_size,
     env = cpu_init(cpu_model);
 
     /* allocate RAM */
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "etraxfs.ram", ram_size);
     cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM);
 
     /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
        internal memory.  */
-    phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
+    phys_intmem = qemu_ram_alloc(NULL, "etraxfs.chipram", INTMEM_SIZE);
     cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
                                  phys_intmem | IO_MEM_RAM);
 
 
-    phys_flash = qemu_ram_alloc(FLASH_SIZE);
+    phys_flash = qemu_ram_alloc(NULL, "etraxfs.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0x0, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
diff --git a/hw/g364fb.c b/hw/g364fb.c
index beafd70..3c8fb98 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -593,7 +593,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
     s = qemu_mallocz(sizeof(G364State));
 
     s->vram_size = 8 * 1024 * 1024;
-    s->vram_offset = qemu_ram_alloc(s->vram_size);
+    s->vram_offset = qemu_ram_alloc(NULL, "g364fb.vram", s->vram_size);
     s->vram = qemu_get_ram_ptr(s->vram_offset);
     s->irq = irq;
 
diff --git a/hw/gumstix.c b/hw/gumstix.c
index b64e04e..c343a16 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -67,7 +67,8 @@ static void connex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(connex_rom),
+    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom",
+                                                          connex_rom),
                                dinfo->bdrv, sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -105,7 +106,8 @@ static void verdex_init(ram_addr_t ram_size,
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(verdex_rom),
+    if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom",
+                                                          verdex_rom),
                                dinfo->bdrv, sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index bee8298..3bf216b 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -253,7 +253,7 @@ static int integratorcm_init(SysBusDevice *dev)
     }
     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
     s->cm_init = 0x00000112;
-    s->flash_offset = qemu_ram_alloc(0x100000);
+    s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000);
 
     iomemtype = cpu_register_io_memory(integratorcm_readfn,
                                        integratorcm_writefn, s);
@@ -467,7 +467,7 @@ static void integratorcp_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "integrator.ram", ram_size);
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero*/
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 54bacfb..cba7e63 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -87,7 +87,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
     /* Setup CPU & memory */
     cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);
     cpu_register_physical_memory(0, MAINSTONE_ROM,
-                    qemu_ram_alloc(MAINSTONE_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "mainstone.rom",
+                                   MAINSTONE_ROM) | IO_MEM_ROM);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
@@ -104,7 +105,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
         }
 
         if (!pflash_cfi01_register(mainstone_flash_base[i],
-                                   qemu_ram_alloc(MAINSTONE_FLASH),
+                                   qemu_ram_alloc(NULL, "mainstone.flash",
+                                                  MAINSTONE_FLASH),
                                    dinfo->bdrv, sector_len,
                                    MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
                                    be)) {
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 5b686c6..38645f7 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -220,11 +220,11 @@ static void mcf5208evb_init(ram_addr_t ram_size,
 
     /* DRAM at 0x40000000 */
     cpu_register_physical_memory(0x40000000, ram_size,
-        qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "mcf5208.ram", ram_size) | IO_MEM_RAM);
 
     /* Internal SRAM.  */
     cpu_register_physical_memory(0x80000000, 16384,
-        qemu_ram_alloc(16384) | IO_MEM_RAM);
+        qemu_ram_alloc(NULL, "mcf5208.sram", 16384) | IO_MEM_RAM);
 
     /* Internal peripherals.  */
     pic = mcf_intc_init(0xfc048000, env);
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 7b1da0d..a97218b 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -292,8 +292,8 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     bios_size = 1024 * 1024;
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(bios_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_fulong2e.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_fulong2e.bios", bios_size);
 
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
     cpu_register_physical_memory(0x1fc00000LL,
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 606cd23..71b05a2 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -158,10 +158,10 @@ void mips_jazz_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_jazz.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
-    bios_offset = qemu_ram_alloc(MAGNUM_BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
     cpu_register_physical_memory(0x1fc00000LL,
                                  MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);
     cpu_register_physical_memory(0xfff00000LL,
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 9042b57..11e220a 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -831,8 +831,8 @@ void mips_malta_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
 
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 293d99e..111c759 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -144,8 +144,8 @@ mips_mipssim_init (ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate RAM. */
-    ram_offset = qemu_ram_alloc(ram_size);
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    ram_offset = qemu_ram_alloc(NULL, "mips_mipssim.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "mips_mipssim.bios", BIOS_SIZE);
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 5a96dea..61cd33a 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -198,7 +198,7 @@ void mips_r4k_init (ram_addr_t ram_size,
                 ((unsigned int)ram_size / (1 << 20)));
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "mips_r4k.ram", ram_size);
 
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
@@ -226,14 +226,14 @@ void mips_r4k_init (ram_addr_t ram_size,
     be = 0;
 #endif
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE);
 	cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
                                      bios_offset | IO_MEM_ROM);
 
         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
-        bios_offset = qemu_ram_alloc(mips_rom);
+        bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom);
         if (!pflash_cfi01_register(0x1fc00000, bios_offset,
                                    dinfo->bdrv, sector_len,
                                    mips_rom / sector_len,
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 95ef2c6..33180a2 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1506,9 +1506,10 @@ static void musicpal_init(ram_addr_t ram_size,
 
     /* For now we use a fixed - the original - RAM size */
     cpu_register_physical_memory(0, MP_RAM_DEFAULT_SIZE,
-                                 qemu_ram_alloc(MP_RAM_DEFAULT_SIZE));
+                                 qemu_ram_alloc(NULL, "musicpal.ram",
+                                                MP_RAM_DEFAULT_SIZE));
 
-    sram_off = qemu_ram_alloc(MP_SRAM_SIZE);
+    sram_off = qemu_ram_alloc(NULL, "musicpal.sram", MP_SRAM_SIZE);
     cpu_register_physical_memory(MP_SRAM_BASE, MP_SRAM_SIZE, sram_off);
 
     dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
@@ -1555,14 +1556,16 @@ static void musicpal_init(ram_addr_t ram_size,
          * image is smaller than 32 MB.
          */
 #ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
+                              "musicpal.flash", flash_size),
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
+        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL,
+                              "musicpal.flash", flash_size),
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
diff --git a/hw/omap1.c b/hw/omap1.c
index d400bbb..cf0d428 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3732,9 +3732,11 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
 
     /* Memory-mapped stuff */
     cpu_register_physical_memory(OMAP_EMIFF_BASE, s->sdram_size,
-                    (emiff_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
+                    (emiff_base = qemu_ram_alloc(NULL, "omap1.dram",
+                                                 s->sdram_size)) | IO_MEM_RAM);
     cpu_register_physical_memory(OMAP_IMIF_BASE, s->sram_size,
-                    (imif_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+                    (imif_base = qemu_ram_alloc(NULL, "omap1.sram",
+                                                s->sram_size)) | IO_MEM_RAM);
 
     omap_clkm_init(0xfffece00, 0xe1008000, s);
 
diff --git a/hw/omap2.c b/hw/omap2.c
index ff349ae..179075e 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2253,9 +2253,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
 
     /* Memory-mapped stuff */
     cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-                    (q2_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
+                    (q2_base = qemu_ram_alloc(NULL, "omap2.dram",
+                                              s->sdram_size)) | IO_MEM_RAM);
     cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-                    (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+                    (sram_base = qemu_ram_alloc(NULL, "omap2.sram",
+                                                s->sram_size)) | IO_MEM_RAM);
 
     s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
 
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 2e9879f..c3f1973 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -139,7 +139,8 @@ static void sx1_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "omap_sx1.flash0-0",
+                                                flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
@@ -157,7 +158,8 @@ static void sx1_init(ram_addr_t ram_size,
 #endif
 
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(flash_size),
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL,
+                                   "omap_sx1.flash0-1", flash_size),
                                    dinfo->bdrv, sector_size,
                                    flash_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
@@ -170,12 +172,14 @@ static void sx1_init(ram_addr_t ram_size,
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
-                                     qemu_ram_alloc(flash1_size) | IO_MEM_ROM);
+                                     qemu_ram_alloc(NULL, "omap_sx1.flash1-0",
+                                                    flash1_size) | IO_MEM_ROM);
         io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
         cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
                         OMAP_CS1_SIZE - flash1_size, io);
 
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(flash1_size),
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL,
+                                   "omap_sx1.flash1-1", flash1_size),
                                    dinfo->bdrv, sector_size,
                                    flash1_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
diff --git a/hw/onenand.c b/hw/onenand.c
index 4118db9..f7afeca 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -638,7 +638,7 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
         s->bdrv = dinfo->bdrv;
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
-    s->ram = qemu_ram_alloc(0xc000 << s->shift);
+    s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
     ram = qemu_get_ram_ptr(s->ram);
     s->boot[0] = ram + (0x0000 << s->shift);
     s->boot[1] = ram + (0x8000 << s->shift);
diff --git a/hw/palm.c b/hw/palm.c
index 8db133d..193aa11 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -213,7 +213,8 @@ static void palmte_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                    qemu_ram_alloc(flash_size) | IO_MEM_ROM);
+                                 qemu_ram_alloc(NULL, "palmte.flash",
+                                                flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
diff --git a/hw/pc.c b/hw/pc.c
index de60686..907b55c 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -885,7 +885,8 @@ void pc_memory_init(ram_addr_t ram_size,
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(below_4g_mem_size + above_4g_mem_size);
+    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
+                              below_4g_mem_size + above_4g_mem_size);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
@@ -908,7 +909,7 @@ void pc_memory_init(ram_addr_t ram_size,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(bios_size);
+    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size));
     if (ret != 0) {
     bios_error:
@@ -926,7 +927,7 @@ void pc_memory_init(ram_addr_t ram_size,
                                  isa_bios_size,
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
-    option_rom_offset = qemu_ram_alloc(PC_ROM_SIZE);
+    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
     cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
 
     /* map all the bios at the top of memory */
diff --git a/hw/pci.c b/hw/pci.c
index 79f1f11..fe7c5c3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1713,6 +1713,7 @@ static int pci_add_option_rom(PCIDevice *pdev)
     int size;
     char *path;
     void *ptr;
+    char name[32];
 
     if (!pdev->romfile)
         return 0;
@@ -1748,7 +1749,11 @@ static int pci_add_option_rom(PCIDevice *pdev)
         size = 1 << qemu_fls(size);
     }
 
-    pdev->rom_offset = qemu_ram_alloc(size);
+    if (pdev->qdev.info->vmsd)
+        snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->vmsd->name);
+    else
+        snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name);
+    pdev->rom_offset = qemu_ram_alloc(&pdev->qdev, name, size);
 
     ptr = qemu_get_ram_ptr(pdev->rom_offset);
     load_image(path, ptr);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index cdde991..70b6a36 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -137,14 +137,15 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, env);
 
     /* Attach emulated BRAM through the LMB.  */
-    phys_lmb_bram = qemu_ram_alloc(LMB_BRAM_SIZE);
+    phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.lmb_bram",
+                                   LMB_BRAM_SIZE);
     cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE,
                                  phys_lmb_bram | IO_MEM_RAM);
 
-    phys_ram = qemu_ram_alloc(ram_size);
+    phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size);
     cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
 
-    phys_flash = qemu_ram_alloc(FLASH_SIZE);
+    phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE);
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(0xa0000000, phys_flash,
                           dinfo ? dinfo->bdrv : NULL, (64 * 1024),
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index 7c7075e..40ff1b3 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -190,7 +190,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* XXX: fix this */
-    ram_bases[0] = qemu_ram_alloc(0x08000000);
+    ram_bases[0] = qemu_ram_alloc(NULL, "ef405ep.ram", 0x08000000);
     ram_sizes[0] = 0x08000000;
     ram_bases[1] = 0x00000000;
     ram_sizes[1] = 0x00000000;
@@ -202,7 +202,7 @@ static void ref405ep_init (ram_addr_t ram_size,
                         kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
-    sram_offset = qemu_ram_alloc(sram_size);
+    sram_offset = qemu_ram_alloc(NULL, "ef405ep.sram", sram_size);
 #ifdef DEBUG_BOARD_INIT
     printf("%s: register SRAM at offset %08lx\n", __func__, sram_offset);
 #endif
@@ -217,7 +217,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
         bios_size = bdrv_getlength(dinfo->bdrv);
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " TARGET_FMT_lx
@@ -236,7 +236,7 @@ static void ref405ep_init (ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -509,9 +509,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
-    ram_bases[0] = qemu_ram_alloc(0x04000000);
+    ram_bases[0] = qemu_ram_alloc(NULL, "taihu_405ep.ram-0", 0x04000000);
     ram_sizes[0] = 0x04000000;
-    ram_bases[1] = qemu_ram_alloc(0x04000000);
+    ram_bases[1] = qemu_ram_alloc(NULL, "taihu_405ep.ram-1", 0x04000000);
     ram_sizes[1] = 0x04000000;
     ram_size = 0x08000000;
 #ifdef DEBUG_BOARD_INIT
@@ -531,7 +531,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size);
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " TARGET_FMT_lx
                " at offset %08lx addr " TARGET_FMT_lx " '%s' %d\n",
@@ -551,7 +551,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 #endif
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
-        bios_offset = qemu_ram_alloc(BIOS_SIZE);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
             bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
@@ -580,7 +580,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
                fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
                bdrv_get_device_name(dinfo->bdrv));
 #endif
-        bios_offset = qemu_ram_alloc(bios_size);
+        bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size);
         pflash_cfi02_register(0xfc000000, bios_offset,
                               dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index d9bbd93..b884ea5 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -995,7 +995,7 @@ static void ppc405_ocm_init(CPUState *env)
     ppc405_ocm_t *ocm;
 
     ocm = qemu_mallocz(sizeof(ppc405_ocm_t));
-    ocm->offset = qemu_ram_alloc(4096);
+    ocm->offset = qemu_ram_alloc(NULL, "ppc405.ocm", 4096);
     qemu_register_reset(&ocm_reset, ocm);
     ppc_dcr_register(env, OCM0_ISARC,
                      ocm, &dcr_read_ocm, &dcr_write_ocm);
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 37a3948..b15db81 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -668,7 +668,9 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
             unsigned int bank_size = sdram_bank_sizes[j];
 
             if (bank_size <= size_left) {
-                ram_bases[i] = qemu_ram_alloc(bank_size);
+                char name[32];
+                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
+                ram_bases[i] = qemu_ram_alloc(NULL, name, bank_size);
                 ram_sizes[i] = bank_size;
                 size_left -= bank_size;
                 break;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index d131aa5..fbba9b6 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -173,11 +173,11 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_core99.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_core99.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -198,7 +198,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
     }
 
     /* allocate and load VGA BIOS */
-    vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
+    vga_bios_offset = qemu_ram_alloc(NULL, "ppc_core99.vbios", VGA_BIOS_SIZE);
     vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME);
     if (filename) {
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 27ddc01..6b3ab89 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -179,11 +179,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_heathrow.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -203,7 +203,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     }
 
     /* allocate and load VGA BIOS */
-    vga_bios_offset = qemu_ram_alloc(VGA_BIOS_SIZE);
+    vga_bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.vbios", VGA_BIOS_SIZE);
     vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset);
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME);
     if (filename) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index bb9e15f..fc3e17a 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -604,11 +604,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "ppc_prep.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(BIOS_SIZE);
+    bios_offset = qemu_ram_alloc(NULL, "ppc_prep.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 0901fa6..1422fad 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -189,7 +189,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
 
     /* Register Memory */
-    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(ram_size));
+    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(NULL,
+                                 "mpc8544ds.ram", ram_size));
 
     /* MPIC */
     irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 4915324..953e9ee 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2054,9 +2054,11 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
-                    sdram_size, qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+                    sdram_size, qemu_ram_alloc(NULL, "pxa270.sdram",
+                                               sdram_size) | IO_MEM_RAM);
     cpu_register_physical_memory(PXA2XX_INTERNAL_BASE,
-                    0x40000, qemu_ram_alloc(0x40000) | IO_MEM_RAM);
+                    0x40000, qemu_ram_alloc(NULL, "pxa270.internal",
+                                            0x40000) | IO_MEM_RAM);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
@@ -2175,9 +2177,11 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size,
-                    qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+                    qemu_ram_alloc(NULL, "pxa255.sdram",
+                                   sdram_size) | IO_MEM_RAM);
     cpu_register_physical_memory(PXA2XX_INTERNAL_BASE, PXA2XX_INTERNAL_SIZE,
-                    qemu_ram_alloc(PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
+                    qemu_ram_alloc(NULL, "pxa255.internal",
+                                   PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
diff --git a/hw/r2d.c b/hw/r2d.c
index bc25756..8c1fbad 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -242,7 +242,7 @@ static void r2d_init(ram_addr_t ram_size,
     }
 
     /* Allocate memory space */
-    sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
+    sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
     cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
     /* Register peripherals */
     s = sh7750_init(env);
@@ -258,7 +258,7 @@ static void r2d_init(ram_addr_t ram_size,
 
     /* onboard flash memory */
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, qemu_ram_alloc(FLASH_SIZE),
+    pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
                           dinfo ? dinfo->bdrv : NULL, (16 * 1024),
                           FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
diff --git a/hw/realview.c b/hw/realview.c
index f786699..70bcdb8 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -196,12 +196,12 @@ static void realview_init(ram_addr_t ram_size,
         /* Core tile RAM.  */
         low_ram_size = ram_size - 0x20000000;
         ram_size = 0x20000000;
-        ram_offset = qemu_ram_alloc(low_ram_size);
+        ram_offset = qemu_ram_alloc(NULL, "realview.lowmem", low_ram_size);
         cpu_register_physical_memory(0x20000000, low_ram_size,
                                      ram_offset | IO_MEM_RAM);
     }
 
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "realview.highmem", ram_size);
     low_ram_size = ram_size;
     if (low_ram_size > 0x10000000)
       low_ram_size = 0x10000000;
@@ -354,7 +354,7 @@ static void realview_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    ram_offset = qemu_ram_alloc(0x1000);
+    ram_offset = qemu_ram_alloc(NULL, "realview.hack", 0x1000);
     cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
                                  ram_offset | IO_MEM_RAM);
 
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 898f442..2fb437b 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -157,7 +157,7 @@ static void s390_init(ram_addr_t ram_size,
     s390_bus = s390_virtio_bus_init(&ram_size);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(ram_size);
+    ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr);
 
     /* init CPUs */
diff --git a/hw/sm501.c b/hw/sm501.c
index b5ec2da..8e6932d 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1371,7 +1371,7 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    s->local_mem_offset = qemu_ram_alloc(local_mem_bytes);
+    s->local_mem_offset = qemu_ram_alloc(NULL, "sm501.local", local_mem_bytes);
     s->local_mem = qemu_get_ram_ptr(s->local_mem_offset);
     cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset);
 
diff --git a/hw/spitz.c b/hw/spitz.c
index 89ea085..ccf2a09 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -962,7 +962,7 @@ static void spitz_common_init(ram_addr_t ram_size,
     sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
     cpu_register_physical_memory(0, SPITZ_ROM,
-                    qemu_ram_alloc(SPITZ_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "spitz.rom", SPITZ_ROM) | IO_MEM_ROM);
 
     /* Setup peripherals */
     spitz_keyboard_register(cpu);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index e4ca8f3..208c8a8 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -592,7 +592,7 @@ static int idreg_init1(SysBusDevice *dev)
 {
     ram_addr_t idreg_offset;
 
-    idreg_offset = qemu_ram_alloc(sizeof(idreg_data));
+    idreg_offset = qemu_ram_alloc(NULL, "sun4m.idreg", sizeof(idreg_data));
     sysbus_init_mmio(dev, sizeof(idreg_data), idreg_offset | IO_MEM_ROM);
     return 0;
 }
@@ -627,7 +627,7 @@ static int afx_init1(SysBusDevice *dev)
 {
     ram_addr_t afx_offset;
 
-    afx_offset = qemu_ram_alloc(4);
+    afx_offset = qemu_ram_alloc(NULL, "sun4m.afx", 4);
     sysbus_init_mmio(dev, 4, afx_offset | IO_MEM_RAM);
     return 0;
 }
@@ -690,7 +690,7 @@ static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
-    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
+    prom_offset = qemu_ram_alloc(NULL, "sun4m.prom", PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
     return 0;
 }
@@ -725,7 +725,7 @@ static int ram_init1(SysBusDevice *dev)
 
     RAM_size = d->size;
 
-    ram_offset = qemu_ram_alloc(RAM_size);
+    ram_offset = qemu_ram_alloc(NULL, "sun4m.ram", RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
     return 0;
 }
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 40b5f1f..2234b4e 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -629,7 +629,7 @@ static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
-    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
+    prom_offset = qemu_ram_alloc(NULL, "sun4u.prom", PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
     return 0;
 }
@@ -665,7 +665,7 @@ static int ram_init1(SysBusDevice *dev)
 
     RAM_size = d->size;
 
-    ram_offset = qemu_ram_alloc(RAM_size);
+    ram_offset = qemu_ram_alloc(NULL, "sun4u.ram", RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
     return 0;
 }
diff --git a/hw/syborg.c b/hw/syborg.c
index 2d08cb2..758c69a 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -51,7 +51,7 @@ static void syborg_init(ram_addr_t ram_size,
     }
 
     /* RAM at address zero. */
-    ram_addr = qemu_ram_alloc(ram_size);
+    ram_addr = qemu_ram_alloc(NULL, "syborg.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr | IO_MEM_RAM);
 
     cpu_pic = arm_pic_init_cpu(env);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index e0c5e5f..16db51d 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -593,7 +593,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
                     tc6393xb_writefn, s);
     cpu_register_physical_memory(base, 0x10000, iomemtype);
 
-    s->vram_addr = qemu_ram_alloc(0x100000);
+    s->vram_addr = qemu_ram_alloc(NULL, "tc6393xb.vram", 0x100000);
     s->vram_ptr = qemu_get_ram_ptr(s->vram_addr);
     cpu_register_physical_memory(base + 0x100000, 0x100000, s->vram_addr);
     s->scr_width = 480;
diff --git a/hw/tcx.c b/hw/tcx.c
index beb30ac..6ee65bb 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -510,7 +510,7 @@ static int tcx_init1(SysBusDevice *dev)
     int size;
     uint8_t *vram_base;
 
-    vram_offset = qemu_ram_alloc(s->vram_size * (1 + 4 + 4));
+    vram_offset = qemu_ram_alloc(NULL, "tcx.vram", s->vram_size * (1 + 4 + 4));
     vram_base = qemu_get_ram_ptr(vram_offset);
     s->vram_offset = vram_offset;
 
diff --git a/hw/tosa.c b/hw/tosa.c
index fbe8d8c..ba6d9e7 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -215,7 +215,7 @@ static void tosa_init(ram_addr_t ram_size,
     cpu = pxa255_init(tosa_binfo.ram_size);
 
     cpu_register_physical_memory(0, TOSA_ROM,
-                    qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM);
+                    qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
 
     tmio = tc6393xb_init(0x10000000,
             pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 391f5b8..1d049f2 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -180,7 +180,7 @@ static void versatile_init(ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    ram_offset = qemu_ram_alloc(ram_size);
+    ram_offset = qemu_ram_alloc(NULL, "versatile.ram", ram_size);
     /* ??? RAM should repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
diff --git a/hw/vga.c b/hw/vga.c
index 01de1e1..b5c7ee7 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2261,7 +2261,7 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    s->vram_offset = qemu_ram_alloc(vga_ram_size);
+    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
     s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 359e5d8..9e72d2e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1164,7 +1164,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 
 
     s->fifo_size = SVGA_FIFO_SIZE;
-    s->fifo_offset = qemu_ram_alloc(s->fifo_size);
+    s->fifo_offset = qemu_ram_alloc(NULL, "vmsvga.fifo", s->fifo_size);
     s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
 
     vga_common_init(&s->vga, vga_ram_size);

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (8 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 09/16] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 11/16] savevm: Migrate RAM based on name/offset Alex Williamson
                     ` (5 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

With these two pieces in place, we can start naming ramblocks.  When
the device is present and it lives on a bus that provides a device
path, we concatenate the path and the provided name.  Otherwise we
just use name.  The resulting id string must be unique.  For now we
assume an allocation for the same name and size is a device that has
been removed and reinserted and return the same block.  This will go
away once qemu_ram_free() is implemented.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-all.h |    1 +
 exec.c    |   29 +++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index dbb2139..5d8342b 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -865,6 +865,7 @@ typedef struct RAMBlock {
     uint8_t *host;
     ram_addr_t offset;
     ram_addr_t length;
+    char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
 } RAMBlock;
 
diff --git a/exec.c b/exec.c
index 164ba16..fd47d5b 100644
--- a/exec.c
+++ b/exec.c
@@ -36,6 +36,7 @@
 #include "qemu-common.h"
 #include "tcg.h"
 #include "hw/hw.h"
+#include "hw/qdev.h"
 #include "osdep.h"
 #include "kvm.h"
 #include "qemu-timer.h"
@@ -2780,10 +2781,34 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
 
 ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 {
-    RAMBlock *new_block;
+    RAMBlock *new_block, *block;
 
     size = TARGET_PAGE_ALIGN(size);
-    new_block = qemu_malloc(sizeof(*new_block));
+    new_block = qemu_mallocz(sizeof(*new_block));
+
+    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
+        char *id = dev->parent_bus->info->get_dev_path(dev);
+        if (id) {
+            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
+            qemu_free(id);
+        }
+    }
+    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (!strcmp(block->idstr, new_block->idstr)) {
+            if (block->length == new_block->length) {
+                fprintf(stderr, "RAMBlock \"%s\" exists, assuming lack of"
+                        "free.\n", new_block->idstr);
+                qemu_free(new_block);
+                return block->offset;
+            } else {
+                fprintf(stderr, "RAMBlock \"%s\" already registered with"
+                        "different size, abort\n", new_block->idstr);
+                abort();
+            }
+        }
+    }
 
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 11/16] savevm: Migrate RAM based on name/offset
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (9 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
@ 2010-07-02 17:12   ` Alex Williamson
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 12/16] savevm: Use RAM blocks for basis of migration Alex Williamson
                     ` (4 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Synchronize RAM blocks with the target and migrate using name/offset
pairs.  This ensures both source and target have the same view of
RAM and that we get the right bits into the right slot.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |  118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 vl.c        |    2 +
 2 files changed, 108 insertions(+), 12 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 109dcef..37aad9d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -113,20 +113,33 @@ static int ram_save_block(QEMUFile *f)
 
     while (addr < total_ram) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
+            RAMBlock *block;
+            ram_addr_t offset;
             uint8_t *p;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
                                             MIGRATION_DIRTY_FLAG);
 
-            p = qemu_get_ram_ptr(current_addr);
+            QLIST_FOREACH(block, &ram_list.blocks, next) {
+                if (current_addr - block->offset < block->length)
+                    break;
+            }
+            offset = current_addr - block->offset;
+            p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
-                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
             } else {
-                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
+                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
@@ -196,6 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        RAMBlock *block;
         uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
@@ -210,6 +224,12 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         cpu_physical_memory_set_dirty_tracking(1);
 
         qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
+
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            qemu_put_byte(f, strlen(block->idstr));
+            qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
+            qemu_put_be64(f, block->length);
+        }
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -257,7 +277,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
     ram_addr_t addr;
     int flags;
 
-    if (version_id != 3) {
+    if (version_id < 3 || version_id > 4) {
         return -EINVAL;
     }
 
@@ -268,23 +288,99 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != ram_bytes_total()) {
-                return -EINVAL;
+            if (version_id == 3) {
+                if (addr != ram_bytes_total()) {
+                    return -EINVAL;
+                }
+            } else {
+                /* Synchronize RAM block list */
+                char id[256];
+                ram_addr_t length;
+                ram_addr_t total_ram_bytes = addr;
+
+                while (total_ram_bytes) {
+                    RAMBlock *block;
+                    uint8_t len;
+
+                    len = qemu_get_byte(f);
+                    qemu_get_buffer(f, (uint8_t *)id, len);
+                    id[len] = 0;
+                    length = qemu_get_be64(f);
+
+                    QLIST_FOREACH(block, &ram_list.blocks, next) {
+                        if (!strncmp(id, block->idstr, sizeof(id))) {
+                            if (block->length != length)
+                                return -EINVAL;
+                            break;
+                        }
+                    }
+
+                    if (!block) {
+                        if (!qemu_ram_alloc(NULL, id, length))
+                            return -ENOMEM;
+                    }
+
+                    total_ram_bytes -= length;
+                }
             }
         }
 
         if (flags & RAM_SAVE_FLAG_COMPRESS) {
-            uint8_t ch = qemu_get_byte(f);
-            memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
+            void *host;
+            uint8_t ch;
+
+            if (version_id == 3) {
+                host = qemu_get_ram_ptr(addr);
+            } else {
+                RAMBlock *block;
+                char id[256];
+                uint8_t len;
+
+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;
+
+                host = block->host + addr;
+            }
+            ch = qemu_get_byte(f);
+            memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
             if (ch == 0 &&
                 (!kvm_enabled() || kvm_has_sync_mmu())) {
-                madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE,
-                        MADV_DONTNEED);
+                madvise(host, TARGET_PAGE_SIZE, MADV_DONTNEED);
             }
 #endif
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
-            qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
+            void *host;
+
+            if (version_id == 3) {
+                host = qemu_get_ram_ptr(addr);
+            } else {
+                RAMBlock *block;
+                char id[256];
+                uint8_t len;
+
+                len = qemu_get_byte(f);
+                qemu_get_buffer(f, (uint8_t *)id, len);
+                id[len] = 0;
+
+                QLIST_FOREACH(block, &ram_list.blocks, next) {
+                    if (!strncmp(id, block->idstr, sizeof(id)))
+                        break;
+                }
+                if (!block)
+                    return -EINVAL;
+
+                host = block->host + addr;
+            }
+            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {
             return -EIO;
diff --git a/vl.c b/vl.c
index 4a1c5f4..8a5de9f 100644
--- a/vl.c
+++ b/vl.c
@@ -2794,7 +2794,7 @@ int main(int argc, char **argv, char **envp)
     if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
-    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
+    register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 12/16] savevm: Use RAM blocks for basis of migration
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (10 preceding siblings ...)
  2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 11/16] savevm: Migrate RAM based on name/offset Alex Williamson
@ 2010-07-02 17:13   ` Alex Williamson
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 13/16] savevm: Create a new continue flag to avoid resending block name Alex Williamson
                     ` (3 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

We don't want to assume a contiguous address space, so migrate based
on RAM blocks instead of a fixed linear address map.  This will allow
us to have holes in the ram_addr_t namespace, so we can implement
qemu_ram_free().

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   67 +++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 37aad9d..186645b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -105,27 +105,26 @@ static int is_dup_page(uint8_t *page, uint8_t ch)
 
 static int ram_save_block(QEMUFile *f)
 {
-    static ram_addr_t current_addr = 0;
-    ram_addr_t saved_addr = current_addr;
-    ram_addr_t addr = 0;
-    uint64_t total_ram = ram_bytes_total();
+    static RAMBlock *last_block = NULL;
+    static ram_addr_t last_offset = 0;
+    RAMBlock *block = last_block;
+    ram_addr_t offset = last_offset;
+    ram_addr_t current_addr;
     int bytes_sent = 0;
 
-    while (addr < total_ram) {
+    if (!block)
+        block = QLIST_FIRST(&ram_list.blocks);
+
+    current_addr = block->offset + offset;
+
+    do {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
-            RAMBlock *block;
-            ram_addr_t offset;
             uint8_t *p;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
                                             MIGRATION_DIRTY_FLAG);
 
-            QLIST_FOREACH(block, &ram_list.blocks, next) {
-                if (current_addr - block->offset < block->length)
-                    break;
-            }
-            offset = current_addr - block->offset;
             p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
@@ -146,9 +145,21 @@ static int ram_save_block(QEMUFile *f)
 
             break;
         }
-        addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % total_ram;
-    }
+
+        offset += TARGET_PAGE_SIZE;
+        if (offset >= block->length) {
+            offset = 0;
+            block = QLIST_NEXT(block, next);
+            if (!block)
+                block = QLIST_FIRST(&ram_list.blocks);
+        }
+
+        current_addr = block->offset + offset;
+
+    } while (current_addr != last_block->offset + last_offset);
+
+    last_block = block;
+    last_offset = offset;
 
     return bytes_sent;
 }
@@ -157,13 +168,16 @@ static uint64_t bytes_transferred;
 
 static ram_addr_t ram_save_remaining(void)
 {
-    ram_addr_t addr;
+    RAMBlock *block;
     ram_addr_t count = 0;
-    uint64_t total_ram = ram_bytes_total();
 
-    for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
-        if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
-            count++;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ram_addr_t addr;
+        for (addr = block->offset; addr < block->offset + block->length;
+             addr += TARGET_PAGE_SIZE) {
+            if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
+                count++;
+            }
         }
     }
 
@@ -210,20 +224,23 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     if (stage == 1) {
         RAMBlock *block;
-        uint64_t total_ram = ram_bytes_total();
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
-            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
-                cpu_physical_memory_set_dirty(addr);
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            for (addr = block->offset; addr < block->offset + block->length;
+                 addr += TARGET_PAGE_SIZE) {
+                if (!cpu_physical_memory_get_dirty(addr,
+                                                   MIGRATION_DIRTY_FLAG)) {
+                    cpu_physical_memory_set_dirty(addr);
+                }
             }
         }
 
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
         QLIST_FOREACH(block, &ram_list.blocks, next) {
             qemu_put_byte(f, strlen(block->idstr));

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 13/16] savevm: Create a new continue flag to avoid resending block name
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (11 preceding siblings ...)
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 12/16] savevm: Use RAM blocks for basis of migration Alex Williamson
@ 2010-07-02 17:13   ` Alex Williamson
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 14/16] qemu_ram_free: Implement it Alex Williamson
                     ` (2 subsequent siblings)
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Allows us to compress the protocol a bit by setting a flag on the
offset which indicates we're still working within the same block
as last time.  That way we can avoid sending the block name for
every page.  Suggested by Anthony Liguori.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |   94 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 50 insertions(+), 44 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 186645b..2f082f3 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -87,6 +87,7 @@ const uint32_t arch_type = QEMU_ARCH;
 #define RAM_SAVE_FLAG_MEM_SIZE	0x04
 #define RAM_SAVE_FLAG_PAGE	0x08
 #define RAM_SAVE_FLAG_EOS	0x10
+#define RAM_SAVE_FLAG_CONTINUE	0x20
 
 static int is_dup_page(uint8_t *page, uint8_t ch)
 {
@@ -120,6 +121,7 @@ static int ram_save_block(QEMUFile *f)
     do {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
+            int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
 
             cpu_physical_memory_reset_dirty(current_addr,
                                             current_addr + TARGET_PAGE_SIZE,
@@ -128,17 +130,21 @@ static int ram_save_block(QEMUFile *f)
             p = block->host + offset;
 
             if (is_dup_page(p, *p)) {
-                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, strlen(block->idstr));
-                qemu_put_buffer(f, (uint8_t *)block->idstr,
-                                strlen(block->idstr));
+                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
+                if (!cont) {
+                    qemu_put_byte(f, strlen(block->idstr));
+                    qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                    strlen(block->idstr));
+                }
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
             } else {
-                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
-                qemu_put_byte(f, strlen(block->idstr));
-                qemu_put_buffer(f, (uint8_t *)block->idstr,
-                                strlen(block->idstr));
+                qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
+                if (!cont) {
+                    qemu_put_byte(f, strlen(block->idstr));
+                    qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                    strlen(block->idstr));
+                }
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
@@ -289,6 +295,36 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     return (stage == 2) && (expected_time <= migrate_max_downtime());
 }
 
+static inline void *host_from_stream_offset(QEMUFile *f,
+                                            ram_addr_t offset,
+                                            int flags)
+{
+    static RAMBlock *block = NULL;
+    char id[256];
+    uint8_t len;
+
+    if (flags & RAM_SAVE_FLAG_CONTINUE) {
+        if (!block) {
+            fprintf(stderr, "Ack, bad migration stream!\n");
+            return NULL;
+        }
+
+        return block->host + offset;
+    }
+
+    len = qemu_get_byte(f);
+    qemu_get_buffer(f, (uint8_t *)id, len);
+    id[len] = 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (!strncmp(id, block->idstr, sizeof(id)))
+            return block->host + offset;
+    }
+
+    fprintf(stderr, "Can't find block %s!\n", id);
+    return NULL;
+}
+
 int ram_load(QEMUFile *f, void *opaque, int version_id)
 {
     ram_addr_t addr;
@@ -346,26 +382,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
             void *host;
             uint8_t ch;
 
-            if (version_id == 3) {
+            if (version_id == 3)
                 host = qemu_get_ram_ptr(addr);
-            } else {
-                RAMBlock *block;
-                char id[256];
-                uint8_t len;
-
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
+            else
+                host = host_from_stream_offset(f, addr, flags);
 
-                QLIST_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id)))
-                        break;
-                }
-                if (!block)
-                    return -EINVAL;
-
-                host = block->host + addr;
-            }
             ch = qemu_get_byte(f);
             memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
@@ -377,26 +398,11 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
-            if (version_id == 3) {
+            if (version_id == 3)
                 host = qemu_get_ram_ptr(addr);
-            } else {
-                RAMBlock *block;
-                char id[256];
-                uint8_t len;
+            else
+                host = host_from_stream_offset(f, addr, flags);
 
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
-
-                QLIST_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id)))
-                        break;
-                }
-                if (!block)
-                    return -EINVAL;
-
-                host = block->host + addr;
-            }
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 14/16] qemu_ram_free: Implement it
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (12 preceding siblings ...)
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 13/16] savevm: Create a new continue flag to avoid resending block name Alex Williamson
@ 2010-07-02 17:13   ` Alex Williamson
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 15/16] pci: Free the space allocated for the option rom on removal Alex Williamson
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 16/16] ramblocks: No more being lazy about duplicate names Alex Williamson
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Now that we can support a ram_addr_t space with holes, we can implement
qemu_ram_free().

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 cpu-all.h |    3 +++
 exec.c    |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index 5d8342b..224ca40 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -867,6 +867,9 @@ typedef struct RAMBlock {
     ram_addr_t length;
     char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
+#if defined(__linux__) && !defined(TARGET_S390X)
+    int fd;
+#endif
 } RAMBlock;
 
 typedef struct RAMList {
diff --git a/exec.c b/exec.c
index fd47d5b..b9a1471 100644
--- a/exec.c
+++ b/exec.c
@@ -2701,7 +2701,9 @@ static long gethugepagesize(const char *path)
     return fs.f_bsize;
 }
 
-static void *file_ram_alloc(ram_addr_t memory, const char *path)
+static void *file_ram_alloc(RAMBlock *block,
+                            ram_addr_t memory,
+                            const char *path)
 {
     char *filename;
     void *area;
@@ -2764,12 +2766,39 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 	close(fd);
 	return (NULL);
     }
+    block->fd = fd;
     return area;
 }
 #endif
 
 static ram_addr_t find_ram_offset(ram_addr_t size)
 {
+    RAMBlock *block, *next_block;
+    ram_addr_t offset, mingap = ULONG_MAX;
+
+    if (QLIST_EMPTY(&ram_list.blocks))
+        return 0;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ram_addr_t end, next = ULONG_MAX;
+
+        end = block->offset + block->length;
+
+        QLIST_FOREACH(next_block, &ram_list.blocks, next) {
+            if (next_block->offset >= end) {
+                next = MIN(next, next_block->offset);
+            }
+        }
+        if (next - end >= size && next - end < mingap) {
+            offset =  end;
+            mingap = next - end;
+        }
+    }
+    return offset;
+}
+
+static ram_addr_t last_ram_offset(void)
+{
     RAMBlock *block;
     ram_addr_t last = 0;
 
@@ -2812,7 +2841,7 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)
-        new_block->host = file_ram_alloc(size, mem_path);
+        new_block->host = file_ram_alloc(new_block, size, mem_path);
         if (!new_block->host) {
             new_block->host = qemu_vmalloc(size);
 #ifdef MADV_MERGEABLE
@@ -2842,7 +2871,7 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
-        (new_block->offset + size) >> TARGET_PAGE_BITS);
+                                       last_ram_offset() >> TARGET_PAGE_BITS);
     memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0xff, size >> TARGET_PAGE_BITS);
 
@@ -2854,7 +2883,32 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
 void qemu_ram_free(ram_addr_t addr)
 {
-    /* TODO: implement this.  */
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (addr == block->offset) {
+            QLIST_REMOVE(block, next);
+            if (mem_path) {
+#if defined (__linux__) && !defined(TARGET_S390X)
+                if (block->fd) {
+                    munmap(block->host, block->length);
+                    close(block->fd);
+                } else {
+                    qemu_vfree(block->host);
+                }
+#endif
+            } else {
+#if defined(TARGET_S390X) && defined(CONFIG_KVM)
+                munmap(block->host, block->length);
+#else
+                qemu_vfree(block->host);
+#endif
+            }
+            qemu_free(block);
+            return;
+        }
+    }
+
 }
 
 /* Return a host pointer to ram allocated with qemu_ram_alloc.

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 15/16] pci: Free the space allocated for the option rom on removal
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (13 preceding siblings ...)
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 14/16] qemu_ram_free: Implement it Alex Williamson
@ 2010-07-02 17:13   ` Alex Williamson
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 16/16] ramblocks: No more being lazy about duplicate names Alex Williamson
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/pci.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index fe7c5c3..a7ff566 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -76,6 +76,7 @@ static struct BusInfo pci_bus_info = {
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev);
+static void pci_del_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
@@ -709,6 +710,7 @@ static int pci_unregister_device(DeviceState *dev)
         return ret;
 
     pci_unregister_io_regions(pci_dev);
+    pci_del_option_rom(pci_dev);
     do_pci_unregister_device(pci_dev);
     return 0;
 }
@@ -1765,6 +1767,15 @@ static int pci_add_option_rom(PCIDevice *pdev)
     return 0;
 }
 
+static void pci_del_option_rom(PCIDevice *pdev)
+{
+    if (!pdev->rom_offset)
+        return;
+
+    qemu_ram_free(pdev->rom_offset);
+    pdev->rom_offset = 0;
+}
+
 /* Reserve space and add capability to the linked list in pci config space */
 int pci_add_capability_at_offset(PCIDevice *pdev, uint8_t cap_id,
                                  uint8_t offset, uint8_t size)

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [Qemu-devel] [PATCH v3 16/16] ramblocks: No more being lazy about duplicate names
  2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
                     ` (14 preceding siblings ...)
  2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 15/16] pci: Free the space allocated for the option rom on removal Alex Williamson
@ 2010-07-02 17:13   ` Alex Williamson
  15 siblings, 0 replies; 60+ messages in thread
From: Alex Williamson @ 2010-07-02 17:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.williamson

Now that we have a working qemu_ram_free() and the primary runtime
user of it has been updated, don't be lenient about duplicate id strings.
We also shouldn't need to create them ondemand at the target.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 arch_init.c |    5 +++--
 exec.c      |   13 +++----------
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 2f082f3..47bb4b2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -369,8 +369,9 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
                     }
 
                     if (!block) {
-                        if (!qemu_ram_alloc(NULL, id, length))
-                            return -ENOMEM;
+                        fprintf(stderr, "Unknown ramblock \"%s\", cannot "
+                                "accept migration\n", id);
+                        return -EINVAL;
                     }
 
                     total_ram_bytes -= length;
diff --git a/exec.c b/exec.c
index b9a1471..5420f56 100644
--- a/exec.c
+++ b/exec.c
@@ -2826,16 +2826,9 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (!strcmp(block->idstr, new_block->idstr)) {
-            if (block->length == new_block->length) {
-                fprintf(stderr, "RAMBlock \"%s\" exists, assuming lack of"
-                        "free.\n", new_block->idstr);
-                qemu_free(new_block);
-                return block->offset;
-            } else {
-                fprintf(stderr, "RAMBlock \"%s\" already registered with"
-                        "different size, abort\n", new_block->idstr);
-                abort();
-            }
+            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
+                    new_block->idstr);
+            abort();
         }
     }
 

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset)
  2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
@ 2010-07-06 15:45     ` Anthony Liguori
  0 siblings, 0 replies; 60+ messages in thread
From: Anthony Liguori @ 2010-07-06 15:45 UTC (permalink / raw)
  To: Alex Williamson; +Cc: qemu-devel

On 06/25/2010 12:08 PM, Alex Williamson wrote:
> We currently need this either to allocate the next ram_addr_t for a
> new block, or for total memory to be migrated.  Both of which we can
> calculate without need of this to keep us in a contiguous address space.
>
> Signed-off-by: Alex Williamson<alex.williamson@redhat.com>
>    

Applied all.  Thanks.

Regards,

Anthony Liguori

> ---
>
>   arch_init.c |   23 ++++++++++++++++-------
>   cpu-all.h   |    1 -
>   exec.c      |   19 ++++++++++++++-----
>   3 files changed, 30 insertions(+), 13 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index eb5b67c..109dcef 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -108,9 +108,10 @@ static int ram_save_block(QEMUFile *f)
>       static ram_addr_t current_addr = 0;
>       ram_addr_t saved_addr = current_addr;
>       ram_addr_t addr = 0;
> +    uint64_t total_ram = ram_bytes_total();
>       int bytes_sent = 0;
>
> -    while (addr<  ram_list.last_offset) {
> +    while (addr<  total_ram) {
>           if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
>               uint8_t *p;
>
> @@ -133,7 +134,7 @@ static int ram_save_block(QEMUFile *f)
>               break;
>           }
>           addr += TARGET_PAGE_SIZE;
> -        current_addr = (saved_addr + addr) % ram_list.last_offset;
> +        current_addr = (saved_addr + addr) % total_ram;
>       }
>
>       return bytes_sent;
> @@ -145,8 +146,9 @@ static ram_addr_t ram_save_remaining(void)
>   {
>       ram_addr_t addr;
>       ram_addr_t count = 0;
> +    uint64_t total_ram = ram_bytes_total();
>
> -    for (addr = 0; addr<  ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
> +    for (addr = 0; addr<  total_ram; addr += TARGET_PAGE_SIZE) {
>           if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
>               count++;
>           }
> @@ -167,7 +169,13 @@ uint64_t ram_bytes_transferred(void)
>
>   uint64_t ram_bytes_total(void)
>   {
> -    return ram_list.last_offset;
> +    RAMBlock *block;
> +    uint64_t total = 0;
> +
> +    QLIST_FOREACH(block,&ram_list.blocks, next)
> +        total += block->length;
> +
> +    return total;
>   }
>
>   int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
> @@ -188,10 +196,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
>       }
>
>       if (stage == 1) {
> +        uint64_t total_ram = ram_bytes_total();
>           bytes_transferred = 0;
>
>           /* Make sure all dirty bits are set */
> -        for (addr = 0; addr<  ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
> +        for (addr = 0; addr<  total_ram; addr += TARGET_PAGE_SIZE) {
>               if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
>                   cpu_physical_memory_set_dirty(addr);
>               }
> @@ -200,7 +209,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
>           /* Enable dirty memory tracking */
>           cpu_physical_memory_set_dirty_tracking(1);
>
> -        qemu_put_be64(f, ram_list.last_offset | RAM_SAVE_FLAG_MEM_SIZE);
> +        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
>       }
>
>       bytes_transferred_last = bytes_transferred;
> @@ -259,7 +268,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
>           addr&= TARGET_PAGE_MASK;
>
>           if (flags&  RAM_SAVE_FLAG_MEM_SIZE) {
> -            if (addr != ram_list.last_offset) {
> +            if (addr != ram_bytes_total()) {
>                   return -EINVAL;
>               }
>           }
> diff --git a/cpu-all.h b/cpu-all.h
> index e31c2de..dbb2139 100644
> --- a/cpu-all.h
> +++ b/cpu-all.h
> @@ -870,7 +870,6 @@ typedef struct RAMBlock {
>
>   typedef struct RAMList {
>       uint8_t *phys_dirty;
> -    ram_addr_t last_offset;
>       QLIST_HEAD(ram, RAMBlock) blocks;
>   } RAMList;
>   extern RAMList ram_list;
> diff --git a/exec.c b/exec.c
> index 7f64384..058b709 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2765,6 +2765,17 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
>   }
>   #endif
>
> +static ram_addr_t find_ram_offset(ram_addr_t size)
> +{
> +    RAMBlock *block;
> +    ram_addr_t last = 0;
> +
> +    QLIST_FOREACH(block,&ram_list.blocks, next)
> +        last = MAX(last, block->offset + block->length);
> +
> +    return last;
> +}
> +
>   ram_addr_t qemu_ram_alloc(ram_addr_t size)
>   {
>       RAMBlock *new_block;
> @@ -2798,18 +2809,16 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
>           madvise(new_block->host, size, MADV_MERGEABLE);
>   #endif
>       }
> -    new_block->offset = ram_list.last_offset;
> +    new_block->offset = find_ram_offset(size);
>       new_block->length = size;
>
>       QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
>
>       ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
> -        (ram_list.last_offset + size)>>  TARGET_PAGE_BITS);
> -    memset(ram_list.phys_dirty + (ram_list.last_offset>>  TARGET_PAGE_BITS),
> +        (new_block->offset + size)>>  TARGET_PAGE_BITS);
> +    memset(ram_list.phys_dirty + (new_block->offset>>  TARGET_PAGE_BITS),
>              0xff, size>>  TARGET_PAGE_BITS);
>
> -    ram_list.last_offset += size;
> -
>       if (kvm_enabled())
>           kvm_setup_guest_memory(new_block->host, size);
>
>
>
>
>    

^ permalink raw reply	[flat|nested] 60+ messages in thread

end of thread, other threads:[~2010-07-06 15:46 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-24  4:40 [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Alex Williamson
2010-06-24  4:40 ` [Qemu-devel] [PATCH 01/15] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 02/15] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 03/15] pci: Implement BusInfo.get_dev_path() Alex Williamson
2010-06-24  7:39   ` Isaku Yamahata
2010-06-24 15:05     ` Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 04/15] savevm: Add DeviceState param Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 05/15] savevm: Make use of DeviceState Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 06/15] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 07/15] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 08/15] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
2010-06-24  4:41 ` [Qemu-devel] [PATCH 09/15] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
2010-06-24  4:42 ` [Qemu-devel] [PATCH 10/15] savevm: Migrate RAM based on name/offset Alex Williamson
2010-06-24  5:49   ` [Qemu-devel] " Paolo Bonzini
2010-06-24  4:42 ` [Qemu-devel] [PATCH 11/15] savevm: Use RAM blocks for basis of migration Alex Williamson
2010-06-24  4:42 ` [Qemu-devel] [PATCH 12/15] savevm: Create a new continue flag to avoid resending block name Alex Williamson
2010-06-24  5:51   ` [Qemu-devel] " Paolo Bonzini
2010-06-24 15:06     ` Alex Williamson
2010-06-24  4:42 ` [Qemu-devel] [PATCH 13/15] qemu_ram_free: Implement it Alex Williamson
2010-06-24  4:42 ` [Qemu-devel] [PATCH 14/15] pci: Free the space allocated for the option rom on removal Alex Williamson
2010-06-24  4:42 ` [Qemu-devel] [PATCH 15/15] ramblocks: No more being lazy about duplicate names Alex Williamson
2010-06-24  6:02 ` [Qemu-devel] [PATCH 00/15] Make migration work with hotplug Yoshiaki Tamura
2010-06-24 15:04   ` Alex Williamson
2010-06-24 15:23     ` Alex Williamson
2010-06-25  2:01       ` Yoshiaki Tamura
2010-06-25 17:08 ` [Qemu-devel] [PATCH v2 00/16] " Alex Williamson
2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
2010-07-06 15:45     ` Anthony Liguori
2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 02/16] pc: Allocate all ram in a single qemu_ram_alloc() Alex Williamson
2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 03/16] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
2010-06-25 17:08   ` [Qemu-devel] [PATCH v2 04/16] pci: Implement BusInfo.get_dev_path() Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 05/16] savevm: Add DeviceState param Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 06/16] savevm: Make use of DeviceState Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 07/16] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 09/16] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 11/16] savevm: Migrate RAM based on name/offset Alex Williamson
2010-06-25 17:09   ` [Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migration Alex Williamson
2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 13/16] savevm: Create a new continue flag to avoid resending block name Alex Williamson
2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 14/16] qemu_ram_free: Implement it Alex Williamson
2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 15/16] pci: Free the space allocated for the option rom on removal Alex Williamson
2010-06-25 17:10   ` [Qemu-devel] [PATCH v2 16/16] ramblocks: No more being lazy about duplicate names Alex Williamson
2010-07-02 17:11 ` [Qemu-devel] [PATCH v3 00/16] Make migration work with hotplug Alex Williamson
2010-07-02 17:11   ` [Qemu-devel] [PATCH v3 01/16] Remove uses of ram.last_offset (aka last_ram_offset) Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 02/16] pc: Allocate all ram in a single qemu_ram_alloc() Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 03/16] qdev: Add a get_dev_path() function to BusInfo Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 04/16] pci: Implement BusInfo.get_dev_path() Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 05/16] savevm: Add DeviceState param Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 06/16] savevm: Make use of DeviceState Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 07/16] eepro100: Add a dev field to eeprom new/free functions Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 09/16] qemu_ram_alloc: Add DeviceState and name parameters Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path Alex Williamson
2010-07-02 17:12   ` [Qemu-devel] [PATCH v3 11/16] savevm: Migrate RAM based on name/offset Alex Williamson
2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 12/16] savevm: Use RAM blocks for basis of migration Alex Williamson
2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 13/16] savevm: Create a new continue flag to avoid resending block name Alex Williamson
2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 14/16] qemu_ram_free: Implement it Alex Williamson
2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 15/16] pci: Free the space allocated for the option rom on removal Alex Williamson
2010-07-02 17:13   ` [Qemu-devel] [PATCH v3 16/16] ramblocks: No more being lazy about duplicate names Alex Williamson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).