summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--arch_init.c183
-rw-r--r--audio/audio.c2
-rw-r--r--block-migration.c4
-rw-r--r--cpu-all.h5
-rw-r--r--cpu-common.h2
-rw-r--r--cpus.c1
-rw-r--r--exec.c107
-rw-r--r--hw/adb.c4
-rw-r--r--hw/ads7846.c2
-rw-r--r--hw/an5206.c4
-rw-r--r--hw/arm_gic.c2
-rw-r--r--hw/arm_timer.c4
-rw-r--r--hw/armv7m.c9
-rw-r--r--hw/armv7m_nvic.c2
-rw-r--r--hw/axis_dev88.c4
-rw-r--r--hw/cirrus_vga.c2
-rw-r--r--hw/cuda.c2
-rw-r--r--hw/dma.c4
-rw-r--r--hw/dummy_m68k.c2
-rw-r--r--hw/eepro100.c8
-rw-r--r--hw/eeprom93xx.c8
-rw-r--r--hw/eeprom93xx.h4
-rw-r--r--hw/etraxfs.c6
-rw-r--r--hw/g364fb.c4
-rw-r--r--hw/grackle_pci.c4
-rw-r--r--hw/gt64xxx.c3
-rw-r--r--hw/gumstix.c6
-rw-r--r--hw/heathrow_pic.c2
-rw-r--r--hw/hw.h18
-rw-r--r--hw/i2c.c2
-rw-r--r--hw/i8254.c2
-rw-r--r--hw/i8259.c2
-rw-r--r--hw/ide/cmd646.c2
-rw-r--r--hw/ide/isa.c2
-rw-r--r--hw/ide/macio.c2
-rw-r--r--hw/ide/microdrive.c2
-rw-r--r--hw/ide/mmio.c2
-rw-r--r--hw/ide/piix.c2
-rw-r--r--hw/ide/via.c2
-rw-r--r--hw/integratorcp.c4
-rw-r--r--hw/lsi53c895a.c15
-rw-r--r--hw/m48t59.c2
-rw-r--r--hw/mac_dbdma.c2
-rw-r--r--hw/mac_nvram.c4
-rw-r--r--hw/mainstone.c6
-rw-r--r--hw/max111x.c3
-rw-r--r--hw/mc146818rtc.c7
-rw-r--r--hw/mcf5208.c4
-rw-r--r--hw/mips_fulong2e.c6
-rw-r--r--hw/mips_jazz.c4
-rw-r--r--hw/mips_malta.c4
-rw-r--r--hw/mips_mipssim.c4
-rw-r--r--hw/mips_r4k.c6
-rw-r--r--hw/mipsnet.c4
-rw-r--r--hw/mst_fpga.c3
-rw-r--r--hw/musicpal.c11
-rw-r--r--hw/nand.c2
-rw-r--r--hw/omap1.c6
-rw-r--r--hw/omap2.c6
-rw-r--r--hw/omap_sx1.c12
-rw-r--r--hw/onenand.c2
-rw-r--r--hw/openpic.c5
-rw-r--r--hw/palm.c3
-rw-r--r--hw/pc.c27
-rw-r--r--hw/pci.c34
-rw-r--r--hw/pckbd.c2
-rw-r--r--hw/petalogix_s3adsp1800_mmu.c7
-rw-r--r--hw/piix4.c2
-rw-r--r--hw/pl011.c2
-rw-r--r--hw/pl022.c2
-rw-r--r--hw/pl061.c2
-rw-r--r--hw/ppc405_boards.c18
-rw-r--r--hw/ppc405_uc.c2
-rw-r--r--hw/ppc4xx_devs.c4
-rw-r--r--hw/ppc4xx_pci.c4
-rw-r--r--hw/ppc_newworld.c6
-rw-r--r--hw/ppc_oldworld.c6
-rw-r--r--hw/ppc_prep.c4
-rw-r--r--hw/ppce500_mpc8544ds.c3
-rw-r--r--hw/ppce500_pci.c4
-rw-r--r--hw/ps2.c4
-rw-r--r--hw/pxa2xx.c39
-rw-r--r--hw/pxa2xx_dma.c2
-rw-r--r--hw/pxa2xx_gpio.c2
-rw-r--r--hw/pxa2xx_keypad.c2
-rw-r--r--hw/pxa2xx_lcd.c2
-rw-r--r--hw/pxa2xx_mmci.c2
-rw-r--r--hw/pxa2xx_pic.c3
-rw-r--r--hw/pxa2xx_timer.c2
-rw-r--r--hw/qdev.c4
-rw-r--r--hw/qdev.h3
-rw-r--r--hw/r2d.c4
-rw-r--r--hw/rc4030.c2
-rw-r--r--hw/realview.c6
-rw-r--r--hw/s390-virtio.c2
-rw-r--r--hw/serial.c4
-rw-r--r--hw/sm501.c2
-rw-r--r--hw/spitz.c11
-rw-r--r--hw/ssd0323.c3
-rw-r--r--hw/ssi-sd.c2
-rw-r--r--hw/stellaris.c11
-rw-r--r--hw/stellaris_enet.c4
-rw-r--r--hw/stellaris_input.c2
-rw-r--r--hw/sun4m.c8
-rw-r--r--hw/sun4u.c4
-rw-r--r--hw/syborg.c2
-rw-r--r--hw/syborg_fb.c2
-rw-r--r--hw/syborg_interrupt.c3
-rw-r--r--hw/syborg_keyboard.c2
-rw-r--r--hw/syborg_pointer.c2
-rw-r--r--hw/syborg_rtc.c3
-rw-r--r--hw/syborg_serial.c2
-rw-r--r--hw/syborg_timer.c2
-rw-r--r--hw/tc6393xb.c2
-rw-r--r--hw/tcx.c2
-rw-r--r--hw/tosa.c2
-rw-r--r--hw/tsc2005.c2
-rw-r--r--hw/tsc210x.c4
-rw-r--r--hw/unin_pci.c6
-rw-r--r--hw/versatilepb.c2
-rw-r--r--hw/vga-isa-mm.c2
-rw-r--r--hw/vga-isa.c2
-rw-r--r--hw/vga.c2
-rw-r--r--hw/virtio-balloon.c3
-rw-r--r--hw/virtio-blk.c2
-rw-r--r--hw/virtio-net.c7
-rw-r--r--hw/virtio-serial-bus.c2
-rw-r--r--hw/vmmouse.c2
-rw-r--r--hw/vmware_vga.c4
-rw-r--r--hw/zaurus.c2
-rw-r--r--os-posix.c2
-rw-r--r--qemu-timer.c2
-rw-r--r--savevm.c106
-rw-r--r--slirp/slirp.c5
-rw-r--r--vl.c2
135 files changed, 689 insertions, 306 deletions
diff --git a/arch_init.c b/arch_init.c
index eb5b67cd3e..47bb4b2d8f 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)
 {
@@ -105,36 +106,66 @@ 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;
+    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 < ram_list.last_offset) {
+    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)) {
             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,
                                             MIGRATION_DIRTY_FLAG);
 
-            p = qemu_get_ram_ptr(current_addr);
+            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 | 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, current_addr | RAM_SAVE_FLAG_PAGE);
+                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;
             }
 
             break;
         }
-        addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % ram_list.last_offset;
-    }
+
+        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;
 }
@@ -143,12 +174,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;
 
-    for (addr = 0; addr < ram_list.last_offset; 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++;
+            }
         }
     }
 
@@ -167,7 +202,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,19 +229,30 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (stage == 1) {
+        RAMBlock *block;
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < ram_list.last_offset; 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, ram_list.last_offset | 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));
+            qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
+            qemu_put_be64(f, block->length);
+        }
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -243,12 +295,42 @@ 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;
     int flags;
 
-    if (version_id != 3) {
+    if (version_id < 3 || version_id > 4) {
         return -EINVAL;
     }
 
@@ -259,23 +341,70 @@ 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) {
-                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) {
+                        fprintf(stderr, "Unknown ramblock \"%s\", cannot "
+                                "accept migration\n", id);
+                        return -EINVAL;
+                    }
+
+                    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
+                host = host_from_stream_offset(f, addr, flags);
+
+            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
+                host = host_from_stream_offset(f, addr, flags);
+
+            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
         if (qemu_file_has_error(f)) {
             return -EIO;
diff --git a/audio/audio.c b/audio/audio.c
index dbf0b96f33..ad51077f32 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 7337349e83..7db6f02b96 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/cpu-all.h b/cpu-all.h
index e31c2de7bf..224ca40c1d 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -865,12 +865,15 @@ typedef struct RAMBlock {
     uint8_t *host;
     ram_addr_t offset;
     ram_addr_t length;
+    char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
+#if defined(__linux__) && !defined(TARGET_S390X)
+    int fd;
+#endif
 } 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/cpu-common.h b/cpu-common.h
index b24cecc75c..71e7933c51 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/cpus.c b/cpus.c
index fcd0f09b42..eef0bb8a0a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -30,6 +30,7 @@
 #include "gdbstub.h"
 #include "dma.h"
 #include "kvm.h"
+#include "exec-all.h"
 
 #include "cpus.h"
 
diff --git a/exec.c b/exec.c
index 137175caa0..5420f564b5 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"
@@ -641,8 +642,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
 }
@@ -2700,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;
@@ -2763,20 +2766,75 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
 	close(fd);
 	return (NULL);
     }
+    block->fd = fd;
     return area;
 }
 #endif
 
-ram_addr_t qemu_ram_alloc(ram_addr_t size)
+static ram_addr_t find_ram_offset(ram_addr_t size)
 {
-    RAMBlock *new_block;
+    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;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next)
+        last = MAX(last, block->offset + block->length);
+
+    return last;
+}
+
+ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
+{
+    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)) {
+            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
+                    new_block->idstr);
+            abort();
+        }
+    }
 
     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
@@ -2800,18 +2858,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),
+                                       last_ram_offset() >> 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);
 
@@ -2820,7 +2876,32 @@ ram_addr_t qemu_ram_alloc(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.
diff --git a/hw/adb.c b/hw/adb.c
index 4fb7a62417..99b30f6bc7 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 184b3dd064..b3bbeaf68e 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/an5206.c b/hw/an5206.c
index f584d8816f..b9f19a9944 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/arm_gic.c b/hw/arm_gic.c
index c4afc6aeb5..8286a282ea 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 9073ffc007..f009e9e51d 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.c b/hw/armv7m.c
index 854261d940..588ec9805c 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/armv7m_nvic.c b/hw/armv7m_nvic.c
index 9f09ef423e..6c7ce01228 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/axis_dev88.c b/hw/axis_dev88.c
index 3ae4105042..f16c76aee2 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/cirrus_vga.c b/hw/cirrus_vga.c
index ba4828996a..bbd4b082d2 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 50950d9100..3f238b630c 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 5b215211e1..8a7302a42f 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/dummy_m68k.c b/hw/dummy_m68k.c
index 9c9e6ff009..61efb39896 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/eepro100.c b/hw/eepro100.c
index 97afa2cd9f..2b75c8f495 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1834,8 +1834,8 @@ 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);
-    eeprom93xx_free(s->eeprom);
+    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
+    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 =
@@ -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 30a35340ad..660b28f225 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(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(&vmstate_eeprom, eeprom);
+    vmstate_unregister(dev, &vmstate_eeprom, eeprom);
     qemu_free(eeprom);
 }
 
diff --git a/hw/eeprom93xx.h b/hw/eeprom93xx.h
index 47282d381e..8ba0e287f2 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);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 01bf92942f..46e2920c23 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 d1d2c12d6c..3c8fb982dc 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -593,12 +593,12 @@ 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;
 
     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 aa0c51b88a..0cf29dc9d1 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 7691e1d48e..313c080450 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/gumstix.c b/hw/gumstix.c
index b64e04e205..c343a166e8 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/heathrow_pic.c b/hw/heathrow_pic.c
index 5e270215ab..cd86121096 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 a49d866532..c2de6fe8c4 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 bee8e88c6b..f80d12db4f 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 faaa884d9d..06b225cf4c 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 a99528059e..a8dbee6476 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 559147ff43..8b71a13154 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 10777caec1..6b57e0d301 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 539c067b00..bd1c73e62b 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 47c3c8cfa5..2ceeb87c0c 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 e75cccf56e..9f20e8bab6 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 fa22226dce..9223834a6b 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 d933caf030..a403e8cd98 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(&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/integratorcp.c b/hw/integratorcp.c
index bee82988b4..3bf216bf85 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/lsi53c895a.c b/hw/lsi53c895a.c
index 1bb1caf478..bd7b661426 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1590,8 +1590,19 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
             BADF("Immediate Arbritration not implemented\n");
         }
         if (val & LSI_SCNTL1_RST) {
-            s->sstat0 |= LSI_SSTAT0_RST;
-            lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
+            if (!(s->sstat0 & LSI_SSTAT0_RST)) {
+                DeviceState *dev;
+                int id;
+
+                for (id = 0; id < s->bus.ndev; id++) {
+                    if (s->bus.devs[id]) {
+                        dev = &s->bus.devs[id]->qdev;
+                        dev->info->reset(dev);
+                    }
+                }
+                s->sstat0 |= LSI_SSTAT0_RST;
+                lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
+            }
         } else {
             s->sstat0 &= ~LSI_SSTAT0_RST;
         }
diff --git a/hw/m48t59.c b/hw/m48t59.c
index c3d7b3a256..c7492a65fe 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 e2697d3a74..03d2d16d29 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 f28db6bb25..ce287c31de 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/mainstone.c b/hw/mainstone.c
index 54bacfb9dc..cba7e63b3c 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/max111x.c b/hw/max111x.c
index bd656bb534..2844665ba3 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/mc146818rtc.c b/hw/mc146818rtc.c
index c3459bf605..2b91fa839e 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -214,7 +214,6 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
         case RTC_SECONDS_ALARM:
         case RTC_MINUTES_ALARM:
         case RTC_HOURS_ALARM:
-            /* XXX: not supported */
             s->cmos_data[s->cmos_index] = data;
             break;
         case RTC_SECONDS:
@@ -414,11 +413,11 @@ static void rtc_update_second2(void *opaque)
     /* check alarm */
     if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
         if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
-             s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
+             rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) &&
             ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
-             s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
+             rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) &&
             ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
-             s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
+             rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) {
 
             s->cmos_data[RTC_REG_C] |= 0xa0;
             qemu_irq_raise(s->irq);
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 5b686c657a..38645f7285 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 d85240a006..a9bbff64b3 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. */
@@ -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, "fulong2e.ram", ram_size);
+    bios_offset = qemu_ram_alloc(NULL, "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 606cd23ef3..71b05a203c 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 9042b57ddf..11e220a944 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 293d99ebee..111c7592ea 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 5a96dea003..61cd33a93c 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/mipsnet.c b/hw/mipsnet.c
index a066f6313d..a95b3ce07b 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 1b6cb77659..8fc348f75b 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/musicpal.c b/hw/musicpal.c
index 95ef2c6746..33180a2656 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/nand.c b/hw/nand.c
index cd7444f9a5..f414aa139b 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/omap1.c b/hw/omap1.c
index d400bbb981..cf0d428692 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 ff349ae910..179075e996 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 2e9879f0ef..c3f197393d 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 4118db922d..f7afecaaab 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/openpic.c b/hw/openpic.c
index ac21993bc8..2b4cb00523 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/palm.c b/hw/palm.c
index 8db133d09e..193aa11d28 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 b577fb1bc6..a96187f5b5 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -901,27 +901,24 @@ 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(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,
                  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)
@@ -936,7 +933,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:
@@ -954,7 +951,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 7787005bdb..a7ff5668a7 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),
@@ -74,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;
@@ -230,7 +233,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);
 }
 
@@ -707,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;
 }
@@ -1711,6 +1715,7 @@ static int pci_add_option_rom(PCIDevice *pdev)
     int size;
     char *path;
     void *ptr;
+    char name[32];
 
     if (!pdev->romfile)
         return 0;
@@ -1746,7 +1751,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);
@@ -1758,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)
@@ -1853,6 +1871,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),
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 381228479e..0533b1d9e3 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/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index cdde991aa5..70b6a36e1e 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/piix4.c b/hw/piix4.c
index f75951b3ea..6f08c5a6dd 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 81de91e4c4..02cf84aee1 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 c2e2ddafef..d7862bc692 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 7b1b636e9b..e4505f5cb6 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/ppc405_boards.c b/hw/ppc405_boards.c
index 7c7075e0da..40ff1b34ea 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 d9bbd93789..b884ea5fbd 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 37a3948293..b15db81b6a 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/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index c9e3279544..6e437e754e 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/ppc_newworld.c b/hw/ppc_newworld.c
index d131aa5e68..fbba9b6fb2 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 27ddc013e6..6b3ab89611 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 bb9e15ffd8..fc3e17a0c3 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 0901fa6ffe..1422fad072 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/ppce500_pci.c b/hw/ppce500_pci.c
index 336d284d55..5358f82b0a 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 f0b206aa86..762bb00048 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 909538653c..953e9ee1d1 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;
 }
@@ -2053,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);
 
@@ -2099,7 +2102,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 +2113,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 +2143,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);
@@ -2173,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);
 
@@ -2219,7 +2225,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 +2236,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 +2266,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 66c2c30a8c..9c479df04e 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 f354f4bd1f..2abcb6543a 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 060df58445..dfa8945b22 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 930299abd3..111a0dc031 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 a415349a7e..ca98660224 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 0a98342328..4d8944bfce 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 d992cc3c43..0f0ffd3f36 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 00ceada615..e99c73f0d9 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);
     }
@@ -344,7 +344,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/qdev.h b/hw/qdev.h
index cbc89f2c1e..3e22eecc06 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;
 };
 
diff --git a/hw/r2d.c b/hw/r2d.c
index bc2575656c..8c1fbad4ba 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/rc4030.c b/hw/rc4030.c
index 2a8233ab9d..223137323b 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/realview.c b/hw/realview.c
index f786699a1c..70bcdb846d 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 6af58e23af..e7aec14fae 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/serial.c b/hw/serial.c
index c7e4e77cb0..b66d13ad41 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/sm501.c b/hw/sm501.c
index b5ec2dae9c..8e6932d747 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 b3e5318e36..ccf2a091fb 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;
 }
 
@@ -961,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/ssd0323.c b/hw/ssd0323.c
index b632825110..8643961144 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 96b33edcbd..a1a63b23e2 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 5755f8a9fc..ccad1348a9 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 d1d755e295..330a9d6130 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 33395a427b..16aae96f2f 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/sun4m.c b/hw/sun4m.c
index e4ca8f3dc5..208c8a86df 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 40b5f1fb37..2234b4e923 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 2d08cb2492..758c69a9cd 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/syborg_fb.c b/hw/syborg_fb.c
index 7be04a3526..ed57203f92 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 f3a1767296..30140fba47 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 4a562f85de..7709100c14 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 563d73067d..69b8d96bba 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 b066213533..78d5edb0f7 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 cac00eac09..8c429563a2 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 3e4a447610..95e07d7bbf 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/tc6393xb.c b/hw/tc6393xb.c
index e0c5e5f087..16db51dc2e 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 beb30ac825..6ee65bb224 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 fbe8d8c693..ba6d9e73bf 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/tsc2005.c b/hw/tsc2005.c
index b75cc862ae..a55853c853 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 e851ca10a6..fca73f16f3 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 f0a773d6ad..362fb7762d 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/versatilepb.c b/hw/versatilepb.c
index 391f5b88c6..1d049f2342 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-isa-mm.c b/hw/vga-isa-mm.c
index 8e31e36ea5..680b557a0b 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 793714417a..304605493a 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/vga.c b/hw/vga.c
index 01de1e1b04..b5c7ee7fe3 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/virtio-balloon.c b/hw/virtio-balloon.c
index 152af803ee..9fe3886b0f 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 0bd57b5055..8747634fbe 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -512,7 +512,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);
     bdrv_set_removable(s->bs, 0);
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 06ba48103d..f41db45b00 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("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("virtio-net", n);
+    unregister_savevm(n->qdev, "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 fa5283cbb5..26d5841154 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 afebad9a0a..f3593047e7 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 bf2a6998c3..9e72d2e9b9 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1164,12 +1164,12 @@ 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);
     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 db6ba75ced..dd999d7d44 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/os-posix.c b/os-posix.c
index 804e20c189..00133a0c76 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -28,6 +28,8 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+/*needed for MAP_POPULATE before including qemu-options.h */
+#include <sys/mman.h>
 #include <pwd.h>
 #include <libgen.h>
 
diff --git a/qemu-timer.c b/qemu-timer.c
index bdc8206710..bc5f207bb6 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 f1f450edc4..ee279895cd 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"
@@ -985,6 +986,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];
@@ -998,6 +1004,7 @@ typedef struct SaveStateEntry {
     LoadStateHandler *load_state;
     const VMStateDescription *vmsd;
     void *opaque;
+    CompatEntry *compat;
 } SaveStateEntry;
 
 
@@ -1019,11 +1026,29 @@ 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
    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,
@@ -1035,7 +1060,6 @@ int register_savevm_live(const char *idstr,
     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;
@@ -1045,40 +1069,69 @@ int register_savevm_live(const char *idstr,
     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;
 }
 
-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;
+    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);
         }
     }
 }
 
-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)
@@ -1089,7 +1142,6 @@ int vmstate_register_with_alias_id(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;
@@ -1099,23 +1151,42 @@ int vmstate_register_with_alias_id(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;
 }
 
-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;
 
@@ -1447,6 +1518,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;
 }
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 3c785cd643..82fd9b424f 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 920717a237..8a5de9fac1 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, 4, NULL, ram_save_live, NULL,
                          ram_load, NULL);
 
     if (nb_numa_nodes > 0) {