Add support for binding guest numa nodes to host numa nodes
v19 cover Add support for binding guest numa nodes to host numa nodes
Based on series `convert -numa to QemuOpts/OptsVisitor' posted by Igor at http://lists.nongnu.org/archive/html/qemu-devel/2014-02/msg02801.html.
You can also checkout this series out at
https://github.com/taohu/qemu/tree/numa-binding-v19, including all required patches.
changes in v19:
- use complete() method of user_creatable in memdev backend
- implement qmp query-memdev by walking through numa_info[...].node_memdev and using object_property_get to get information as suggested by Paolo
- implement info memdev
- drop ram_backend->relative
- make string output visitor parse int list
- introduce libnuma
Hu Tao (5):
qapi: make string input visitor parse int list
qapi: make string output visitor parse int list
hostmem backend: implement memory policy
qmp: add query-memdev
hmp: add info memdev
Igor Mammedov (2):
object_add: allow completion handler to get canonical path add memdev backend infrastructure
Paolo Bonzini (3):
pc: pass QEMUMachineInitArgs to pc_memory_init
numa: introduce memory_region_allocate_system_memory
numa: add -numa node,memdev= option
Wanlong Gao (1):
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.
backends/Makefile.objs | 2 + backends/hostmem-ram.c | 77 ++++++++++++++ backends/hostmem.c | 202 +++++++++++++++++++++++++++++++++++++ configure | 33 ++++++ hmp.c | 27 +++++ hmp.h | 1 + hw/i386/pc.c | 15 ++- hw/i386/pc_piix.c | 8 +- hw/i386/pc_q35.c | 4 +- include/hw/i386/pc.h | 7 +- include/sysemu/hostmem.h | 64 ++++++++++++ include/sysemu/sysemu.h | 8 ++ monitor.c | 7 ++ numa.c | 133 ++++++++++++++++++++++++ qapi-schema.json | 57 ++++++++++- qapi/string-input-visitor.c | 160 +++++++++++++++++++++++++++-- qapi/string-output-visitor.c | 156 +++++++++++++++++++++++++++- qmp-commands.hx | 32 ++++++ qmp.c | 8 +- tests/test-string-input-visitor.c | 21 ++++ tests/test-string-output-visitor.c | 26 +++++ vl.c | 9 +- 22 files changed, 1017 insertions(+), 40 deletions(-) create mode 100644 backends/hostmem-ram.c create mode 100644 backends/hostmem.c create mode 100644 include/sysemu/hostmem.h
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 1/11 object_add: allow completion handler to get canonical path
From: Igor Mammedov <[email protected]>
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.
--- qmp.c | 8 +++++--- vl.c | 9 +++++---- 2 files changed, 10 insertions(+), 7 deletions(-)
qmp.c +5 -3
@@ -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);
vl.c +5 -4
@@ -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) {
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 2/11 add memdev backend infrastructure
In reply to Hu TaoFrom: Igor Mammedov <[email protected]>
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().
--- 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
backends/Makefile.objs +2 -0
@@ -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
backends/hostmem-ram.c new file +77 -0
77 lines not on this page · raw message
backends/hostmem.c new file +110 -0
110 lines not on this page · raw message
include/sysemu/hostmem.h new file +60 -0
60 lines not on this page · raw message
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 3/11 pc: pass QEMUMachineInitArgs to pc_memory_init
In reply to Hu TaoFrom: Paolo Bonzini <[email protected]>
--- 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(-)
hw/i386/pc.c +5 -6
@@ -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++) {
hw/i386/pc_piix.c +3 -5
@@ -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));
hw/i386/pc_q35.c +1 -3
@@ -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); }
include/hw/i386/pc.h +3 -4
@@ -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,
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 4/11 numa: introduce memory_region_allocate_system_memory
In reply to Hu TaoFrom: Paolo Bonzini <[email protected]>
--- hw/i386/pc.c | 4 +--- include/sysemu/sysemu.h | 5 +++++ numa.c | 10 ++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-)
hw/i386/pc.c +1 -3
@@ -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,
include/sysemu/sysemu.h +5 -0
@@ -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 {
numa.c +10 -0
@@ -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); +}
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 5/11 numa: add -numa node, memdev= option
In reply to Hu TaoFrom: Paolo Bonzini <[email protected]>
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".
[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(-)
include/sysemu/sysemu.h +3 -0
@@ -137,9 +137,12 @@ extern QEMUClockType rtc_clock;#define MAX_NODES 128#define MAX_CPUMASK_BITS 255extern 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 );
numa.c +64 -2
108 lines not on this page · raw message
qapi-schema.json +5 -1
@@ -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' }}
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 6/11 qapi: make string input visitor parse int list
In reply to Hu Tao--- qapi/string-input-visitor.c | 160 ++++++++++++++++++++++++++++++++++++-- tests/test-string-input-visitor.c | 21 +++++ 2 files changed, 175 insertions(+), 6 deletions(-)
qapi/string-input-visitor.c +154 -6
@@ -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;
tests/test-string-input-visitor.c +21 -0
@@ -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",
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 7/11 qapi: make string output visitor parse int list
In reply to Hu TaoFrom: Hu Tao <[email protected]>
--- qapi/string-output-visitor.c | 156 +++++++++++++++++++++++++++++++++++-- tests/test-string-output-visitor.c | 26 +++++++ 2 files changed, 177 insertions(+), 5 deletions(-)
qapi/string-output-visitor.c +151 -5
@@ -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; }
tests/test-string-output-visitor.c +26 -0
@@ -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 ();
Signature · 1 line
1.8.5.2.229.g4448466
Re: [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
Il 04/03/2014 08:28, Hu Tao ha scritto:
Quoted 111 lines
From: Hu Tao <[email protected]>
Signed-off-by Hu Tao <[email protected]>--- qapi/string-output-visitor.c | 156 +++++++++++++++++++++++++++++++++++-- tests/test-string-output-visitor.c | 26 +++++++ 2 files changed, 177 insertions(+), 5 deletions(-)qapi/string-output-visitor.c +77
-5@@ -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);
qapi/string-output-visitor.c static void print_type_int(Visitor *v, int64_t *obj, const char *name, · line 124
Quoted 10 lines
qapi/string-output-visitor.c +10
-0+ }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)"?
qapi/string-output-visitor.c static void print_type_int(Visitor *v, int64_t *obj, const char *name, · line 130
Quoted 6 lines
qapi/string-output-visitor.c +6
-0+ }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
Quoted 121 lines
qapi/string-output-visitor.c +58
-0+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; }tests/test-string-output-visitor.c +26
-0@@ -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 ();
Re: [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
Quoted 116 lines · Paolo Bonzini
Il 04/03/2014 08:28, Hu Tao ha scritto:
Quoted 115 lines
From: Hu Tao <[email protected]>
Signed-off-by Hu Tao <[email protected]>---
qapi/string-output-visitor.c| 156 +++++++++++++++++++++++++++++++++++--tests/test-string-output-visitor.c| 26 +++++++2 files changed, 177 insertions(+), 5 deletions(-)qapi/string-output-visitor.c +35
-0@@ -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;qapi/string-output-visitor.c +11
-0+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)qapi/string-output-visitor.c +35
-5@@ -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 {
Quoted 8 lines
qapi/string-output-visitor.c static void print_type_int(Visitor *v, int64_t *obj, const char *name, · line 124
Quoted 6 lines
qapi/string-output-visitor.c +6
-0+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.
Quoted 11 lines
qapi/string-output-visitor.c static void print_type_int(Visitor *v, int64_t *obj, const char *name, · line 130
Quoted 7 lines
qapi/string-output-visitor.c +6
-0+ }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.
Re: [Qemu-devel] [PATCH v19 07/11] qapi: make string output visitor parse int list
Il 04/03/2014 10:23, Hu Tao ha scritto:
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
qapi/string-output-visitor.c +6
-0+ }else { + out =g_strdup_printf ("%lld-%lld" , + (long long ) sov->range_start.s, + (long long ) sov->range_end.s); + } + }
Quoted 6 lines
Quoted 3 lines
Quoted 3 lines
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
PATCH v19 8/11 Add Linux libnuma detection
In reply to Hu TaoFrom: Wanlong Gao <[email protected]>
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.
--- configure | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
configure +33 -0
@@ -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"
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 9/11 hostmem backend: implement memory policy
In reply to Hu Tao--- backends/hostmem.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++-- include/sysemu/hostmem.h | 4 ++ qapi-schema.json | 20 ++++++++++ 3 files changed, 118 insertions(+), 3 deletions(-)
backends/hostmem.c +94 -3
@@ -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 *
include/sysemu/hostmem.h +4 -0
@@ -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; };
qapi-schema.json +20 -0
@@ -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' ] }
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 10/11 qmp: add query-memdev
In reply to Hu TaoAdd qmp command query-memdev to query for information of memory devices
--- backends/hostmem.c | 1 + numa.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ qapi-schema.json | 31 +++++++++++++++++++++++++++ qmp-commands.hx | 32 ++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+)
backends/hostmem.c +1 -0
@@ -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,
numa.c +61 -0
71 lines not on this page · raw message
qapi-schema.json +31 -0
@@ -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'] }
qmp-commands.hx +32 -0
@@ -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
Signature · 1 line
1.8.5.2.229.g4448466
PATCH v19 11/11 hmp: add info memdev
In reply to Hu TaoThis is the hmp counterpart of qmp query-memdev.
--- hmp.c | 27 +++++++++++++++++++++++++++ hmp.h | 1 + monitor.c | 7 +++++++ 3 files changed, 35 insertions(+)
hmp.c +27 -0
@@ -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); +}
hmp.h +1 -0
@@ -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
monitor.c +7 -0
@@ -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, }, };
Signature · 1 line
1.8.5.2.229.g4448466