199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2018 Intel Corporation. 399a2dd95SBruce Richardson * Copyright(c) 2014 6WIND S.A. 499a2dd95SBruce Richardson */ 599a2dd95SBruce Richardson 672b452c5SDmitry Kozlyuk #include <ctype.h> 799a2dd95SBruce Richardson #include <stdio.h> 899a2dd95SBruce Richardson #include <stdlib.h> 999a2dd95SBruce Richardson #include <stdint.h> 1099a2dd95SBruce Richardson #include <string.h> 1199a2dd95SBruce Richardson #include <stdarg.h> 1299a2dd95SBruce Richardson #include <unistd.h> 1399a2dd95SBruce Richardson #include <pthread.h> 1499a2dd95SBruce Richardson #include <getopt.h> 1599a2dd95SBruce Richardson #include <sys/file.h> 1699a2dd95SBruce Richardson #include <stddef.h> 1799a2dd95SBruce Richardson #include <errno.h> 1899a2dd95SBruce Richardson #include <limits.h> 1999a2dd95SBruce Richardson #include <sys/mman.h> 2099a2dd95SBruce Richardson #include <sys/queue.h> 2199a2dd95SBruce Richardson #include <sys/stat.h> 2299a2dd95SBruce Richardson 2399a2dd95SBruce Richardson #include <rte_common.h> 2499a2dd95SBruce Richardson #include <rte_debug.h> 2599a2dd95SBruce Richardson #include <rte_memory.h> 2699a2dd95SBruce Richardson #include <rte_launch.h> 2799a2dd95SBruce Richardson #include <rte_eal.h> 282e2f0272SDavid Marchand #include <rte_eal_memconfig.h> 2999a2dd95SBruce Richardson #include <rte_errno.h> 3099a2dd95SBruce Richardson #include <rte_per_lcore.h> 3199a2dd95SBruce Richardson #include <rte_lcore.h> 3299a2dd95SBruce Richardson #include <rte_service_component.h> 3399a2dd95SBruce Richardson #include <rte_log.h> 3499a2dd95SBruce Richardson #include <rte_random.h> 3599a2dd95SBruce Richardson #include <rte_cycles.h> 3699a2dd95SBruce Richardson #include <rte_string_fns.h> 3799a2dd95SBruce Richardson #include <rte_cpuflags.h> 3899a2dd95SBruce Richardson #include <rte_interrupts.h> 3999a2dd95SBruce Richardson #include <rte_bus.h> 4099a2dd95SBruce Richardson #include <rte_dev.h> 4199a2dd95SBruce Richardson #include <rte_devargs.h> 4299a2dd95SBruce Richardson #include <rte_version.h> 4399a2dd95SBruce Richardson #include <rte_vfio.h> 4499a2dd95SBruce Richardson #include <malloc_heap.h> 4599a2dd95SBruce Richardson #include <telemetry_internal.h> 4699a2dd95SBruce Richardson 4799a2dd95SBruce Richardson #include "eal_private.h" 4899a2dd95SBruce Richardson #include "eal_thread.h" 495bce9bedSMattias Rönnblom #include "eal_lcore_var.h" 5099a2dd95SBruce Richardson #include "eal_internal_cfg.h" 5199a2dd95SBruce Richardson #include "eal_filesystem.h" 5299a2dd95SBruce Richardson #include "eal_hugepages.h" 5399a2dd95SBruce Richardson #include "eal_options.h" 5499a2dd95SBruce Richardson #include "eal_memcfg.h" 5599a2dd95SBruce Richardson #include "eal_trace.h" 56*2773d39fSStephen Hemminger #include "log_internal.h" 5799a2dd95SBruce Richardson 5899a2dd95SBruce Richardson #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) 5999a2dd95SBruce Richardson 6099a2dd95SBruce Richardson /* define fd variable here, because file needs to be kept open for the 6199a2dd95SBruce Richardson * duration of the program, as we hold a write lock on it in the primary proc */ 6299a2dd95SBruce Richardson static int mem_cfg_fd = -1; 6399a2dd95SBruce Richardson 6499a2dd95SBruce Richardson static struct flock wr_lock = { 6599a2dd95SBruce Richardson .l_type = F_WRLCK, 6699a2dd95SBruce Richardson .l_whence = SEEK_SET, 6799a2dd95SBruce Richardson .l_start = offsetof(struct rte_mem_config, memsegs), 6899a2dd95SBruce Richardson .l_len = RTE_SIZEOF_FIELD(struct rte_mem_config, memsegs), 6999a2dd95SBruce Richardson }; 7099a2dd95SBruce Richardson 7199a2dd95SBruce Richardson /* internal configuration (per-core) */ 7299a2dd95SBruce Richardson struct lcore_config lcore_config[RTE_MAX_LCORE]; 7399a2dd95SBruce Richardson 7499a2dd95SBruce Richardson /* used by rte_rdtsc() */ 7599a2dd95SBruce Richardson int rte_cycles_vmware_tsc_map; 7699a2dd95SBruce Richardson 7799a2dd95SBruce Richardson 7899a2dd95SBruce Richardson int 7999a2dd95SBruce Richardson eal_clean_runtime_dir(void) 8099a2dd95SBruce Richardson { 8199a2dd95SBruce Richardson /* FreeBSD doesn't need this implemented for now, because, unlike Linux, 8299a2dd95SBruce Richardson * FreeBSD doesn't create per-process files, so no need to clean up. 8399a2dd95SBruce Richardson */ 8499a2dd95SBruce Richardson return 0; 8599a2dd95SBruce Richardson } 8699a2dd95SBruce Richardson 8799a2dd95SBruce Richardson /* create memory configuration in shared/mmap memory. Take out 8899a2dd95SBruce Richardson * a write lock on the memsegs, so we can auto-detect primary/secondary. 8999a2dd95SBruce Richardson * This means we never close the file while running (auto-close on exit). 9099a2dd95SBruce Richardson * We also don't lock the whole file, so that in future we can use read-locks 9199a2dd95SBruce Richardson * on other parts, e.g. memzones, to detect if there are running secondary 9299a2dd95SBruce Richardson * processes. */ 9399a2dd95SBruce Richardson static int 9499a2dd95SBruce Richardson rte_eal_config_create(void) 9599a2dd95SBruce Richardson { 9699a2dd95SBruce Richardson struct rte_config *config = rte_eal_get_configuration(); 9799a2dd95SBruce Richardson const struct internal_config *internal_conf = 9899a2dd95SBruce Richardson eal_get_internal_configuration(); 9999a2dd95SBruce Richardson size_t page_sz = sysconf(_SC_PAGE_SIZE); 10099a2dd95SBruce Richardson size_t cfg_len = sizeof(struct rte_mem_config); 10199a2dd95SBruce Richardson size_t cfg_len_aligned = RTE_ALIGN(cfg_len, page_sz); 10299a2dd95SBruce Richardson void *rte_mem_cfg_addr, *mapped_mem_cfg_addr; 10399a2dd95SBruce Richardson int retval; 10499a2dd95SBruce Richardson 10599a2dd95SBruce Richardson const char *pathname = eal_runtime_config_path(); 10699a2dd95SBruce Richardson 10799a2dd95SBruce Richardson if (internal_conf->no_shconf) 10899a2dd95SBruce Richardson return 0; 10999a2dd95SBruce Richardson 11099a2dd95SBruce Richardson /* map the config before base address so that we don't waste a page */ 11199a2dd95SBruce Richardson if (internal_conf->base_virtaddr != 0) 11299a2dd95SBruce Richardson rte_mem_cfg_addr = (void *) 11399a2dd95SBruce Richardson RTE_ALIGN_FLOOR(internal_conf->base_virtaddr - 11499a2dd95SBruce Richardson sizeof(struct rte_mem_config), page_sz); 11599a2dd95SBruce Richardson else 11699a2dd95SBruce Richardson rte_mem_cfg_addr = NULL; 11799a2dd95SBruce Richardson 11899a2dd95SBruce Richardson if (mem_cfg_fd < 0){ 11999a2dd95SBruce Richardson mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0600); 12099a2dd95SBruce Richardson if (mem_cfg_fd < 0) { 121ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot open '%s' for rte_mem_config", 12299a2dd95SBruce Richardson pathname); 12399a2dd95SBruce Richardson return -1; 12499a2dd95SBruce Richardson } 12599a2dd95SBruce Richardson } 12699a2dd95SBruce Richardson 12799a2dd95SBruce Richardson retval = ftruncate(mem_cfg_fd, cfg_len); 12899a2dd95SBruce Richardson if (retval < 0){ 12999a2dd95SBruce Richardson close(mem_cfg_fd); 13099a2dd95SBruce Richardson mem_cfg_fd = -1; 131ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot resize '%s' for rte_mem_config", 13299a2dd95SBruce Richardson pathname); 13399a2dd95SBruce Richardson return -1; 13499a2dd95SBruce Richardson } 13599a2dd95SBruce Richardson 13699a2dd95SBruce Richardson retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock); 13799a2dd95SBruce Richardson if (retval < 0){ 13899a2dd95SBruce Richardson close(mem_cfg_fd); 13999a2dd95SBruce Richardson mem_cfg_fd = -1; 140ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot create lock on '%s'. Is another primary " 141ae67895bSDavid Marchand "process running?", pathname); 14299a2dd95SBruce Richardson return -1; 14399a2dd95SBruce Richardson } 14499a2dd95SBruce Richardson 14599a2dd95SBruce Richardson /* reserve space for config */ 14699a2dd95SBruce Richardson rte_mem_cfg_addr = eal_get_virtual_area(rte_mem_cfg_addr, 14799a2dd95SBruce Richardson &cfg_len_aligned, page_sz, 0, 0); 14899a2dd95SBruce Richardson if (rte_mem_cfg_addr == NULL) { 149ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot mmap memory for rte_config"); 15099a2dd95SBruce Richardson close(mem_cfg_fd); 15199a2dd95SBruce Richardson mem_cfg_fd = -1; 15299a2dd95SBruce Richardson return -1; 15399a2dd95SBruce Richardson } 15499a2dd95SBruce Richardson 15599a2dd95SBruce Richardson /* remap the actual file into the space we've just reserved */ 15699a2dd95SBruce Richardson mapped_mem_cfg_addr = mmap(rte_mem_cfg_addr, 15799a2dd95SBruce Richardson cfg_len_aligned, PROT_READ | PROT_WRITE, 15899a2dd95SBruce Richardson MAP_SHARED | MAP_FIXED, mem_cfg_fd, 0); 15999a2dd95SBruce Richardson if (mapped_mem_cfg_addr == MAP_FAILED) { 160ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot remap memory for rte_config"); 16199a2dd95SBruce Richardson munmap(rte_mem_cfg_addr, cfg_len); 16299a2dd95SBruce Richardson close(mem_cfg_fd); 16399a2dd95SBruce Richardson mem_cfg_fd = -1; 16499a2dd95SBruce Richardson return -1; 16599a2dd95SBruce Richardson } 16699a2dd95SBruce Richardson 16799a2dd95SBruce Richardson memcpy(rte_mem_cfg_addr, config->mem_config, sizeof(struct rte_mem_config)); 16899a2dd95SBruce Richardson config->mem_config = rte_mem_cfg_addr; 16999a2dd95SBruce Richardson 17099a2dd95SBruce Richardson /* store address of the config in the config itself so that secondary 17199a2dd95SBruce Richardson * processes could later map the config into this exact location 17299a2dd95SBruce Richardson */ 17399a2dd95SBruce Richardson config->mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr; 17499a2dd95SBruce Richardson return 0; 17599a2dd95SBruce Richardson } 17699a2dd95SBruce Richardson 17799a2dd95SBruce Richardson /* attach to an existing shared memory config */ 17899a2dd95SBruce Richardson static int 17999a2dd95SBruce Richardson rte_eal_config_attach(void) 18099a2dd95SBruce Richardson { 18199a2dd95SBruce Richardson void *rte_mem_cfg_addr; 18299a2dd95SBruce Richardson const char *pathname = eal_runtime_config_path(); 18399a2dd95SBruce Richardson struct rte_config *config = rte_eal_get_configuration(); 18499a2dd95SBruce Richardson const struct internal_config *internal_conf = 18599a2dd95SBruce Richardson eal_get_internal_configuration(); 18699a2dd95SBruce Richardson 18799a2dd95SBruce Richardson 18899a2dd95SBruce Richardson if (internal_conf->no_shconf) 18999a2dd95SBruce Richardson return 0; 19099a2dd95SBruce Richardson 19199a2dd95SBruce Richardson if (mem_cfg_fd < 0){ 19299a2dd95SBruce Richardson mem_cfg_fd = open(pathname, O_RDWR); 19399a2dd95SBruce Richardson if (mem_cfg_fd < 0) { 194ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot open '%s' for rte_mem_config", 19599a2dd95SBruce Richardson pathname); 19699a2dd95SBruce Richardson return -1; 19799a2dd95SBruce Richardson } 19899a2dd95SBruce Richardson } 19999a2dd95SBruce Richardson 20099a2dd95SBruce Richardson rte_mem_cfg_addr = mmap(NULL, sizeof(*config->mem_config), 20199a2dd95SBruce Richardson PROT_READ, MAP_SHARED, mem_cfg_fd, 0); 20299a2dd95SBruce Richardson /* don't close the fd here, it will be closed on reattach */ 20399a2dd95SBruce Richardson if (rte_mem_cfg_addr == MAP_FAILED) { 20499a2dd95SBruce Richardson close(mem_cfg_fd); 20599a2dd95SBruce Richardson mem_cfg_fd = -1; 206ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot mmap memory for rte_config! error %i (%s)", 20799a2dd95SBruce Richardson errno, strerror(errno)); 20899a2dd95SBruce Richardson return -1; 20999a2dd95SBruce Richardson } 21099a2dd95SBruce Richardson 21199a2dd95SBruce Richardson config->mem_config = rte_mem_cfg_addr; 21299a2dd95SBruce Richardson 21399a2dd95SBruce Richardson return 0; 21499a2dd95SBruce Richardson } 21599a2dd95SBruce Richardson 21699a2dd95SBruce Richardson /* reattach the shared config at exact memory location primary process has it */ 21799a2dd95SBruce Richardson static int 21899a2dd95SBruce Richardson rte_eal_config_reattach(void) 21999a2dd95SBruce Richardson { 22099a2dd95SBruce Richardson struct rte_mem_config *mem_config; 22199a2dd95SBruce Richardson void *rte_mem_cfg_addr; 22299a2dd95SBruce Richardson struct rte_config *config = rte_eal_get_configuration(); 22399a2dd95SBruce Richardson const struct internal_config *internal_conf = 22499a2dd95SBruce Richardson eal_get_internal_configuration(); 22599a2dd95SBruce Richardson 22699a2dd95SBruce Richardson if (internal_conf->no_shconf) 22799a2dd95SBruce Richardson return 0; 22899a2dd95SBruce Richardson 22999a2dd95SBruce Richardson /* save the address primary process has mapped shared config to */ 23099a2dd95SBruce Richardson rte_mem_cfg_addr = 23199a2dd95SBruce Richardson (void *)(uintptr_t)config->mem_config->mem_cfg_addr; 23299a2dd95SBruce Richardson 23399a2dd95SBruce Richardson /* unmap original config */ 23499a2dd95SBruce Richardson munmap(config->mem_config, sizeof(struct rte_mem_config)); 23599a2dd95SBruce Richardson 23699a2dd95SBruce Richardson /* remap the config at proper address */ 23799a2dd95SBruce Richardson mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr, 23899a2dd95SBruce Richardson sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED, 23999a2dd95SBruce Richardson mem_cfg_fd, 0); 24099a2dd95SBruce Richardson close(mem_cfg_fd); 24199a2dd95SBruce Richardson mem_cfg_fd = -1; 24299a2dd95SBruce Richardson 24399a2dd95SBruce Richardson if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr) { 24499a2dd95SBruce Richardson if (mem_config != MAP_FAILED) { 24599a2dd95SBruce Richardson /* errno is stale, don't use */ 246ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot mmap memory for rte_config at [%p], got [%p]" 24799a2dd95SBruce Richardson " - please use '--" OPT_BASE_VIRTADDR 248ae67895bSDavid Marchand "' option", 24999a2dd95SBruce Richardson rte_mem_cfg_addr, mem_config); 25099a2dd95SBruce Richardson munmap(mem_config, sizeof(struct rte_mem_config)); 25199a2dd95SBruce Richardson return -1; 25299a2dd95SBruce Richardson } 253ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot mmap memory for rte_config! error %i (%s)", 25499a2dd95SBruce Richardson errno, strerror(errno)); 25599a2dd95SBruce Richardson return -1; 25699a2dd95SBruce Richardson } 25799a2dd95SBruce Richardson 25899a2dd95SBruce Richardson config->mem_config = mem_config; 25999a2dd95SBruce Richardson 26099a2dd95SBruce Richardson return 0; 26199a2dd95SBruce Richardson } 26299a2dd95SBruce Richardson 26399a2dd95SBruce Richardson /* Detect if we are a primary or a secondary process */ 26499a2dd95SBruce Richardson enum rte_proc_type_t 26599a2dd95SBruce Richardson eal_proc_type_detect(void) 26699a2dd95SBruce Richardson { 26799a2dd95SBruce Richardson enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; 26899a2dd95SBruce Richardson const char *pathname = eal_runtime_config_path(); 26999a2dd95SBruce Richardson const struct internal_config *internal_conf = 27099a2dd95SBruce Richardson eal_get_internal_configuration(); 27199a2dd95SBruce Richardson 27299a2dd95SBruce Richardson /* if there no shared config, there can be no secondary processes */ 27399a2dd95SBruce Richardson if (!internal_conf->no_shconf) { 27499a2dd95SBruce Richardson /* if we can open the file but not get a write-lock we are a 27599a2dd95SBruce Richardson * secondary process. NOTE: if we get a file handle back, we 27699a2dd95SBruce Richardson * keep that open and don't close it to prevent a race condition 27799a2dd95SBruce Richardson * between multiple opens. 27899a2dd95SBruce Richardson */ 27999a2dd95SBruce Richardson if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) && 28099a2dd95SBruce Richardson (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0)) 28199a2dd95SBruce Richardson ptype = RTE_PROC_SECONDARY; 28299a2dd95SBruce Richardson } 28399a2dd95SBruce Richardson 284ae67895bSDavid Marchand EAL_LOG(INFO, "Auto-detected process type: %s", 28599a2dd95SBruce Richardson ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); 28699a2dd95SBruce Richardson 28799a2dd95SBruce Richardson return ptype; 28899a2dd95SBruce Richardson } 28999a2dd95SBruce Richardson 29099a2dd95SBruce Richardson /* Sets up rte_config structure with the pointer to shared memory config.*/ 29199a2dd95SBruce Richardson static int 29299a2dd95SBruce Richardson rte_config_init(void) 29399a2dd95SBruce Richardson { 29499a2dd95SBruce Richardson struct rte_config *config = rte_eal_get_configuration(); 29599a2dd95SBruce Richardson const struct internal_config *internal_conf = 29699a2dd95SBruce Richardson eal_get_internal_configuration(); 29799a2dd95SBruce Richardson 29899a2dd95SBruce Richardson config->process_type = internal_conf->process_type; 29999a2dd95SBruce Richardson 30099a2dd95SBruce Richardson switch (config->process_type) { 30199a2dd95SBruce Richardson case RTE_PROC_PRIMARY: 30299a2dd95SBruce Richardson if (rte_eal_config_create() < 0) 30399a2dd95SBruce Richardson return -1; 30499a2dd95SBruce Richardson eal_mcfg_update_from_internal(); 30599a2dd95SBruce Richardson break; 30699a2dd95SBruce Richardson case RTE_PROC_SECONDARY: 30799a2dd95SBruce Richardson if (rte_eal_config_attach() < 0) 30899a2dd95SBruce Richardson return -1; 30999a2dd95SBruce Richardson eal_mcfg_wait_complete(); 31099a2dd95SBruce Richardson if (eal_mcfg_check_version() < 0) { 311ae67895bSDavid Marchand EAL_LOG(ERR, "Primary and secondary process DPDK version mismatch"); 31299a2dd95SBruce Richardson return -1; 31399a2dd95SBruce Richardson } 31499a2dd95SBruce Richardson if (rte_eal_config_reattach() < 0) 31599a2dd95SBruce Richardson return -1; 31699a2dd95SBruce Richardson if (!__rte_mp_enable()) { 317ae67895bSDavid Marchand EAL_LOG(ERR, "Primary process refused secondary attachment"); 31899a2dd95SBruce Richardson return -1; 31999a2dd95SBruce Richardson } 32099a2dd95SBruce Richardson eal_mcfg_update_internal(); 32199a2dd95SBruce Richardson break; 32299a2dd95SBruce Richardson case RTE_PROC_AUTO: 32399a2dd95SBruce Richardson case RTE_PROC_INVALID: 324ae67895bSDavid Marchand EAL_LOG(ERR, "Invalid process type %d", 32599a2dd95SBruce Richardson config->process_type); 32699a2dd95SBruce Richardson return -1; 32799a2dd95SBruce Richardson } 32899a2dd95SBruce Richardson 32999a2dd95SBruce Richardson return 0; 33099a2dd95SBruce Richardson } 33199a2dd95SBruce Richardson 33299a2dd95SBruce Richardson /* display usage */ 33399a2dd95SBruce Richardson static void 33499a2dd95SBruce Richardson eal_usage(const char *prgname) 33599a2dd95SBruce Richardson { 33699a2dd95SBruce Richardson rte_usage_hook_t hook = eal_get_application_usage_hook(); 33799a2dd95SBruce Richardson 33899a2dd95SBruce Richardson printf("\nUsage: %s ", prgname); 33999a2dd95SBruce Richardson eal_common_usage(); 34099a2dd95SBruce Richardson /* Allow the application to print its usage message too if hook is set */ 34199a2dd95SBruce Richardson if (hook) { 34299a2dd95SBruce Richardson printf("===== Application Usage =====\n\n"); 34399a2dd95SBruce Richardson (hook)(prgname); 34499a2dd95SBruce Richardson } 34599a2dd95SBruce Richardson } 34699a2dd95SBruce Richardson 34799a2dd95SBruce Richardson static inline size_t 34899a2dd95SBruce Richardson eal_get_hugepage_mem_size(void) 34999a2dd95SBruce Richardson { 35099a2dd95SBruce Richardson uint64_t size = 0; 35199a2dd95SBruce Richardson unsigned i, j; 35299a2dd95SBruce Richardson struct internal_config *internal_conf = 35399a2dd95SBruce Richardson eal_get_internal_configuration(); 35499a2dd95SBruce Richardson 35599a2dd95SBruce Richardson for (i = 0; i < internal_conf->num_hugepage_sizes; i++) { 35699a2dd95SBruce Richardson struct hugepage_info *hpi = &internal_conf->hugepage_info[i]; 35799a2dd95SBruce Richardson if (strnlen(hpi->hugedir, sizeof(hpi->hugedir)) != 0) { 35899a2dd95SBruce Richardson for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { 35999a2dd95SBruce Richardson size += hpi->hugepage_sz * hpi->num_pages[j]; 36099a2dd95SBruce Richardson } 36199a2dd95SBruce Richardson } 36299a2dd95SBruce Richardson } 36399a2dd95SBruce Richardson 36499a2dd95SBruce Richardson return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX; 36599a2dd95SBruce Richardson } 36699a2dd95SBruce Richardson 36799a2dd95SBruce Richardson /* Parse the argument given in the command line of the application */ 36899a2dd95SBruce Richardson static int 36999a2dd95SBruce Richardson eal_parse_args(int argc, char **argv) 37099a2dd95SBruce Richardson { 37199a2dd95SBruce Richardson int opt, ret; 37299a2dd95SBruce Richardson char **argvopt; 37399a2dd95SBruce Richardson int option_index; 37499a2dd95SBruce Richardson char *prgname = argv[0]; 37599a2dd95SBruce Richardson const int old_optind = optind; 37699a2dd95SBruce Richardson const int old_optopt = optopt; 37799a2dd95SBruce Richardson const int old_optreset = optreset; 37899a2dd95SBruce Richardson char * const old_optarg = optarg; 37999a2dd95SBruce Richardson struct internal_config *internal_conf = 38099a2dd95SBruce Richardson eal_get_internal_configuration(); 38199a2dd95SBruce Richardson 38299a2dd95SBruce Richardson argvopt = argv; 38399a2dd95SBruce Richardson optind = 1; 38499a2dd95SBruce Richardson optreset = 1; 38599a2dd95SBruce Richardson 38699a2dd95SBruce Richardson while ((opt = getopt_long(argc, argvopt, eal_short_options, 38799a2dd95SBruce Richardson eal_long_options, &option_index)) != EOF) { 38899a2dd95SBruce Richardson 38999a2dd95SBruce Richardson /* getopt didn't recognise the option */ 39099a2dd95SBruce Richardson if (opt == '?') { 39199a2dd95SBruce Richardson eal_usage(prgname); 39299a2dd95SBruce Richardson ret = -1; 39399a2dd95SBruce Richardson goto out; 39499a2dd95SBruce Richardson } 39599a2dd95SBruce Richardson 3969a4276f9SDavid Marchand /* eal_parse_log_options() already handled this option */ 3979a4276f9SDavid Marchand if (eal_option_is_log(opt)) 39899a2dd95SBruce Richardson continue; 39999a2dd95SBruce Richardson 40099a2dd95SBruce Richardson ret = eal_parse_common_option(opt, optarg, internal_conf); 40199a2dd95SBruce Richardson /* common parser is not happy */ 40299a2dd95SBruce Richardson if (ret < 0) { 40399a2dd95SBruce Richardson eal_usage(prgname); 40499a2dd95SBruce Richardson ret = -1; 40599a2dd95SBruce Richardson goto out; 40699a2dd95SBruce Richardson } 40799a2dd95SBruce Richardson /* common parser handled this option */ 40899a2dd95SBruce Richardson if (ret == 0) 40999a2dd95SBruce Richardson continue; 41099a2dd95SBruce Richardson 41199a2dd95SBruce Richardson switch (opt) { 41299a2dd95SBruce Richardson case OPT_MBUF_POOL_OPS_NAME_NUM: 41399a2dd95SBruce Richardson { 41499a2dd95SBruce Richardson char *ops_name = strdup(optarg); 41599a2dd95SBruce Richardson if (ops_name == NULL) 416ae67895bSDavid Marchand EAL_LOG(ERR, "Could not store mbuf pool ops name"); 41799a2dd95SBruce Richardson else { 41899a2dd95SBruce Richardson /* free old ops name */ 41999a2dd95SBruce Richardson free(internal_conf->user_mbuf_pool_ops_name); 42099a2dd95SBruce Richardson 42199a2dd95SBruce Richardson internal_conf->user_mbuf_pool_ops_name = 42299a2dd95SBruce Richardson ops_name; 42399a2dd95SBruce Richardson } 42499a2dd95SBruce Richardson break; 42599a2dd95SBruce Richardson } 426df60837cSThomas Monjalon case OPT_HELP_NUM: 42799a2dd95SBruce Richardson eal_usage(prgname); 42899a2dd95SBruce Richardson exit(EXIT_SUCCESS); 42999a2dd95SBruce Richardson default: 43099a2dd95SBruce Richardson if (opt < OPT_LONG_MIN_NUM && isprint(opt)) { 431ae67895bSDavid Marchand EAL_LOG(ERR, "Option %c is not supported " 432ae67895bSDavid Marchand "on FreeBSD", opt); 43399a2dd95SBruce Richardson } else if (opt >= OPT_LONG_MIN_NUM && 43499a2dd95SBruce Richardson opt < OPT_LONG_MAX_NUM) { 435ae67895bSDavid Marchand EAL_LOG(ERR, "Option %s is not supported " 436ae67895bSDavid Marchand "on FreeBSD", 43799a2dd95SBruce Richardson eal_long_options[option_index].name); 43899a2dd95SBruce Richardson } else { 439ae67895bSDavid Marchand EAL_LOG(ERR, "Option %d is not supported " 440ae67895bSDavid Marchand "on FreeBSD", opt); 44199a2dd95SBruce Richardson } 44299a2dd95SBruce Richardson eal_usage(prgname); 44399a2dd95SBruce Richardson ret = -1; 44499a2dd95SBruce Richardson goto out; 44599a2dd95SBruce Richardson } 44699a2dd95SBruce Richardson } 44799a2dd95SBruce Richardson 448ce382fddSBruce Richardson /* create runtime data directory. In no_shconf mode, skip any errors */ 449ce382fddSBruce Richardson if (eal_create_runtime_dir() < 0) { 450ce382fddSBruce Richardson if (internal_conf->no_shconf == 0) { 451ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot create runtime directory"); 45299a2dd95SBruce Richardson ret = -1; 45399a2dd95SBruce Richardson goto out; 454ce382fddSBruce Richardson } else 455ae67895bSDavid Marchand EAL_LOG(WARNING, "No DPDK runtime directory created"); 45699a2dd95SBruce Richardson } 45799a2dd95SBruce Richardson 45899a2dd95SBruce Richardson if (eal_adjust_config(internal_conf) != 0) { 45999a2dd95SBruce Richardson ret = -1; 46099a2dd95SBruce Richardson goto out; 46199a2dd95SBruce Richardson } 46299a2dd95SBruce Richardson 46399a2dd95SBruce Richardson /* sanity checks */ 46499a2dd95SBruce Richardson if (eal_check_common_options(internal_conf) != 0) { 46599a2dd95SBruce Richardson eal_usage(prgname); 46699a2dd95SBruce Richardson ret = -1; 46799a2dd95SBruce Richardson goto out; 46899a2dd95SBruce Richardson } 46999a2dd95SBruce Richardson 47099a2dd95SBruce Richardson if (optind >= 0) 47199a2dd95SBruce Richardson argv[optind-1] = prgname; 47299a2dd95SBruce Richardson ret = optind-1; 47399a2dd95SBruce Richardson 47499a2dd95SBruce Richardson out: 47599a2dd95SBruce Richardson /* restore getopt lib */ 47699a2dd95SBruce Richardson optind = old_optind; 47799a2dd95SBruce Richardson optopt = old_optopt; 47899a2dd95SBruce Richardson optreset = old_optreset; 47999a2dd95SBruce Richardson optarg = old_optarg; 48099a2dd95SBruce Richardson 48199a2dd95SBruce Richardson return ret; 48299a2dd95SBruce Richardson } 48399a2dd95SBruce Richardson 48499a2dd95SBruce Richardson static int 48599a2dd95SBruce Richardson check_socket(const struct rte_memseg_list *msl, void *arg) 48699a2dd95SBruce Richardson { 48799a2dd95SBruce Richardson int *socket_id = arg; 48899a2dd95SBruce Richardson 48999a2dd95SBruce Richardson if (msl->external) 49099a2dd95SBruce Richardson return 0; 49199a2dd95SBruce Richardson 49299a2dd95SBruce Richardson if (msl->socket_id == *socket_id && msl->memseg_arr.count != 0) 49399a2dd95SBruce Richardson return 1; 49499a2dd95SBruce Richardson 49599a2dd95SBruce Richardson return 0; 49699a2dd95SBruce Richardson } 49799a2dd95SBruce Richardson 49899a2dd95SBruce Richardson static void 49999a2dd95SBruce Richardson eal_check_mem_on_local_socket(void) 50099a2dd95SBruce Richardson { 50199a2dd95SBruce Richardson int socket_id; 50299a2dd95SBruce Richardson const struct rte_config *config = rte_eal_get_configuration(); 50399a2dd95SBruce Richardson 50499a2dd95SBruce Richardson socket_id = rte_lcore_to_socket_id(config->main_lcore); 50599a2dd95SBruce Richardson 50699a2dd95SBruce Richardson if (rte_memseg_list_walk(check_socket, &socket_id) == 0) 507ae67895bSDavid Marchand EAL_LOG(WARNING, "WARNING: Main core has no memory on local socket!"); 50899a2dd95SBruce Richardson } 50999a2dd95SBruce Richardson 51099a2dd95SBruce Richardson 51199a2dd95SBruce Richardson static int 51299a2dd95SBruce Richardson sync_func(__rte_unused void *arg) 51399a2dd95SBruce Richardson { 51499a2dd95SBruce Richardson return 0; 51599a2dd95SBruce Richardson } 51699a2dd95SBruce Richardson /* Abstraction for port I/0 privilege */ 51799a2dd95SBruce Richardson int 51899a2dd95SBruce Richardson rte_eal_iopl_init(void) 51999a2dd95SBruce Richardson { 52099a2dd95SBruce Richardson static int fd = -1; 52199a2dd95SBruce Richardson 52299a2dd95SBruce Richardson if (fd < 0) 52399a2dd95SBruce Richardson fd = open("/dev/io", O_RDWR); 52499a2dd95SBruce Richardson 52599a2dd95SBruce Richardson if (fd < 0) 52699a2dd95SBruce Richardson return -1; 52799a2dd95SBruce Richardson /* keep fd open for iopl */ 52899a2dd95SBruce Richardson return 0; 52999a2dd95SBruce Richardson } 53099a2dd95SBruce Richardson 53199a2dd95SBruce Richardson static void rte_eal_init_alert(const char *msg) 53299a2dd95SBruce Richardson { 53372bf6da8SStephen Hemminger EAL_LOG(ALERT, "%s", msg); 53499a2dd95SBruce Richardson } 53599a2dd95SBruce Richardson 53699a2dd95SBruce Richardson /* Launch threads, called at application init(). */ 53799a2dd95SBruce Richardson int 53899a2dd95SBruce Richardson rte_eal_init(int argc, char **argv) 53999a2dd95SBruce Richardson { 54099a2dd95SBruce Richardson int i, fctret, ret; 54199a2dd95SBruce Richardson static uint32_t run_once; 54299a2dd95SBruce Richardson uint32_t has_run = 0; 54399a2dd95SBruce Richardson char cpuset[RTE_CPU_AFFINITY_STR_LEN]; 54493d8a7edSThomas Monjalon char thread_name[RTE_THREAD_NAME_SIZE]; 54599a2dd95SBruce Richardson const struct rte_config *config = rte_eal_get_configuration(); 54699a2dd95SBruce Richardson struct internal_config *internal_conf = 54799a2dd95SBruce Richardson eal_get_internal_configuration(); 5489790fc21SDmitry Kozlyuk bool has_phys_addr; 5499790fc21SDmitry Kozlyuk enum rte_iova_mode iova_mode; 55099a2dd95SBruce Richardson 551*2773d39fSStephen Hemminger /* setup log as early as possible */ 552*2773d39fSStephen Hemminger if (eal_parse_log_options(argc, argv) < 0) { 553*2773d39fSStephen Hemminger rte_eal_init_alert("invalid log arguments."); 554*2773d39fSStephen Hemminger rte_errno = EINVAL; 555*2773d39fSStephen Hemminger return -1; 556*2773d39fSStephen Hemminger } 557*2773d39fSStephen Hemminger 558*2773d39fSStephen Hemminger eal_log_init(getprogname()); 559*2773d39fSStephen Hemminger 56099a2dd95SBruce Richardson /* checks if the machine is adequate */ 56199a2dd95SBruce Richardson if (!rte_cpu_is_supported()) { 56299a2dd95SBruce Richardson rte_eal_init_alert("unsupported cpu type."); 56399a2dd95SBruce Richardson rte_errno = ENOTSUP; 56499a2dd95SBruce Richardson return -1; 56599a2dd95SBruce Richardson } 56699a2dd95SBruce Richardson 567e168b189SDavid Christensen /* verify if DPDK supported on architecture MMU */ 568e168b189SDavid Christensen if (!eal_mmu_supported()) { 569e168b189SDavid Christensen rte_eal_init_alert("unsupported MMU type."); 570e168b189SDavid Christensen rte_errno = ENOTSUP; 571e168b189SDavid Christensen return -1; 572e168b189SDavid Christensen } 573e168b189SDavid Christensen 5742a7a42a5STyler Retzlaff if (!rte_atomic_compare_exchange_strong_explicit(&run_once, &has_run, 1, 5752a7a42a5STyler Retzlaff rte_memory_order_relaxed, rte_memory_order_relaxed)) { 57699a2dd95SBruce Richardson rte_eal_init_alert("already called initialization."); 57799a2dd95SBruce Richardson rte_errno = EALREADY; 57899a2dd95SBruce Richardson return -1; 57999a2dd95SBruce Richardson } 58099a2dd95SBruce Richardson 58199a2dd95SBruce Richardson eal_reset_internal_config(internal_conf); 58299a2dd95SBruce Richardson 58399a2dd95SBruce Richardson /* clone argv to report out later in telemetry */ 58499a2dd95SBruce Richardson eal_save_args(argc, argv); 58599a2dd95SBruce Richardson 58699a2dd95SBruce Richardson if (rte_eal_cpu_init() < 0) { 58799a2dd95SBruce Richardson rte_eal_init_alert("Cannot detect lcores."); 58899a2dd95SBruce Richardson rte_errno = ENOTSUP; 58999a2dd95SBruce Richardson return -1; 59099a2dd95SBruce Richardson } 59199a2dd95SBruce Richardson 59299a2dd95SBruce Richardson fctret = eal_parse_args(argc, argv); 59399a2dd95SBruce Richardson if (fctret < 0) { 59499a2dd95SBruce Richardson rte_eal_init_alert("Invalid 'command line' arguments."); 59599a2dd95SBruce Richardson rte_errno = EINVAL; 5962a7a42a5STyler Retzlaff rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed); 59799a2dd95SBruce Richardson return -1; 59899a2dd95SBruce Richardson } 59999a2dd95SBruce Richardson 60099a2dd95SBruce Richardson /* FreeBSD always uses legacy memory model */ 60199a2dd95SBruce Richardson internal_conf->legacy_mem = true; 6020faa4cfcSBruce Richardson if (internal_conf->in_memory) { 603ae67895bSDavid Marchand EAL_LOG(WARNING, "Warning: ignoring unsupported flag, '%s'", 604ae67895bSDavid Marchand OPT_IN_MEMORY); 6050faa4cfcSBruce Richardson internal_conf->in_memory = false; 6060faa4cfcSBruce Richardson } 60799a2dd95SBruce Richardson 60899a2dd95SBruce Richardson if (eal_plugins_init() < 0) { 60999a2dd95SBruce Richardson rte_eal_init_alert("Cannot init plugins"); 61099a2dd95SBruce Richardson rte_errno = EINVAL; 6112a7a42a5STyler Retzlaff rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed); 61299a2dd95SBruce Richardson return -1; 61399a2dd95SBruce Richardson } 61499a2dd95SBruce Richardson 61599a2dd95SBruce Richardson if (eal_trace_init() < 0) { 61699a2dd95SBruce Richardson rte_eal_init_alert("Cannot init trace"); 61799a2dd95SBruce Richardson rte_errno = EFAULT; 6182a7a42a5STyler Retzlaff rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed); 61999a2dd95SBruce Richardson return -1; 62099a2dd95SBruce Richardson } 62199a2dd95SBruce Richardson 62299a2dd95SBruce Richardson if (eal_option_device_parse()) { 62399a2dd95SBruce Richardson rte_errno = ENODEV; 6242a7a42a5STyler Retzlaff rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed); 62599a2dd95SBruce Richardson return -1; 62699a2dd95SBruce Richardson } 62799a2dd95SBruce Richardson 62899a2dd95SBruce Richardson if (rte_config_init() < 0) { 62999a2dd95SBruce Richardson rte_eal_init_alert("Cannot init config"); 63099a2dd95SBruce Richardson return -1; 63199a2dd95SBruce Richardson } 63299a2dd95SBruce Richardson 63399a2dd95SBruce Richardson if (rte_eal_intr_init() < 0) { 63499a2dd95SBruce Richardson rte_eal_init_alert("Cannot init interrupt-handling thread"); 63599a2dd95SBruce Richardson return -1; 63699a2dd95SBruce Richardson } 63799a2dd95SBruce Richardson 63899a2dd95SBruce Richardson if (rte_eal_alarm_init() < 0) { 63999a2dd95SBruce Richardson rte_eal_init_alert("Cannot init alarm"); 64099a2dd95SBruce Richardson /* rte_eal_alarm_init sets rte_errno on failure. */ 64199a2dd95SBruce Richardson return -1; 64299a2dd95SBruce Richardson } 64399a2dd95SBruce Richardson 64499a2dd95SBruce Richardson /* Put mp channel init before bus scan so that we can init the vdev 64599a2dd95SBruce Richardson * bus through mp channel in the secondary process before the bus scan. 64699a2dd95SBruce Richardson */ 64799a2dd95SBruce Richardson if (rte_mp_channel_init() < 0 && rte_errno != ENOTSUP) { 64899a2dd95SBruce Richardson rte_eal_init_alert("failed to init mp channel"); 64999a2dd95SBruce Richardson if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 65099a2dd95SBruce Richardson rte_errno = EFAULT; 65199a2dd95SBruce Richardson return -1; 65299a2dd95SBruce Richardson } 65399a2dd95SBruce Richardson } 65499a2dd95SBruce Richardson 65599a2dd95SBruce Richardson if (rte_bus_scan()) { 65699a2dd95SBruce Richardson rte_eal_init_alert("Cannot scan the buses for devices"); 65799a2dd95SBruce Richardson rte_errno = ENODEV; 6582a7a42a5STyler Retzlaff rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed); 65999a2dd95SBruce Richardson return -1; 66099a2dd95SBruce Richardson } 66199a2dd95SBruce Richardson 6629790fc21SDmitry Kozlyuk /* 6639790fc21SDmitry Kozlyuk * PA are only available for hugepages via contigmem. 6649790fc21SDmitry Kozlyuk * If contigmem is inaccessible, rte_eal_hugepage_init() will fail 6659790fc21SDmitry Kozlyuk * with a message describing the cause. 6669790fc21SDmitry Kozlyuk */ 6679790fc21SDmitry Kozlyuk has_phys_addr = internal_conf->no_hugetlbfs == 0; 6689790fc21SDmitry Kozlyuk iova_mode = internal_conf->iova_mode; 6699790fc21SDmitry Kozlyuk if (iova_mode == RTE_IOVA_DC) { 670ae67895bSDavid Marchand EAL_LOG(DEBUG, "Specific IOVA mode is not requested, autodetecting"); 6719790fc21SDmitry Kozlyuk if (has_phys_addr) { 672ae67895bSDavid Marchand EAL_LOG(DEBUG, "Selecting IOVA mode according to bus requests"); 6739790fc21SDmitry Kozlyuk iova_mode = rte_bus_get_iommu_class(); 674a37335bcSViacheslav Ovsiienko if (iova_mode == RTE_IOVA_DC) { 675a37335bcSViacheslav Ovsiienko if (!RTE_IOVA_IN_MBUF) { 676a37335bcSViacheslav Ovsiienko iova_mode = RTE_IOVA_VA; 677ae67895bSDavid Marchand EAL_LOG(DEBUG, "IOVA as VA mode is forced by build option."); 678a37335bcSViacheslav Ovsiienko } else { 67999a2dd95SBruce Richardson iova_mode = RTE_IOVA_PA; 680a37335bcSViacheslav Ovsiienko } 681a37335bcSViacheslav Ovsiienko } 68299a2dd95SBruce Richardson } else { 6839790fc21SDmitry Kozlyuk iova_mode = RTE_IOVA_VA; 68499a2dd95SBruce Richardson } 6859790fc21SDmitry Kozlyuk } 686a37335bcSViacheslav Ovsiienko 687a37335bcSViacheslav Ovsiienko if (iova_mode == RTE_IOVA_PA && !has_phys_addr) { 688a37335bcSViacheslav Ovsiienko rte_eal_init_alert("Cannot use IOVA as 'PA' since physical addresses are not available"); 689a37335bcSViacheslav Ovsiienko rte_errno = EINVAL; 690a37335bcSViacheslav Ovsiienko return -1; 691a37335bcSViacheslav Ovsiienko } 692a37335bcSViacheslav Ovsiienko 693a37335bcSViacheslav Ovsiienko if (iova_mode == RTE_IOVA_PA && !RTE_IOVA_IN_MBUF) { 694a37335bcSViacheslav Ovsiienko rte_eal_init_alert("Cannot use IOVA as 'PA' as it is disabled during build"); 695a37335bcSViacheslav Ovsiienko rte_errno = EINVAL; 696a37335bcSViacheslav Ovsiienko return -1; 697a37335bcSViacheslav Ovsiienko } 698a37335bcSViacheslav Ovsiienko 6999790fc21SDmitry Kozlyuk rte_eal_get_configuration()->iova_mode = iova_mode; 700ae67895bSDavid Marchand EAL_LOG(INFO, "Selected IOVA mode '%s'", 70199a2dd95SBruce Richardson rte_eal_iova_mode() == RTE_IOVA_PA ? "PA" : "VA"); 70299a2dd95SBruce Richardson 70399a2dd95SBruce Richardson if (internal_conf->no_hugetlbfs == 0) { 70499a2dd95SBruce Richardson /* rte_config isn't initialized yet */ 70599a2dd95SBruce Richardson ret = internal_conf->process_type == RTE_PROC_PRIMARY ? 70699a2dd95SBruce Richardson eal_hugepage_info_init() : 70799a2dd95SBruce Richardson eal_hugepage_info_read(); 70899a2dd95SBruce Richardson if (ret < 0) { 70999a2dd95SBruce Richardson rte_eal_init_alert("Cannot get hugepage information."); 71099a2dd95SBruce Richardson rte_errno = EACCES; 7112a7a42a5STyler Retzlaff rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed); 71299a2dd95SBruce Richardson return -1; 71399a2dd95SBruce Richardson } 71499a2dd95SBruce Richardson } 71599a2dd95SBruce Richardson 71699a2dd95SBruce Richardson if (internal_conf->memory == 0 && internal_conf->force_sockets == 0) { 71799a2dd95SBruce Richardson if (internal_conf->no_hugetlbfs) 71899a2dd95SBruce Richardson internal_conf->memory = MEMSIZE_IF_NO_HUGE_PAGE; 71999a2dd95SBruce Richardson else 72099a2dd95SBruce Richardson internal_conf->memory = eal_get_hugepage_mem_size(); 72199a2dd95SBruce Richardson } 72299a2dd95SBruce Richardson 72399a2dd95SBruce Richardson if (internal_conf->vmware_tsc_map == 1) { 72499a2dd95SBruce Richardson #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT 72599a2dd95SBruce Richardson rte_cycles_vmware_tsc_map = 1; 726ae67895bSDavid Marchand EAL_LOG(DEBUG, "Using VMWARE TSC MAP, " 727ae67895bSDavid Marchand "you must have monitor_control.pseudo_perfctr = TRUE"); 72899a2dd95SBruce Richardson #else 729ae67895bSDavid Marchand EAL_LOG(WARNING, "Ignoring --vmware-tsc-map because " 730ae67895bSDavid Marchand "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set"); 73199a2dd95SBruce Richardson #endif 73299a2dd95SBruce Richardson } 73399a2dd95SBruce Richardson 73499a2dd95SBruce Richardson /* in secondary processes, memory init may allocate additional fbarrays 73599a2dd95SBruce Richardson * not present in primary processes, so to avoid any potential issues, 73699a2dd95SBruce Richardson * initialize memzones first. 73799a2dd95SBruce Richardson */ 73899a2dd95SBruce Richardson if (rte_eal_memzone_init() < 0) { 73999a2dd95SBruce Richardson rte_eal_init_alert("Cannot init memzone"); 74099a2dd95SBruce Richardson rte_errno = ENODEV; 74199a2dd95SBruce Richardson return -1; 74299a2dd95SBruce Richardson } 74399a2dd95SBruce Richardson 7442e2f0272SDavid Marchand rte_mcfg_mem_read_lock(); 7452e2f0272SDavid Marchand 74699a2dd95SBruce Richardson if (rte_eal_memory_init() < 0) { 7472e2f0272SDavid Marchand rte_mcfg_mem_read_unlock(); 74899a2dd95SBruce Richardson rte_eal_init_alert("Cannot init memory"); 74999a2dd95SBruce Richardson rte_errno = ENOMEM; 75099a2dd95SBruce Richardson return -1; 75199a2dd95SBruce Richardson } 75299a2dd95SBruce Richardson 75399a2dd95SBruce Richardson if (rte_eal_malloc_heap_init() < 0) { 7542e2f0272SDavid Marchand rte_mcfg_mem_read_unlock(); 7552e2f0272SDavid Marchand rte_eal_init_alert("Cannot init malloc heap"); 7562e2f0272SDavid Marchand rte_errno = ENODEV; 7572e2f0272SDavid Marchand return -1; 7582e2f0272SDavid Marchand } 7592e2f0272SDavid Marchand 7602e2f0272SDavid Marchand rte_mcfg_mem_read_unlock(); 7612e2f0272SDavid Marchand 7622e2f0272SDavid Marchand if (rte_eal_malloc_heap_populate() < 0) { 76399a2dd95SBruce Richardson rte_eal_init_alert("Cannot init malloc heap"); 76499a2dd95SBruce Richardson rte_errno = ENODEV; 76599a2dd95SBruce Richardson return -1; 76699a2dd95SBruce Richardson } 76799a2dd95SBruce Richardson 76899a2dd95SBruce Richardson if (rte_eal_tailqs_init() < 0) { 76999a2dd95SBruce Richardson rte_eal_init_alert("Cannot init tail queues for objects"); 77099a2dd95SBruce Richardson rte_errno = EFAULT; 77199a2dd95SBruce Richardson return -1; 77299a2dd95SBruce Richardson } 77399a2dd95SBruce Richardson 77499a2dd95SBruce Richardson if (rte_eal_timer_init() < 0) { 77599a2dd95SBruce Richardson rte_eal_init_alert("Cannot init HPET or TSC timers"); 77699a2dd95SBruce Richardson rte_errno = ENOTSUP; 77799a2dd95SBruce Richardson return -1; 77899a2dd95SBruce Richardson } 77999a2dd95SBruce Richardson 78099a2dd95SBruce Richardson eal_check_mem_on_local_socket(); 78199a2dd95SBruce Richardson 7828b0a1b8cSTyler Retzlaff if (rte_thread_set_affinity_by_id(rte_thread_self(), 78399a2dd95SBruce Richardson &lcore_config[config->main_lcore].cpuset) != 0) { 78499a2dd95SBruce Richardson rte_eal_init_alert("Cannot set affinity"); 78599a2dd95SBruce Richardson rte_errno = EINVAL; 78699a2dd95SBruce Richardson return -1; 78799a2dd95SBruce Richardson } 78899a2dd95SBruce Richardson __rte_thread_init(config->main_lcore, 78999a2dd95SBruce Richardson &lcore_config[config->main_lcore].cpuset); 79099a2dd95SBruce Richardson 79199a2dd95SBruce Richardson ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset)); 79299a2dd95SBruce Richardson 793ae67895bSDavid Marchand EAL_LOG(DEBUG, "Main lcore %u is ready (tid=%zx;cpuset=[%s%s])", 794a95d7054SDavid Marchand config->main_lcore, (uintptr_t)pthread_self(), cpuset, 79599a2dd95SBruce Richardson ret == 0 ? "" : "..."); 79699a2dd95SBruce Richardson 79799a2dd95SBruce Richardson RTE_LCORE_FOREACH_WORKER(i) { 79899a2dd95SBruce Richardson 79999a2dd95SBruce Richardson /* 80099a2dd95SBruce Richardson * create communication pipes between main thread 80199a2dd95SBruce Richardson * and children 80299a2dd95SBruce Richardson */ 80399a2dd95SBruce Richardson if (pipe(lcore_config[i].pipe_main2worker) < 0) 80499a2dd95SBruce Richardson rte_panic("Cannot create pipe\n"); 80599a2dd95SBruce Richardson if (pipe(lcore_config[i].pipe_worker2main) < 0) 80699a2dd95SBruce Richardson rte_panic("Cannot create pipe\n"); 80799a2dd95SBruce Richardson 80899a2dd95SBruce Richardson lcore_config[i].state = WAIT; 80999a2dd95SBruce Richardson 81099a2dd95SBruce Richardson /* create a thread for each lcore */ 8118b0a1b8cSTyler Retzlaff ret = rte_thread_create(&lcore_config[i].thread_id, NULL, 812449e7dbcSDavid Marchand eal_thread_loop, (void *)(uintptr_t)i); 81399a2dd95SBruce Richardson if (ret != 0) 81499a2dd95SBruce Richardson rte_panic("Cannot create thread\n"); 81599a2dd95SBruce Richardson 81699a2dd95SBruce Richardson /* Set thread_name for aid in debugging. */ 81799a2dd95SBruce Richardson snprintf(thread_name, sizeof(thread_name), 81862774b78SThomas Monjalon "dpdk-worker%d", i); 8196d87be58STyler Retzlaff rte_thread_set_name(lcore_config[i].thread_id, thread_name); 82099a2dd95SBruce Richardson 8218b0a1b8cSTyler Retzlaff ret = rte_thread_set_affinity_by_id(lcore_config[i].thread_id, 8228b0a1b8cSTyler Retzlaff &lcore_config[i].cpuset); 82399a2dd95SBruce Richardson if (ret != 0) 82499a2dd95SBruce Richardson rte_panic("Cannot set affinity\n"); 82599a2dd95SBruce Richardson } 82699a2dd95SBruce Richardson 82799a2dd95SBruce Richardson /* 82899a2dd95SBruce Richardson * Launch a dummy function on all worker lcores, so that main lcore 82999a2dd95SBruce Richardson * knows they are all ready when this function returns. 83099a2dd95SBruce Richardson */ 83199a2dd95SBruce Richardson rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MAIN); 83299a2dd95SBruce Richardson rte_eal_mp_wait_lcore(); 83399a2dd95SBruce Richardson 83499a2dd95SBruce Richardson /* initialize services so vdevs register service during bus_probe. */ 83599a2dd95SBruce Richardson ret = rte_service_init(); 83699a2dd95SBruce Richardson if (ret) { 83799a2dd95SBruce Richardson rte_eal_init_alert("rte_service_init() failed"); 83899a2dd95SBruce Richardson rte_errno = -ret; 83999a2dd95SBruce Richardson return -1; 84099a2dd95SBruce Richardson } 84199a2dd95SBruce Richardson 84299a2dd95SBruce Richardson /* Probe all the buses and devices/drivers on them */ 84399a2dd95SBruce Richardson if (rte_bus_probe()) { 84499a2dd95SBruce Richardson rte_eal_init_alert("Cannot probe devices"); 84599a2dd95SBruce Richardson rte_errno = ENOTSUP; 84699a2dd95SBruce Richardson return -1; 84799a2dd95SBruce Richardson } 84899a2dd95SBruce Richardson 84999a2dd95SBruce Richardson /* initialize default service/lcore mappings and start running. Ignore 85099a2dd95SBruce Richardson * -ENOTSUP, as it indicates no service coremask passed to EAL. 85199a2dd95SBruce Richardson */ 85299a2dd95SBruce Richardson ret = rte_service_start_with_defaults(); 85399a2dd95SBruce Richardson if (ret < 0 && ret != -ENOTSUP) { 85499a2dd95SBruce Richardson rte_errno = -ret; 85599a2dd95SBruce Richardson return -1; 85699a2dd95SBruce Richardson } 85799a2dd95SBruce Richardson 85899a2dd95SBruce Richardson /* 85999a2dd95SBruce Richardson * Clean up unused files in runtime directory. We do this at the end of 86099a2dd95SBruce Richardson * init and not at the beginning because we want to clean stuff up 86199a2dd95SBruce Richardson * whether we are primary or secondary process, but we cannot remove 86299a2dd95SBruce Richardson * primary process' files because secondary should be able to run even 86399a2dd95SBruce Richardson * if primary process is dead. 86499a2dd95SBruce Richardson * 86599a2dd95SBruce Richardson * In no_shconf mode, no runtime directory is created in the first 86699a2dd95SBruce Richardson * place, so no cleanup needed. 86799a2dd95SBruce Richardson */ 86899a2dd95SBruce Richardson if (!internal_conf->no_shconf && eal_clean_runtime_dir() < 0) { 86999a2dd95SBruce Richardson rte_eal_init_alert("Cannot clear runtime directory"); 87099a2dd95SBruce Richardson return -1; 87199a2dd95SBruce Richardson } 872e89463a3SBruce Richardson if (rte_eal_process_type() == RTE_PROC_PRIMARY && !internal_conf->no_telemetry) { 87399a2dd95SBruce Richardson if (rte_telemetry_init(rte_eal_get_runtime_dir(), 87499a2dd95SBruce Richardson rte_version(), 87568150b90SBruce Richardson &internal_conf->ctrl_cpuset) != 0) 87699a2dd95SBruce Richardson return -1; 87799a2dd95SBruce Richardson } 87899a2dd95SBruce Richardson 87999a2dd95SBruce Richardson eal_mcfg_complete(); 88099a2dd95SBruce Richardson 88199a2dd95SBruce Richardson return fctret; 88299a2dd95SBruce Richardson } 88399a2dd95SBruce Richardson 88499a2dd95SBruce Richardson int 88599a2dd95SBruce Richardson rte_eal_cleanup(void) 88699a2dd95SBruce Richardson { 887a4a2ac98SBruce Richardson static uint32_t run_once; 888a4a2ac98SBruce Richardson uint32_t has_run = 0; 889a4a2ac98SBruce Richardson 8902a7a42a5STyler Retzlaff if (!rte_atomic_compare_exchange_strong_explicit(&run_once, &has_run, 1, 8912a7a42a5STyler Retzlaff rte_memory_order_relaxed, rte_memory_order_relaxed)) { 892ae67895bSDavid Marchand EAL_LOG(WARNING, "Already called cleanup"); 893a4a2ac98SBruce Richardson rte_errno = EALREADY; 894a4a2ac98SBruce Richardson return -1; 895a4a2ac98SBruce Richardson } 896a4a2ac98SBruce Richardson 89799a2dd95SBruce Richardson struct internal_config *internal_conf = 89899a2dd95SBruce Richardson eal_get_internal_configuration(); 89999a2dd95SBruce Richardson rte_service_finalize(); 90099a2dd95SBruce Richardson rte_mp_channel_cleanup(); 9011cab1a40SKevin Laatz eal_bus_cleanup(); 902a8f23b44SChengwen Feng rte_trace_save(); 903a8f23b44SChengwen Feng eal_trace_fini(); 904cc759682SFengnan Chang rte_eal_alarm_cleanup(); 90599a2dd95SBruce Richardson /* after this point, any DPDK pointers will become dangling */ 90699a2dd95SBruce Richardson rte_eal_memory_detach(); 90799a2dd95SBruce Richardson eal_cleanup_config(internal_conf); 9085bce9bedSMattias Rönnblom eal_lcore_var_cleanup(); 90999a2dd95SBruce Richardson return 0; 91099a2dd95SBruce Richardson } 91199a2dd95SBruce Richardson 91299a2dd95SBruce Richardson int rte_eal_create_uio_dev(void) 91399a2dd95SBruce Richardson { 91499a2dd95SBruce Richardson const struct internal_config *internal_conf = 91599a2dd95SBruce Richardson eal_get_internal_configuration(); 91699a2dd95SBruce Richardson return internal_conf->create_uio_dev; 91799a2dd95SBruce Richardson } 91899a2dd95SBruce Richardson 91999a2dd95SBruce Richardson enum rte_intr_mode 92099a2dd95SBruce Richardson rte_eal_vfio_intr_mode(void) 92199a2dd95SBruce Richardson { 92299a2dd95SBruce Richardson return RTE_INTR_MODE_NONE; 92399a2dd95SBruce Richardson } 92499a2dd95SBruce Richardson 92599a2dd95SBruce Richardson void 92699a2dd95SBruce Richardson rte_eal_vfio_get_vf_token(__rte_unused rte_uuid_t vf_token) 92799a2dd95SBruce Richardson { 92899a2dd95SBruce Richardson } 92999a2dd95SBruce Richardson 93099a2dd95SBruce Richardson int rte_vfio_setup_device(__rte_unused const char *sysfs_base, 93199a2dd95SBruce Richardson __rte_unused const char *dev_addr, 93299a2dd95SBruce Richardson __rte_unused int *vfio_dev_fd, 93399a2dd95SBruce Richardson __rte_unused struct vfio_device_info *device_info) 93499a2dd95SBruce Richardson { 9354fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 93699a2dd95SBruce Richardson return -1; 93799a2dd95SBruce Richardson } 93899a2dd95SBruce Richardson 93999a2dd95SBruce Richardson int rte_vfio_release_device(__rte_unused const char *sysfs_base, 94099a2dd95SBruce Richardson __rte_unused const char *dev_addr, 94199a2dd95SBruce Richardson __rte_unused int fd) 94299a2dd95SBruce Richardson { 9434fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 94499a2dd95SBruce Richardson return -1; 94599a2dd95SBruce Richardson } 94699a2dd95SBruce Richardson 94799a2dd95SBruce Richardson int rte_vfio_enable(__rte_unused const char *modname) 94899a2dd95SBruce Richardson { 9494fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 95099a2dd95SBruce Richardson return -1; 95199a2dd95SBruce Richardson } 95299a2dd95SBruce Richardson 95399a2dd95SBruce Richardson int rte_vfio_is_enabled(__rte_unused const char *modname) 95499a2dd95SBruce Richardson { 95599a2dd95SBruce Richardson return 0; 95699a2dd95SBruce Richardson } 95799a2dd95SBruce Richardson 95899a2dd95SBruce Richardson int rte_vfio_noiommu_is_enabled(void) 95999a2dd95SBruce Richardson { 96099a2dd95SBruce Richardson return 0; 96199a2dd95SBruce Richardson } 96299a2dd95SBruce Richardson 96399a2dd95SBruce Richardson int rte_vfio_clear_group(__rte_unused int vfio_group_fd) 96499a2dd95SBruce Richardson { 9654fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 966bf8b792fSAnatoly Burakov return -1; 96799a2dd95SBruce Richardson } 96899a2dd95SBruce Richardson 96999a2dd95SBruce Richardson int 97099a2dd95SBruce Richardson rte_vfio_get_group_num(__rte_unused const char *sysfs_base, 97199a2dd95SBruce Richardson __rte_unused const char *dev_addr, 97299a2dd95SBruce Richardson __rte_unused int *iommu_group_num) 97399a2dd95SBruce Richardson { 9744fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 97599a2dd95SBruce Richardson return -1; 97699a2dd95SBruce Richardson } 97799a2dd95SBruce Richardson 97899a2dd95SBruce Richardson int 97999a2dd95SBruce Richardson rte_vfio_get_container_fd(void) 98099a2dd95SBruce Richardson { 9814fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 98299a2dd95SBruce Richardson return -1; 98399a2dd95SBruce Richardson } 98499a2dd95SBruce Richardson 98599a2dd95SBruce Richardson int 98699a2dd95SBruce Richardson rte_vfio_get_group_fd(__rte_unused int iommu_group_num) 98799a2dd95SBruce Richardson { 9884fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 98999a2dd95SBruce Richardson return -1; 99099a2dd95SBruce Richardson } 99199a2dd95SBruce Richardson 99299a2dd95SBruce Richardson int 99399a2dd95SBruce Richardson rte_vfio_container_create(void) 99499a2dd95SBruce Richardson { 9954fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 99699a2dd95SBruce Richardson return -1; 99799a2dd95SBruce Richardson } 99899a2dd95SBruce Richardson 99999a2dd95SBruce Richardson int 100099a2dd95SBruce Richardson rte_vfio_container_destroy(__rte_unused int container_fd) 100199a2dd95SBruce Richardson { 10024fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 100399a2dd95SBruce Richardson return -1; 100499a2dd95SBruce Richardson } 100599a2dd95SBruce Richardson 100699a2dd95SBruce Richardson int 100799a2dd95SBruce Richardson rte_vfio_container_group_bind(__rte_unused int container_fd, 100899a2dd95SBruce Richardson __rte_unused int iommu_group_num) 100999a2dd95SBruce Richardson { 10104fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 101199a2dd95SBruce Richardson return -1; 101299a2dd95SBruce Richardson } 101399a2dd95SBruce Richardson 101499a2dd95SBruce Richardson int 101599a2dd95SBruce Richardson rte_vfio_container_group_unbind(__rte_unused int container_fd, 101699a2dd95SBruce Richardson __rte_unused int iommu_group_num) 101799a2dd95SBruce Richardson { 10184fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 101999a2dd95SBruce Richardson return -1; 102099a2dd95SBruce Richardson } 102199a2dd95SBruce Richardson 102299a2dd95SBruce Richardson int 102399a2dd95SBruce Richardson rte_vfio_container_dma_map(__rte_unused int container_fd, 102499a2dd95SBruce Richardson __rte_unused uint64_t vaddr, 102599a2dd95SBruce Richardson __rte_unused uint64_t iova, 102699a2dd95SBruce Richardson __rte_unused uint64_t len) 102799a2dd95SBruce Richardson { 10284fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 102999a2dd95SBruce Richardson return -1; 103099a2dd95SBruce Richardson } 103199a2dd95SBruce Richardson 103299a2dd95SBruce Richardson int 103399a2dd95SBruce Richardson rte_vfio_container_dma_unmap(__rte_unused int container_fd, 103499a2dd95SBruce Richardson __rte_unused uint64_t vaddr, 103599a2dd95SBruce Richardson __rte_unused uint64_t iova, 103699a2dd95SBruce Richardson __rte_unused uint64_t len) 103799a2dd95SBruce Richardson { 10384fd15c6aSAnatoly Burakov rte_errno = ENOTSUP; 103999a2dd95SBruce Richardson return -1; 104099a2dd95SBruce Richardson } 1041