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