* [Qemu-devel] [PATCH v19 01/11] object_add: allow completion handler to get canonical path
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 02/11] add memdev backend infrastructure Hu Tao
` (9 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
From: Igor Mammedov <imammedo@redhat.com>
Add object to /objects before calling user_creatable_complete()
handler, so that object might be able to call
object_get_canonical_path() in its completion handler.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
qmp.c | 8 +++++---
vl.c | 9 +++++----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/qmp.c b/qmp.c
index d0d98e7..2ff943d 100644
--- a/qmp.c
+++ b/qmp.c
@@ -561,13 +561,15 @@ void object_add(const char *type, const char *id, const QDict *qdict,
goto out;
}
+ object_property_add_child(container_get(object_get_root(), "/objects"),
+ id, obj, &local_err);
+
user_creatable_complete(obj, &local_err);
if (local_err) {
+ object_property_del(container_get(object_get_root(), "/objects"),
+ id, &error_abort);
goto out;
}
-
- object_property_add_child(container_get(object_get_root(), "/objects"),
- id, obj, &local_err);
out:
if (local_err) {
error_propagate(errp, local_err);
diff --git a/vl.c b/vl.c
index 899b63f..7d9ac8a 100644
--- a/vl.c
+++ b/vl.c
@@ -2673,14 +2673,15 @@ static int object_create(QemuOpts *opts, void *opaque)
goto out;
}
+ object_property_add_child(container_get(object_get_root(), "/objects"),
+ id, obj, &local_err);
+
user_creatable_complete(obj, &local_err);
if (local_err) {
+ object_property_del(container_get(object_get_root(), "/objects"),
+ id, &error_abort);
goto out;
}
-
- object_property_add_child(container_get(object_get_root(), "/objects"),
- id, obj, &local_err);
-
out:
object_unref(obj);
if (local_err) {
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 02/11] add memdev backend infrastructure
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 01/11] object_add: allow completion handler to get canonical path Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 03/11] pc: pass QEMUMachineInitArgs to pc_memory_init Hu Tao
` (8 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
From: Igor Mammedov <imammedo@redhat.com>
Provides framework for splitting host RAM allocation/
policies into a separate backend that could be used
by devices.
Initially only legacy RAM backend is provided, which
uses memory_region_init_ram() allocator and compatible
with every CLI option that affects memory_region_init_ram().
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
[override UserCreatableClass::complete in HostMemoryBackendRamClass]
---
backends/Makefile.objs | 2 +
backends/hostmem-ram.c | 77 +++++++++++++++++++++++++++++++++
backends/hostmem.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++
include/sysemu/hostmem.h | 60 ++++++++++++++++++++++++++
4 files changed, 249 insertions(+)
create mode 100644 backends/hostmem-ram.c
create mode 100644 backends/hostmem.c
create mode 100644 include/sysemu/hostmem.h
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 42557d5..e6bdc11 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -6,3 +6,5 @@ common-obj-$(CONFIG_BRLAPI) += baum.o
$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
common-obj-$(CONFIG_TPM) += tpm.o
+
+common-obj-y += hostmem.o hostmem-ram.o
diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
new file mode 100644
index 0000000..a4dc734
--- /dev/null
+++ b/backends/hostmem-ram.c
@@ -0,0 +1,77 @@
+/*
+ * QEMU Host Memory Backend
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "sysemu/hostmem.h"
+#include "qom/object_interfaces.h"
+
+#define TYPE_MEMORY_BACKEND_RAM "memory-ram"
+#define MEMORY_BACKEND_RAM(obj) \
+ OBJECT_CHECK(HostMemoryBackendRam, (obj), TYPE_MEMORY_BACKEND_RAM)
+#define MEMORY_BACKEND_RAM_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(HostMemoryBackendRamClass, (obj), \
+ TYPE_MEMORY_BACKEND_RAM)
+#define MEMORY_BACKEND_RAM_CLASS(klass) \
+ OBJECT_CLASS_CHECK(HostMemoryBackendRamClass, (klass), \
+ TYPE_MEMORY_BACKEND_RAM)
+
+/**
+ * @HostMemoryBackendRamClass:
+ * @parent_complete: The parent class complete handler.
+ */
+typedef struct HostMemoryBackendRamClass {
+ /*< private >*/
+ HostMemoryBackendClass parent_class;
+ /*< public >*/
+
+ void (*parent_complete)(UserCreatable *uc, Error **errp);
+} HostMemoryBackendRamClass;
+
+static void
+ram_backend_memory_init(UserCreatable *uc, Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(uc);
+ HostMemoryBackendRamClass *mbrc = MEMORY_BACKEND_RAM_GET_CLASS(uc);
+
+ if (!backend->size) {
+ error_setg(errp, "can't create backend with size 0");
+ return;
+ }
+
+ memory_region_init_ram(&backend->mr, OBJECT(backend),
+ object_get_canonical_path(OBJECT(backend)),
+ backend->size);
+ mbrc->parent_complete(uc, errp);
+}
+
+static void
+ram_backend_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ HostMemoryBackendRamClass *mbrc = MEMORY_BACKEND_RAM_CLASS(oc);
+
+ mbrc->parent_complete = ucc->complete;
+ ucc->complete = ram_backend_memory_init;
+
+}
+
+static const TypeInfo ram_backend_info = {
+ .name = TYPE_MEMORY_BACKEND_RAM,
+ .parent = TYPE_MEMORY_BACKEND,
+ .class_size = sizeof(HostMemoryBackendRamClass),
+ .class_init = ram_backend_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&ram_backend_info);
+}
+
+type_init(register_types);
diff --git a/backends/hostmem.c b/backends/hostmem.c
new file mode 100644
index 0000000..0bd3900
--- /dev/null
+++ b/backends/hostmem.c
@@ -0,0 +1,110 @@
+/*
+ * QEMU Host Memory Backend
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "sysemu/hostmem.h"
+#include "sysemu/sysemu.h"
+#include "qapi/visitor.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/config-file.h"
+#include "qom/object_interfaces.h"
+
+static void
+hostmemory_backend_get_size(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ uint64_t value = backend->size;
+
+ visit_type_size(v, &value, name, errp);
+}
+
+static void
+hostmemory_backend_set_size(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ uint64_t value;
+
+ if (memory_region_size(&backend->mr)) {
+ error_setg(errp, "cannot change property value\n");
+ return;
+ }
+
+ visit_type_size(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (!value) {
+ error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu64 "'",
+ object_get_typename(obj), name , value);
+ return;
+ }
+ backend->size = value;
+}
+
+static void hostmemory_backend_initfn(Object *obj)
+{
+ object_property_add(obj, "size", "int",
+ hostmemory_backend_get_size,
+ hostmemory_backend_set_size, NULL, NULL, NULL);
+}
+
+static void hostmemory_backend_finalize(Object *obj)
+{
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+
+ if (memory_region_size(&backend->mr)) {
+ memory_region_destroy(&backend->mr);
+ }
+}
+
+static void
+hostmemory_backend_memory_init(UserCreatable *uc, Error **errp)
+{
+ error_setg(errp, "memory_init is not implemented for type [%s]",
+ object_get_typename(OBJECT(uc)));
+}
+
+MemoryRegion *
+host_memory_backend_get_memory(HostMemoryBackend *backend, Error **errp)
+{
+ return memory_region_size(&backend->mr) ? &backend->mr : NULL;
+}
+
+static void
+hostmemory_backend_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+ ucc->complete = hostmemory_backend_memory_init;
+}
+
+static const TypeInfo hostmemory_backend_info = {
+ .name = TYPE_MEMORY_BACKEND,
+ .parent = TYPE_OBJECT,
+ .abstract = true,
+ .class_size = sizeof(HostMemoryBackendClass),
+ .class_init = hostmemory_backend_class_init,
+ .instance_size = sizeof(HostMemoryBackend),
+ .instance_init = hostmemory_backend_initfn,
+ .instance_finalize = hostmemory_backend_finalize,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void register_types(void)
+{
+ type_register_static(&hostmemory_backend_info);
+}
+
+type_init(register_types);
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
new file mode 100644
index 0000000..bc3ffb3
--- /dev/null
+++ b/include/sysemu/hostmem.h
@@ -0,0 +1,60 @@
+/*
+ * QEMU Host Memory Backend
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_RAM_H
+#define QEMU_RAM_H
+
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "exec/memory.h"
+#include "qemu/option.h"
+
+#define TYPE_MEMORY_BACKEND "memory"
+#define MEMORY_BACKEND(obj) \
+ OBJECT_CHECK(HostMemoryBackend, (obj), TYPE_MEMORY_BACKEND)
+#define MEMORY_BACKEND_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(HostMemoryBackendClass, (obj), TYPE_MEMORY_BACKEND)
+#define MEMORY_BACKEND_CLASS(klass) \
+ OBJECT_CLASS_CHECK(HostMemoryBackendClass, (klass), TYPE_MEMORY_BACKEND)
+
+typedef struct HostMemoryBackend HostMemoryBackend;
+typedef struct HostMemoryBackendClass HostMemoryBackendClass;
+
+/**
+ * HostMemoryBackendClass:
+ * @parent_class: opaque parent class container
+ */
+struct HostMemoryBackendClass {
+ ObjectClass parent_class;
+};
+
+/**
+ * @HostMemoryBackend
+ *
+ * @parent: opaque parent object container
+ * @size: amount of memory backend provides
+ * @id: unique identification string in memdev namespace
+ * @mr: MemoryRegion representing host memory belonging to backend
+ */
+struct HostMemoryBackend {
+ /* private */
+ Object parent;
+
+ /* protected */
+ uint64_t size;
+
+ MemoryRegion mr;
+};
+
+MemoryRegion *host_memory_backend_get_memory(HostMemoryBackend *backend,
+ Error **errp);
+
+#endif
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 03/11] pc: pass QEMUMachineInitArgs to pc_memory_init
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 01/11] object_add: allow completion handler to get canonical path Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 02/11] add memdev backend infrastructure Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 04/11] numa: introduce memory_region_allocate_system_memory Hu Tao
` (7 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
From: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/i386/pc.c | 11 +++++------
hw/i386/pc_piix.c | 8 +++-----
hw/i386/pc_q35.c | 4 +---
include/hw/i386/pc.h | 7 +++----
4 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 42182f9..44ee3b8 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1145,10 +1145,8 @@ void pc_acpi_init(const char *default_dsdt)
}
}
-FWCfgState *pc_memory_init(MemoryRegion *system_memory,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
+FWCfgState *pc_memory_init(QEMUMachineInitArgs *args,
+ MemoryRegion *system_memory,
ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size,
MemoryRegion *rom_memory,
@@ -1160,7 +1158,7 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory,
MemoryRegion *ram_below_4g, *ram_above_4g;
FWCfgState *fw_cfg;
- linux_boot = (kernel_filename != NULL);
+ linux_boot = (args->kernel_filename != NULL);
/* Allocate RAM. We allocate it as a single memory region and use
* aliases to address portions of it, mostly for backwards compatibility
@@ -1201,7 +1199,8 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory,
rom_set_fw(fw_cfg);
if (linux_boot) {
- load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
+ load_linux(fw_cfg, args->kernel_filename, args->initrd_filename,
+ args->kernel_cmdline, below_4g_mem_size);
}
for (i = 0; i < nb_option_roms; i++) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index d5dc1ef..96adc01 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -151,11 +151,9 @@ static void pc_init1(QEMUMachineInitArgs *args,
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
- fw_cfg = pc_memory_init(system_memory,
- args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename,
- below_4g_mem_size, above_4g_mem_size,
- rom_memory, &ram_memory, guest_info);
+ fw_cfg = pc_memory_init(args, system_memory,
+ below_4g_mem_size, above_4g_mem_size,
+ rom_memory, &ram_memory, guest_info);
}
gsi_state = g_malloc0(sizeof(*gsi_state));
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index a7f6260..95fa01fc 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -138,9 +138,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
- pc_memory_init(get_system_memory(),
- args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename,
+ pc_memory_init(args, get_system_memory(),
below_4g_mem_size, above_4g_mem_size,
rom_memory, &ram_memory, guest_info);
}
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 9010246..8fc0527 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -3,6 +3,7 @@
#include "qemu-common.h"
#include "exec/memory.h"
+#include "hw/boards.h"
#include "hw/isa/isa.h"
#include "hw/block/fdc.h"
#include "net/net.h"
@@ -134,10 +135,8 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory,
MemoryRegion *pci_address_space);
-FWCfgState *pc_memory_init(MemoryRegion *system_memory,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
+FWCfgState *pc_memory_init(QEMUMachineInitArgs *args,
+ MemoryRegion *system_memory,
ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size,
MemoryRegion *rom_memory,
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 04/11] numa: introduce memory_region_allocate_system_memory
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (2 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 03/11] pc: pass QEMUMachineInitArgs to pc_memory_init Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 05/11] numa: add -numa node, memdev= option Hu Tao
` (6 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
From: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/i386/pc.c | 4 +---
include/sysemu/sysemu.h | 5 +++++
numa.c | 10 ++++++++++
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 44ee3b8..27f0f1f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1165,9 +1165,7 @@ FWCfgState *pc_memory_init(QEMUMachineInitArgs *args,
* with older qemus that used qemu_ram_alloc().
*/
ram = g_malloc(sizeof(*ram));
- memory_region_init_ram(ram, NULL, "pc.ram",
- below_4g_mem_size + above_4g_mem_size);
- vmstate_register_ram_global(ram);
+ memory_region_allocate_system_memory(ram, NULL, "pc.ram", args);
*ram_memory = ram;
ram_below_4g = g_malloc(sizeof(*ram_below_4g));
memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 4c94cf5..e9da760 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -10,6 +10,8 @@
#include "qemu/notify.h"
#include "qemu/main-loop.h"
#include "qemu/bitmap.h"
+#include "qom/object.h"
+#include "hw/boards.h"
/* vl.c */
@@ -144,6 +146,9 @@ void set_numa_nodes(void);
void set_numa_modes(void);
extern QemuOptsList qemu_numa_opts;
int numa_init_func(QemuOpts *opts, void *opaque);
+void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
+ const char *name,
+ QEMUMachineInitArgs *args);
#define MAX_OPTION_ROMS 16
typedef struct QEMUOptionRom {
diff --git a/numa.c b/numa.c
index 40c28b3..6441d14 100644
--- a/numa.c
+++ b/numa.c
@@ -187,3 +187,13 @@ void set_numa_modes(void)
}
}
}
+
+void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
+ const char *name,
+ QEMUMachineInitArgs *args)
+{
+ uint64_t ram_size = args->ram_size;
+
+ memory_region_init_ram(mr, owner, name, ram_size);
+ vmstate_register_ram_global(mr);
+}
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 05/11] numa: add -numa node, memdev= option
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (3 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 04/11] numa: introduce memory_region_allocate_system_memory Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 06/11] qapi: make string input visitor parse int list Hu Tao
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
From: Paolo Bonzini <pbonzini@redhat.com>
This option provides the infrastructure for binding guest NUMA nodes
to host NUMA nodes. For example:
-object memory-ram,size=1024M,policy=membind,host-nodes=0,id=ram-node0 \
-numa node,nodeid=0,cpus=0,memdev=ram-node0 \
-object memory-ram,size=1024M,policy=interleave,host-nodes=1-3,id=ram-node1 \
-numa node,nodeid=1,cpus=1,memdev=ram-node1
The option replaces "-numa mem".
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
[don't include sysemu/hostmem.h in sysemu/sysemu.h to avoid mutual
inclusion.]
---
include/sysemu/sysemu.h | 3 +++
numa.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++--
qapi-schema.json | 6 ++++-
3 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index e9da760..40f1df9 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -137,9 +137,12 @@ extern QEMUClockType rtc_clock;
#define MAX_NODES 128
#define MAX_CPUMASK_BITS 255
extern int nb_numa_nodes;
+struct HostMemoryBackend;
+typedef struct HostMemoryBackend HostMemoryBackend;
typedef struct node_info {
uint64_t node_mem;
DECLARE_BITMAP(node_cpu, MAX_CPUMASK_BITS);
+ HostMemoryBackend *node_memdev;
} NodeInfo;
extern NodeInfo numa_info[MAX_NODES];
void set_numa_nodes(void);
diff --git a/numa.c b/numa.c
index 6441d14..8d05078 100644
--- a/numa.c
+++ b/numa.c
@@ -24,9 +24,12 @@
*/
#include "sysemu/sysemu.h"
+#include "sysemu/hostmem.h"
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
+#include "qapi/qmp/qerror.h"
+
QemuOptsList qemu_numa_opts = {
.name = "numa",
.implied_opt_name = "type",
@@ -34,10 +37,13 @@ QemuOptsList qemu_numa_opts = {
.desc = { { 0 } } /* validated with OptsVisitor */
};
+static int have_memdevs = -1;
+
static int numa_node_parse(NumaNodeOptions *node, QemuOpts *opts)
{
uint16_t nodenr;
uint16List *cpus = NULL;
+ Error *local_err = NULL;
if (node->has_nodeid) {
nodenr = node->nodeid;
@@ -60,6 +66,20 @@ static int numa_node_parse(NumaNodeOptions *node, QemuOpts *opts)
bitmap_set(numa_info[nodenr].node_cpu, cpus->value, 1);
}
+ if (node->has_mem && node->has_memdev) {
+ fprintf(stderr, "qemu: cannot specify both mem= and memdev=\n");
+ return -1;
+ }
+
+ if (have_memdevs == -1) {
+ have_memdevs = node->has_memdev;
+ }
+
+ if (node->has_memdev != have_memdevs) {
+ fprintf(stderr, "qemu: memdev option must be specified for either "
+ "all or no nodes\n");
+ }
+
if (node->has_mem) {
uint64_t mem_size = node->mem;
const char *mem_str = qemu_opt_get(opts, "mem");
@@ -69,7 +89,19 @@ static int numa_node_parse(NumaNodeOptions *node, QemuOpts *opts)
}
numa_info[nodenr].node_mem = mem_size;
}
+ if (node->has_memdev) {
+ Object *o;
+ o = object_resolve_path_type(node->memdev, TYPE_MEMORY_BACKEND, NULL);
+ if (!o) {
+ error_setg(&local_err, "memdev=%s is ambiguous", node->memdev);
+ qerror_report_err(local_err);
+ return -1;
+ }
+ object_ref(o);
+ numa_info[nodenr].node_mem = object_property_get_int(o, "size", NULL);
+ numa_info[nodenr].node_memdev = MEMORY_BACKEND(o);
+ }
return 0;
}
@@ -188,12 +220,42 @@ void set_numa_modes(void)
}
}
+static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
+ const char *name,
+ QEMUMachineInitArgs *args)
+{
+ uint64_t ram_size = args->ram_size;
+
+ memory_region_init_ram(mr, owner, name, ram_size);
+ vmstate_register_ram_global(mr);
+}
+
void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
const char *name,
QEMUMachineInitArgs *args)
{
uint64_t ram_size = args->ram_size;
+ uint64_t addr = 0;
+ int i;
- memory_region_init_ram(mr, owner, name, ram_size);
- vmstate_register_ram_global(mr);
+ if (nb_numa_nodes == 0 || !have_memdevs) {
+ allocate_system_memory_nonnuma(mr, owner, name, args);
+ return;
+ }
+
+ memory_region_init(mr, owner, name, ram_size);
+ for (i = 0; i < nb_numa_nodes; i++) {
+ Error *local_err = NULL;
+ uint64_t size = numa_info[i].node_mem;
+ HostMemoryBackend *backend = numa_info[i].node_memdev;
+ MemoryRegion *seg = host_memory_backend_get_memory(backend, &local_err);
+ if (local_err) {
+ qerror_report_err(local_err);
+ exit(1);
+ }
+
+ memory_region_add_subregion(mr, addr, seg);
+ vmstate_register_ram_global(seg);
+ addr += size;
+ }
}
diff --git a/qapi-schema.json b/qapi-schema.json
index 951cc0a..62e0b83 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4542,6 +4542,9 @@
#
# @mem: #optional memory size of this node (equally divide total memory among
# nodes if omitted)
+# @memdev: #optional memory backend object. If specified for one node,
+# it must be specified for all nodes.
+#
#
# Since: 2.1
##
@@ -4549,4 +4552,5 @@
'data': {
'*nodeid': 'uint16',
'*cpus': ['uint16'],
- '*mem': 'size' }}
+ '*mem': 'size',
+ '*memdev': 'str' }}
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 06/11] qapi: make string input visitor parse int list
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (4 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 05/11] numa: add -numa node, memdev= option Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 07/11] qapi: make string output " Hu Tao
` (4 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, Laszlo Ersek, gaowanlong, imammedo
Cc: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
---
qapi/string-input-visitor.c | 160 ++++++++++++++++++++++++++++++++++++--
tests/test-string-input-visitor.c | 21 +++++
2 files changed, 175 insertions(+), 6 deletions(-)
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 793548a..24aab5e 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -16,30 +16,175 @@
#include "qapi/qmp/qerror.h"
#include "qemu/option.h"
+enum ListMode {
+ LM_NONE, /* not traversing a list of repeated options */
+ LM_STARTED, /* start_list() succeeded */
+
+ LM_IN_PROGRESS, /* next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently parsed QemuOpt instance of the repeated
+ * option.
+ *
+ * Parsing a value into the list link will examine the
+ * next QemuOpt instance of the repeated option, and
+ * possibly enter LM_SIGNED_INTERVAL or
+ * LM_UNSIGNED_INTERVAL.
+ */
+
+ LM_SIGNED_INTERVAL, /* next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently stored element from the signed interval,
+ * parsed from the most recent QemuOpt instance of the
+ * repeated option. This may consume QemuOpt itself
+ * and return to LM_IN_PROGRESS.
+ *
+ * Parsing a value into the list link will store the
+ * next element of the signed interval.
+ */
+
+ LM_UNSIGNED_INTERVAL,/* Same as above, only for an unsigned interval. */
+
+ LM_END
+};
+
+typedef enum ListMode ListMode;
+
struct StringInputVisitor
{
Visitor visitor;
+
+ ListMode list_mode;
+
+ /* When parsing a list of repeating options as integers, values of the form
+ * "a-b", representing a closed interval, are allowed. Elements in the
+ * range are generated individually.
+ */
+ union {
+ int64_t s;
+ uint64_t u;
+ } range_next, range_limit;
+
const char *string;
};
+static void
+start_list(Visitor *v, const char *name, Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+
+ /* we can't traverse a list in a list */
+ assert(siv->list_mode == LM_NONE);
+ siv->list_mode = LM_STARTED;
+}
+
+static GenericList *
+next_list(Visitor *v, GenericList **list, Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ GenericList **link;
+
+ switch (siv->list_mode) {
+ case LM_STARTED:
+ siv->list_mode = LM_IN_PROGRESS;
+ link = list;
+ break;
+
+ case LM_SIGNED_INTERVAL:
+ case LM_UNSIGNED_INTERVAL:
+ link = &(*list)->next;
+
+ if (siv->list_mode == LM_SIGNED_INTERVAL) {
+ if (siv->range_next.s < siv->range_limit.s) {
+ ++siv->range_next.s;
+ break;
+ }
+ } else if (siv->range_next.u < siv->range_limit.u) {
+ ++siv->range_next.u;
+ break;
+ }
+ siv->list_mode = LM_END;
+ /* range has been completed, fall through */
+
+ case LM_END:
+ return NULL;
+
+ case LM_IN_PROGRESS:
+ link = &(*list)->next;
+ break;
+
+ default:
+ abort();
+ }
+
+ *link = g_malloc0(sizeof **link);
+ return *link;
+}
+
+static void
+end_list(Visitor *v, Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+
+ assert(siv->list_mode == LM_STARTED ||
+ siv->list_mode == LM_END ||
+ siv->list_mode == LM_IN_PROGRESS ||
+ siv->list_mode == LM_SIGNED_INTERVAL ||
+ siv->list_mode == LM_UNSIGNED_INTERVAL);
+ siv->list_mode = LM_NONE;
+}
+
static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
Error **errp)
{
StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
- char *endp = (char *) siv->string;
+ char *str = (char *) siv->string;
long long val;
+ char *endptr;
- errno = 0;
- if (siv->string) {
- val = strtoll(siv->string, &endp, 0);
+ if (siv->list_mode == LM_SIGNED_INTERVAL) {
+ *obj = siv->range_next.s;
+ return;
}
- if (!siv->string || errno || endp == siv->string || *endp) {
+
+ if (!siv->string) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"integer");
return;
}
- *obj = val;
+ errno = 0;
+ val = strtoll(siv->string, &endptr, 0);
+
+ if (errno == 0 && endptr > str && INT64_MIN <= val && val <= INT64_MAX) {
+ if (*endptr == '\0') {
+ *obj = val;
+ siv->list_mode = LM_END;
+ return;
+ }
+ if (*endptr == '-' && siv->list_mode == LM_IN_PROGRESS) {
+ long long val2;
+
+ str = endptr + 1;
+ val2 = strtoll(str, &endptr, 0);
+ if (errno == 0 && endptr > str && *endptr == '\0' &&
+ INT64_MIN <= val2 && val2 <= INT64_MAX && val <= val2 &&
+ (val > INT64_MAX - 65536 ||
+ val2 < val + 65536)) {
+ siv->range_next.s = val;
+ siv->range_limit.s = val2;
+ siv->list_mode = LM_SIGNED_INTERVAL;
+
+ /* as if entering on the top */
+ *obj = siv->range_next.s;
+ return;
+ }
+ }
+ }
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
+ (siv->list_mode == LM_NONE) ? "an int64 value" :
+ "an int64 value or range");
}
static void parse_type_size(Visitor *v, uint64_t *obj, const char *name,
@@ -155,6 +300,9 @@ StringInputVisitor *string_input_visitor_new(const char *str)
v->visitor.type_bool = parse_type_bool;
v->visitor.type_str = parse_type_str;
v->visitor.type_number = parse_type_number;
+ v->visitor.start_list = start_list;
+ v->visitor.next_list = next_list;
+ v->visitor.end_list = end_list;
v->visitor.start_optional = parse_start_optional;
v->string = str;
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index d406263..31925cb 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -64,6 +64,25 @@ static void test_visitor_in_int(TestInputVisitorData *data,
g_assert_cmpint(res, ==, value);
}
+static void test_visitor_in_intList(TestInputVisitorData *data,
+ const void *unused)
+{
+ int64_t value[] = {-2, -1, 0, 1, 2, 3, 4};
+ int16List *res = NULL;
+ Error *errp = NULL;
+ Visitor *v;
+ int i = 0;
+
+ v = visitor_input_test_init(data, "-2-4");
+
+ visit_type_int16List(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ while (res && i < sizeof(value) / sizeof(value[0])) {
+ g_assert_cmpint(res->value, ==, value[i++]);
+ res = res->next;
+ }
+}
+
static void test_visitor_in_bool(TestInputVisitorData *data,
const void *unused)
{
@@ -228,6 +247,8 @@ int main(int argc, char **argv)
input_visitor_test_add("/string-visitor/input/int",
&in_visitor_data, test_visitor_in_int);
+ input_visitor_test_add("/string-visitor/input/intList",
+ &in_visitor_data, test_visitor_in_intList);
input_visitor_test_add("/string-visitor/input/bool",
&in_visitor_data, test_visitor_in_bool);
input_visitor_test_add("/string-visitor/input/number",
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (5 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 06/11] qapi: make string input visitor parse int list Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 9:03 ` Paolo Bonzini
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 08/11] Add Linux libnuma detection Hu Tao
` (3 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: Hu Tao, pbonzini, gaowanlong, imammedo
From: Hu Tao <hu.taoo@gmail.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
---
qapi/string-output-visitor.c | 156 +++++++++++++++++++++++++++++++++++--
tests/test-string-output-visitor.c | 26 +++++++
2 files changed, 177 insertions(+), 5 deletions(-)
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index fb1d2e8..bc9bb36 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -17,11 +17,57 @@
#include "qemu/host-utils.h"
#include <math.h>
+enum ListMode {
+ LM_NONE, /* not traversing a list of repeated options */
+ LM_STARTED, /* start_list() succeeded */
+
+ LM_IN_PROGRESS, /* next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently parsed QemuOpt instance of the repeated
+ * option.
+ *
+ * Parsing a value into the list link will examine the
+ * next QemuOpt instance of the repeated option, and
+ * possibly enter LM_SIGNED_INTERVAL or
+ * LM_UNSIGNED_INTERVAL.
+ */
+
+ LM_SIGNED_INTERVAL, /* next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently stored element from the signed interval,
+ * parsed from the most recent QemuOpt instance of the
+ * repeated option. This may consume QemuOpt itself
+ * and return to LM_IN_PROGRESS.
+ *
+ * Parsing a value into the list link will store the
+ * next element of the signed interval.
+ */
+
+ LM_UNSIGNED_INTERVAL,/* Same as above, only for an unsigned interval. */
+
+ LM_END
+};
+
+typedef enum ListMode ListMode;
+
struct StringOutputVisitor
{
Visitor visitor;
bool human;
+ bool head;
char *string;
+ ListMode list_mode;
+ /* When parsing a list of repeating options as integers, values of the form
+ * "a-b", representing a closed interval, are allowed. Elements in the
+ * range are generated individually.
+ */
+ union {
+ int64_t s;
+ uint64_t u;
+ } range_start, range_end;
+
};
static void string_output_set(StringOutputVisitor *sov, char *string)
@@ -34,13 +80,60 @@ static void print_type_int(Visitor *v, int64_t *obj, const char *name,
Error **errp)
{
StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
- char *out;
+ char *out = NULL;
- if (sov->human) {
- out = g_strdup_printf("%lld (%#llx)", (long long) *obj, (long long) *obj);
- } else {
- out = g_strdup_printf("%lld", (long long) *obj);
+ switch (sov->list_mode) {
+ case LM_NONE:
+ if (sov->human) {
+ out = g_strdup_printf("%lld (%#llx)", (long long) *obj,
+ (long long) *obj);
+ } else {
+ out = g_strdup_printf("%lld", (long long) *obj);
+ }
+ sov->list_mode = LM_END;
+ break;
+
+ case LM_STARTED:
+ sov->range_start.s = *obj;
+ sov->range_end.s = *obj;
+ sov->list_mode = LM_IN_PROGRESS;
+ break;
+
+ case LM_IN_PROGRESS:
+ assert(sov->range_end.s + 1 == *obj);
+ sov->range_end.s++;
+ break;
+
+ case LM_END:
+ assert(sov->range_end.s + 1 == *obj);
+ sov->range_end.s++;
+ if (sov->range_end.s == sov->range_start.s) {
+ if (sov->human) {
+ out = g_strdup_printf("%lld (%#llx)",
+ (long long)sov->range_start.s,
+ (long long)sov->range_start.s);
+ } else {
+ out = g_strdup_printf("%lld", (long long)sov->range_start.s);
+ }
+ } else {
+ if (sov->human) {
+ out = g_strdup_printf("%lld(%#llx)-%lld(%#llx)",
+ (long long) sov->range_start.s,
+ (long long) sov->range_start.s,
+ (long long) sov->range_end.s,
+ (long long) sov->range_end.s);
+ } else {
+ out = g_strdup_printf("%lld-%lld",
+ (long long) sov->range_start.s,
+ (long long) sov->range_end.s);
+ }
+ }
+ break;
+
+ default:
+ abort();
}
+
string_output_set(sov, out);
}
@@ -103,6 +196,56 @@ static void print_type_number(Visitor *v, double *obj, const char *name,
string_output_set(sov, g_strdup_printf("%f", *obj));
}
+static void
+start_list(Visitor *v, const char *name, Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+
+ /* we can't traverse a list in a list */
+ assert(sov->list_mode == LM_NONE);
+ sov->list_mode = LM_STARTED;
+ sov->head = true;
+}
+
+static GenericList *
+next_list(Visitor *v, GenericList **list, Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ GenericList *ret = NULL;
+ if (*list) {
+ if (sov->head) {
+ ret = *list;
+ } else {
+ ret = (*list)->next;
+ }
+
+ if (sov->head) {
+ if (ret && ret->next == NULL) {
+ sov->list_mode = LM_NONE;
+ }
+ sov->head = false;
+ } else {
+ if (ret && ret->next == NULL) {
+ sov->list_mode = LM_END;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void
+end_list(Visitor *v, Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+
+ assert(sov->list_mode == LM_STARTED ||
+ sov->list_mode == LM_END ||
+ sov->list_mode == LM_IN_PROGRESS);
+ sov->list_mode = LM_NONE;
+ sov->head = true;
+}
+
char *string_output_get_string(StringOutputVisitor *sov)
{
char *string = sov->string;
@@ -134,6 +277,9 @@ StringOutputVisitor *string_output_visitor_new(bool human)
v->visitor.type_bool = print_type_bool;
v->visitor.type_str = print_type_str;
v->visitor.type_number = print_type_number;
+ v->visitor.start_list = start_list;
+ v->visitor.next_list = next_list;
+ v->visitor.end_list = end_list;
return v;
}
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 22363d1..511ef14 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -57,6 +57,30 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
g_free(str);
}
+static void test_visitor_out_intList(TestOutputVisitorData *data,
+ const void *unused)
+{
+ int64_t value[] = {-2, -1, 0, 1, 2, 3, 4};
+ intList *list = NULL, **tmp = &list;
+ int i;
+ Error *errp = NULL;
+ char *str;
+
+ for (i = 0; i < sizeof(value) / sizeof(value[0]); i++) {
+ *tmp = g_malloc0(sizeof(**tmp));
+ (*tmp)->value = value[i];
+ tmp = &(*tmp)->next;
+ }
+
+ visit_type_intList(data->ov, &list, NULL, &errp);
+ g_assert(error_is_set(&errp) == 0);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, "-2-4");
+ g_free(str);
+}
+
static void test_visitor_out_bool(TestOutputVisitorData *data,
const void *unused)
{
@@ -182,6 +206,8 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_enum);
output_visitor_test_add("/string-visitor/output/enum-errors",
&out_visitor_data, test_visitor_out_enum_errors);
+ output_visitor_test_add("/string-visitor/output/intList",
+ &out_visitor_data, test_visitor_out_intList);
g_test_run();
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 07/11] qapi: make string output " Hu Tao
@ 2014-03-04 9:03 ` Paolo Bonzini
2014-03-04 9:23 ` Hu Tao
0 siblings, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2014-03-04 9:03 UTC (permalink / raw)
To: Hu Tao, qemu-devel; +Cc: imammedo, Hu Tao, gaowanlong
Il 04/03/2014 08:28, Hu Tao ha scritto:
> From: Hu Tao <hu.taoo@gmail.com>
>
> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
> ---
> qapi/string-output-visitor.c | 156 +++++++++++++++++++++++++++++++++++--
> tests/test-string-output-visitor.c | 26 +++++++
> 2 files changed, 177 insertions(+), 5 deletions(-)
>
> diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
> index fb1d2e8..bc9bb36 100644
> --- a/qapi/string-output-visitor.c
> +++ b/qapi/string-output-visitor.c
> @@ -17,11 +17,57 @@
> #include "qemu/host-utils.h"
> #include <math.h>
>
> +enum ListMode {
> + LM_NONE, /* not traversing a list of repeated options */
> + LM_STARTED, /* start_list() succeeded */
> +
> + LM_IN_PROGRESS, /* next_list() has been called.
> + *
> + * Generating the next list link will consume the most
> + * recently parsed QemuOpt instance of the repeated
> + * option.
> + *
> + * Parsing a value into the list link will examine the
> + * next QemuOpt instance of the repeated option, and
> + * possibly enter LM_SIGNED_INTERVAL or
> + * LM_UNSIGNED_INTERVAL.
> + */
> +
> + LM_SIGNED_INTERVAL, /* next_list() has been called.
> + *
> + * Generating the next list link will consume the most
> + * recently stored element from the signed interval,
> + * parsed from the most recent QemuOpt instance of the
> + * repeated option. This may consume QemuOpt itself
> + * and return to LM_IN_PROGRESS.
> + *
> + * Parsing a value into the list link will store the
> + * next element of the signed interval.
> + */
> +
> + LM_UNSIGNED_INTERVAL,/* Same as above, only for an unsigned interval. */
> +
> + LM_END
> +};
> +
> +typedef enum ListMode ListMode;
> +
> struct StringOutputVisitor
> {
> Visitor visitor;
> bool human;
> + bool head;
> char *string;
> + ListMode list_mode;
> + /* When parsing a list of repeating options as integers, values of the form
> + * "a-b", representing a closed interval, are allowed. Elements in the
> + * range are generated individually.
> + */
> + union {
> + int64_t s;
> + uint64_t u;
> + } range_start, range_end;
> +
> };
>
> static void string_output_set(StringOutputVisitor *sov, char *string)
> @@ -34,13 +80,60 @@ static void print_type_int(Visitor *v, int64_t *obj, const char *name,
> Error **errp)
> {
> StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
> - char *out;
> + char *out = NULL;
>
> - if (sov->human) {
> - out = g_strdup_printf("%lld (%#llx)", (long long) *obj, (long long) *obj);
> - } else {
> - out = g_strdup_printf("%lld", (long long) *obj);
> + switch (sov->list_mode) {
> + case LM_NONE:
> + if (sov->human) {
> + out = g_strdup_printf("%lld (%#llx)", (long long) *obj,
> + (long long) *obj);
> + } else {
> + out = g_strdup_printf("%lld", (long long) *obj);
> + }
> + sov->list_mode = LM_END;
> + break;
> +
> + case LM_STARTED:
> + sov->range_start.s = *obj;
> + sov->range_end.s = *obj;
> + sov->list_mode = LM_IN_PROGRESS;
> + break;
> +
> + case LM_IN_PROGRESS:
> + assert(sov->range_end.s + 1 == *obj);
> + sov->range_end.s++;
> + break;
> +
> + case LM_END:
> + assert(sov->range_end.s + 1 == *obj);
> + sov->range_end.s++;
> + if (sov->range_end.s == sov->range_start.s) {
> + if (sov->human) {
> + out = g_strdup_printf("%lld (%#llx)",
> + (long long)sov->range_start.s,
> + (long long)sov->range_start.s);
> + } else {
> + out = g_strdup_printf("%lld", (long long)sov->range_start.s);
> + }
> + } else {
> + if (sov->human) {
> + out = g_strdup_printf("%lld(%#llx)-%lld(%#llx)",
> + (long long) sov->range_start.s,
> + (long long) sov->range_start.s,
> + (long long) sov->range_end.s,
> + (long long) sov->range_end.s);
Perhaps "10-15 (0xa-0xf)"?
> + } else {
> + out = g_strdup_printf("%lld-%lld",
> + (long long) sov->range_start.s,
> + (long long) sov->range_end.s);
> + }
> + }
This looks wrong. You do not insert any separator, and you do not
handle things like "0-3,8-11". You probably should use a GString
instead of string_output_set.
Paolo
> + break;
> +
> + default:
> + abort();
> }
> +
> string_output_set(sov, out);
> }
>
> @@ -103,6 +196,56 @@ static void print_type_number(Visitor *v, double *obj, const char *name,
> string_output_set(sov, g_strdup_printf("%f", *obj));
> }
>
> +static void
> +start_list(Visitor *v, const char *name, Error **errp)
> +{
> + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
> +
> + /* we can't traverse a list in a list */
> + assert(sov->list_mode == LM_NONE);
> + sov->list_mode = LM_STARTED;
> + sov->head = true;
> +}
> +
> +static GenericList *
> +next_list(Visitor *v, GenericList **list, Error **errp)
> +{
> + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
> + GenericList *ret = NULL;
> + if (*list) {
> + if (sov->head) {
> + ret = *list;
> + } else {
> + ret = (*list)->next;
> + }
> +
> + if (sov->head) {
> + if (ret && ret->next == NULL) {
> + sov->list_mode = LM_NONE;
> + }
> + sov->head = false;
> + } else {
> + if (ret && ret->next == NULL) {
> + sov->list_mode = LM_END;
> + }
> + }
> + }
> +
> + return ret;
> +}
> +
> +static void
> +end_list(Visitor *v, Error **errp)
> +{
> + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
> +
> + assert(sov->list_mode == LM_STARTED ||
> + sov->list_mode == LM_END ||
> + sov->list_mode == LM_IN_PROGRESS);
> + sov->list_mode = LM_NONE;
> + sov->head = true;
> +}
> +
> char *string_output_get_string(StringOutputVisitor *sov)
> {
> char *string = sov->string;
> @@ -134,6 +277,9 @@ StringOutputVisitor *string_output_visitor_new(bool human)
> v->visitor.type_bool = print_type_bool;
> v->visitor.type_str = print_type_str;
> v->visitor.type_number = print_type_number;
> + v->visitor.start_list = start_list;
> + v->visitor.next_list = next_list;
> + v->visitor.end_list = end_list;
>
> return v;
> }
> diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
> index 22363d1..511ef14 100644
> --- a/tests/test-string-output-visitor.c
> +++ b/tests/test-string-output-visitor.c
> @@ -57,6 +57,30 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
> g_free(str);
> }
>
> +static void test_visitor_out_intList(TestOutputVisitorData *data,
> + const void *unused)
> +{
> + int64_t value[] = {-2, -1, 0, 1, 2, 3, 4};
> + intList *list = NULL, **tmp = &list;
> + int i;
> + Error *errp = NULL;
> + char *str;
> +
> + for (i = 0; i < sizeof(value) / sizeof(value[0]); i++) {
> + *tmp = g_malloc0(sizeof(**tmp));
> + (*tmp)->value = value[i];
> + tmp = &(*tmp)->next;
> + }
> +
> + visit_type_intList(data->ov, &list, NULL, &errp);
> + g_assert(error_is_set(&errp) == 0);
> +
> + str = string_output_get_string(data->sov);
> + g_assert(str != NULL);
> + g_assert_cmpstr(str, ==, "-2-4");
> + g_free(str);
> +}
> +
> static void test_visitor_out_bool(TestOutputVisitorData *data,
> const void *unused)
> {
> @@ -182,6 +206,8 @@ int main(int argc, char **argv)
> &out_visitor_data, test_visitor_out_enum);
> output_visitor_test_add("/string-visitor/output/enum-errors",
> &out_visitor_data, test_visitor_out_enum_errors);
> + output_visitor_test_add("/string-visitor/output/intList",
> + &out_visitor_data, test_visitor_out_intList);
>
> g_test_run();
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
2014-03-04 9:03 ` Paolo Bonzini
@ 2014-03-04 9:23 ` Hu Tao
2014-03-04 9:33 ` Paolo Bonzini
0 siblings, 1 reply; 15+ messages in thread
From: Hu Tao @ 2014-03-04 9:23 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: imammedo, Hu Tao, qemu-devel, gaowanlong
On Tue, Mar 04, 2014 at 10:03:49AM +0100, Paolo Bonzini wrote:
> Il 04/03/2014 08:28, Hu Tao ha scritto:
> >From: Hu Tao <hu.taoo@gmail.com>
> >
> >Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
> >---
> > qapi/string-output-visitor.c | 156 +++++++++++++++++++++++++++++++++++--
> > tests/test-string-output-visitor.c | 26 +++++++
> > 2 files changed, 177 insertions(+), 5 deletions(-)
> >
> >diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
> >index fb1d2e8..bc9bb36 100644
> >--- a/qapi/string-output-visitor.c
> >+++ b/qapi/string-output-visitor.c
> >@@ -17,11 +17,57 @@
> > #include "qemu/host-utils.h"
> > #include <math.h>
> >
> >+enum ListMode {
> >+ LM_NONE, /* not traversing a list of repeated options */
> >+ LM_STARTED, /* start_list() succeeded */
> >+
> >+ LM_IN_PROGRESS, /* next_list() has been called.
> >+ *
> >+ * Generating the next list link will consume the most
> >+ * recently parsed QemuOpt instance of the repeated
> >+ * option.
> >+ *
> >+ * Parsing a value into the list link will examine the
> >+ * next QemuOpt instance of the repeated option, and
> >+ * possibly enter LM_SIGNED_INTERVAL or
> >+ * LM_UNSIGNED_INTERVAL.
> >+ */
> >+
> >+ LM_SIGNED_INTERVAL, /* next_list() has been called.
> >+ *
> >+ * Generating the next list link will consume the most
> >+ * recently stored element from the signed interval,
> >+ * parsed from the most recent QemuOpt instance of the
> >+ * repeated option. This may consume QemuOpt itself
> >+ * and return to LM_IN_PROGRESS.
> >+ *
> >+ * Parsing a value into the list link will store the
> >+ * next element of the signed interval.
> >+ */
> >+
> >+ LM_UNSIGNED_INTERVAL,/* Same as above, only for an unsigned interval. */
> >+
> >+ LM_END
> >+};
> >+
> >+typedef enum ListMode ListMode;
> >+
> > struct StringOutputVisitor
> > {
> > Visitor visitor;
> > bool human;
> >+ bool head;
> > char *string;
> >+ ListMode list_mode;
> >+ /* When parsing a list of repeating options as integers, values of the form
> >+ * "a-b", representing a closed interval, are allowed. Elements in the
> >+ * range are generated individually.
> >+ */
> >+ union {
> >+ int64_t s;
> >+ uint64_t u;
> >+ } range_start, range_end;
> >+
> > };
> >
> > static void string_output_set(StringOutputVisitor *sov, char *string)
> >@@ -34,13 +80,60 @@ static void print_type_int(Visitor *v, int64_t *obj, const char *name,
> > Error **errp)
> > {
> > StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
> >- char *out;
> >+ char *out = NULL;
> >
> >- if (sov->human) {
> >- out = g_strdup_printf("%lld (%#llx)", (long long) *obj, (long long) *obj);
> >- } else {
> >- out = g_strdup_printf("%lld", (long long) *obj);
> >+ switch (sov->list_mode) {
> >+ case LM_NONE:
> >+ if (sov->human) {
> >+ out = g_strdup_printf("%lld (%#llx)", (long long) *obj,
> >+ (long long) *obj);
> >+ } else {
> >+ out = g_strdup_printf("%lld", (long long) *obj);
> >+ }
> >+ sov->list_mode = LM_END;
> >+ break;
> >+
> >+ case LM_STARTED:
> >+ sov->range_start.s = *obj;
> >+ sov->range_end.s = *obj;
> >+ sov->list_mode = LM_IN_PROGRESS;
> >+ break;
> >+
> >+ case LM_IN_PROGRESS:
> >+ assert(sov->range_end.s + 1 == *obj);
> >+ sov->range_end.s++;
> >+ break;
> >+
> >+ case LM_END:
> >+ assert(sov->range_end.s + 1 == *obj);
> >+ sov->range_end.s++;
> >+ if (sov->range_end.s == sov->range_start.s) {
> >+ if (sov->human) {
> >+ out = g_strdup_printf("%lld (%#llx)",
> >+ (long long)sov->range_start.s,
> >+ (long long)sov->range_start.s);
> >+ } else {
> >+ out = g_strdup_printf("%lld", (long long)sov->range_start.s);
> >+ }
> >+ } else {
> >+ if (sov->human) {
> >+ out = g_strdup_printf("%lld(%#llx)-%lld(%#llx)",
> >+ (long long) sov->range_start.s,
> >+ (long long) sov->range_start.s,
> >+ (long long) sov->range_end.s,
> >+ (long long) sov->range_end.s);
>
> Perhaps "10-15 (0xa-0xf)"?
Looks better.
>
> >+ } else {
> >+ out = g_strdup_printf("%lld-%lld",
> >+ (long long) sov->range_start.s,
> >+ (long long) sov->range_end.s);
> >+ }
> >+ }
>
> This looks wrong. You do not insert any separator, and you do not
> handle things like "0-3,8-11". You probably should use a GString
> instead of string_output_set.
Right. We should also handle "0-3,8-11"-like lists in string input
visitor and opts visitor.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
2014-03-04 9:23 ` Hu Tao
@ 2014-03-04 9:33 ` Paolo Bonzini
0 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2014-03-04 9:33 UTC (permalink / raw)
To: Hu Tao; +Cc: imammedo, Hu Tao, qemu-devel, gaowanlong
Il 04/03/2014 10:23, Hu Tao ha scritto:
>> >
>>> > >+ } else {
>>> > >+ out = g_strdup_printf("%lld-%lld",
>>> > >+ (long long) sov->range_start.s,
>>> > >+ (long long) sov->range_end.s);
>>> > >+ }
>>> > >+ }
>> >
>> > This looks wrong. You do not insert any separator, and you do not
>> > handle things like "0-3,8-11". You probably should use a GString
>> > instead of string_output_set.
>
> Right. We should also handle "0-3,8-11"-like lists in string input
> visitor and opts visitor.
Ok, no big deal; let's do one thing at a time.
Regarding string input visitor, I believe we can avoid the code
duplication by:
(1) using Qmp input/output visitors in query-memdev
(2) using OptsVisitor in -object
The string output visitor becomes more important than the string input
visitor, but it is only needed for HMP so it is not urgent.
We can then work on making OptsVisitor use the string input visitor
internally.
But I'm already applying patches 1-5, 8, 9, 10 (the latter with the
above changes) to the numa tree.
Paolo
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 08/11] Add Linux libnuma detection
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (6 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 07/11] qapi: make string output " Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 09/11] hostmem backend: implement memory policy Hu Tao
` (2 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, Andre Przywara, gaowanlong, imammedo
From: Wanlong Gao <gaowanlong@cn.fujitsu.com>
Add detection of libnuma (mostly contained in the numactl package)
to the configure script. Can be enabled or disabled on the command
line, default is use if available.
Signed-off-by: Andre Przywara <andre.przywara@amd.com>
Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
---
configure | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/configure b/configure
index 8ad03ea..585b40c 100755
--- a/configure
+++ b/configure
@@ -303,6 +303,7 @@ tpm="no"
libssh2=""
vhdx=""
quorum="no"
+numa=""
# parse CC options first
for opt do
@@ -1051,6 +1052,10 @@ for opt do
;;
--enable-quorum) quorum="yes"
;;
+ --disable-numa) numa="no"
+ ;;
+ --enable-numa) numa="yes"
+ ;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
@@ -1310,6 +1315,8 @@ Advanced options (experts only):
--enable-vhdx enable support for the Microsoft VHDX image format
--disable-quorum disable quorum block filter support
--enable-quorum enable quorum block filter support
+ --disable-numa disable libnuma support
+ --enable-numa enable libnuma support
NOTE: The object files are built at the place where configure is launched
EOF
@@ -2983,6 +2990,27 @@ if compile_prog "" "" ; then
fi
##########################################
+# libnuma probe
+
+if test "$numa" != "no" ; then
+ numa=no
+ cat > $TMPC << EOF
+#include <numa.h>
+int main(void) { return numa_available(); }
+EOF
+
+ if compile_prog "" "-lnuma" ; then
+ numa=yes
+ libs_softmmu="-lnuma $libs_softmmu"
+ else
+ if test "$numa" = "yes" ; then
+ feature_not_found "linux NUMA (install numactl?)"
+ fi
+ numa=no
+ fi
+fi
+
+##########################################
# signalfd probe
signalfd="no"
cat > $TMPC << EOF
@@ -4045,6 +4073,7 @@ echo "TPM passthrough $tpm_passthrough"
echo "QOM debugging $qom_cast_debug"
echo "vhdx $vhdx"
echo "Quorum $quorum"
+echo "NUMA host support $numa"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -4983,6 +5012,10 @@ if [ "$dtc_internal" = "yes" ]; then
echo "config-host.h: subdir-dtc" >> $config_host_mak
fi
+if test "$numa" = "yes"; then
+ echo "CONFIG_NUMA=y" >> $config_host_mak
+fi
+
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests"
DIRS="$DIRS fsdev"
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 09/11] hostmem backend: implement memory policy
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (7 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 08/11] Add Linux libnuma detection Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 10/11] qmp: add query-memdev Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 11/11] hmp: add info memdev Hu Tao
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
---
backends/hostmem.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++--
include/sysemu/hostmem.h | 4 ++
qapi-schema.json | 20 ++++++++++
3 files changed, 118 insertions(+), 3 deletions(-)
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 0bd3900..077e8cc 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -10,11 +10,14 @@
* See the COPYING file in the top-level directory.
*/
#include "sysemu/hostmem.h"
-#include "sysemu/sysemu.h"
#include "qapi/visitor.h"
+#include "qapi-visit.h"
#include "qapi/qmp/qerror.h"
#include "qemu/config-file.h"
#include "qom/object_interfaces.h"
+#ifdef CONFIG_NUMA
+#include <numaif.h>
+#endif
static void
hostmemory_backend_get_size(Object *obj, Visitor *v, void *opaque,
@@ -50,11 +53,85 @@ hostmemory_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)
+{
+ 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;
+ }
+}
+
+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;
+}
+
static void hostmemory_backend_initfn(Object *obj)
{
object_property_add(obj, "size", "int",
hostmemory_backend_get_size,
hostmemory_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 hostmemory_backend_finalize(Object *obj)
@@ -69,8 +146,22 @@ static void hostmemory_backend_finalize(Object *obj)
static void
hostmemory_backend_memory_init(UserCreatable *uc, Error **errp)
{
- error_setg(errp, "memory_init is not implemented for type [%s]",
- object_get_typename(OBJECT(uc)));
+#ifdef CONFIG_NUMA
+ HostMemoryBackend *backend = MEMORY_BACKEND(uc);
+ void *p = memory_region_get_ram_ptr(&backend->mr);
+ 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(p, backend->size, backend->policy, backend->host_nodes,
+ maxnode + 2, 0)) {
+ error_setg_errno(errp, errno,
+ "cannot bind memory to host NUMA nodes\n");
+ return;
+ }
+#endif
}
MemoryRegion *
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index bc3ffb3..a2b0702 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -12,10 +12,12 @@
#ifndef QEMU_RAM_H
#define QEMU_RAM_H
+#include "sysemu/sysemu.h" /* for MAX_NODES */
#include "qom/object.h"
#include "qapi/error.h"
#include "exec/memory.h"
#include "qemu/option.h"
+#include "qemu/bitmap.h"
#define TYPE_MEMORY_BACKEND "memory"
#define MEMORY_BACKEND(obj) \
@@ -50,6 +52,8 @@ struct HostMemoryBackend {
/* protected */
uint64_t size;
+ DECLARE_BITMAP(host_nodes, MAX_NODES);
+ HostMemPolicy policy;
MemoryRegion mr;
};
diff --git a/qapi-schema.json b/qapi-schema.json
index 62e0b83..86b78a5 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4554,3 +4554,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
+#
+# @membind: 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', 'membind', 'interleave' ] }
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 10/11] qmp: add query-memdev
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (8 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 09/11] hostmem backend: implement memory policy Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 11/11] hmp: add info memdev Hu Tao
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
Add qmp command query-memdev to query for information
of memory devices
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
---
backends/hostmem.c | 1 +
numa.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
qapi-schema.json | 31 +++++++++++++++++++++++++++
qmp-commands.hx | 32 ++++++++++++++++++++++++++++
4 files changed, 125 insertions(+)
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 077e8cc..0d4f863 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -18,6 +18,7 @@
#ifdef CONFIG_NUMA
#include <numaif.h>
#endif
+#include "qmp-commands.h"
static void
hostmemory_backend_get_size(Object *obj, Visitor *v, void *opaque,
diff --git a/numa.c b/numa.c
index 8d05078..933f6b8 100644
--- a/numa.c
+++ b/numa.c
@@ -28,7 +28,11 @@
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
+#include "qapi/string-output-visitor.h"
+#include "qapi/string-input-visitor.h"
#include "qapi/qmp/qerror.h"
+#include "qmp-commands.h"
+
QemuOptsList qemu_numa_opts = {
.name = "numa",
@@ -259,3 +263,60 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
addr += size;
}
}
+
+MemdevList *qmp_query_memdev(Error **errp)
+{
+ StringOutputVisitor *ov = string_output_visitor_new(false);
+ StringInputVisitor *iv;
+ MemdevList *list = NULL, *m;
+ HostMemoryBackend *backend;
+ Error *err = NULL;
+ int i;
+
+ for (i = 0; i < nb_numa_nodes; i++) {
+ backend = numa_info[i].node_memdev;
+
+ m = g_malloc0(sizeof(*m));
+ m->value = g_malloc0(sizeof(*m->value));
+ m->value->size = object_property_get_int(OBJECT(backend), "size",
+ &err);
+ if (err) {
+ goto error;
+ }
+ m->value->policy = object_property_get_str(OBJECT(backend), "policy",
+ &err);
+ if (err) {
+ goto error;
+ }
+ object_property_get(OBJECT(backend), string_output_get_visitor(ov),
+ "host-nodes", &err);
+ if (err) {
+ goto error;
+ }
+ iv = string_input_visitor_new(string_output_get_string(ov));
+ visit_type_uint16List(string_input_get_visitor(iv),
+ &m->value->host_nodes, NULL, &err);
+ if (err) {
+ string_input_visitor_cleanup(iv);
+ goto error;
+ }
+
+ m->next = list;
+ list = m;
+ string_input_visitor_cleanup(iv);
+ }
+
+ string_output_visitor_cleanup(ov);
+
+ return list;
+error:
+ while (list) {
+ m = list;
+ list = list->next;
+ g_free(m->value);
+ g_free(m);
+ }
+ qerror_report_err(err);
+ return NULL;
+}
+
diff --git a/qapi-schema.json b/qapi-schema.json
index 86b78a5..b5dccfa 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4574,3 +4574,34 @@
##
{ 'enum': 'HostMemPolicy',
'data': [ 'default', 'preferred', 'membind', 'interleave' ] }
+
+##
+# @Memdev:
+#
+# Information of memory device
+#
+# @size: memory device size
+#
+# @host-nodes: host nodes for its memory policy
+#
+# @policy: memory policy of memory device
+#
+# Since: 2.1
+##
+
+{ 'type': 'Memdev',
+ 'data': {
+ 'size': 'size',
+ 'host-nodes': ['uint16'],
+ 'policy': 'str' }}
+
+##
+# @query-memdev:
+#
+# Returns information for all memory devices.
+#
+# Returns: a list of @Memdev.
+#
+# Since: 2.1
+##
+{ 'command': 'query-memdev', 'returns': ['Memdev'] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8a0e832..903a48a 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3498,3 +3498,35 @@ Example:
} } ] }
EQMP
+
+ {
+ .name = "query-memdev",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_memdev,
+ },
+
+SQMP
+query-memdev
+------------
+
+Show memory devices information.
+
+
+Example (1):
+
+-> { "execute": "query-memdev" }
+<- { "return": [
+ {
+ "size": 536870912,
+ "host-nodes": [0, 1],
+ "policy": "bind"
+ },
+ {
+ "size": 536870912,
+ "host-nodes": [2, 3],
+ "policy": "preferred"
+ }
+ ]
+ }
+
+EQMP
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v19 11/11] hmp: add info memdev
2014-03-04 7:28 [Qemu-devel] [PATCH v19 00/11] Add support for binding guest numa nodes to host numa nodes Hu Tao
` (9 preceding siblings ...)
2014-03-04 7:28 ` [Qemu-devel] [PATCH v19 10/11] qmp: add query-memdev Hu Tao
@ 2014-03-04 7:28 ` Hu Tao
10 siblings, 0 replies; 15+ messages in thread
From: Hu Tao @ 2014-03-04 7:28 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, gaowanlong, imammedo
This is the hmp counterpart of qmp query-memdev.
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
---
hmp.c | 27 +++++++++++++++++++++++++++
hmp.h | 1 +
monitor.c | 7 +++++++
3 files changed, 35 insertions(+)
diff --git a/hmp.c b/hmp.c
index e3ddd46..3bbe5ff 100644
--- a/hmp.c
+++ b/hmp.c
@@ -22,6 +22,8 @@
#include "qemu/sockets.h"
#include "monitor/monitor.h"
#include "qapi/opts-visitor.h"
+#include "qapi/string-output-visitor.h"
+#include "qapi-visit.h"
#include "ui/console.h"
#include "block/qapi.h"
#include "qemu-io.h"
@@ -1644,3 +1646,28 @@ void hmp_object_del(Monitor *mon, const QDict *qdict)
qmp_object_del(id, &err);
hmp_handle_error(mon, &err);
}
+
+void hmp_info_memdev(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ MemdevList *memdev_list = qmp_query_memdev(&err);
+ MemdevList *m = memdev_list;
+ StringOutputVisitor *ov = string_output_visitor_new(false);
+ int i = 0;
+
+
+ while (m) {
+ visit_type_uint16List(string_output_get_visitor(ov),
+ &m->value->host_nodes, NULL, NULL);
+ monitor_printf(mon, "memory device %d\n", i);
+ monitor_printf(mon, " size: %ld\n", m->value->size);
+ monitor_printf(mon, " policy: %s\n", m->value->policy);
+ monitor_printf(mon, " host nodes: %s\n", string_output_get_string(ov));
+
+ m = m->next;
+ i++;
+ }
+
+ monitor_printf(mon, "\n");
+ string_output_visitor_cleanup(ov);
+}
diff --git a/hmp.h b/hmp.h
index ed58f0e..b6f5d02 100644
--- a/hmp.h
+++ b/hmp.h
@@ -92,5 +92,6 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict);
void hmp_cpu_add(Monitor *mon, const QDict *qdict);
void hmp_object_add(Monitor *mon, const QDict *qdict);
void hmp_object_del(Monitor *mon, const QDict *qdict);
+void hmp_info_memdev(Monitor *mon, const QDict *qdict);
#endif
diff --git a/monitor.c b/monitor.c
index d7f1ade..fec4836 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2949,6 +2949,13 @@ static mon_cmd_t info_cmds[] = {
.mhandler.cmd = hmp_info_tpm,
},
{
+ .name = "memdev",
+ .args_type = "",
+ .params = "",
+ .help = "show the memory device",
+ .mhandler.cmd = hmp_info_memdev,
+ },
+ {
.name = NULL,
},
};
--
1.8.5.2.229.g4448466
^ permalink raw reply related [flat|nested] 15+ messages in thread