#include "qemu/osdep.h"
#include "sysemu/hostmem.h"
+#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "qapi/error.h"
#include "qapi/qapi-builtin-visit.h"
#include "qapi/visitor.h"
#include "qemu/config-file.h"
#include "qom/object_interfaces.h"
+#include "qemu/mmap-alloc.h"
#ifdef CONFIG_NUMA
#include <numaif.h>
QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_INTERLEAVE != MPOL_INTERLEAVE);
#endif
+char *
+host_memory_backend_get_name(HostMemoryBackend *backend)
+{
+ if (!backend->use_canonical_path) {
+ return object_get_canonical_path_component(OBJECT(backend));
+ }
+
+ return object_get_canonical_path(OBJECT(backend));
+}
+
static void
host_memory_backend_get_size(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
uint64_t value;
if (host_memory_backend_mr_inited(backend)) {
- error_setg(&local_err, "cannot change property value");
+ error_setg(&local_err, "cannot change property %s of %s ",
+ name, object_get_typename(obj));
goto out;
}
goto out;
}
if (!value) {
- error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
- PRIu64 "'", object_get_typename(obj), name, value);
+ error_setg(&local_err,
+ "property '%s' of %s doesn't take value '%" PRIu64 "'",
+ name, object_get_typename(obj), value);
goto out;
}
backend->size = value;
value = find_first_bit(backend->host_nodes, MAX_NODES);
if (value == MAX_NODES) {
- return;
+ goto ret;
}
*node = g_malloc0(sizeof(**node));
node = &(*node)->next;
} while (true);
+ret:
visit_type_uint16List(v, name, &host_nodes, errp);
}
{
#ifdef CONFIG_NUMA
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
- uint16List *l = NULL;
+ uint16List *l, *host_nodes = NULL;
- visit_type_uint16List(v, name, &l, errp);
+ visit_type_uint16List(v, name, &host_nodes, errp);
+
+ for (l = host_nodes; l; l = l->next) {
+ if (l->value >= MAX_NODES) {
+ error_setg(errp, "Invalid host-nodes value: %d", l->value);
+ goto out;
+ }
+ }
- while (l) {
+ for (l = host_nodes; l; l = l->next) {
bitmap_set(backend->host_nodes, l->value, 1);
- l = l->next;
}
+
+out:
+ qapi_free_uint16List(host_nodes);
#else
error_setg(errp, "NUMA node binding are not supported by this QEMU");
#endif
{
Error *local_err = NULL;
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ MachineState *ms = MACHINE(qdev_get_machine());
if (backend->force_prealloc) {
if (value) {
void *ptr = memory_region_get_ram_ptr(&backend->mr);
uint64_t sz = memory_region_size(&backend->mr);
- os_mem_prealloc(fd, ptr, sz, smp_cpus, &local_err);
+ os_mem_prealloc(fd, ptr, sz, ms->smp.cpus, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
backend->prealloc = mem_prealloc;
}
+static void host_memory_backend_post_init(Object *obj)
+{
+ object_apply_compat_props(obj);
+}
+
bool host_memory_backend_mr_inited(HostMemoryBackend *backend)
{
/*
return memory_region_size(&backend->mr) != 0;
}
-MemoryRegion *
-host_memory_backend_get_memory(HostMemoryBackend *backend, Error **errp)
+MemoryRegion *host_memory_backend_get_memory(HostMemoryBackend *backend)
{
return host_memory_backend_mr_inited(backend) ? &backend->mr : NULL;
}
return backend->is_mapped;
}
+#ifdef __linux__
+size_t host_memory_backend_pagesize(HostMemoryBackend *memdev)
+{
+ Object *obj = OBJECT(memdev);
+ char *path = object_property_get_str(obj, "mem-path", NULL);
+ size_t pagesize = qemu_mempath_getpagesize(path);
+
+ g_free(path);
+ return pagesize;
+}
+#else
+size_t host_memory_backend_pagesize(HostMemoryBackend *memdev)
+{
+ return getpagesize();
+}
+#endif
+
static void
host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(uc);
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
+ MachineState *ms = MACHINE(qdev_get_machine());
Error *local_err = NULL;
void *ptr;
uint64_t sz;
*/
if (backend->prealloc) {
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz,
- smp_cpus, &local_err);
+ ms->smp.cpus, &local_err);
if (local_err) {
goto out;
}
}
}
-static char *get_id(Object *o, Error **errp)
+static bool host_memory_backend_get_share(Object *o, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(o);
- return g_strdup(backend->id);
+ return backend->share;
}
-static void set_id(Object *o, const char *str, Error **errp)
+static void host_memory_backend_set_share(Object *o, bool value, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(o);
- if (backend->id) {
+ if (host_memory_backend_mr_inited(backend)) {
error_setg(errp, "cannot change property value");
return;
}
- backend->id = g_strdup(str);
+ backend->share = value;
}
-static bool host_memory_backend_get_share(Object *o, Error **errp)
+static bool
+host_memory_backend_get_use_canonical_path(Object *obj, Error **errp)
{
- HostMemoryBackend *backend = MEMORY_BACKEND(o);
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
- return backend->share;
+ return backend->use_canonical_path;
}
-static void host_memory_backend_set_share(Object *o, bool value, Error **errp)
+static void
+host_memory_backend_set_use_canonical_path(Object *obj, bool value,
+ Error **errp)
{
- HostMemoryBackend *backend = MEMORY_BACKEND(o);
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
- if (host_memory_backend_mr_inited(backend)) {
- error_setg(errp, "cannot change property value");
- return;
- }
- backend->share = value;
+ backend->use_canonical_path = value;
}
static void
object_class_property_add_bool(oc, "merge",
host_memory_backend_get_merge,
host_memory_backend_set_merge, &error_abort);
+ object_class_property_set_description(oc, "merge",
+ "Mark memory as mergeable", &error_abort);
object_class_property_add_bool(oc, "dump",
host_memory_backend_get_dump,
host_memory_backend_set_dump, &error_abort);
+ object_class_property_set_description(oc, "dump",
+ "Set to 'off' to exclude from core dump", &error_abort);
object_class_property_add_bool(oc, "prealloc",
host_memory_backend_get_prealloc,
host_memory_backend_set_prealloc, &error_abort);
+ object_class_property_set_description(oc, "prealloc",
+ "Preallocate memory", &error_abort);
object_class_property_add(oc, "size", "int",
host_memory_backend_get_size,
host_memory_backend_set_size,
NULL, NULL, &error_abort);
+ object_class_property_set_description(oc, "size",
+ "Size of the memory region (ex: 500M)", &error_abort);
object_class_property_add(oc, "host-nodes", "int",
host_memory_backend_get_host_nodes,
host_memory_backend_set_host_nodes,
NULL, NULL, &error_abort);
+ object_class_property_set_description(oc, "host-nodes",
+ "Binds memory to the list of NUMA host nodes", &error_abort);
object_class_property_add_enum(oc, "policy", "HostMemPolicy",
&HostMemPolicy_lookup,
host_memory_backend_get_policy,
host_memory_backend_set_policy, &error_abort);
- object_class_property_add_str(oc, "id", get_id, set_id, &error_abort);
+ object_class_property_set_description(oc, "policy",
+ "Set the NUMA policy", &error_abort);
object_class_property_add_bool(oc, "share",
host_memory_backend_get_share, host_memory_backend_set_share,
&error_abort);
-}
-
-static void host_memory_backend_finalize(Object *o)
-{
- HostMemoryBackend *backend = MEMORY_BACKEND(o);
- g_free(backend->id);
+ object_class_property_set_description(oc, "share",
+ "Mark the memory as private to QEMU or shared", &error_abort);
+ object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id",
+ host_memory_backend_get_use_canonical_path,
+ host_memory_backend_set_use_canonical_path, &error_abort);
}
static const TypeInfo host_memory_backend_info = {
.class_init = host_memory_backend_class_init,
.instance_size = sizeof(HostMemoryBackend),
.instance_init = host_memory_backend_init,
- .instance_finalize = host_memory_backend_finalize,
+ .instance_post_init = host_memory_backend_post_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }