[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 27/34] hostmem: add properties for NUMA memory po
From: |
address@hidden |
Subject: |
[Qemu-devel] [PATCH v3 27/34] hostmem: add properties for NUMA memory policy |
Date: |
Wed, 26 Mar 2014 10:37:01 +0000 |
Signed-off-by: Hu Tao <address@hidden>
[Raise errors on setting properties if !CONFIG_NUMA. Add BUILD_BUG_ON
checks. - Paolo]
Signed-off-by: Paolo Bonzini <address@hidden>
---
backends/hostmem.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++-
include/sysemu/hostmem.h | 4 ++
qapi-schema.json | 20 +++++++++
3 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 738bb31..d3f8476 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -10,11 +10,20 @@
* See the COPYING file in the top-level directory.
*/
#include "sysemu/hostmem.h"
-#include "sysemu/sysemu.h"
#include "qapi/visitor.h"
+#include "qapi-types.h"
+#include "qapi-visit.h"
#include "qapi/qmp/qerror.h"
#include "qom/object_interfaces.h"
+#ifdef CONFIG_NUMA
+#include <numaif.h>
+QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_DEFAULT != MPOL_DEFAULT);
+QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_PREFERRED != MPOL_PREFERRED);
+QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_BIND != MPOL_BIND);
+QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_INTERLEAVE != MPOL_INTERLEAVE);
+#endif
+
static void
host_memory_backend_get_size(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
@@ -49,6 +58,84 @@ host_memory_backend_set_size(Object *obj, Visitor *v, void
*opaque,
backend->size = value;
}
+static void
+get_host_nodes(Object *obj, Visitor *v, void *opaque, const char *name,
+ Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ uint16List *host_nodes = NULL;
+ uint16List **node = &host_nodes;
+ unsigned long value;
+
+ value = find_first_bit(backend->host_nodes, MAX_NODES);
+ if (value == MAX_NODES) {
+ return;
+ }
+
+ *node = g_malloc0(sizeof(**node));
+ (*node)->value = value;
+ node = &(*node)->next;
+
+ do {
+ value = find_next_bit(backend->host_nodes, MAX_NODES, value + 1);
+ if (value == MAX_NODES) {
+ break;
+ }
+
+ *node = g_malloc0(sizeof(**node));
+ (*node)->value = value;
+ node = &(*node)->next;
+ } while (true);
+
+ visit_type_uint16List(v, &host_nodes, name, errp);
+}
+
+static void
+set_host_nodes(Object *obj, Visitor *v, void *opaque, const char *name,
+ Error **errp)
+{
+#ifdef CONFIG_NUMA
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ uint16List *l = NULL;
+
+ visit_type_uint16List(v, &l, name, errp);
+
+ while (l) {
+ bitmap_set(backend->host_nodes, l->value, 1);
+ l = l->next;
+ }
+#else
+ error_setg(errp, "NUMA node binding are not supported by this QEMU");
+#endif
+}
+
+static void
+get_policy(Object *obj, Visitor *v, void *opaque, const char *name,
+ Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ int policy = backend->policy;
+
+ visit_type_enum(v, &policy, HostMemPolicy_lookup, NULL, name, errp);
+}
+
+static void
+set_policy(Object *obj, Visitor *v, void *opaque, const char *name,
+ Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ int policy;
+
+ visit_type_enum(v, &policy, HostMemPolicy_lookup, NULL, name, errp);
+ backend->policy = policy;
+
+#ifndef CONFIG_NUMA
+ if (policy != HOST_MEM_POLICY_DEFAULT) {
+ error_setg(errp, "NUMA policies are not supported by this QEMU");
+ }
+#endif
+}
+
static bool host_memory_backend_get_merge(Object *obj, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
@@ -159,6 +246,12 @@ static void host_memory_backend_initfn(Object *obj)
object_property_add(obj, "size", "int",
host_memory_backend_get_size,
host_memory_backend_set_size, NULL, NULL, NULL);
+ object_property_add(obj, "host-nodes", "int",
+ get_host_nodes,
+ set_host_nodes, NULL, NULL, NULL);
+ object_property_add(obj, "policy", "str",
+ get_policy,
+ set_policy, NULL, NULL, NULL);
}
static void host_memory_backend_finalize(Object *obj)
@@ -203,6 +296,20 @@ host_memory_backend_memory_init(UserCreatable *uc, Error
**errp)
if (backend->prealloc) {
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz);
}
+
+#ifdef CONFIG_NUMA
+ unsigned long maxnode = find_last_bit(backend->host_nodes, MAX_NODES);
+
+ /* This is a workaround for a long standing bug in Linux'
+ * mbind implementation, which cuts off the last specified
+ * node.
+ */
+ if (mbind(ptr, sz, backend->policy, backend->host_nodes, maxnode + 2, 0)) {
+ error_setg_errno(errp, errno,
+ "cannot bind memory to host NUMA nodes");
+ return;
+ }
+#endif
}
MemoryRegion *
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index fdbc41c..9e1a816 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -12,9 +12,11 @@
#ifndef QEMU_HOSTMEM_H
#define QEMU_HOSTMEM_H
+#include "sysemu/sysemu.h" /* for MAX_NODES */
#include "qom/object.h"
#include "qapi/error.h"
#include "exec/memory.h"
+#include "qemu/bitmap.h"
#define TYPE_MEMORY_BACKEND "memory"
#define MEMORY_BACKEND(obj) \
@@ -53,6 +55,8 @@ struct HostMemoryBackend {
uint64_t size;
bool merge, dump;
bool prealloc, force_prealloc;
+ DECLARE_BITMAP(host_nodes, MAX_NODES);
+ HostMemPolicy policy;
MemoryRegion mr;
};
diff --git a/qapi-schema.json b/qapi-schema.json
index a8c16bc..5aea3ed 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4723,3 +4723,23 @@
'*cpus': ['uint16'],
'*mem': 'size',
'*memdev': 'str' }}
+
+##
+# @HostMemPolicy
+#
+# Host memory policy types
+#
+# @default: restore default policy, remove any nondefault policy
+#
+# @preferred: set the preferred host nodes for allocation
+#
+# @bind: a strict policy that restricts memory allocation to the
+# host nodes specified
+#
+# @interleave: memory allocations are interleaved across the set
+# of host nodes specified
+#
+# Since 2.1
+##
+{ 'enum': 'HostMemPolicy',
+ 'data': [ 'default', 'preferred', 'bind', 'interleave' ] }
--
1.8.5.2.229.g4448466
- [Qemu-devel] [PATCH v3 15/34] numa: add -numa node,memdev= option, (continued)
- [Qemu-devel] [PATCH v3 15/34] numa: add -numa node,memdev= option, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 09/34] vl: redo -object parsing, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 05/34] NUMA: expand MAX_NODES from 64 to 128, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 18/34] memory: add error propagation to file-based RAM allocation, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 08/34] vl: convert -m to QemuOpts, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 14/34] add memdev backend infrastructure, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 21/34] hostmem: add file-based HostMemoryBackend, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 22/34] hostmem: separate allocation from UserCreatable complete method, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 26/34] configure: add Linux libnuma detection, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 24/34] hostmem: allow preallocation of any memory region, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 27/34] hostmem: add properties for NUMA memory policy,
address@hidden <=
- [Qemu-devel] [PATCH v3 11/34] qmp: improve error reporting for -object and object-add, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 32/34] qom: introduce object_property_get_enum and object_property_get_uint16List, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 20/34] memory: move RAM_PREALLOC_MASK to exec.c, rename, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 25/34] hostmem: add property to map memory with MAP_SHARED, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 23/34] hostmem: add merge and dump properties, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 34/34] hmp: add info memdev, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 28/34] hw: switch all boards to use memory_region_allocate_system_memory, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 31/34] qapi: make string output visitor parse int list, address@hidden, 2014/03/26
- [Qemu-devel] [PATCH v3 33/34] qmp: add query-memdev, address@hidden, 2014/03/26