qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/3] nvdimm: platform capabilities command line opti


From: Ross Zwisler
Subject: [Qemu-devel] [PATCH 3/3] nvdimm: platform capabilities command line option
Date: Fri, 27 Apr 2018 15:53:14 -0600

Add a device command line option to allow the user to control the Platform
Capabilities Structure in the virtualized NFIT.

Signed-off-by: Ross Zwisler <address@hidden>
---
 docs/nvdimm.txt         | 22 ++++++++++++++++++++++
 hw/acpi/nvdimm.c        | 29 +++++++++++++++++++++++++----
 hw/mem/nvdimm.c         | 28 ++++++++++++++++++++++++++++
 include/hw/mem/nvdimm.h |  6 ++++++
 4 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
index e903d8bb09..13a2c15b70 100644
--- a/docs/nvdimm.txt
+++ b/docs/nvdimm.txt
@@ -153,3 +153,25 @@ 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.
+
+Platform Capabilities
+---------------------
+
+ACPI 6.2 Errata A added support for a new Platform Capabilities Structure
+which allows the platform to communicate what features it supports related to
+NVDIMM data durability.  Users can provide a capabilities value to a guest via
+the optional "cap" device command line option:
+
+ -device nvdimm,id=nvdimm1,memdev=mem1,cap=3
+
+As of ACPI 6.2 Errata A, the following values are valid for the bottom two
+bits:
+
+2 - Memory Controller Flush to NVDIMM Durability on Power Loss Capable.
+3 - CPU Cache Flush to NVDIMM Durability on Power Loss Capable.
+
+For a complete list of the flags available please consult the ACPI spec.
+
+These platform capabilities apply to the entire virtual platform, so it is
+recommended that only one "cap" device command option be given per virtual
+machine.  This value will apply to all NVDIMMs in the virtual platform.
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 859b390e07..375237c96c 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -370,7 +370,7 @@ static void nvdimm_build_structure_dcr(GArray *structures, 
DeviceState *dev)
  * ACPI 6.2 Errata A: 5.2.25.9 NVDIMM Platform Capabilities Structure
  */
 static void
-nvdimm_build_structure_caps(GArray *structures)
+nvdimm_build_structure_caps(GArray *structures, uint32_t capabilities)
 {
     NvdimmNfitPlatformCaps *nfit_caps;
 
@@ -378,13 +378,31 @@ nvdimm_build_structure_caps(GArray *structures)
 
     nfit_caps->type = cpu_to_le16(7 /* NVDIMM Platform Capabilities */);
     nfit_caps->length = cpu_to_le16(sizeof(*nfit_caps));
-    nfit_caps->highest_cap = 1;
-    nfit_caps->capabilities = cpu_to_le32(2 /* memory controller */);
+    nfit_caps->highest_cap = 2;
+    nfit_caps->capabilities = cpu_to_le32(capabilities);
 }
+
+static uint32_t nvdimm_get_capabilities(DeviceState *dev)
+{
+    static uint32_t capabilities = 0;
+    uint32_t this_cap = object_property_get_uint(OBJECT(dev),
+                                            NVDIMM_CAPABILITIES_PROP, NULL);
+
+    if (this_cap && !capabilities)
+        capabilities = this_cap;
+
+    if (this_cap && this_cap != capabilities)
+        nvdimm_debug("WARNING: multiple capabilities (%d and %d) defined\n",
+                this_cap, capabilities);
+
+    return capabilities;
+}
+
 static GArray *nvdimm_build_device_structure(void)
 {
     GSList *device_list = nvdimm_get_device_list();
     GArray *structures = g_array_new(false, true /* clear */, 1);
+    uint32_t capabilities = 0;
 
     for (; device_list; device_list = device_list->next) {
         DeviceState *dev = device_list->data;
@@ -400,10 +418,13 @@ static GArray *nvdimm_build_device_structure(void)
 
         /* build NVDIMM Control Region Structure. */
         nvdimm_build_structure_dcr(structures, dev);
+
+        capabilities = nvdimm_get_capabilities(dev);
     }
     g_slist_free(device_list);
 
-    nvdimm_build_structure_caps(structures);
+    if (capabilities)
+        nvdimm_build_structure_caps(structures, capabilities);
 
     return structures;
 }
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 4087aca25e..923364e190 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -87,6 +87,31 @@ static void nvdimm_set_unarmed(Object *obj, bool value, 
Error **errp)
     error_propagate(errp, local_err);
 }
 
+static void nvdimm_get_capabilities(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(obj);
+    uint32_t value = nvdimm->capabilities;
+
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void nvdimm_set_capabilities(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    NVDIMMDevice *nvdimm = NVDIMM(obj);
+    Error *local_err = NULL;
+    uint32_t value;
+
+    visit_type_uint32(v, name, &value, &local_err);
+    if (local_err)
+        goto out;
+
+    nvdimm->capabilities = value;
+out:
+    error_propagate(errp, local_err);
+}
+
 static void nvdimm_init(Object *obj)
 {
     object_property_add(obj, NVDIMM_LABEL_SIZE_PROP, "int",
@@ -94,6 +119,9 @@ static void nvdimm_init(Object *obj)
                         NULL, NULL);
     object_property_add_bool(obj, NVDIMM_UNARMED_PROP,
                              nvdimm_get_unarmed, nvdimm_set_unarmed, NULL);
+    object_property_add(obj, NVDIMM_CAPABILITIES_PROP, "uint32",
+                        nvdimm_get_capabilities, nvdimm_set_capabilities,
+                        NULL, NULL, NULL);
 }
 
 static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm, Error **errp)
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 74c60332e1..68af64ff46 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -50,6 +50,7 @@
 
 #define NVDIMM_LABEL_SIZE_PROP "label-size"
 #define NVDIMM_UNARMED_PROP    "unarmed"
+#define NVDIMM_CAPABILITIES_PROP "cap"
 
 struct NVDIMMDevice {
     /* private */
@@ -83,6 +84,11 @@ struct NVDIMMDevice {
      * the guest write persistence.
      */
     bool unarmed;
+
+    /*
+     * Platform capabilities, section 5.2.25.9 of ACPI 6.2 Errata A
+     */
+    uint32_t capabilities;
 };
 typedef struct NVDIMMDevice NVDIMMDevice;
 
-- 
2.14.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]