@@ -634,6 +634,27 @@ QemuOptsList qemu_smp_opts = {
},
};
+QemuOptsList qemu_numa_opts = {
+ .name = "numa",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_numa_opts.head),
+ .desc = {
+ {
+ .name = "nodeid",
+ .type = QEMU_OPT_NUMBER,
+ .help = "Numeric identifier for the node",
+ }, {
+ .name = "mem",
+ .type = QEMU_OPT_SIZE,
+ .help = "Amount of memory for this node",
+ }, {
+ .name = "cpus",
+ .type = QEMU_OPT_STRING,
+ .help = "Identifier or range of identifiers for CPUs in this node",
+ },
+ { /*End of list */ }
+ },
+};
+
QemuOptsList qemu_boot_opts = {
.name = "boot-opts",
.head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
@@ -674,6 +695,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_option_rom_opts,
&qemu_machine_opts,
&qemu_smp_opts,
+ &qemu_numa_opts,
&qemu_boot_opts,
&qemu_iscsi_opts,
NULL,
@@ -935,41 +935,29 @@ char *get_boot_devices_list(uint32_t *size)
return list;
}
-static void numa_add(const char *optarg)
+static int numa_add(QemuOpts *opts, void *opaque)
{
- char option[128];
+ const char *option;
char *endptr;
unsigned long long value, endvalue;
int nodenr;
- optarg = get_opt_name(option, 128, optarg, ',') + 1;
- if (strcmp(option, "node")) {
- return;
- }
- if (get_param_value(option, 128, "nodeid", optarg) == 0) {
- nodenr = nb_numa_nodes;
- } else {
- nodenr = strtoull(option, NULL, 10);
+ nodenr = qemu_opt_get_number(opts, "nodeid", nb_numa_nodes);
+ if (nodenr >= MAX_NODES) {
+ fprintf(stderr, "only %d NUMA nodes supported.\n", MAX_NODES);
+ return 1;
}
- if (get_param_value(option, 128, "mem", optarg) == 0) {
- node_mem[nodenr] = 0;
- } else {
- int64_t sval;
- sval = strtosz(option, &endptr);
- if (sval < 0 || *endptr) {
- fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg);
- exit(1);
- }
- node_mem[nodenr] = sval;
- }
- if (get_param_value(option, 128, "cpus", optarg) == 0) {
- node_cpumask[nodenr] = 0;
- } else {
+ node_mem[nodenr] = qemu_opt_get_size(opts, "mem", 0);
+ node_cpumask[nodenr] = 0;
+
+ option = qemu_opt_get(opts, "cpus");
+ if (option) {
value = strtoull(option, &endptr, 10);
if (value >= 64) {
value = 63;
fprintf(stderr, "only 64 CPUs in NUMA mode supported.\n");
+ return 1;
} else {
if (*endptr == '-') {
endvalue = strtoull(endptr+1, &endptr, 10);
@@ -977,6 +965,7 @@ static void numa_add(const char *optarg)
endvalue = 62;
fprintf(stderr,
"only 63 CPUs in NUMA mode supported.\n");
+ return 1;
}
value = (2ULL << endvalue) - (1ULL << value);
} else {
@@ -986,6 +975,7 @@ static void numa_add(const char *optarg)
node_cpumask[nodenr] = value;
}
nb_numa_nodes++;
+ return 0;
}
static int smp_init_func(QemuOpts *opts, void *opaque)
@@ -2488,7 +2478,13 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "qemu: too many NUMA nodes\n");
exit(1);
}
- numa_add(optarg);
+ if (strcmp(optarg, "node") == 0) {
+ qemu_opts_create(qemu_find_opts("numa"), NULL, 0);
+ } else if (memcmp(optarg, "node,", 5) == 0) {
+ qemu_opts_parse(qemu_find_opts("numa"), optarg + 5, 0);
+ } else {
+ fprintf(stderr, "qemu: expected 'node', -numa ignored\n");
+ }
break;
case QEMU_OPTION_display:
display_type = select_display(optarg);
@@ -3221,6 +3217,10 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ if (qemu_opts_foreach(qemu_find_opts("numa"), numa_add, NULL, 1) != 0) {
+ exit(1);
+ }
+
/*
* Get the default machine options from the machine if it is not already
* specified either by the configuration file or by the command line.
This requires some special casing to skip the fake "node" option and to handle the automatic "-numa node" syntax. Besides this, the option parsing maps easily to QemuOpts. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- qemu-config.c | 22 ++++++++++++++++++++++ vl.c | 50 +++++++++++++++++++++++++------------------------- 2 files changed, 47 insertions(+), 25 deletions(-)