summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorHaozhong Zhang <haozhong.zhang@intel.com>2017-12-11 15:28:06 +0800
committerEduardo Habkost <ehabkost@redhat.com>2018-01-19 11:18:51 -0200
commitcb836434cda103fac3c06174e70bf5c9b7083b8e (patch)
treedbdfa8f28c5c8bd9d9811e5395fd4c65a8764b04 /hw
parentda6789c27c2ea71765cfab04bad9a42b5426f0bd (diff)
downloadqemu-cb836434cda103fac3c06174e70bf5c9b7083b8e.tar.gz
nvdimm: add 'unarmed' option
Currently the only vNVDIMM backend can guarantee the guest write persistence is device DAX on Linux, because no host-side kernel cache is involved in the guest access to it. The approach to detect whether the backend is device DAX needs to access sysfs, which may not work with SELinux. Instead, we add the 'unarmed' option to device 'nvdimm', so that users or management utils, which have enough knowledge about the backend, can control the unarmed flag in guest ACPI NFIT via this option. The guest Linux NVDIMM driver, for example, will mark the corresponding vNVDIMM device read-only if the unarmed flag in guest NFIT is set. The default value of 'unarmed' option is 'off' in order to keep the backwards compatibility. Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com> Message-Id: <20171211072806.2812-4-haozhong.zhang@intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/nvdimm.c7
-rw-r--r--hw/mem/nvdimm.c26
2 files changed, 33 insertions, 0 deletions
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 6ceea196e7..59d6e4254c 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -138,6 +138,8 @@ struct NvdimmNfitMemDev {
} QEMU_PACKED;
typedef struct NvdimmNfitMemDev NvdimmNfitMemDev;
+#define ACPI_NFIT_MEM_NOT_ARMED (1 << 3)
+
/*
* NVDIMM Control Region Structure
*
@@ -284,6 +286,7 @@ static void
nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
{
NvdimmNfitMemDev *nfit_memdev;
+ NVDIMMDevice *nvdimm = NVDIMM(OBJECT(dev));
uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP,
NULL);
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
@@ -312,6 +315,10 @@ nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
/* Only one interleave for PMEM. */
nfit_memdev->interleave_ways = cpu_to_le16(1);
+
+ if (nvdimm->unarmed) {
+ nfit_memdev->flags |= cpu_to_le16(ACPI_NFIT_MEM_NOT_ARMED);
+ }
}
/*
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 618c3d677b..61e677f92f 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
+#include "qapi-visit.h"
#include "hw/mem/nvdimm.h"
static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name,
@@ -64,11 +65,36 @@ out:
error_propagate(errp, local_err);
}
+static bool nvdimm_get_unarmed(Object *obj, Error **errp)
+{
+ NVDIMMDevice *nvdimm = NVDIMM(obj);
+
+ return nvdimm->unarmed;
+}
+
+static void nvdimm_set_unarmed(Object *obj, bool value, Error **errp)
+{
+ NVDIMMDevice *nvdimm = NVDIMM(obj);
+ Error *local_err = NULL;
+
+ if (memory_region_size(&nvdimm->nvdimm_mr)) {
+ error_setg(&local_err, "cannot change property value");
+ goto out;
+ }
+
+ nvdimm->unarmed = value;
+
+ out:
+ error_propagate(errp, local_err);
+}
+
static void nvdimm_init(Object *obj)
{
object_property_add(obj, NVDIMM_LABLE_SIZE_PROP, "int",
nvdimm_get_label_size, nvdimm_set_label_size, NULL,
NULL, NULL);
+ object_property_add_bool(obj, NVDIMM_UNARMED_PROP,
+ nvdimm_get_unarmed, nvdimm_set_unarmed, NULL);
}
static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm, Error **errp)