@@ -34,6 +34,7 @@ struct HostMemoryBackendFile {
bool discard_data;
char *mem_path;
uint64_t align;
+ bool is_pmem;
};
static void
@@ -59,7 +60,8 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
path,
backend->size, fb->align,
- backend->share ? QEMU_RAM_SHARE : 0,
+ (backend->share ? QEMU_RAM_SHARE : 0) |
+ (fb->is_pmem ? QEMU_RAM_PMEM : 0),
fb->mem_path, errp);
g_free(path);
}
@@ -131,6 +133,25 @@ static void file_memory_backend_set_align(Object *o, Visitor *v,
error_propagate(errp, local_err);
}
+static bool file_memory_backend_get_pmem(Object *o, Error **errp)
+{
+ return MEMORY_BACKEND_FILE(o)->is_pmem;
+}
+
+static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(o);
+ HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+
+ if (host_memory_backend_mr_inited(backend)) {
+ error_setg(errp, "cannot change property 'pmem' of %s '%s'",
+ object_get_typename(o), backend->id);
+ return;
+ }
+
+ fb->is_pmem = value;
+}
+
static void file_backend_unparent(Object *obj)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
@@ -162,6 +183,9 @@ file_backend_class_init(ObjectClass *oc, void *data)
file_memory_backend_get_align,
file_memory_backend_set_align,
NULL, NULL, &error_abort);
+ object_class_property_add_bool(oc, "pmem",
+ file_memory_backend_get_pmem, file_memory_backend_set_pmem,
+ &error_abort);
}
static void file_backend_instance_finalize(Object *o)
@@ -153,3 +153,17 @@ guest NVDIMM region mapping structure. This unarmed flag indicates
guest software that this vNVDIMM device contains a region that cannot
accept persistent writes. In result, for example, the guest Linux
NVDIMM driver, marks such vNVDIMM device as read-only.
+
+If the vNVDIMM backend is on the host persistent memory that can be
+accessed in SNIA NVM Programming Model [1] (e.g., Intel NVDIMM), it's
+suggested to set the 'pmem' option of memory-backend-file to 'on'. When
+'pmem=on' and QEMU is built with libpmem [2] support (configured with
+--enable-libpmem), QEMU will take necessary operations to guarantee
+the persistence of its own writes to the vNVDIMM backend (e.g., in
+vNVDIMM label emulation and live migration).
+
+References
+----------
+
+[1] SNIA NVM Programming Model: https://www.snia.org/sites/default/files/technical_work/final/NVMProgrammingModel_v1.2.pdf
+[2] PMDK: http://pmem.io/pmdk/
@@ -52,6 +52,9 @@
#include <linux/falloc.h>
#endif
+/* RAM is backed by the persistent memory. */
+#define RAM_PMEM (1 << 3)
+
#endif
#include "qemu/rcu_queue.h"
#include "qemu/main-loop.h"
@@ -2037,6 +2040,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
Error *local_err = NULL;
int64_t file_size;
bool share = flags & QEMU_RAM_SHARE;
+ bool is_pmem = flags & QEMU_RAM_PMEM;
if (xen_enabled()) {
error_setg(errp, "-mem-path not supported with Xen");
@@ -2073,7 +2077,8 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
new_block->mr = mr;
new_block->used_length = size;
new_block->max_length = size;
- new_block->flags = share ? RAM_SHARED : 0;
+ new_block->flags = (share ? RAM_SHARED : 0) |
+ (is_pmem ? RAM_PMEM : 0);
new_block->host = file_ram_alloc(new_block, size, fd, !file_size, errp);
if (!new_block->host) {
g_free(new_block);
@@ -3836,6 +3841,11 @@ err:
return ret;
}
+bool ramblock_is_pmem(RAMBlock *rb)
+{
+ return rb->flags & RAM_PMEM;
+}
+
#endif
void page_size_init(void)
@@ -3934,3 +3944,4 @@ void mtree_print_dispatch(fprintf_function mon, void *f,
}
#endif
+
@@ -509,6 +509,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
#ifdef __linux__
#define QEMU_RAM_SHARE (1UL << 0)
+#define QEMU_RAM_PMEM (1UL << 1)
/**
* memory_region_init_ram_from_file: Initialize RAM memory region with a
@@ -524,6 +525,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
* @flags: specify properties of this memory region, which can be one or bit-or
* of following values:
* - QEMU_RAM_SHARE: memory must be mmaped with the MAP_SHARED flag
+ * - QEMU_RAM_PMEM: the backend @path is persistent memory
* Other bits are ignored.
* @path: the path in which to allocate the RAM.
* @errp: pointer to Error*, to store an error if it happens.
@@ -70,6 +70,8 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
return host_addr_offset >> TARGET_PAGE_BITS;
}
+bool ramblock_is_pmem(RAMBlock *rb);
+
long qemu_getrampagesize(void);
unsigned long last_ram_page(void);
@@ -84,6 +86,7 @@ unsigned long last_ram_page(void);
* @flags: specify the properties of the ram block, which can be one
* or bit-or of following values
* - QEMU_RAM_SHARE: mmap the back file or device with MAP_SHARED
+ * - QEMU_RAM_PMEM: the backend @mem_path or @fd is persistent memory
* Other bits are ignored.
* @mem_path or @fd: specify the back file or device
* @errp: pointer to Error*, to store an error if it happens
@@ -4047,6 +4047,13 @@ requires an alignment different than the default one used by QEMU, eg
the device DAX /dev/dax0.0 requires 2M alignment rather than 4K. In
such cases, users can specify the required alignment via this option.
+The @option{pmem} option specifies whether the backend store specified
+by @option{mem-path} is on the persistent memory that can be accessed
+in the SNIA NVM programming model (e.g. Intel NVDIMM).
+If @address@hidden, QEMU will take necessary operations to
+guarantee the persistence of its own writes to @option{mem-path}
+(e.g. in vNVDIMM label emulation and live migration).
+
@item -object memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},share=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave}
Creates a memory backend object, which can be used to back the guest RAM.