NUMA: convert -numa option to use OptsVisitor
Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com> Signed-off-by: Igor Mammedov <imammedo@redhat.com> Tested-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									8c85901ed3
								
							
						
					
					
						commit
						0042109a6a
					
				| @ -148,9 +148,10 @@ typedef struct node_info { | ||||
|     DECLARE_BITMAP(node_cpu, MAX_CPUMASK_BITS); | ||||
| } NodeInfo; | ||||
| extern NodeInfo numa_info[MAX_NODES]; | ||||
| void numa_add(const char *optarg); | ||||
| void set_numa_nodes(void); | ||||
| void set_numa_modes(void); | ||||
| extern QemuOptsList qemu_numa_opts; | ||||
| int numa_init_func(QemuOpts *opts, void *opaque); | ||||
| 
 | ||||
| #define MAX_OPTION_ROMS 16 | ||||
| typedef struct QEMUOptionRom { | ||||
|  | ||||
							
								
								
									
										155
									
								
								numa.c
									
									
									
									
									
								
							
							
						
						
									
										155
									
								
								numa.c
									
									
									
									
									
								
							| @ -28,101 +28,96 @@ | ||||
| #include "qom/cpu.h" | ||||
| #include "qemu/error-report.h" | ||||
| #include "include/exec/cpu-common.h" /* for RAM_ADDR_FMT */ | ||||
| #include "qapi-visit.h" | ||||
| #include "qapi/opts-visitor.h" | ||||
| #include "qapi/dealloc-visitor.h" | ||||
| #include "qapi/qmp/qerror.h" | ||||
| 
 | ||||
| static void numa_node_parse_cpus(int nodenr, const char *cpus) | ||||
| QemuOptsList qemu_numa_opts = { | ||||
|     .name = "numa", | ||||
|     .implied_opt_name = "type", | ||||
|     .head = QTAILQ_HEAD_INITIALIZER(qemu_numa_opts.head), | ||||
|     .desc = { { 0 } } /* validated with OptsVisitor */ | ||||
| }; | ||||
| 
 | ||||
| static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp) | ||||
| { | ||||
|     char *endptr; | ||||
|     unsigned long long value, endvalue; | ||||
|     uint16_t nodenr; | ||||
|     uint16List *cpus = NULL; | ||||
| 
 | ||||
|     /* Empty CPU range strings will be considered valid, they will simply
 | ||||
|      * not set any bit in the CPU bitmap. | ||||
|      */ | ||||
|     if (!*cpus) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (parse_uint(cpus, &value, &endptr, 10) < 0) { | ||||
|         goto error; | ||||
|     } | ||||
|     if (*endptr == '-') { | ||||
|         if (parse_uint_full(endptr + 1, &endvalue, 10) < 0) { | ||||
|             goto error; | ||||
|         } | ||||
|     } else if (*endptr == '\0') { | ||||
|         endvalue = value; | ||||
|     if (node->has_nodeid) { | ||||
|         nodenr = node->nodeid; | ||||
|     } else { | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     if (endvalue >= MAX_CPUMASK_BITS) { | ||||
|         endvalue = MAX_CPUMASK_BITS - 1; | ||||
|         fprintf(stderr, | ||||
|             "qemu: NUMA: A max of %d VCPUs are supported\n", | ||||
|              MAX_CPUMASK_BITS); | ||||
|     } | ||||
| 
 | ||||
|     if (endvalue < value) { | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     bitmap_set(numa_info[nodenr].node_cpu, value, endvalue-value+1); | ||||
|     return; | ||||
| 
 | ||||
| error: | ||||
|     fprintf(stderr, "qemu: Invalid NUMA CPU range: %s\n", cpus); | ||||
|     exit(1); | ||||
| } | ||||
| 
 | ||||
| void numa_add(const char *optarg) | ||||
| { | ||||
|     char option[128]; | ||||
|     char *endptr; | ||||
|     unsigned long long nodenr; | ||||
| 
 | ||||
|     optarg = get_opt_name(option, 128, optarg, ','); | ||||
|     if (*optarg == ',') { | ||||
|         optarg++; | ||||
|     } | ||||
|     if (!strcmp(option, "node")) { | ||||
| 
 | ||||
|         if (nb_numa_nodes >= MAX_NODES) { | ||||
|             fprintf(stderr, "qemu: too many NUMA nodes\n"); | ||||
|             exit(1); | ||||
|         } | ||||
| 
 | ||||
|         if (get_param_value(option, 128, "nodeid", optarg) == 0) { | ||||
|         nodenr = nb_numa_nodes; | ||||
|         } else { | ||||
|             if (parse_uint_full(option, &nodenr, 10) < 0) { | ||||
|                 fprintf(stderr, "qemu: Invalid NUMA nodeid: %s\n", option); | ||||
|                 exit(1); | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     if (nodenr >= MAX_NODES) { | ||||
|             fprintf(stderr, "qemu: invalid NUMA nodeid: %llu\n", nodenr); | ||||
|             exit(1); | ||||
|         error_setg(errp, "Max number of NUMA nodes reached: %" | ||||
|                    PRIu16 "\n", nodenr); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|         if (get_param_value(option, 128, "mem", optarg) == 0) { | ||||
|             numa_info[nodenr].node_mem = 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); | ||||
|     for (cpus = node->cpus; cpus; cpus = cpus->next) { | ||||
|         if (cpus->value > MAX_CPUMASK_BITS) { | ||||
|             error_setg(errp, "CPU number %" PRIu16 " is bigger than %d", | ||||
|                        cpus->value, MAX_CPUMASK_BITS); | ||||
|             return; | ||||
|         } | ||||
|             numa_info[nodenr].node_mem = sval; | ||||
|         bitmap_set(numa_info[nodenr].node_cpu, cpus->value, 1); | ||||
|     } | ||||
|         if (get_param_value(option, 128, "cpus", optarg) != 0) { | ||||
|             numa_node_parse_cpus(nodenr, option); | ||||
| 
 | ||||
|     if (node->has_mem) { | ||||
|         uint64_t mem_size = node->mem; | ||||
|         const char *mem_str = qemu_opt_get(opts, "mem"); | ||||
|         /* Fix up legacy suffix-less format */ | ||||
|         if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) { | ||||
|             mem_size <<= 20; | ||||
|         } | ||||
|         numa_info[nodenr].node_mem = mem_size; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int numa_init_func(QemuOpts *opts, void *opaque) | ||||
| { | ||||
|     NumaOptions *object = NULL; | ||||
|     Error *err = NULL; | ||||
| 
 | ||||
|     { | ||||
|         OptsVisitor *ov = opts_visitor_new(opts); | ||||
|         visit_type_NumaOptions(opts_get_visitor(ov), &object, NULL, &err); | ||||
|         opts_visitor_cleanup(ov); | ||||
|     } | ||||
| 
 | ||||
|     if (err) { | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     switch (object->kind) { | ||||
|     case NUMA_OPTIONS_KIND_NODE: | ||||
|         numa_node_parse(object->node, opts, &err); | ||||
|         if (err) { | ||||
|             goto error; | ||||
|         } | ||||
|         nb_numa_nodes++; | ||||
|     } else { | ||||
|         fprintf(stderr, "Invalid -numa option: %s\n", option); | ||||
|         exit(1); | ||||
|         break; | ||||
|     default: | ||||
|         abort(); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| 
 | ||||
| error: | ||||
|     qerror_report_err(err); | ||||
|     error_free(err); | ||||
| 
 | ||||
|     if (object) { | ||||
|         QapiDeallocVisitor *dv = qapi_dealloc_visitor_new(); | ||||
|         visit_type_NumaOptions(qapi_dealloc_get_visitor(dv), | ||||
|                                &object, NULL, NULL); | ||||
|         qapi_dealloc_visitor_cleanup(dv); | ||||
|     } | ||||
| 
 | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| void set_numa_nodes(void) | ||||
|  | ||||
| @ -3097,3 +3097,35 @@ | ||||
|               'btn'     : 'InputBtnEvent', | ||||
|               'rel'     : 'InputMoveEvent', | ||||
|               'abs'     : 'InputMoveEvent' } } | ||||
| 
 | ||||
| ## | ||||
| # @NumaOptions | ||||
| # | ||||
| # A discriminated record of NUMA options. (for OptsVisitor) | ||||
| # | ||||
| # Since 2.1 | ||||
| ## | ||||
| { 'union': 'NumaOptions', | ||||
|   'data': { | ||||
|     'node': 'NumaNodeOptions' }} | ||||
| 
 | ||||
| ## | ||||
| # @NumaNodeOptions | ||||
| # | ||||
| # Create a guest NUMA node. (for OptsVisitor) | ||||
| # | ||||
| # @nodeid: #optional NUMA node ID (increase by 1 from 0 if omitted) | ||||
| # | ||||
| # @cpus: #optional VCPUs belonging to this node (assign VCPUS round-robin | ||||
| #         if omitted) | ||||
| # | ||||
| # @mem: #optional memory size of this node (equally divide total memory among | ||||
| #        nodes if omitted) | ||||
| # | ||||
| # Since: 2.1 | ||||
| ## | ||||
| { 'type': 'NumaNodeOptions', | ||||
|   'data': { | ||||
|    '*nodeid': 'uint16', | ||||
|    '*cpus':   ['uint16'], | ||||
|    '*mem':    'size' }} | ||||
|  | ||||
							
								
								
									
										11
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								vl.c
									
									
									
									
									
								
							| @ -2938,6 +2938,7 @@ int main(int argc, char **argv, char **envp) | ||||
|     qemu_add_opts(&qemu_realtime_opts); | ||||
|     qemu_add_opts(&qemu_msg_opts); | ||||
|     qemu_add_opts(&qemu_name_opts); | ||||
|     qemu_add_opts(&qemu_numa_opts); | ||||
| 
 | ||||
|     runstate_init(); | ||||
| 
 | ||||
| @ -3133,7 +3134,10 @@ int main(int argc, char **argv, char **envp) | ||||
|                 } | ||||
|                 break; | ||||
|             case QEMU_OPTION_numa: | ||||
|                 numa_add(optarg); | ||||
|                 opts = qemu_opts_parse(qemu_find_opts("numa"), optarg, 1); | ||||
|                 if (!opts) { | ||||
|                     exit(1); | ||||
|                 } | ||||
|                 break; | ||||
|             case QEMU_OPTION_display: | ||||
|                 display_type = select_display(optarg); | ||||
| @ -4303,6 +4307,11 @@ int main(int argc, char **argv, char **envp) | ||||
|     default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS); | ||||
|     default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS); | ||||
| 
 | ||||
|     if (qemu_opts_foreach(qemu_find_opts("numa"), numa_init_func, | ||||
|                           NULL, 1) != 0) { | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     set_numa_nodes(); | ||||
| 
 | ||||
|     if (qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, 1) != 0) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Wanlong Gao
						Wanlong Gao