aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr_nvdimm.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc/spapr_nvdimm.c')
-rw-r--r--hw/ppc/spapr_nvdimm.c68
1 files changed, 43 insertions, 25 deletions
diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c
index 81410aa63f..63872054f3 100644
--- a/hw/ppc/spapr_nvdimm.c
+++ b/hw/ppc/spapr_nvdimm.c
@@ -27,16 +27,41 @@
#include "hw/ppc/spapr_nvdimm.h"
#include "hw/mem/nvdimm.h"
#include "qemu/nvdimm-utils.h"
+#include "qemu/option.h"
#include "hw/ppc/fdt.h"
#include "qemu/range.h"
+#include "sysemu/sysemu.h"
+#include "hw/ppc/spapr_numa.h"
-void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size,
- Error **errp)
+void spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
+ uint64_t size, Error **errp)
{
- char *uuidstr = NULL;
+ const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
+ const MachineState *ms = MACHINE(hotplug_dev);
+ const char *nvdimm_opt = qemu_opt_get(qemu_get_machine_opts(), "nvdimm");
+ g_autofree char *uuidstr = NULL;
QemuUUID uuid;
int ret;
+ if (!mc->nvdimm_supported) {
+ error_setg(errp, "NVDIMM hotplug not supported for this machine");
+ return;
+ }
+
+ /*
+ * NVDIMM support went live in 5.1 without considering that, in
+ * other archs, the user needs to enable NVDIMM support with the
+ * 'nvdimm' machine option and the default behavior is NVDIMM
+ * support disabled. It is too late to roll back to the standard
+ * behavior without breaking 5.1 guests. What we can do is to
+ * ensure that, if the user sets nvdimm=off, we error out
+ * regardless of being 5.1 or newer.
+ */
+ if (!ms->nvdimms_state->is_enabled && nvdimm_opt) {
+ error_setg(errp, "nvdimm device found but 'nvdimm=off' was set");
+ return;
+ }
+
if (object_property_get_int(OBJECT(nvdimm), NVDIMM_LABEL_SIZE_PROP,
&error_abort) == 0) {
error_setg(errp, "PAPR requires NVDIMM devices to have label-size set");
@@ -54,7 +79,6 @@ void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size,
&error_abort);
ret = qemu_uuid_parse(uuidstr, &uuid);
g_assert(!ret);
- g_free(uuidstr);
if (qemu_uuid_is_null(&uuid)) {
error_setg(errp, "NVDIMM device requires the uuid to be set");
@@ -83,16 +107,6 @@ void spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp)
}
}
-int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
- void *fdt, int *fdt_start_offset, Error **errp)
-{
- NVDIMMDevice *nvdimm = NVDIMM(drc->dev);
-
- *fdt_start_offset = spapr_dt_nvdimm(fdt, 0, nvdimm);
-
- return 0;
-}
-
void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr)
{
MachineState *machine = MACHINE(spapr);
@@ -104,8 +118,8 @@ void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr)
}
-int spapr_dt_nvdimm(void *fdt, int parent_offset,
- NVDIMMDevice *nvdimm)
+static int spapr_dt_nvdimm(SpaprMachineState *spapr, void *fdt,
+ int parent_offset, NVDIMMDevice *nvdimm)
{
int child_offset;
char *buf;
@@ -115,11 +129,6 @@ int spapr_dt_nvdimm(void *fdt, int parent_offset,
&error_abort);
uint64_t slot = object_property_get_uint(OBJECT(nvdimm), PC_DIMM_SLOT_PROP,
&error_abort);
- uint32_t associativity[] = {
- cpu_to_be32(0x4), /* length */
- cpu_to_be32(0x0), cpu_to_be32(0x0),
- cpu_to_be32(0x0), cpu_to_be32(node)
- };
uint64_t lsize = nvdimm->label_size;
uint64_t size = object_property_get_int(OBJECT(nvdimm), PC_DIMM_SIZE_PROP,
NULL);
@@ -139,8 +148,7 @@ int spapr_dt_nvdimm(void *fdt, int parent_offset,
_FDT((fdt_setprop_string(fdt, child_offset, "compatible", "ibm,pmemory")));
_FDT((fdt_setprop_string(fdt, child_offset, "device_type", "ibm,pmemory")));
- _FDT((fdt_setprop(fdt, child_offset, "ibm,associativity", associativity,
- sizeof(associativity))));
+ spapr_numa_write_associativity_dt(spapr, fdt, child_offset, node);
buf = qemu_uuid_unparse_strdup(&nvdimm->uuid);
_FDT((fdt_setprop_string(fdt, child_offset, "ibm,unit-guid", buf)));
@@ -161,7 +169,17 @@ int spapr_dt_nvdimm(void *fdt, int parent_offset,
return child_offset;
}
-void spapr_dt_persistent_memory(void *fdt)
+int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ NVDIMMDevice *nvdimm = NVDIMM(drc->dev);
+
+ *fdt_start_offset = spapr_dt_nvdimm(spapr, fdt, 0, nvdimm);
+
+ return 0;
+}
+
+void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt)
{
int offset = fdt_subnode_offset(fdt, 0, "persistent-memory");
GSList *iter, *nvdimms = nvdimm_get_device_list();
@@ -179,7 +197,7 @@ void spapr_dt_persistent_memory(void *fdt)
for (iter = nvdimms; iter; iter = iter->next) {
NVDIMMDevice *nvdimm = iter->data;
- spapr_dt_nvdimm(fdt, offset, nvdimm);
+ spapr_dt_nvdimm(spapr, fdt, offset, nvdimm);
}
g_slist_free(nvdimms);