xref: /dpdk/lib/eal/common/eal_common_options.c (revision bbbe38a6d59ccdda25917712701e629d0b10af6f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright(c) 2014 6WIND S.A.
4  */
5 
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #ifndef RTE_EXEC_ENV_WINDOWS
10 #include <syslog.h>
11 #endif
12 #include <ctype.h>
13 #include <limits.h>
14 #include <errno.h>
15 #include <getopt.h>
16 #ifndef RTE_EXEC_ENV_WINDOWS
17 #include <dlfcn.h>
18 #include <libgen.h>
19 #endif
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #ifndef RTE_EXEC_ENV_WINDOWS
23 #include <dirent.h>
24 #endif
25 
26 #include <rte_string_fns.h>
27 #include <rte_eal.h>
28 #include <rte_log.h>
29 #include <rte_lcore.h>
30 #include <rte_memory.h>
31 #include <rte_tailq.h>
32 #include <rte_version.h>
33 #include <rte_devargs.h>
34 #include <rte_memcpy.h>
35 #ifndef RTE_EXEC_ENV_WINDOWS
36 #include <rte_telemetry.h>
37 #endif
38 #include <rte_vect.h>
39 
40 #include "eal_internal_cfg.h"
41 #include "eal_options.h"
42 #include "eal_filesystem.h"
43 #include "eal_private.h"
44 #include "eal_log.h"
45 #ifndef RTE_EXEC_ENV_WINDOWS
46 #include "eal_trace.h"
47 #endif
48 
49 #define BITS_PER_HEX 4
50 #define LCORE_OPT_LST 1
51 #define LCORE_OPT_MSK 2
52 #define LCORE_OPT_MAP 3
53 
54 const char
55 eal_short_options[] =
56 	"a:" /* allow */
57 	"b:" /* block */
58 	"c:" /* coremask */
59 	"s:" /* service coremask */
60 	"d:" /* driver */
61 	"h"  /* help */
62 	"l:" /* corelist */
63 	"S:" /* service corelist */
64 	"m:" /* memory size */
65 	"n:" /* memory channels */
66 	"r:" /* memory ranks */
67 	"v"  /* version */
68 	"w:" /* pci-whitelist (deprecated) */
69 	;
70 
71 const struct option
72 eal_long_options[] = {
73 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
74 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
75 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
76 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
77 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
78 	{OPT_HUGE_UNLINK,       0, NULL, OPT_HUGE_UNLINK_NUM      },
79 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
80 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
81 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
82 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
83 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
84 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
85 	{OPT_TRACE_MODE,        1, NULL, OPT_TRACE_MODE_NUM       },
86 	{OPT_MASTER_LCORE,      1, NULL, OPT_MASTER_LCORE_NUM     },
87 	{OPT_MAIN_LCORE,        1, NULL, OPT_MAIN_LCORE_NUM       },
88 	{OPT_MBUF_POOL_OPS_NAME, 1, NULL, OPT_MBUF_POOL_OPS_NAME_NUM},
89 	{OPT_NO_HPET,           0, NULL, OPT_NO_HPET_NUM          },
90 	{OPT_NO_HUGE,           0, NULL, OPT_NO_HUGE_NUM          },
91 	{OPT_NO_PCI,            0, NULL, OPT_NO_PCI_NUM           },
92 	{OPT_NO_SHCONF,         0, NULL, OPT_NO_SHCONF_NUM        },
93 	{OPT_IN_MEMORY,         0, NULL, OPT_IN_MEMORY_NUM        },
94 	{OPT_DEV_BLOCK,         1, NULL, OPT_DEV_BLOCK_NUM        },
95 	{OPT_DEV_ALLOW,		1, NULL, OPT_DEV_ALLOW_NUM	  },
96 	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
97 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
98 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
99 	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
100 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
101 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
102 	{OPT_VFIO_VF_TOKEN,     1, NULL, OPT_VFIO_VF_TOKEN_NUM    },
103 	{OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
104 	{OPT_LEGACY_MEM,        0, NULL, OPT_LEGACY_MEM_NUM       },
105 	{OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM},
106 	{OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM},
107 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
108 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
109 	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
110 
111 	/* legacy options that will be removed in future */
112 	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
113 	{OPT_PCI_WHITELIST,     1, NULL, OPT_PCI_WHITELIST_NUM    },
114 
115 	{0,                     0, NULL, 0                        }
116 };
117 
118 TAILQ_HEAD(shared_driver_list, shared_driver);
119 
120 /* Definition for shared object drivers. */
121 struct shared_driver {
122 	TAILQ_ENTRY(shared_driver) next;
123 
124 	char    name[PATH_MAX];
125 	void*   lib_handle;
126 };
127 
128 /* List of external loadable drivers */
129 static struct shared_driver_list solib_list =
130 TAILQ_HEAD_INITIALIZER(solib_list);
131 
132 #ifndef RTE_EXEC_ENV_WINDOWS
133 /* Default path of external loadable drivers */
134 static const char *default_solib_dir = RTE_EAL_PMD_PATH;
135 #endif
136 
137 /*
138  * Stringified version of solib path used by dpdk-pmdinfo.py
139  * Note: PLEASE DO NOT ALTER THIS without making a corresponding
140  * change to usertools/dpdk-pmdinfo.py
141  */
142 static const char dpdk_solib_path[] __rte_used =
143 "DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
144 
145 TAILQ_HEAD(device_option_list, device_option);
146 
147 struct device_option {
148 	TAILQ_ENTRY(device_option) next;
149 
150 	enum rte_devtype type;
151 	char arg[];
152 };
153 
154 static struct device_option_list devopt_list =
155 TAILQ_HEAD_INITIALIZER(devopt_list);
156 
157 static int main_lcore_parsed;
158 static int mem_parsed;
159 static int core_parsed;
160 
161 /* Allow the application to print its usage message too if set */
162 static rte_usage_hook_t rte_application_usage_hook;
163 
164 /* Returns rte_usage_hook_t */
165 rte_usage_hook_t
166 eal_get_application_usage_hook(void)
167 {
168 	return rte_application_usage_hook;
169 }
170 
171 /* Set a per-application usage message */
172 rte_usage_hook_t
173 rte_set_application_usage_hook(rte_usage_hook_t usage_func)
174 {
175 	rte_usage_hook_t old_func;
176 
177 	/* Will be NULL on the first call to denote the last usage routine. */
178 	old_func = rte_application_usage_hook;
179 	rte_application_usage_hook = usage_func;
180 
181 	return old_func;
182 }
183 
184 #ifndef RTE_EXEC_ENV_WINDOWS
185 static char **eal_args;
186 static char **eal_app_args;
187 
188 #define EAL_PARAM_REQ "/eal/params"
189 #define EAL_APP_PARAM_REQ "/eal/app_params"
190 
191 /* callback handler for telemetry library to report out EAL flags */
192 int
193 handle_eal_info_request(const char *cmd, const char *params __rte_unused,
194 		struct rte_tel_data *d)
195 {
196 	char **args;
197 	int used = 0;
198 	int i = 0;
199 
200 	if (strcmp(cmd, EAL_PARAM_REQ) == 0)
201 		args = eal_args;
202 	else
203 		args = eal_app_args;
204 
205 	rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
206 	if (args == NULL || args[0] == NULL)
207 		return 0;
208 
209 	for ( ; args[i] != NULL; i++)
210 		used = rte_tel_data_add_array_string(d, args[i]);
211 	return used;
212 }
213 
214 int
215 eal_save_args(int argc, char **argv)
216 {
217 	int i, j;
218 
219 	rte_telemetry_register_cmd(EAL_PARAM_REQ, handle_eal_info_request,
220 			"Returns EAL commandline parameters used. Takes no parameters");
221 	rte_telemetry_register_cmd(EAL_APP_PARAM_REQ, handle_eal_info_request,
222 			"Returns app commandline parameters used. Takes no parameters");
223 
224 	/* clone argv to report out later. We overprovision, but
225 	 * this does not waste huge amounts of memory
226 	 */
227 	eal_args = calloc(argc + 1, sizeof(*eal_args));
228 	if (eal_args == NULL)
229 		return -1;
230 
231 	for (i = 0; i < argc; i++) {
232 		eal_args[i] = strdup(argv[i]);
233 		if (strcmp(argv[i], "--") == 0)
234 			break;
235 	}
236 	eal_args[i++] = NULL; /* always finish with NULL */
237 
238 	/* allow reporting of any app args we know about too */
239 	if (i >= argc)
240 		return 0;
241 
242 	eal_app_args = calloc(argc - i + 1, sizeof(*eal_args));
243 	if (eal_app_args == NULL)
244 		return -1;
245 
246 	for (j = 0; i < argc; j++, i++)
247 		eal_app_args[j] = strdup(argv[i]);
248 	eal_app_args[j] = NULL;
249 
250 	return 0;
251 }
252 #endif
253 
254 static int
255 eal_option_device_add(enum rte_devtype type, const char *optarg)
256 {
257 	struct device_option *devopt;
258 	size_t optlen;
259 	int ret;
260 
261 	optlen = strlen(optarg) + 1;
262 	devopt = calloc(1, sizeof(*devopt) + optlen);
263 	if (devopt == NULL) {
264 		RTE_LOG(ERR, EAL, "Unable to allocate device option\n");
265 		return -ENOMEM;
266 	}
267 
268 	devopt->type = type;
269 	ret = strlcpy(devopt->arg, optarg, optlen);
270 	if (ret < 0) {
271 		RTE_LOG(ERR, EAL, "Unable to copy device option\n");
272 		free(devopt);
273 		return -EINVAL;
274 	}
275 	TAILQ_INSERT_TAIL(&devopt_list, devopt, next);
276 	return 0;
277 }
278 
279 int
280 eal_option_device_parse(void)
281 {
282 	struct device_option *devopt;
283 	void *tmp;
284 	int ret = 0;
285 
286 	TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {
287 		if (ret == 0) {
288 			ret = rte_devargs_add(devopt->type, devopt->arg);
289 			if (ret)
290 				RTE_LOG(ERR, EAL, "Unable to parse device '%s'\n",
291 					devopt->arg);
292 		}
293 		TAILQ_REMOVE(&devopt_list, devopt, next);
294 		free(devopt);
295 	}
296 	return ret;
297 }
298 
299 const char *
300 eal_get_hugefile_prefix(void)
301 {
302 	const struct internal_config *internal_conf =
303 		eal_get_internal_configuration();
304 
305 	if (internal_conf->hugefile_prefix != NULL)
306 		return internal_conf->hugefile_prefix;
307 	return HUGEFILE_PREFIX_DEFAULT;
308 }
309 
310 void
311 eal_reset_internal_config(struct internal_config *internal_cfg)
312 {
313 	int i;
314 
315 	internal_cfg->memory = 0;
316 	internal_cfg->force_nrank = 0;
317 	internal_cfg->force_nchannel = 0;
318 	internal_cfg->hugefile_prefix = NULL;
319 	internal_cfg->hugepage_dir = NULL;
320 	internal_cfg->force_sockets = 0;
321 	/* zero out the NUMA config */
322 	for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
323 		internal_cfg->socket_mem[i] = 0;
324 	internal_cfg->force_socket_limits = 0;
325 	/* zero out the NUMA limits config */
326 	for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
327 		internal_cfg->socket_limit[i] = 0;
328 	/* zero out hugedir descriptors */
329 	for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) {
330 		memset(&internal_cfg->hugepage_info[i], 0,
331 				sizeof(internal_cfg->hugepage_info[0]));
332 		internal_cfg->hugepage_info[i].lock_descriptor = -1;
333 	}
334 	internal_cfg->base_virtaddr = 0;
335 
336 #ifdef LOG_DAEMON
337 	internal_cfg->syslog_facility = LOG_DAEMON;
338 #endif
339 
340 	/* if set to NONE, interrupt mode is determined automatically */
341 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
342 	memset(internal_cfg->vfio_vf_token, 0,
343 			sizeof(internal_cfg->vfio_vf_token));
344 
345 #ifdef RTE_LIBEAL_USE_HPET
346 	internal_cfg->no_hpet = 0;
347 #else
348 	internal_cfg->no_hpet = 1;
349 #endif
350 	internal_cfg->vmware_tsc_map = 0;
351 	internal_cfg->create_uio_dev = 0;
352 	internal_cfg->iova_mode = RTE_IOVA_DC;
353 	internal_cfg->user_mbuf_pool_ops_name = NULL;
354 	CPU_ZERO(&internal_cfg->ctrl_cpuset);
355 	internal_cfg->init_complete = 0;
356 	internal_cfg->max_simd_bitwidth.bitwidth = RTE_VECT_DEFAULT_SIMD_BITWIDTH;
357 	internal_cfg->max_simd_bitwidth.forced = 0;
358 }
359 
360 static int
361 eal_plugin_add(const char *path)
362 {
363 	struct shared_driver *solib;
364 
365 	solib = malloc(sizeof(*solib));
366 	if (solib == NULL) {
367 		RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
368 		return -1;
369 	}
370 	memset(solib, 0, sizeof(*solib));
371 	strlcpy(solib->name, path, PATH_MAX);
372 	TAILQ_INSERT_TAIL(&solib_list, solib, next);
373 
374 	return 0;
375 }
376 
377 #ifdef RTE_EXEC_ENV_WINDOWS
378 int
379 eal_plugins_init(void)
380 {
381 	return 0;
382 }
383 #else
384 
385 static int
386 eal_plugindir_init(const char *path)
387 {
388 	DIR *d = NULL;
389 	struct dirent *dent = NULL;
390 	char sopath[PATH_MAX];
391 
392 	if (path == NULL || *path == '\0')
393 		return 0;
394 
395 	d = opendir(path);
396 	if (d == NULL) {
397 		RTE_LOG(ERR, EAL, "failed to open directory %s: %s\n",
398 			path, strerror(errno));
399 		return -1;
400 	}
401 
402 	while ((dent = readdir(d)) != NULL) {
403 		struct stat sb;
404 		int nlen = strnlen(dent->d_name, sizeof(dent->d_name));
405 
406 		/* check if name ends in .so or .so.ABI_VERSION */
407 		if (strcmp(&dent->d_name[nlen - 3], ".so") != 0 &&
408 		    strcmp(&dent->d_name[nlen - 4 - strlen(ABI_VERSION)],
409 			   ".so."ABI_VERSION) != 0)
410 			continue;
411 
412 		snprintf(sopath, sizeof(sopath), "%s/%s", path, dent->d_name);
413 
414 		/* if a regular file, add to list to load */
415 		if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
416 			continue;
417 
418 		if (eal_plugin_add(sopath) == -1)
419 			break;
420 	}
421 
422 	closedir(d);
423 	/* XXX this ignores failures from readdir() itself */
424 	return (dent == NULL) ? 0 : -1;
425 }
426 
427 static int
428 verify_perms(const char *dirpath)
429 {
430 	struct stat st;
431 
432 	/* if not root, check down one level first */
433 	if (strcmp(dirpath, "/") != 0) {
434 		static __thread char last_dir_checked[PATH_MAX];
435 		char copy[PATH_MAX];
436 		const char *dir;
437 
438 		strlcpy(copy, dirpath, PATH_MAX);
439 		dir = dirname(copy);
440 		if (strncmp(dir, last_dir_checked, PATH_MAX) != 0) {
441 			if (verify_perms(dir) != 0)
442 				return -1;
443 			strlcpy(last_dir_checked, dir, PATH_MAX);
444 		}
445 	}
446 
447 	/* call stat to check for permissions and ensure not world writable */
448 	if (stat(dirpath, &st) != 0) {
449 		RTE_LOG(ERR, EAL, "Error with stat on %s, %s\n",
450 				dirpath, strerror(errno));
451 		return -1;
452 	}
453 	if (st.st_mode & S_IWOTH) {
454 		RTE_LOG(ERR, EAL,
455 				"Error, directory path %s is world-writable and insecure\n",
456 				dirpath);
457 		return -1;
458 	}
459 
460 	return 0;
461 }
462 
463 static void *
464 eal_dlopen(const char *pathname)
465 {
466 	void *retval = NULL;
467 	char *realp = realpath(pathname, NULL);
468 
469 	if (realp == NULL && errno == ENOENT) {
470 		/* not a full or relative path, try a load from system dirs */
471 		retval = dlopen(pathname, RTLD_NOW);
472 		if (retval == NULL)
473 			RTE_LOG(ERR, EAL, "%s\n", dlerror());
474 		return retval;
475 	}
476 	if (realp == NULL) {
477 		RTE_LOG(ERR, EAL, "Error with realpath for %s, %s\n",
478 				pathname, strerror(errno));
479 		goto out;
480 	}
481 	if (strnlen(realp, PATH_MAX) == PATH_MAX) {
482 		RTE_LOG(ERR, EAL, "Error, driver path greater than PATH_MAX\n");
483 		goto out;
484 	}
485 
486 	/* do permissions checks */
487 	if (verify_perms(realp) != 0)
488 		goto out;
489 
490 	retval = dlopen(realp, RTLD_NOW);
491 	if (retval == NULL)
492 		RTE_LOG(ERR, EAL, "%s\n", dlerror());
493 out:
494 	free(realp);
495 	return retval;
496 }
497 
498 static int
499 is_shared_build(void)
500 {
501 #define EAL_SO "librte_eal.so"
502 	char soname[32];
503 	size_t len, minlen = strlen(EAL_SO);
504 
505 	len = strlcpy(soname, EAL_SO"."ABI_VERSION, sizeof(soname));
506 	if (len > sizeof(soname)) {
507 		RTE_LOG(ERR, EAL, "Shared lib name too long in shared build check\n");
508 		len = sizeof(soname) - 1;
509 	}
510 
511 	while (len >= minlen) {
512 		void *handle;
513 
514 		/* check if we have this .so loaded, if so - shared build */
515 		RTE_LOG(DEBUG, EAL, "Checking presence of .so '%s'\n", soname);
516 		handle = dlopen(soname, RTLD_LAZY | RTLD_NOLOAD);
517 		if (handle != NULL) {
518 			RTE_LOG(INFO, EAL, "Detected shared linkage of DPDK\n");
519 			dlclose(handle);
520 			return 1;
521 		}
522 
523 		/* remove any version numbers off the end to retry */
524 		while (len-- > 0)
525 			if (soname[len] == '.') {
526 				soname[len] = '\0';
527 				break;
528 			}
529 	}
530 
531 	RTE_LOG(INFO, EAL, "Detected static linkage of DPDK\n");
532 	return 0;
533 }
534 
535 int
536 eal_plugins_init(void)
537 {
538 	struct shared_driver *solib = NULL;
539 	struct stat sb;
540 
541 	/* If we are not statically linked, add default driver loading
542 	 * path if it exists as a directory.
543 	 * (Using dlopen with NOLOAD flag on EAL, will return NULL if the EAL
544 	 * shared library is not already loaded i.e. it's statically linked.)
545 	 */
546 	if (is_shared_build() &&
547 			*default_solib_dir != '\0' &&
548 			stat(default_solib_dir, &sb) == 0 &&
549 			S_ISDIR(sb.st_mode))
550 		eal_plugin_add(default_solib_dir);
551 
552 	TAILQ_FOREACH(solib, &solib_list, next) {
553 
554 		if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
555 			if (eal_plugindir_init(solib->name) == -1) {
556 				RTE_LOG(ERR, EAL,
557 					"Cannot init plugin directory %s\n",
558 					solib->name);
559 				return -1;
560 			}
561 		} else {
562 			RTE_LOG(DEBUG, EAL, "open shared lib %s\n",
563 				solib->name);
564 			solib->lib_handle = eal_dlopen(solib->name);
565 			if (solib->lib_handle == NULL)
566 				return -1;
567 		}
568 
569 	}
570 	return 0;
571 }
572 #endif
573 
574 /*
575  * Parse the coremask given as argument (hexadecimal string) and fill
576  * the global configuration (core role and core count) with the parsed
577  * value.
578  */
579 static int xdigit2val(unsigned char c)
580 {
581 	int val;
582 
583 	if (isdigit(c))
584 		val = c - '0';
585 	else if (isupper(c))
586 		val = c - 'A' + 10;
587 	else
588 		val = c - 'a' + 10;
589 	return val;
590 }
591 
592 static int
593 eal_parse_service_coremask(const char *coremask)
594 {
595 	struct rte_config *cfg = rte_eal_get_configuration();
596 	int i, j, idx = 0;
597 	unsigned int count = 0;
598 	char c;
599 	int val;
600 	uint32_t taken_lcore_count = 0;
601 
602 	if (coremask == NULL)
603 		return -1;
604 	/* Remove all blank characters ahead and after .
605 	 * Remove 0x/0X if exists.
606 	 */
607 	while (isblank(*coremask))
608 		coremask++;
609 	if (coremask[0] == '0' && ((coremask[1] == 'x')
610 		|| (coremask[1] == 'X')))
611 		coremask += 2;
612 	i = strlen(coremask);
613 	while ((i > 0) && isblank(coremask[i - 1]))
614 		i--;
615 
616 	if (i == 0)
617 		return -1;
618 
619 	for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
620 		c = coremask[i];
621 		if (isxdigit(c) == 0) {
622 			/* invalid characters */
623 			return -1;
624 		}
625 		val = xdigit2val(c);
626 		for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE;
627 				j++, idx++) {
628 			if ((1 << j) & val) {
629 				/* handle main lcore already parsed */
630 				uint32_t lcore = idx;
631 				if (main_lcore_parsed &&
632 						cfg->main_lcore == lcore) {
633 					RTE_LOG(ERR, EAL,
634 						"lcore %u is main lcore, cannot use as service core\n",
635 						idx);
636 					return -1;
637 				}
638 
639 				if (eal_cpu_detected(idx) == 0) {
640 					RTE_LOG(ERR, EAL,
641 						"lcore %u unavailable\n", idx);
642 					return -1;
643 				}
644 
645 				if (cfg->lcore_role[idx] == ROLE_RTE)
646 					taken_lcore_count++;
647 
648 				lcore_config[idx].core_role = ROLE_SERVICE;
649 				count++;
650 			}
651 		}
652 	}
653 
654 	for (; i >= 0; i--)
655 		if (coremask[i] != '0')
656 			return -1;
657 
658 	for (; idx < RTE_MAX_LCORE; idx++)
659 		lcore_config[idx].core_index = -1;
660 
661 	if (count == 0)
662 		return -1;
663 
664 	if (core_parsed && taken_lcore_count != count) {
665 		RTE_LOG(WARNING, EAL,
666 			"Not all service cores are in the coremask. "
667 			"Please ensure -c or -l includes service cores\n");
668 	}
669 
670 	cfg->service_lcore_count = count;
671 	return 0;
672 }
673 
674 static int
675 eal_service_cores_parsed(void)
676 {
677 	int idx;
678 	for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
679 		if (lcore_config[idx].core_role == ROLE_SERVICE)
680 			return 1;
681 	}
682 	return 0;
683 }
684 
685 static int
686 update_lcore_config(int *cores)
687 {
688 	struct rte_config *cfg = rte_eal_get_configuration();
689 	unsigned int count = 0;
690 	unsigned int i;
691 	int ret = 0;
692 
693 	for (i = 0; i < RTE_MAX_LCORE; i++) {
694 		if (cores[i] != -1) {
695 			if (eal_cpu_detected(i) == 0) {
696 				RTE_LOG(ERR, EAL, "lcore %u unavailable\n", i);
697 				ret = -1;
698 				continue;
699 			}
700 			cfg->lcore_role[i] = ROLE_RTE;
701 			count++;
702 		} else {
703 			cfg->lcore_role[i] = ROLE_OFF;
704 		}
705 		lcore_config[i].core_index = cores[i];
706 	}
707 	if (!ret)
708 		cfg->lcore_count = count;
709 	return ret;
710 }
711 
712 static int
713 eal_parse_coremask(const char *coremask, int *cores)
714 {
715 	unsigned count = 0;
716 	int i, j, idx;
717 	int val;
718 	char c;
719 
720 	for (idx = 0; idx < RTE_MAX_LCORE; idx++)
721 		cores[idx] = -1;
722 	idx = 0;
723 
724 	/* Remove all blank characters ahead and after .
725 	 * Remove 0x/0X if exists.
726 	 */
727 	while (isblank(*coremask))
728 		coremask++;
729 	if (coremask[0] == '0' && ((coremask[1] == 'x')
730 		|| (coremask[1] == 'X')))
731 		coremask += 2;
732 	i = strlen(coremask);
733 	while ((i > 0) && isblank(coremask[i - 1]))
734 		i--;
735 	if (i == 0)
736 		return -1;
737 
738 	for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
739 		c = coremask[i];
740 		if (isxdigit(c) == 0) {
741 			/* invalid characters */
742 			return -1;
743 		}
744 		val = xdigit2val(c);
745 		for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++)
746 		{
747 			if ((1 << j) & val) {
748 				cores[idx] = count;
749 				count++;
750 			}
751 		}
752 	}
753 	for (; i >= 0; i--)
754 		if (coremask[i] != '0')
755 			return -1;
756 	if (count == 0)
757 		return -1;
758 	return 0;
759 }
760 
761 static int
762 eal_parse_service_corelist(const char *corelist)
763 {
764 	struct rte_config *cfg = rte_eal_get_configuration();
765 	int i;
766 	unsigned count = 0;
767 	char *end = NULL;
768 	uint32_t min, max, idx;
769 	uint32_t taken_lcore_count = 0;
770 
771 	if (corelist == NULL)
772 		return -1;
773 
774 	/* Remove all blank characters ahead and after */
775 	while (isblank(*corelist))
776 		corelist++;
777 	i = strlen(corelist);
778 	while ((i > 0) && isblank(corelist[i - 1]))
779 		i--;
780 
781 	/* Get list of cores */
782 	min = RTE_MAX_LCORE;
783 	do {
784 		while (isblank(*corelist))
785 			corelist++;
786 		if (*corelist == '\0')
787 			return -1;
788 		errno = 0;
789 		idx = strtoul(corelist, &end, 10);
790 		if (errno || end == NULL)
791 			return -1;
792 		if (idx >= RTE_MAX_LCORE)
793 			return -1;
794 		while (isblank(*end))
795 			end++;
796 		if (*end == '-') {
797 			min = idx;
798 		} else if ((*end == ',') || (*end == '\0')) {
799 			max = idx;
800 			if (min == RTE_MAX_LCORE)
801 				min = idx;
802 			for (idx = min; idx <= max; idx++) {
803 				if (cfg->lcore_role[idx] != ROLE_SERVICE) {
804 					/* handle main lcore already parsed */
805 					uint32_t lcore = idx;
806 					if (cfg->main_lcore == lcore &&
807 							main_lcore_parsed) {
808 						RTE_LOG(ERR, EAL,
809 							"Error: lcore %u is main lcore, cannot use as service core\n",
810 							idx);
811 						return -1;
812 					}
813 					if (cfg->lcore_role[idx] == ROLE_RTE)
814 						taken_lcore_count++;
815 
816 					lcore_config[idx].core_role =
817 							ROLE_SERVICE;
818 					count++;
819 				}
820 			}
821 			min = RTE_MAX_LCORE;
822 		} else
823 			return -1;
824 		corelist = end + 1;
825 	} while (*end != '\0');
826 
827 	if (count == 0)
828 		return -1;
829 
830 	if (core_parsed && taken_lcore_count != count) {
831 		RTE_LOG(WARNING, EAL,
832 			"Not all service cores were in the coremask. "
833 			"Please ensure -c or -l includes service cores\n");
834 	}
835 
836 	return 0;
837 }
838 
839 static int
840 eal_parse_corelist(const char *corelist, int *cores)
841 {
842 	unsigned count = 0;
843 	char *end = NULL;
844 	int min, max;
845 	int idx;
846 
847 	for (idx = 0; idx < RTE_MAX_LCORE; idx++)
848 		cores[idx] = -1;
849 
850 	/* Remove all blank characters ahead */
851 	while (isblank(*corelist))
852 		corelist++;
853 
854 	/* Get list of cores */
855 	min = RTE_MAX_LCORE;
856 	do {
857 		while (isblank(*corelist))
858 			corelist++;
859 		if (*corelist == '\0')
860 			return -1;
861 		errno = 0;
862 		idx = strtol(corelist, &end, 10);
863 		if (errno || end == NULL)
864 			return -1;
865 		if (idx < 0 || idx >= RTE_MAX_LCORE)
866 			return -1;
867 		while (isblank(*end))
868 			end++;
869 		if (*end == '-') {
870 			min = idx;
871 		} else if ((*end == ',') || (*end == '\0')) {
872 			max = idx;
873 			if (min == RTE_MAX_LCORE)
874 				min = idx;
875 			for (idx = min; idx <= max; idx++) {
876 				if (cores[idx] == -1) {
877 					cores[idx] = count;
878 					count++;
879 				}
880 			}
881 			min = RTE_MAX_LCORE;
882 		} else
883 			return -1;
884 		corelist = end + 1;
885 	} while (*end != '\0');
886 
887 	if (count == 0)
888 		return -1;
889 	return 0;
890 }
891 
892 /* Changes the lcore id of the main thread */
893 static int
894 eal_parse_main_lcore(const char *arg)
895 {
896 	char *parsing_end;
897 	struct rte_config *cfg = rte_eal_get_configuration();
898 
899 	errno = 0;
900 	cfg->main_lcore = (uint32_t) strtol(arg, &parsing_end, 0);
901 	if (errno || parsing_end[0] != 0)
902 		return -1;
903 	if (cfg->main_lcore >= RTE_MAX_LCORE)
904 		return -1;
905 	main_lcore_parsed = 1;
906 
907 	/* ensure main core is not used as service core */
908 	if (lcore_config[cfg->main_lcore].core_role == ROLE_SERVICE) {
909 		RTE_LOG(ERR, EAL,
910 			"Error: Main lcore is used as a service core\n");
911 		return -1;
912 	}
913 
914 	return 0;
915 }
916 
917 /*
918  * Parse elem, the elem could be single number/range or '(' ')' group
919  * 1) A single number elem, it's just a simple digit. e.g. 9
920  * 2) A single range elem, two digits with a '-' between. e.g. 2-6
921  * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
922  *    Within group elem, '-' used for a range separator;
923  *                       ',' used for a single number.
924  */
925 static int
926 eal_parse_set(const char *input, rte_cpuset_t *set)
927 {
928 	unsigned idx;
929 	const char *str = input;
930 	char *end = NULL;
931 	unsigned min, max;
932 
933 	CPU_ZERO(set);
934 
935 	while (isblank(*str))
936 		str++;
937 
938 	/* only digit or left bracket is qualify for start point */
939 	if ((!isdigit(*str) && *str != '(') || *str == '\0')
940 		return -1;
941 
942 	/* process single number or single range of number */
943 	if (*str != '(') {
944 		errno = 0;
945 		idx = strtoul(str, &end, 10);
946 		if (errno || end == NULL || idx >= CPU_SETSIZE)
947 			return -1;
948 		else {
949 			while (isblank(*end))
950 				end++;
951 
952 			min = idx;
953 			max = idx;
954 			if (*end == '-') {
955 				/* process single <number>-<number> */
956 				end++;
957 				while (isblank(*end))
958 					end++;
959 				if (!isdigit(*end))
960 					return -1;
961 
962 				errno = 0;
963 				idx = strtoul(end, &end, 10);
964 				if (errno || end == NULL || idx >= CPU_SETSIZE)
965 					return -1;
966 				max = idx;
967 				while (isblank(*end))
968 					end++;
969 				if (*end != ',' && *end != '\0')
970 					return -1;
971 			}
972 
973 			if (*end != ',' && *end != '\0' &&
974 			    *end != '@')
975 				return -1;
976 
977 			for (idx = RTE_MIN(min, max);
978 			     idx <= RTE_MAX(min, max); idx++)
979 				CPU_SET(idx, set);
980 
981 			return end - input;
982 		}
983 	}
984 
985 	/* process set within bracket */
986 	str++;
987 	while (isblank(*str))
988 		str++;
989 	if (*str == '\0')
990 		return -1;
991 
992 	min = RTE_MAX_LCORE;
993 	do {
994 
995 		/* go ahead to the first digit */
996 		while (isblank(*str))
997 			str++;
998 		if (!isdigit(*str))
999 			return -1;
1000 
1001 		/* get the digit value */
1002 		errno = 0;
1003 		idx = strtoul(str, &end, 10);
1004 		if (errno || end == NULL || idx >= CPU_SETSIZE)
1005 			return -1;
1006 
1007 		/* go ahead to separator '-',',' and ')' */
1008 		while (isblank(*end))
1009 			end++;
1010 		if (*end == '-') {
1011 			if (min == RTE_MAX_LCORE)
1012 				min = idx;
1013 			else /* avoid continuous '-' */
1014 				return -1;
1015 		} else if ((*end == ',') || (*end == ')')) {
1016 			max = idx;
1017 			if (min == RTE_MAX_LCORE)
1018 				min = idx;
1019 			for (idx = RTE_MIN(min, max);
1020 			     idx <= RTE_MAX(min, max); idx++)
1021 				CPU_SET(idx, set);
1022 
1023 			min = RTE_MAX_LCORE;
1024 		} else
1025 			return -1;
1026 
1027 		str = end + 1;
1028 	} while (*end != '\0' && *end != ')');
1029 
1030 	/*
1031 	 * to avoid failure that tail blank makes end character check fail
1032 	 * in eal_parse_lcores( )
1033 	 */
1034 	while (isblank(*str))
1035 		str++;
1036 
1037 	return str - input;
1038 }
1039 
1040 static int
1041 check_cpuset(rte_cpuset_t *set)
1042 {
1043 	unsigned int idx;
1044 
1045 	for (idx = 0; idx < CPU_SETSIZE; idx++) {
1046 		if (!CPU_ISSET(idx, set))
1047 			continue;
1048 
1049 		if (eal_cpu_detected(idx) == 0) {
1050 			RTE_LOG(ERR, EAL, "core %u "
1051 				"unavailable\n", idx);
1052 			return -1;
1053 		}
1054 	}
1055 	return 0;
1056 }
1057 
1058 /*
1059  * The format pattern: --lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
1060  * lcores, cpus could be a single digit/range or a group.
1061  * '(' and ')' are necessary if it's a group.
1062  * If not supply '@cpus', the value of cpus uses the same as lcores.
1063  * e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below
1064  *   lcore 0 runs on cpuset 0x41 (cpu 0,6)
1065  *   lcore 1 runs on cpuset 0x2 (cpu 1)
1066  *   lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
1067  *   lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
1068  *   lcore 6 runs on cpuset 0x41 (cpu 0,6)
1069  *   lcore 7 runs on cpuset 0x80 (cpu 7)
1070  *   lcore 8 runs on cpuset 0x100 (cpu 8)
1071  */
1072 static int
1073 eal_parse_lcores(const char *lcores)
1074 {
1075 	struct rte_config *cfg = rte_eal_get_configuration();
1076 	rte_cpuset_t lcore_set;
1077 	unsigned int set_count;
1078 	unsigned idx = 0;
1079 	unsigned count = 0;
1080 	const char *lcore_start = NULL;
1081 	const char *end = NULL;
1082 	int offset;
1083 	rte_cpuset_t cpuset;
1084 	int lflags;
1085 	int ret = -1;
1086 
1087 	if (lcores == NULL)
1088 		return -1;
1089 
1090 	/* Remove all blank characters ahead and after */
1091 	while (isblank(*lcores))
1092 		lcores++;
1093 
1094 	CPU_ZERO(&cpuset);
1095 
1096 	/* Reset lcore config */
1097 	for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1098 		cfg->lcore_role[idx] = ROLE_OFF;
1099 		lcore_config[idx].core_index = -1;
1100 		CPU_ZERO(&lcore_config[idx].cpuset);
1101 	}
1102 
1103 	/* Get list of cores */
1104 	do {
1105 		while (isblank(*lcores))
1106 			lcores++;
1107 		if (*lcores == '\0')
1108 			goto err;
1109 
1110 		lflags = 0;
1111 
1112 		/* record lcore_set start point */
1113 		lcore_start = lcores;
1114 
1115 		/* go across a complete bracket */
1116 		if (*lcore_start == '(') {
1117 			lcores += strcspn(lcores, ")");
1118 			if (*lcores++ == '\0')
1119 				goto err;
1120 		}
1121 
1122 		/* scan the separator '@', ','(next) or '\0'(finish) */
1123 		lcores += strcspn(lcores, "@,");
1124 
1125 		if (*lcores == '@') {
1126 			/* explicit assign cpuset and update the end cursor */
1127 			offset = eal_parse_set(lcores + 1, &cpuset);
1128 			if (offset < 0)
1129 				goto err;
1130 			end = lcores + 1 + offset;
1131 		} else { /* ',' or '\0' */
1132 			/* haven't given cpuset, current loop done */
1133 			end = lcores;
1134 
1135 			/* go back to check <number>-<number> */
1136 			offset = strcspn(lcore_start, "(-");
1137 			if (offset < (end - lcore_start) &&
1138 			    *(lcore_start + offset) != '(')
1139 				lflags = 1;
1140 		}
1141 
1142 		if (*end != ',' && *end != '\0')
1143 			goto err;
1144 
1145 		/* parse lcore_set from start point */
1146 		if (eal_parse_set(lcore_start, &lcore_set) < 0)
1147 			goto err;
1148 
1149 		/* without '@', by default using lcore_set as cpuset */
1150 		if (*lcores != '@')
1151 			rte_memcpy(&cpuset, &lcore_set, sizeof(cpuset));
1152 
1153 		set_count = CPU_COUNT(&lcore_set);
1154 		/* start to update lcore_set */
1155 		for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1156 			if (!CPU_ISSET(idx, &lcore_set))
1157 				continue;
1158 			set_count--;
1159 
1160 			if (cfg->lcore_role[idx] != ROLE_RTE) {
1161 				lcore_config[idx].core_index = count;
1162 				cfg->lcore_role[idx] = ROLE_RTE;
1163 				count++;
1164 			}
1165 
1166 			if (lflags) {
1167 				CPU_ZERO(&cpuset);
1168 				CPU_SET(idx, &cpuset);
1169 			}
1170 
1171 			if (check_cpuset(&cpuset) < 0)
1172 				goto err;
1173 			rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
1174 				   sizeof(rte_cpuset_t));
1175 		}
1176 
1177 		/* some cores from the lcore_set can't be handled by EAL */
1178 		if (set_count != 0)
1179 			goto err;
1180 
1181 		lcores = end + 1;
1182 	} while (*end != '\0');
1183 
1184 	if (count == 0)
1185 		goto err;
1186 
1187 	cfg->lcore_count = count;
1188 	ret = 0;
1189 
1190 err:
1191 
1192 	return ret;
1193 }
1194 
1195 #ifndef RTE_EXEC_ENV_WINDOWS
1196 static int
1197 eal_parse_syslog(const char *facility, struct internal_config *conf)
1198 {
1199 	int i;
1200 	static const struct {
1201 		const char *name;
1202 		int value;
1203 	} map[] = {
1204 		{ "auth", LOG_AUTH },
1205 		{ "cron", LOG_CRON },
1206 		{ "daemon", LOG_DAEMON },
1207 		{ "ftp", LOG_FTP },
1208 		{ "kern", LOG_KERN },
1209 		{ "lpr", LOG_LPR },
1210 		{ "mail", LOG_MAIL },
1211 		{ "news", LOG_NEWS },
1212 		{ "syslog", LOG_SYSLOG },
1213 		{ "user", LOG_USER },
1214 		{ "uucp", LOG_UUCP },
1215 		{ "local0", LOG_LOCAL0 },
1216 		{ "local1", LOG_LOCAL1 },
1217 		{ "local2", LOG_LOCAL2 },
1218 		{ "local3", LOG_LOCAL3 },
1219 		{ "local4", LOG_LOCAL4 },
1220 		{ "local5", LOG_LOCAL5 },
1221 		{ "local6", LOG_LOCAL6 },
1222 		{ "local7", LOG_LOCAL7 },
1223 		{ NULL, 0 }
1224 	};
1225 
1226 	for (i = 0; map[i].name; i++) {
1227 		if (!strcmp(facility, map[i].name)) {
1228 			conf->syslog_facility = map[i].value;
1229 			return 0;
1230 		}
1231 	}
1232 	return -1;
1233 }
1234 #endif
1235 
1236 static void
1237 eal_log_usage(void)
1238 {
1239 	unsigned int level;
1240 
1241 	printf("Log type is a pattern matching items of this list"
1242 			" (plugins may be missing):\n");
1243 	rte_log_list_types(stdout, "\t");
1244 	printf("\n");
1245 	printf("Syntax using globbing pattern:     ");
1246 	printf("--"OPT_LOG_LEVEL" pattern:level\n");
1247 	printf("Syntax using regular expression:   ");
1248 	printf("--"OPT_LOG_LEVEL" regexp,level\n");
1249 	printf("Syntax for the global level:       ");
1250 	printf("--"OPT_LOG_LEVEL" level\n");
1251 	printf("Logs are emitted if allowed by both global and specific levels.\n");
1252 	printf("\n");
1253 	printf("Log level can be a number or the first letters of its name:\n");
1254 	for (level = 1; level <= RTE_LOG_MAX; level++)
1255 		printf("\t%d   %s\n", level, eal_log_level2str(level));
1256 }
1257 
1258 static int
1259 eal_parse_log_priority(const char *level)
1260 {
1261 	size_t len = strlen(level);
1262 	unsigned long tmp;
1263 	char *end;
1264 	unsigned int i;
1265 
1266 	if (len == 0)
1267 		return -1;
1268 
1269 	/* look for named values, skip 0 which is not a valid level */
1270 	for (i = 1; i <= RTE_LOG_MAX; i++) {
1271 		if (strncmp(eal_log_level2str(i), level, len) == 0)
1272 			return i;
1273 	}
1274 
1275 	/* not a string, maybe it is numeric */
1276 	errno = 0;
1277 	tmp = strtoul(level, &end, 0);
1278 
1279 	/* check for errors */
1280 	if (errno != 0 || end == NULL || *end != '\0' ||
1281 	    tmp >= UINT32_MAX)
1282 		return -1;
1283 
1284 	return tmp;
1285 }
1286 
1287 static int
1288 eal_parse_log_level(const char *arg)
1289 {
1290 	const char *pattern = NULL;
1291 	const char *regex = NULL;
1292 	char *str, *level;
1293 	int priority;
1294 
1295 	if (strcmp(arg, "help") == 0) {
1296 		eal_log_usage();
1297 		exit(EXIT_SUCCESS);
1298 	}
1299 
1300 	str = strdup(arg);
1301 	if (str == NULL)
1302 		return -1;
1303 
1304 	if ((level = strchr(str, ','))) {
1305 		regex = str;
1306 		*level++ = '\0';
1307 	} else if ((level = strchr(str, ':'))) {
1308 		pattern = str;
1309 		*level++ = '\0';
1310 	} else {
1311 		level = str;
1312 	}
1313 
1314 	priority = eal_parse_log_priority(level);
1315 	if (priority <= 0) {
1316 		fprintf(stderr, "Invalid log level: %s\n", level);
1317 		goto fail;
1318 	}
1319 	if (priority > (int)RTE_LOG_MAX) {
1320 		fprintf(stderr, "Log level %d higher than maximum (%d)\n",
1321 				priority, RTE_LOG_MAX);
1322 		priority = RTE_LOG_MAX;
1323 	}
1324 
1325 	if (regex) {
1326 		if (rte_log_set_level_regexp(regex, priority) < 0) {
1327 			fprintf(stderr, "cannot set log level %s,%d\n",
1328 				regex, priority);
1329 			goto fail;
1330 		}
1331 		if (eal_log_save_regexp(regex, priority) < 0)
1332 			goto fail;
1333 	} else if (pattern) {
1334 		if (rte_log_set_level_pattern(pattern, priority) < 0) {
1335 			fprintf(stderr, "cannot set log level %s:%d\n",
1336 				pattern, priority);
1337 			goto fail;
1338 		}
1339 		if (eal_log_save_pattern(pattern, priority) < 0)
1340 			goto fail;
1341 	} else {
1342 		rte_log_set_global_level(priority);
1343 	}
1344 
1345 	free(str);
1346 	return 0;
1347 
1348 fail:
1349 	free(str);
1350 	return -1;
1351 }
1352 
1353 static enum rte_proc_type_t
1354 eal_parse_proc_type(const char *arg)
1355 {
1356 	if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
1357 		return RTE_PROC_PRIMARY;
1358 	if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
1359 		return RTE_PROC_SECONDARY;
1360 	if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
1361 		return RTE_PROC_AUTO;
1362 
1363 	return RTE_PROC_INVALID;
1364 }
1365 
1366 static int
1367 eal_parse_iova_mode(const char *name)
1368 {
1369 	int mode;
1370 	struct internal_config *internal_conf =
1371 		eal_get_internal_configuration();
1372 
1373 	if (name == NULL)
1374 		return -1;
1375 
1376 	if (!strcmp("pa", name))
1377 		mode = RTE_IOVA_PA;
1378 	else if (!strcmp("va", name))
1379 		mode = RTE_IOVA_VA;
1380 	else
1381 		return -1;
1382 
1383 	internal_conf->iova_mode = mode;
1384 	return 0;
1385 }
1386 
1387 static int
1388 eal_parse_simd_bitwidth(const char *arg)
1389 {
1390 	char *end;
1391 	unsigned long bitwidth;
1392 	int ret;
1393 	struct internal_config *internal_conf =
1394 		eal_get_internal_configuration();
1395 
1396 	if (arg == NULL || arg[0] == '\0')
1397 		return -1;
1398 
1399 	errno = 0;
1400 	bitwidth = strtoul(arg, &end, 0);
1401 
1402 	/* check for errors */
1403 	if (errno != 0 || end == NULL || *end != '\0' || bitwidth > RTE_VECT_SIMD_MAX)
1404 		return -1;
1405 
1406 	if (bitwidth == 0)
1407 		bitwidth = (unsigned long) RTE_VECT_SIMD_MAX;
1408 	ret = rte_vect_set_max_simd_bitwidth(bitwidth);
1409 	if (ret < 0)
1410 		return -1;
1411 	internal_conf->max_simd_bitwidth.forced = 1;
1412 	return 0;
1413 }
1414 
1415 static int
1416 eal_parse_base_virtaddr(const char *arg)
1417 {
1418 	char *end;
1419 	uint64_t addr;
1420 	struct internal_config *internal_conf =
1421 		eal_get_internal_configuration();
1422 
1423 	errno = 0;
1424 	addr = strtoull(arg, &end, 16);
1425 
1426 	/* check for errors */
1427 	if ((errno != 0) || (arg[0] == '\0') || end == NULL || (*end != '\0'))
1428 		return -1;
1429 
1430 	/* make sure we don't exceed 32-bit boundary on 32-bit target */
1431 #ifndef RTE_ARCH_64
1432 	if (addr >= UINTPTR_MAX)
1433 		return -1;
1434 #endif
1435 
1436 	/* align the addr on 16M boundary, 16MB is the minimum huge page
1437 	 * size on IBM Power architecture. If the addr is aligned to 16MB,
1438 	 * it can align to 2MB for x86. So this alignment can also be used
1439 	 * on x86 and other architectures.
1440 	 */
1441 	internal_conf->base_virtaddr =
1442 		RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M);
1443 
1444 	return 0;
1445 }
1446 
1447 /* caller is responsible for freeing the returned string */
1448 static char *
1449 available_cores(void)
1450 {
1451 	char *str = NULL;
1452 	int previous;
1453 	int sequence;
1454 	char *tmp;
1455 	int idx;
1456 
1457 	/* find the first available cpu */
1458 	for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1459 		if (eal_cpu_detected(idx) == 0)
1460 			continue;
1461 		break;
1462 	}
1463 	if (idx >= RTE_MAX_LCORE)
1464 		return NULL;
1465 
1466 	/* first sequence */
1467 	if (asprintf(&str, "%d", idx) < 0)
1468 		return NULL;
1469 	previous = idx;
1470 	sequence = 0;
1471 
1472 	for (idx++ ; idx < RTE_MAX_LCORE; idx++) {
1473 		if (eal_cpu_detected(idx) == 0)
1474 			continue;
1475 
1476 		if (idx == previous + 1) {
1477 			previous = idx;
1478 			sequence = 1;
1479 			continue;
1480 		}
1481 
1482 		/* finish current sequence */
1483 		if (sequence) {
1484 			if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
1485 				free(str);
1486 				return NULL;
1487 			}
1488 			free(str);
1489 			str = tmp;
1490 		}
1491 
1492 		/* new sequence */
1493 		if (asprintf(&tmp, "%s,%d", str, idx) < 0) {
1494 			free(str);
1495 			return NULL;
1496 		}
1497 		free(str);
1498 		str = tmp;
1499 		previous = idx;
1500 		sequence = 0;
1501 	}
1502 
1503 	/* finish last sequence */
1504 	if (sequence) {
1505 		if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
1506 			free(str);
1507 			return NULL;
1508 		}
1509 		free(str);
1510 		str = tmp;
1511 	}
1512 
1513 	return str;
1514 }
1515 
1516 int
1517 eal_parse_common_option(int opt, const char *optarg,
1518 			struct internal_config *conf)
1519 {
1520 	static int b_used;
1521 	static int a_used;
1522 
1523 	switch (opt) {
1524 	case OPT_PCI_BLACKLIST_NUM:
1525 		fprintf(stderr,
1526 			"Option --pci-blacklist is deprecated, use -b, --block instead\n");
1527 		/* fallthrough */
1528 	case 'b':
1529 		if (a_used)
1530 			goto ba_conflict;
1531 		if (eal_option_device_add(RTE_DEVTYPE_BLOCKED, optarg) < 0)
1532 			return -1;
1533 		b_used = 1;
1534 		break;
1535 
1536 	case 'w':
1537 		fprintf(stderr,
1538 			"Option -w, --pci-whitelist is deprecated, use -a, --allow option instead\n");
1539 		/* fallthrough */
1540 	case 'a':
1541 		if (b_used)
1542 			goto ba_conflict;
1543 		if (eal_option_device_add(RTE_DEVTYPE_ALLOWED, optarg) < 0)
1544 			return -1;
1545 		a_used = 1;
1546 		break;
1547 	/* coremask */
1548 	case 'c': {
1549 		int lcore_indexes[RTE_MAX_LCORE];
1550 
1551 		if (eal_service_cores_parsed())
1552 			RTE_LOG(WARNING, EAL,
1553 				"Service cores parsed before dataplane cores. Please ensure -c is before -s or -S\n");
1554 		if (eal_parse_coremask(optarg, lcore_indexes) < 0) {
1555 			RTE_LOG(ERR, EAL, "invalid coremask syntax\n");
1556 			return -1;
1557 		}
1558 		if (update_lcore_config(lcore_indexes) < 0) {
1559 			char *available = available_cores();
1560 
1561 			RTE_LOG(ERR, EAL,
1562 				"invalid coremask, please check specified cores are part of %s\n",
1563 				available);
1564 			free(available);
1565 			return -1;
1566 		}
1567 
1568 		if (core_parsed) {
1569 			RTE_LOG(ERR, EAL, "Option -c is ignored, because (%s) is set!\n",
1570 				(core_parsed == LCORE_OPT_LST) ? "-l" :
1571 				(core_parsed == LCORE_OPT_MAP) ? "--lcore" :
1572 				"-c");
1573 			return -1;
1574 		}
1575 
1576 		core_parsed = LCORE_OPT_MSK;
1577 		break;
1578 	}
1579 	/* corelist */
1580 	case 'l': {
1581 		int lcore_indexes[RTE_MAX_LCORE];
1582 
1583 		if (eal_service_cores_parsed())
1584 			RTE_LOG(WARNING, EAL,
1585 				"Service cores parsed before dataplane cores. Please ensure -l is before -s or -S\n");
1586 
1587 		if (eal_parse_corelist(optarg, lcore_indexes) < 0) {
1588 			RTE_LOG(ERR, EAL, "invalid core list syntax\n");
1589 			return -1;
1590 		}
1591 		if (update_lcore_config(lcore_indexes) < 0) {
1592 			char *available = available_cores();
1593 
1594 			RTE_LOG(ERR, EAL,
1595 				"invalid core list, please check specified cores are part of %s\n",
1596 				available);
1597 			free(available);
1598 			return -1;
1599 		}
1600 
1601 		if (core_parsed) {
1602 			RTE_LOG(ERR, EAL, "Option -l is ignored, because (%s) is set!\n",
1603 				(core_parsed == LCORE_OPT_MSK) ? "-c" :
1604 				(core_parsed == LCORE_OPT_MAP) ? "--lcore" :
1605 				"-l");
1606 			return -1;
1607 		}
1608 
1609 		core_parsed = LCORE_OPT_LST;
1610 		break;
1611 	}
1612 	/* service coremask */
1613 	case 's':
1614 		if (eal_parse_service_coremask(optarg) < 0) {
1615 			RTE_LOG(ERR, EAL, "invalid service coremask\n");
1616 			return -1;
1617 		}
1618 		break;
1619 	/* service corelist */
1620 	case 'S':
1621 		if (eal_parse_service_corelist(optarg) < 0) {
1622 			RTE_LOG(ERR, EAL, "invalid service core list\n");
1623 			return -1;
1624 		}
1625 		break;
1626 	/* size of memory */
1627 	case 'm':
1628 		conf->memory = atoi(optarg);
1629 		conf->memory *= 1024ULL;
1630 		conf->memory *= 1024ULL;
1631 		mem_parsed = 1;
1632 		break;
1633 	/* force number of channels */
1634 	case 'n':
1635 		conf->force_nchannel = atoi(optarg);
1636 		if (conf->force_nchannel == 0) {
1637 			RTE_LOG(ERR, EAL, "invalid channel number\n");
1638 			return -1;
1639 		}
1640 		break;
1641 	/* force number of ranks */
1642 	case 'r':
1643 		conf->force_nrank = atoi(optarg);
1644 		if (conf->force_nrank == 0 ||
1645 		    conf->force_nrank > 16) {
1646 			RTE_LOG(ERR, EAL, "invalid rank number\n");
1647 			return -1;
1648 		}
1649 		break;
1650 	/* force loading of external driver */
1651 	case 'd':
1652 		if (eal_plugin_add(optarg) == -1)
1653 			return -1;
1654 		break;
1655 	case 'v':
1656 		/* since message is explicitly requested by user, we
1657 		 * write message at highest log level so it can always
1658 		 * be seen
1659 		 * even if info or warning messages are disabled */
1660 		RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
1661 		break;
1662 
1663 	/* long options */
1664 	case OPT_HUGE_UNLINK_NUM:
1665 		conf->hugepage_unlink = 1;
1666 		break;
1667 
1668 	case OPT_NO_HUGE_NUM:
1669 		conf->no_hugetlbfs = 1;
1670 		/* no-huge is legacy mem */
1671 		conf->legacy_mem = 1;
1672 		break;
1673 
1674 	case OPT_NO_PCI_NUM:
1675 		conf->no_pci = 1;
1676 		break;
1677 
1678 	case OPT_NO_HPET_NUM:
1679 		conf->no_hpet = 1;
1680 		break;
1681 
1682 	case OPT_VMWARE_TSC_MAP_NUM:
1683 		conf->vmware_tsc_map = 1;
1684 		break;
1685 
1686 	case OPT_NO_SHCONF_NUM:
1687 		conf->no_shconf = 1;
1688 		break;
1689 
1690 	case OPT_IN_MEMORY_NUM:
1691 		conf->in_memory = 1;
1692 		/* in-memory is a superset of noshconf and huge-unlink */
1693 		conf->no_shconf = 1;
1694 		conf->hugepage_unlink = 1;
1695 		break;
1696 
1697 	case OPT_PROC_TYPE_NUM:
1698 		conf->process_type = eal_parse_proc_type(optarg);
1699 		break;
1700 
1701 	case OPT_MASTER_LCORE_NUM:
1702 		fprintf(stderr,
1703 			"Option --" OPT_MASTER_LCORE
1704 			" is deprecated use " OPT_MAIN_LCORE "\n");
1705 		/* fallthrough */
1706 	case OPT_MAIN_LCORE_NUM:
1707 		if (eal_parse_main_lcore(optarg) < 0) {
1708 			RTE_LOG(ERR, EAL, "invalid parameter for --"
1709 					OPT_MAIN_LCORE "\n");
1710 			return -1;
1711 		}
1712 		break;
1713 
1714 	case OPT_VDEV_NUM:
1715 		if (eal_option_device_add(RTE_DEVTYPE_VIRTUAL,
1716 				optarg) < 0) {
1717 			return -1;
1718 		}
1719 		break;
1720 
1721 #ifndef RTE_EXEC_ENV_WINDOWS
1722 	case OPT_SYSLOG_NUM:
1723 		if (eal_parse_syslog(optarg, conf) < 0) {
1724 			RTE_LOG(ERR, EAL, "invalid parameters for --"
1725 					OPT_SYSLOG "\n");
1726 			return -1;
1727 		}
1728 		break;
1729 #endif
1730 
1731 	case OPT_LOG_LEVEL_NUM: {
1732 		if (eal_parse_log_level(optarg) < 0) {
1733 			RTE_LOG(ERR, EAL,
1734 				"invalid parameters for --"
1735 				OPT_LOG_LEVEL "\n");
1736 			return -1;
1737 		}
1738 		break;
1739 	}
1740 
1741 #ifndef RTE_EXEC_ENV_WINDOWS
1742 	case OPT_TRACE_NUM: {
1743 		if (eal_trace_args_save(optarg) < 0) {
1744 			RTE_LOG(ERR, EAL, "invalid parameters for --"
1745 				OPT_TRACE "\n");
1746 			return -1;
1747 		}
1748 		break;
1749 	}
1750 
1751 	case OPT_TRACE_DIR_NUM: {
1752 		if (eal_trace_dir_args_save(optarg) < 0) {
1753 			RTE_LOG(ERR, EAL, "invalid parameters for --"
1754 				OPT_TRACE_DIR "\n");
1755 			return -1;
1756 		}
1757 		break;
1758 	}
1759 
1760 	case OPT_TRACE_BUF_SIZE_NUM: {
1761 		if (eal_trace_bufsz_args_save(optarg) < 0) {
1762 			RTE_LOG(ERR, EAL, "invalid parameters for --"
1763 				OPT_TRACE_BUF_SIZE "\n");
1764 			return -1;
1765 		}
1766 		break;
1767 	}
1768 
1769 	case OPT_TRACE_MODE_NUM: {
1770 		if (eal_trace_mode_args_save(optarg) < 0) {
1771 			RTE_LOG(ERR, EAL, "invalid parameters for --"
1772 				OPT_TRACE_MODE "\n");
1773 			return -1;
1774 		}
1775 		break;
1776 	}
1777 #endif /* !RTE_EXEC_ENV_WINDOWS */
1778 
1779 	case OPT_LCORES_NUM:
1780 		if (eal_parse_lcores(optarg) < 0) {
1781 			RTE_LOG(ERR, EAL, "invalid parameter for --"
1782 				OPT_LCORES "\n");
1783 			return -1;
1784 		}
1785 
1786 		if (core_parsed) {
1787 			RTE_LOG(ERR, EAL, "Option --lcore is ignored, because (%s) is set!\n",
1788 				(core_parsed == LCORE_OPT_LST) ? "-l" :
1789 				(core_parsed == LCORE_OPT_MSK) ? "-c" :
1790 				"--lcore");
1791 			return -1;
1792 		}
1793 
1794 		core_parsed = LCORE_OPT_MAP;
1795 		break;
1796 	case OPT_LEGACY_MEM_NUM:
1797 		conf->legacy_mem = 1;
1798 		break;
1799 	case OPT_SINGLE_FILE_SEGMENTS_NUM:
1800 		conf->single_file_segments = 1;
1801 		break;
1802 	case OPT_IOVA_MODE_NUM:
1803 		if (eal_parse_iova_mode(optarg) < 0) {
1804 			RTE_LOG(ERR, EAL, "invalid parameters for --"
1805 				OPT_IOVA_MODE "\n");
1806 			return -1;
1807 		}
1808 		break;
1809 	case OPT_BASE_VIRTADDR_NUM:
1810 		if (eal_parse_base_virtaddr(optarg) < 0) {
1811 			RTE_LOG(ERR, EAL, "invalid parameter for --"
1812 					OPT_BASE_VIRTADDR "\n");
1813 			return -1;
1814 		}
1815 		break;
1816 	case OPT_TELEMETRY_NUM:
1817 		break;
1818 	case OPT_NO_TELEMETRY_NUM:
1819 		conf->no_telemetry = 1;
1820 		break;
1821 	case OPT_FORCE_MAX_SIMD_BITWIDTH_NUM:
1822 		if (eal_parse_simd_bitwidth(optarg) < 0) {
1823 			RTE_LOG(ERR, EAL, "invalid parameter for --"
1824 					OPT_FORCE_MAX_SIMD_BITWIDTH "\n");
1825 			return -1;
1826 		}
1827 		break;
1828 
1829 	/* don't know what to do, leave this to caller */
1830 	default:
1831 		return 1;
1832 
1833 	}
1834 
1835 	return 0;
1836 
1837 ba_conflict:
1838 	RTE_LOG(ERR, EAL,
1839 		"Options allow (-a) and block (-b) can't be used at the same time\n");
1840 	return -1;
1841 }
1842 
1843 static void
1844 eal_auto_detect_cores(struct rte_config *cfg)
1845 {
1846 	unsigned int lcore_id;
1847 	unsigned int removed = 0;
1848 	rte_cpuset_t affinity_set;
1849 
1850 	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
1851 				&affinity_set))
1852 		CPU_ZERO(&affinity_set);
1853 
1854 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1855 		if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
1856 		    !CPU_ISSET(lcore_id, &affinity_set)) {
1857 			cfg->lcore_role[lcore_id] = ROLE_OFF;
1858 			removed++;
1859 		}
1860 	}
1861 
1862 	cfg->lcore_count -= removed;
1863 }
1864 
1865 static void
1866 compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
1867 {
1868 	rte_cpuset_t *cpuset = &internal_cfg->ctrl_cpuset;
1869 	rte_cpuset_t default_set;
1870 	unsigned int lcore_id;
1871 
1872 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1873 		if (rte_lcore_has_role(lcore_id, ROLE_OFF))
1874 			continue;
1875 		RTE_CPU_OR(cpuset, cpuset, &lcore_config[lcore_id].cpuset);
1876 	}
1877 	RTE_CPU_NOT(cpuset, cpuset);
1878 
1879 	if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
1880 				&default_set))
1881 		CPU_ZERO(&default_set);
1882 
1883 	RTE_CPU_AND(cpuset, cpuset, &default_set);
1884 
1885 	/* if no remaining cpu, use main lcore cpu affinity */
1886 	if (!CPU_COUNT(cpuset)) {
1887 		memcpy(cpuset, &lcore_config[rte_get_main_lcore()].cpuset,
1888 			sizeof(*cpuset));
1889 	}
1890 }
1891 
1892 int
1893 eal_cleanup_config(struct internal_config *internal_cfg)
1894 {
1895 	if (internal_cfg->hugefile_prefix != NULL)
1896 		free(internal_cfg->hugefile_prefix);
1897 	if (internal_cfg->hugepage_dir != NULL)
1898 		free(internal_cfg->hugepage_dir);
1899 	if (internal_cfg->user_mbuf_pool_ops_name != NULL)
1900 		free(internal_cfg->user_mbuf_pool_ops_name);
1901 
1902 	return 0;
1903 }
1904 
1905 int
1906 eal_adjust_config(struct internal_config *internal_cfg)
1907 {
1908 	int i;
1909 	struct rte_config *cfg = rte_eal_get_configuration();
1910 	struct internal_config *internal_conf =
1911 		eal_get_internal_configuration();
1912 
1913 	if (!core_parsed)
1914 		eal_auto_detect_cores(cfg);
1915 
1916 	if (internal_conf->process_type == RTE_PROC_AUTO)
1917 		internal_conf->process_type = eal_proc_type_detect();
1918 
1919 	/* default main lcore is the first one */
1920 	if (!main_lcore_parsed) {
1921 		cfg->main_lcore = rte_get_next_lcore(-1, 0, 0);
1922 		if (cfg->main_lcore >= RTE_MAX_LCORE)
1923 			return -1;
1924 		lcore_config[cfg->main_lcore].core_role = ROLE_RTE;
1925 	}
1926 
1927 	compute_ctrl_threads_cpuset(internal_cfg);
1928 
1929 	/* if no memory amounts were requested, this will result in 0 and
1930 	 * will be overridden later, right after eal_hugepage_info_init() */
1931 	for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
1932 		internal_cfg->memory += internal_cfg->socket_mem[i];
1933 
1934 	return 0;
1935 }
1936 
1937 int
1938 eal_check_common_options(struct internal_config *internal_cfg)
1939 {
1940 	struct rte_config *cfg = rte_eal_get_configuration();
1941 	const struct internal_config *internal_conf =
1942 		eal_get_internal_configuration();
1943 
1944 	if (cfg->lcore_role[cfg->main_lcore] != ROLE_RTE) {
1945 		RTE_LOG(ERR, EAL, "Main lcore is not enabled for DPDK\n");
1946 		return -1;
1947 	}
1948 
1949 	if (internal_cfg->process_type == RTE_PROC_INVALID) {
1950 		RTE_LOG(ERR, EAL, "Invalid process type specified\n");
1951 		return -1;
1952 	}
1953 	if (internal_cfg->hugefile_prefix != NULL &&
1954 			strlen(internal_cfg->hugefile_prefix) < 1) {
1955 		RTE_LOG(ERR, EAL, "Invalid length of --" OPT_FILE_PREFIX " option\n");
1956 		return -1;
1957 	}
1958 	if (internal_cfg->hugepage_dir != NULL &&
1959 			strlen(internal_cfg->hugepage_dir) < 1) {
1960 		RTE_LOG(ERR, EAL, "Invalid length of --" OPT_HUGE_DIR" option\n");
1961 		return -1;
1962 	}
1963 	if (internal_cfg->user_mbuf_pool_ops_name != NULL &&
1964 			strlen(internal_cfg->user_mbuf_pool_ops_name) < 1) {
1965 		RTE_LOG(ERR, EAL, "Invalid length of --" OPT_MBUF_POOL_OPS_NAME" option\n");
1966 		return -1;
1967 	}
1968 	if (strchr(eal_get_hugefile_prefix(), '%') != NULL) {
1969 		RTE_LOG(ERR, EAL, "Invalid char, '%%', in --"OPT_FILE_PREFIX" "
1970 			"option\n");
1971 		return -1;
1972 	}
1973 	if (mem_parsed && internal_cfg->force_sockets == 1) {
1974 		RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot "
1975 			"be specified at the same time\n");
1976 		return -1;
1977 	}
1978 	if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) {
1979 		RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot "
1980 			"be specified together with --"OPT_NO_HUGE"\n");
1981 		return -1;
1982 	}
1983 	if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink &&
1984 			!internal_cfg->in_memory) {
1985 		RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot "
1986 			"be specified together with --"OPT_NO_HUGE"\n");
1987 		return -1;
1988 	}
1989 	if (internal_conf->force_socket_limits && internal_conf->legacy_mem) {
1990 		RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_LIMIT
1991 			" is only supported in non-legacy memory mode\n");
1992 	}
1993 	if (internal_cfg->single_file_segments &&
1994 			internal_cfg->hugepage_unlink &&
1995 			!internal_cfg->in_memory) {
1996 		RTE_LOG(ERR, EAL, "Option --"OPT_SINGLE_FILE_SEGMENTS" is "
1997 			"not compatible with --"OPT_HUGE_UNLINK"\n");
1998 		return -1;
1999 	}
2000 	if (internal_cfg->legacy_mem &&
2001 			internal_cfg->in_memory) {
2002 		RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible "
2003 				"with --"OPT_IN_MEMORY"\n");
2004 		return -1;
2005 	}
2006 	if (internal_cfg->legacy_mem && internal_cfg->match_allocations) {
2007 		RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible "
2008 				"with --"OPT_MATCH_ALLOCATIONS"\n");
2009 		return -1;
2010 	}
2011 	if (internal_cfg->no_hugetlbfs && internal_cfg->match_allocations) {
2012 		RTE_LOG(ERR, EAL, "Option --"OPT_NO_HUGE" is not compatible "
2013 				"with --"OPT_MATCH_ALLOCATIONS"\n");
2014 		return -1;
2015 	}
2016 	if (internal_cfg->legacy_mem && internal_cfg->memory == 0) {
2017 		RTE_LOG(NOTICE, EAL, "Static memory layout is selected, "
2018 			"amount of reserved memory can be adjusted with "
2019 			"-m or --"OPT_SOCKET_MEM"\n");
2020 	}
2021 
2022 	return 0;
2023 }
2024 
2025 uint16_t
2026 rte_vect_get_max_simd_bitwidth(void)
2027 {
2028 	const struct internal_config *internal_conf =
2029 		eal_get_internal_configuration();
2030 	return internal_conf->max_simd_bitwidth.bitwidth;
2031 }
2032 
2033 int
2034 rte_vect_set_max_simd_bitwidth(uint16_t bitwidth)
2035 {
2036 	struct internal_config *internal_conf =
2037 		eal_get_internal_configuration();
2038 	if (internal_conf->max_simd_bitwidth.forced) {
2039 		RTE_LOG(NOTICE, EAL, "Cannot set max SIMD bitwidth - user runtime override enabled");
2040 		return -EPERM;
2041 	}
2042 
2043 	if (bitwidth < RTE_VECT_SIMD_DISABLED || !rte_is_power_of_2(bitwidth)) {
2044 		RTE_LOG(ERR, EAL, "Invalid bitwidth value!\n");
2045 		return -EINVAL;
2046 	}
2047 	internal_conf->max_simd_bitwidth.bitwidth = bitwidth;
2048 	return 0;
2049 }
2050 
2051 void
2052 eal_common_usage(void)
2053 {
2054 	printf("[options]\n\n"
2055 	       "EAL common options:\n"
2056 	       "  -c COREMASK         Hexadecimal bitmask of cores to run on\n"
2057 	       "  -l CORELIST         List of cores to run on\n"
2058 	       "                      The argument format is <c1>[-c2][,c3[-c4],...]\n"
2059 	       "                      where c1, c2, etc are core indexes between 0 and %d\n"
2060 	       "  --"OPT_LCORES" COREMAP    Map lcore set to physical cpu set\n"
2061 	       "                      The argument format is\n"
2062 	       "                            '<lcores[@cpus]>[<,lcores[@cpus]>...]'\n"
2063 	       "                      lcores and cpus list are grouped by '(' and ')'\n"
2064 	       "                      Within the group, '-' is used for range separator,\n"
2065 	       "                      ',' is used for single number separator.\n"
2066 	       "                      '( )' can be omitted for single element group,\n"
2067 	       "                      '@' can be omitted if cpus and lcores have the same value\n"
2068 	       "  -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores\n"
2069 	       "  --"OPT_MAIN_LCORE" ID     Core ID that is used as main\n"
2070 	       "  --"OPT_MBUF_POOL_OPS_NAME" Pool ops name for mbuf to use\n"
2071 	       "  -n CHANNELS         Number of memory channels\n"
2072 	       "  -m MB               Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
2073 	       "  -r RANKS            Force number of memory ranks (don't detect)\n"
2074 	       "  -b, --block         Add a device to the blocked list.\n"
2075 	       "                      Prevent EAL from using this device. The argument\n"
2076 	       "                      format for PCI devices is <domain:bus:devid.func>.\n"
2077 	       "  -a, --allow         Add a device to the allow list.\n"
2078 	       "                      Only use the specified devices. The argument format\n"
2079 	       "                      for PCI devices is <[domain:]bus:devid.func>.\n"
2080 	       "                      This option can be present several times.\n"
2081 	       "                      [NOTE: " OPT_DEV_ALLOW " cannot be used with "OPT_DEV_BLOCK" option]\n"
2082 	       "  --"OPT_VDEV"              Add a virtual device.\n"
2083 	       "                      The argument format is <driver><id>[,key=val,...]\n"
2084 	       "                      (ex: --vdev=net_pcap0,iface=eth2).\n"
2085 	       "  --"OPT_IOVA_MODE"   Set IOVA mode. 'pa' for IOVA_PA\n"
2086 	       "                      'va' for IOVA_VA\n"
2087 	       "  -d LIB.so|DIR       Add a driver or driver directory\n"
2088 	       "                      (can be used multiple times)\n"
2089 	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
2090 	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
2091 #ifndef RTE_EXEC_ENV_WINDOWS
2092 	       "  --"OPT_SYSLOG"            Set syslog facility\n"
2093 #endif
2094 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
2095 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
2096 	       "                      Set specific log level\n"
2097 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
2098 #ifndef RTE_EXEC_ENV_WINDOWS
2099 	       "  --"OPT_TRACE"=<regex-match>\n"
2100 	       "                      Enable trace based on regular expression trace name.\n"
2101 	       "                      By default, the trace is disabled.\n"
2102 	       "		      User must specify this option to enable trace.\n"
2103 	       "  --"OPT_TRACE_DIR"=<directory path>\n"
2104 	       "                      Specify trace directory for trace output.\n"
2105 	       "                      By default, trace output will created at\n"
2106 	       "                      $HOME directory and parameter must be\n"
2107 	       "                      specified once only.\n"
2108 	       "  --"OPT_TRACE_BUF_SIZE"=<int>\n"
2109 	       "                      Specify maximum size of allocated memory\n"
2110 	       "                      for trace output for each thread. Valid\n"
2111 	       "                      unit can be either 'B|K|M' for 'Bytes',\n"
2112 	       "                      'KBytes' and 'MBytes' respectively.\n"
2113 	       "                      Default is 1MB and parameter must be\n"
2114 	       "                      specified once only.\n"
2115 	       "  --"OPT_TRACE_MODE"=<o[verwrite] | d[iscard]>\n"
2116 	       "                      Specify the mode of update of trace\n"
2117 	       "                      output file. Either update on a file can\n"
2118 	       "                      be wrapped or discarded when file size\n"
2119 	       "                      reaches its maximum limit.\n"
2120 	       "                      Default mode is 'overwrite' and parameter\n"
2121 	       "                      must be specified once only.\n"
2122 #endif /* !RTE_EXEC_ENV_WINDOWS */
2123 	       "  -v                  Display version information on startup\n"
2124 	       "  -h, --help          This help\n"
2125 	       "  --"OPT_IN_MEMORY"   Operate entirely in memory. This will\n"
2126 	       "                      disable secondary process support\n"
2127 	       "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
2128 	       "  --"OPT_TELEMETRY"   Enable telemetry support (on by default)\n"
2129 	       "  --"OPT_NO_TELEMETRY"   Disable telemetry support\n"
2130 	       "  --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD bitwidth\n"
2131 	       "\nEAL options for DEBUG use only:\n"
2132 	       "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
2133 	       "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
2134 	       "  --"OPT_NO_PCI"            Disable PCI\n"
2135 	       "  --"OPT_NO_HPET"           Disable HPET\n"
2136 	       "  --"OPT_NO_SHCONF"         No shared config (mmap'd files)\n"
2137 	       "\n", RTE_MAX_LCORE);
2138 }
2139