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