[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
- [PATCH V8 06/39] cpr: reboot mode, (continued)
- [PATCH V8 06/39] cpr: reboot mode, Steve Sistare, 2022/06/15
- [PATCH V8 02/39] migration: qemu file wrappers, Steve Sistare, 2022/06/15
- [PATCH V8 08/39] cpr: blockers, Steve Sistare, 2022/06/15
- [PATCH V8 10/39] cpr: cpr-enable option, Steve Sistare, 2022/06/15
- [PATCH V8 12/39] memory: flat section iterator, Steve Sistare, 2022/06/15
- [PATCH V8 09/39] cpr: register blockers, Steve Sistare, 2022/06/15
- [PATCH V8 11/39] cpr: save ram blocks,
Steve Sistare <=
- [PATCH V8 13/39] oslib: qemu_clear_cloexec, Steve Sistare, 2022/06/15
- [PATCH V8 25/39] cpr: notifiers, Steve Sistare, 2022/06/15
- [PATCH V8 20/39] cpr: restart mode, Steve Sistare, 2022/06/15
- [PATCH V8 29/39] vfio-pci: cpr part 3 (intx), Steve Sistare, 2022/06/15
- [PATCH V8 17/39] qapi: strList unit tests, Steve Sistare, 2022/06/15
- [PATCH V8 14/39] qapi: strList_from_string, Steve Sistare, 2022/06/15