qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH V8 11/39] cpr: save ram blocks


From: Steve Sistare
Subject: [PATCH V8 11/39] cpr: save ram blocks
Date: Wed, 15 Jun 2022 07:51:58 -0700

Add a vmstate handler to save volatile ram blocks in the state file.  This
is used to preserve secondary guest ram blocks (those that cannot be
specified on the command line) such as video ram and roms for cpr reboot,
as there is no option to allocate them in shared memory.  For efficiency,
the user should create a shared memory-backend-file for the VM's main ram,
so it is not copied to the state file, but this is not enforced.

Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
---
 include/exec/memory.h |  6 +++++
 migration/savevm.c    |  2 ++
 softmmu/memory.c      | 18 ++++++++++++++
 softmmu/physmem.c     | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 93 insertions(+)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0daddd7..a03301d 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -3002,6 +3002,12 @@ bool ram_block_discard_is_disabled(void);
  */
 bool ram_block_discard_is_required(void);
 
+/*
+ * Register/unregister a ram block for cpr.
+ */
+void ram_block_register(RAMBlock *rb);
+void ram_block_unregister(RAMBlock *rb);
+
 #endif
 
 #endif
diff --git a/migration/savevm.c b/migration/savevm.c
index 0b2c5cd..9d528ed 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -3108,10 +3108,12 @@ void vmstate_register_ram(MemoryRegion *mr, DeviceState 
*dev)
     qemu_ram_set_idstr(mr->ram_block,
                        memory_region_name(mr), dev);
     qemu_ram_set_migratable(mr->ram_block);
+    ram_block_register(mr->ram_block);
 }
 
 void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
 {
+    ram_block_unregister(mr->ram_block);
     qemu_ram_unset_idstr(mr->ram_block);
     qemu_ram_unset_migratable(mr->ram_block);
 }
diff --git a/softmmu/memory.c b/softmmu/memory.c
index 7ba2048..0fe6fac 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -3541,13 +3541,31 @@ void __attribute__((weak)) fuzz_dma_read_cb(size_t addr,
 }
 #endif
 
+static char *
+memory_region_vmstate_if_get_id(VMStateIf *obj)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+    return strdup(mr->ram_block->idstr);
+}
+
+static void memory_region_class_init(ObjectClass *class, void *data)
+{
+    VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
+    vc->get_id = memory_region_vmstate_if_get_id;
+}
+
 static const TypeInfo memory_region_info = {
     .parent             = TYPE_OBJECT,
     .name               = TYPE_MEMORY_REGION,
     .class_size         = sizeof(MemoryRegionClass),
+    .class_init         = memory_region_class_init,
     .instance_size      = sizeof(MemoryRegion),
     .instance_init      = memory_region_initfn,
     .instance_finalize  = memory_region_finalize,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_VMSTATE_IF },
+        { }
+    }
 };
 
 static const TypeInfo iommu_memory_region_info = {
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 0f1ce28..822c424 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -66,7 +66,9 @@
 
 #include "qemu/pmem.h"
 
+#include "migration/cpr.h"
 #include "migration/vmstate.h"
+#include "migration/qemu-file.h"
 
 #include "qemu/range.h"
 #ifndef _WIN32
@@ -2450,6 +2452,71 @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
     return block->offset + offset;
 }
 
+static int put_ram_block(QEMUFile *f, void *pv, size_t size,
+                         const VMStateField *field, JSONWriter *vmdesc)
+{
+    RAMBlock *rb = pv;
+
+    if (rb->used_length > 1024 * 1024) {
+        warn_report("Large RAM block %s size %ld saved to state file. "
+                    "Use a shared file memory backend to avoid the copy.",
+                    rb->idstr, rb->used_length);
+    }
+    qemu_put_buffer(f, rb->host, rb->used_length);
+    return 0;
+}
+
+static int get_ram_block(QEMUFile *f, void *pv, size_t size,
+                         const VMStateField *field)
+{
+    RAMBlock *rb = pv;
+    qemu_get_buffer(f, rb->host, rb->used_length);
+    return 0;
+}
+
+static const VMStateInfo vmstate_info_ram_block = {
+    .name = "ram block host",
+    .get  = get_ram_block,
+    .put  = put_ram_block,
+};
+
+#define VMSTATE_RAM_BLOCK() {           \
+    .name  = "ram_block_host",          \
+    .info  = &vmstate_info_ram_block,   \
+    .flags = VMS_SINGLE,                \
+}
+
+static bool ram_block_needed(void *opaque)
+{
+    RAMBlock *rb = opaque;
+
+    return cpr_get_mode() == CPR_MODE_REBOOT &&
+        qemu_ram_is_migratable(rb) &&
+        (!qemu_ram_is_shared(rb) || ramblock_is_anon(rb));
+}
+
+const VMStateDescription vmstate_ram_block = {
+    .name = "RAMBlock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = ram_block_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(used_length, RAMBlock),
+        VMSTATE_RAM_BLOCK(),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+void ram_block_register(RAMBlock *rb)
+{
+    vmstate_register(VMSTATE_IF(rb->mr), 0, &vmstate_ram_block, rb);
+}
+
+void ram_block_unregister(RAMBlock *rb)
+{
+    vmstate_unregister(VMSTATE_IF(rb->mr), &vmstate_ram_block, rb);
+}
+
 static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
                                  MemTxAttrs attrs, void *buf, hwaddr len);
 static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]