summaryrefslogtreecommitdiffstats
path: root/qemu/hw/mem
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/mem')
-rw-r--r--qemu/hw/mem/Makefile.objs1
-rw-r--r--qemu/hw/mem/nvdimm.c47
-rw-r--r--qemu/hw/mem/pc-dimm.c61
3 files changed, 74 insertions, 35 deletions
diff --git a/qemu/hw/mem/Makefile.objs b/qemu/hw/mem/Makefile.objs
index b000fb42b..f12f8b97a 100644
--- a/qemu/hw/mem/Makefile.objs
+++ b/qemu/hw/mem/Makefile.objs
@@ -1 +1,2 @@
common-obj-$(CONFIG_MEM_HOTPLUG) += pc-dimm.o
+common-obj-$(CONFIG_NVDIMM) += nvdimm.o
diff --git a/qemu/hw/mem/nvdimm.c b/qemu/hw/mem/nvdimm.c
new file mode 100644
index 000000000..0a602f28b
--- /dev/null
+++ b/qemu/hw/mem/nvdimm.c
@@ -0,0 +1,47 @@
+/*
+ * Non-Volatile Dual In-line Memory Module Virtualization Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * Currently, it only supports PMEM Virtualization.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "qemu/osdep.h"
+#include "hw/mem/nvdimm.h"
+
+static void nvdimm_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ /* nvdimm hotplug has not been supported yet. */
+ dc->hotpluggable = false;
+}
+
+static TypeInfo nvdimm_info = {
+ .name = TYPE_NVDIMM,
+ .parent = TYPE_PC_DIMM,
+ .class_init = nvdimm_class_init,
+};
+
+static void nvdimm_register_types(void)
+{
+ type_register_static(&nvdimm_info);
+}
+
+type_init(nvdimm_register_types)
diff --git a/qemu/hw/mem/pc-dimm.c b/qemu/hw/mem/pc-dimm.c
index bb04862de..9e7de5682 100644
--- a/qemu/hw/mem/pc-dimm.c
+++ b/qemu/hw/mem/pc-dimm.c
@@ -18,13 +18,16 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>
*/
+#include "qemu/osdep.h"
#include "hw/mem/pc-dimm.h"
+#include "qapi/error.h"
#include "qemu/config-file.h"
#include "qapi/visitor.h"
#include "qemu/range.h"
#include "sysemu/numa.h"
#include "sysemu/kvm.h"
#include "trace.h"
+#include "hw/virtio/vhost.h"
typedef struct pc_dimms_capacity {
uint64_t size;
@@ -95,6 +98,12 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
goto out;
}
+ if (!vhost_has_free_slot()) {
+ error_setg(&local_err, "a used vhost backend has no free"
+ " memory slots left");
+ goto out;
+ }
+
memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr);
vmstate_register_ram(mr, dev);
numa_set_mem_node_id(addr, memory_region_size(mr), dimm->node);
@@ -172,7 +181,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
NULL);
di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));
- info->dimm = di;
+ info->u.dimm.data = di;
elem->value = info;
elem->next = NULL;
**prev = elem;
@@ -184,32 +193,6 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
return 0;
}
-ram_addr_t get_current_ram_size(void)
-{
- MemoryDeviceInfoList *info_list = NULL;
- MemoryDeviceInfoList **prev = &info_list;
- MemoryDeviceInfoList *info;
- ram_addr_t size = ram_size;
-
- qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
- for (info = info_list; info; info = info->next) {
- MemoryDeviceInfo *value = info->value;
-
- if (value) {
- switch (value->kind) {
- case MEMORY_DEVICE_INFO_KIND_DIMM:
- size += value->dimm->size;
- break;
- default:
- break;
- }
- }
- }
- qapi_free_MemoryDeviceInfoList(info_list);
-
- return size;
-}
-
static int pc_dimm_slot2bitmap(Object *obj, void *opaque)
{
unsigned long *bitmap = opaque;
@@ -365,8 +348,8 @@ static Property pc_dimm_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
int64_t value;
MemoryRegion *mr;
@@ -375,22 +358,29 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque,
mr = host_memory_backend_get_memory(dimm->hostmem, errp);
value = memory_region_size(mr);
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
Object *val, Error **errp)
{
MemoryRegion *mr;
+ Error *local_err = NULL;
- mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), errp);
+ mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), &local_err);
+ if (local_err) {
+ goto out;
+ }
if (memory_region_is_mapped(mr)) {
char *path = object_get_canonical_path_component(val);
- error_setg(errp, "can't use already busy memdev: %s", path);
+ error_setg(&local_err, "can't use already busy memdev: %s", path);
g_free(path);
} else {
- qdev_prop_allow_set_link_before_realize(obj, name, val, errp);
+ qdev_prop_allow_set_link_before_realize(obj, name, val, &local_err);
}
+
+out:
+ error_propagate(errp, local_err);
}
static void pc_dimm_init(Object *obj)
@@ -414,10 +404,11 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
return;
}
- if ((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) {
+ if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
+ (!nb_numa_nodes && dimm->node)) {
error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
PRIu32 "' which exceeds the number of numa nodes: %d",
- dimm->node, nb_numa_nodes);
+ dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
return;
}
}