|
|
357786 |
From 0b7c71b8b4afcbc92a9ef549d485c54da92204b3 Mon Sep 17 00:00:00 2001
|
|
|
357786 |
From: "plai@redhat.com" <plai@redhat.com>
|
|
|
357786 |
Date: Fri, 31 Aug 2018 16:25:56 +0200
|
|
|
357786 |
Subject: [PATCH 14/29] hostmem-file: add the 'pmem' option
|
|
|
357786 |
|
|
|
357786 |
RH-Author: plai@redhat.com
|
|
|
357786 |
Message-id: <1535732759-22481-7-git-send-email-plai@redhat.com>
|
|
|
357786 |
Patchwork-id: 82007
|
|
|
357786 |
O-Subject: [RHEL7.6 PATCH BZ 1539280 6/9] hostmem-file: add the 'pmem' option
|
|
|
357786 |
Bugzilla: 1539280
|
|
|
357786 |
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
357786 |
RH-Acked-by: Pankaj Gupta <pagupta@redhat.com>
|
|
|
357786 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
357786 |
|
|
|
357786 |
From: Junyan He <junyan.he@intel.com>
|
|
|
357786 |
|
|
|
357786 |
When QEMU emulates vNVDIMM labels and migrates vNVDIMM devices, it
|
|
|
357786 |
needs to know whether the backend storage is a real persistent memory,
|
|
|
357786 |
in order to decide whether special operations should be performed to
|
|
|
357786 |
ensure the data persistence.
|
|
|
357786 |
|
|
|
357786 |
This boolean option 'pmem' allows users to specify whether the backend
|
|
|
357786 |
storage of memory-backend-file is a real persistent memory. If
|
|
|
357786 |
'pmem=on', QEMU will set the flag RAM_PMEM in the RAM block of the
|
|
|
357786 |
corresponding memory region. If 'pmem' is set while lack of libpmem
|
|
|
357786 |
support, a error is generated.
|
|
|
357786 |
|
|
|
357786 |
Signed-off-by: Junyan He <junyan.he@intel.com>
|
|
|
357786 |
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
|
|
|
357786 |
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
357786 |
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
|
|
357786 |
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
|
|
357786 |
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
357786 |
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
357786 |
(cherry picked from commit a4de8552b2580adf6fa4874439217b65d3bdd88b)
|
|
|
357786 |
Signed-off-by: Paul Lai <plai@redhat.com>
|
|
|
357786 |
|
|
|
357786 |
Resolved Conflicts:
|
|
|
357786 |
docs/nvdimm.txt
|
|
|
357786 |
|
|
|
357786 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
357786 |
---
|
|
|
357786 |
backends/hostmem-file.c | 43 +++++++++++++++++++++++++++++++++++++++++--
|
|
|
357786 |
docs/nvdimm.txt | 42 ++++++++++++++++++++++++++++++++++++++++++
|
|
|
357786 |
exec.c | 8 ++++++++
|
|
|
357786 |
include/exec/memory.h | 4 ++++
|
|
|
357786 |
include/exec/ram_addr.h | 3 +++
|
|
|
357786 |
qemu-options.hx | 7 +++++++
|
|
|
357786 |
6 files changed, 105 insertions(+), 2 deletions(-)
|
|
|
357786 |
|
|
|
357786 |
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
|
|
|
357786 |
index 34c68bb..2476dcb 100644
|
|
|
357786 |
--- a/backends/hostmem-file.c
|
|
|
357786 |
+++ b/backends/hostmem-file.c
|
|
|
357786 |
@@ -12,6 +12,7 @@
|
|
|
357786 |
#include "qemu/osdep.h"
|
|
|
357786 |
#include "qapi/error.h"
|
|
|
357786 |
#include "qemu-common.h"
|
|
|
357786 |
+#include "qemu/error-report.h"
|
|
|
357786 |
#include "sysemu/hostmem.h"
|
|
|
357786 |
#include "sysemu/sysemu.h"
|
|
|
357786 |
#include "qom/object_interfaces.h"
|
|
|
357786 |
@@ -31,9 +32,10 @@ typedef struct HostMemoryBackendFile HostMemoryBackendFile;
|
|
|
357786 |
struct HostMemoryBackendFile {
|
|
|
357786 |
HostMemoryBackend parent_obj;
|
|
|
357786 |
|
|
|
357786 |
- bool discard_data;
|
|
|
357786 |
char *mem_path;
|
|
|
357786 |
uint64_t align;
|
|
|
357786 |
+ bool discard_data;
|
|
|
357786 |
+ bool is_pmem;
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
static void
|
|
|
357786 |
@@ -59,7 +61,8 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
|
|
357786 |
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
|
|
|
357786 |
path,
|
|
|
357786 |
backend->size, fb->align,
|
|
|
357786 |
- backend->share ? RAM_SHARED : 0,
|
|
|
357786 |
+ (backend->share ? RAM_SHARED : 0) |
|
|
|
357786 |
+ (fb->is_pmem ? RAM_PMEM : 0),
|
|
|
357786 |
fb->mem_path, errp);
|
|
|
357786 |
g_free(path);
|
|
|
357786 |
}
|
|
|
357786 |
@@ -131,6 +134,39 @@ static void file_memory_backend_set_align(Object *o, Visitor *v,
|
|
|
357786 |
error_propagate(errp, local_err);
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
+static bool file_memory_backend_get_pmem(Object *o, Error **errp)
|
|
|
357786 |
+{
|
|
|
357786 |
+ return MEMORY_BACKEND_FILE(o)->is_pmem;
|
|
|
357786 |
+}
|
|
|
357786 |
+
|
|
|
357786 |
+static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp)
|
|
|
357786 |
+{
|
|
|
357786 |
+ HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
|
|
357786 |
+ HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
|
|
|
357786 |
+
|
|
|
357786 |
+ if (host_memory_backend_mr_inited(backend)) {
|
|
|
357786 |
+ error_setg(errp, "cannot change property 'pmem' of %s '%s'",
|
|
|
357786 |
+ object_get_typename(o),
|
|
|
357786 |
+ object_get_canonical_path_component(o));
|
|
|
357786 |
+ return;
|
|
|
357786 |
+ }
|
|
|
357786 |
+
|
|
|
357786 |
+#ifndef CONFIG_LIBPMEM
|
|
|
357786 |
+ if (value) {
|
|
|
357786 |
+ Error *local_err = NULL;
|
|
|
357786 |
+ error_setg(&local_err,
|
|
|
357786 |
+ "Lack of libpmem support while setting the 'pmem=on'"
|
|
|
357786 |
+ " of %s '%s'. We can't ensure data persistence.",
|
|
|
357786 |
+ object_get_typename(o),
|
|
|
357786 |
+ object_get_canonical_path_component(o));
|
|
|
357786 |
+ error_propagate(errp, local_err);
|
|
|
357786 |
+ return;
|
|
|
357786 |
+ }
|
|
|
357786 |
+#endif
|
|
|
357786 |
+
|
|
|
357786 |
+ fb->is_pmem = value;
|
|
|
357786 |
+}
|
|
|
357786 |
+
|
|
|
357786 |
static void file_backend_unparent(Object *obj)
|
|
|
357786 |
{
|
|
|
357786 |
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
|
|
357786 |
@@ -162,6 +198,9 @@ file_backend_class_init(ObjectClass *oc, void *data)
|
|
|
357786 |
file_memory_backend_get_align,
|
|
|
357786 |
file_memory_backend_set_align,
|
|
|
357786 |
NULL, NULL, &error_abort);
|
|
|
357786 |
+ object_class_property_add_bool(oc, "pmem",
|
|
|
357786 |
+ file_memory_backend_get_pmem, file_memory_backend_set_pmem,
|
|
|
357786 |
+ &error_abort);
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
static void file_backend_instance_finalize(Object *o)
|
|
|
357786 |
diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
|
|
|
357786 |
index e903d8b..5f158a6 100644
|
|
|
357786 |
--- a/docs/nvdimm.txt
|
|
|
357786 |
+++ b/docs/nvdimm.txt
|
|
|
357786 |
@@ -153,3 +153,45 @@ guest NVDIMM region mapping structure. This unarmed flag indicates
|
|
|
357786 |
guest software that this vNVDIMM device contains a region that cannot
|
|
|
357786 |
accept persistent writes. In result, for example, the guest Linux
|
|
|
357786 |
NVDIMM driver, marks such vNVDIMM device as read-only.
|
|
|
357786 |
+
|
|
|
357786 |
+NVDIMM Persistence
|
|
|
357786 |
+------------------
|
|
|
357786 |
+
|
|
|
357786 |
+ACPI 6.2 Errata A added support for a new Platform Capabilities Structure
|
|
|
357786 |
+which allows the platform to communicate what features it supports related to
|
|
|
357786 |
+NVDIMM data persistence. Users can provide a persistence value to a guest via
|
|
|
357786 |
+the optional "nvdimm-persistence" machine command line option:
|
|
|
357786 |
+
|
|
|
357786 |
+ -machine pc,accel=kvm,nvdimm,nvdimm-persistence=cpu
|
|
|
357786 |
+
|
|
|
357786 |
+There are currently two valid values for this option:
|
|
|
357786 |
+
|
|
|
357786 |
+"mem-ctrl" - The platform supports flushing dirty data from the memory
|
|
|
357786 |
+ controller to the NVDIMMs in the event of power loss.
|
|
|
357786 |
+
|
|
|
357786 |
+"cpu" - The platform supports flushing dirty data from the CPU cache to
|
|
|
357786 |
+ the NVDIMMs in the event of power loss. This implies that the
|
|
|
357786 |
+ platform also supports flushing dirty data through the memory
|
|
|
357786 |
+ controller on power loss.
|
|
|
357786 |
+
|
|
|
357786 |
+If the vNVDIMM backend is in host persistent memory that can be accessed in
|
|
|
357786 |
+SNIA NVM Programming Model [1] (e.g., Intel NVDIMM), it's suggested to set
|
|
|
357786 |
+the 'pmem' option of memory-backend-file to 'on'. When 'pmem' is 'on' and QEMU
|
|
|
357786 |
+is built with libpmem [2] support (configured with --enable-libpmem), QEMU
|
|
|
357786 |
+will take necessary operations to guarantee the persistence of its own writes
|
|
|
357786 |
+to the vNVDIMM backend(e.g., in vNVDIMM label emulation and live migration).
|
|
|
357786 |
+If 'pmem' is 'on' while there is no libpmem support, qemu will exit and report
|
|
|
357786 |
+a "lack of libpmem support" message to ensure the persistence is available.
|
|
|
357786 |
+For example, if we want to ensure the persistence for some backend file,
|
|
|
357786 |
+use the QEMU command line:
|
|
|
357786 |
+
|
|
|
357786 |
+ -object memory-backend-file,id=nv_mem,mem-path=/XXX/yyy,size=4G,pmem=on
|
|
|
357786 |
+
|
|
|
357786 |
+References
|
|
|
357786 |
+----------
|
|
|
357786 |
+
|
|
|
357786 |
+[1] NVM Programming Model (NPM)
|
|
|
357786 |
+ Version 1.2
|
|
|
357786 |
+ https://www.snia.org/sites/default/files/technical_work/final/NVMProgrammingModel_v1.2.pdf
|
|
|
357786 |
+[2] Persistent Memory Development Kit (PMDK), formerly known as NVML project, home page:
|
|
|
357786 |
+ http://pmem.io/pmdk/
|
|
|
357786 |
diff --git a/exec.c b/exec.c
|
|
|
357786 |
index 295142b..c670185 100644
|
|
|
357786 |
--- a/exec.c
|
|
|
357786 |
+++ b/exec.c
|
|
|
357786 |
@@ -2045,6 +2045,9 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
|
|
357786 |
Error *local_err = NULL;
|
|
|
357786 |
int64_t file_size;
|
|
|
357786 |
|
|
|
357786 |
+ /* Just support these ram flags by now. */
|
|
|
357786 |
+ assert((ram_flags & ~(RAM_SHARED | RAM_PMEM)) == 0);
|
|
|
357786 |
+
|
|
|
357786 |
if (xen_enabled()) {
|
|
|
357786 |
error_setg(errp, "-mem-path not supported with Xen");
|
|
|
357786 |
return NULL;
|
|
|
357786 |
@@ -3863,6 +3866,11 @@ err:
|
|
|
357786 |
return ret;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
+bool ramblock_is_pmem(RAMBlock *rb)
|
|
|
357786 |
+{
|
|
|
357786 |
+ return rb->flags & RAM_PMEM;
|
|
|
357786 |
+}
|
|
|
357786 |
+
|
|
|
357786 |
#endif
|
|
|
357786 |
|
|
|
357786 |
void page_size_init(void)
|
|
|
357786 |
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
|
|
357786 |
index b3abe61..fd2c574 100644
|
|
|
357786 |
--- a/include/exec/memory.h
|
|
|
357786 |
+++ b/include/exec/memory.h
|
|
|
357786 |
@@ -122,6 +122,9 @@ typedef struct IOMMUNotifier IOMMUNotifier;
|
|
|
357786 |
/* RAM can be migrated */
|
|
|
357786 |
#define RAM_MIGRATABLE (1 << 4)
|
|
|
357786 |
|
|
|
357786 |
+/* RAM is a persistent kind memory */
|
|
|
357786 |
+#define RAM_PMEM (1 << 5)
|
|
|
357786 |
+
|
|
|
357786 |
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
|
|
|
357786 |
IOMMUNotifierFlag flags,
|
|
|
357786 |
hwaddr start, hwaddr end)
|
|
|
357786 |
@@ -541,6 +544,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
|
|
|
357786 |
* (getpagesize()) will be used.
|
|
|
357786 |
* @ram_flags: Memory region features:
|
|
|
357786 |
* - RAM_SHARED: memory must be mmaped with the MAP_SHARED flag
|
|
|
357786 |
+ * - RAM_PMEM: the memory is persistent memory
|
|
|
357786 |
* Other bits are ignored now.
|
|
|
357786 |
* @path: the path in which to allocate the RAM.
|
|
|
357786 |
* @errp: pointer to Error*, to store an error if it happens.
|
|
|
357786 |
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
|
|
|
357786 |
index 67e163e..922305d 100644
|
|
|
357786 |
--- a/include/exec/ram_addr.h
|
|
|
357786 |
+++ b/include/exec/ram_addr.h
|
|
|
357786 |
@@ -70,6 +70,8 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
|
|
|
357786 |
return host_addr_offset >> TARGET_PAGE_BITS;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
+bool ramblock_is_pmem(RAMBlock *rb);
|
|
|
357786 |
+
|
|
|
357786 |
long qemu_getrampagesize(void);
|
|
|
357786 |
unsigned long last_ram_page(void);
|
|
|
357786 |
|
|
|
357786 |
@@ -84,6 +86,7 @@ unsigned long last_ram_page(void);
|
|
|
357786 |
* @ram_flags: specify the properties of the ram block, which can be one
|
|
|
357786 |
* or bit-or of following values
|
|
|
357786 |
* - RAM_SHARED: mmap the backing file or device with MAP_SHARED
|
|
|
357786 |
+ * - RAM_PMEM: the backend @mem_path or @fd is persistent memory
|
|
|
357786 |
* Other bits are ignored.
|
|
|
357786 |
* @mem_path or @fd: specify the backing file or device
|
|
|
357786 |
* @errp: pointer to Error*, to store an error if it happens
|
|
|
357786 |
diff --git a/qemu-options.hx b/qemu-options.hx
|
|
|
357786 |
index 4271cd3..5c58760 100644
|
|
|
357786 |
--- a/qemu-options.hx
|
|
|
357786 |
+++ b/qemu-options.hx
|
|
|
357786 |
@@ -4045,6 +4045,13 @@ requires an alignment different than the default one used by QEMU, eg
|
|
|
357786 |
the device DAX /dev/dax0.0 requires 2M alignment rather than 4K. In
|
|
|
357786 |
such cases, users can specify the required alignment via this option.
|
|
|
357786 |
|
|
|
357786 |
+The @option{pmem} option specifies whether the backing file specified
|
|
|
357786 |
+by @option{mem-path} is in host persistent memory that can be accessed
|
|
|
357786 |
+using the SNIA NVM programming model (e.g. Intel NVDIMM).
|
|
|
357786 |
+If @option{pmem} is set to 'on', QEMU will take necessary operations to
|
|
|
357786 |
+guarantee the persistence of its own writes to @option{mem-path}
|
|
|
357786 |
+(e.g. in vNVDIMM label emulation and live migration).
|
|
|
357786 |
+
|
|
|
357786 |
@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}
|
|
|
357786 |
|
|
|
357786 |
Creates a memory backend object, which can be used to back the guest RAM.
|
|
|
357786 |
--
|
|
|
357786 |
1.8.3.1
|
|
|
357786 |
|