LCOV - code coverage report
Current view: top level - lib/eal/linux - eal.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 392 610 64.3 %
Date: 2024-01-22 16:26:08 Functions: 25 29 86.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 199 324 61.4 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2018 Intel Corporation.
       3                 :            :  * Copyright(c) 2012-2014 6WIND S.A.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <ctype.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <string.h>
      11                 :            : #include <unistd.h>
      12                 :            : #include <pthread.h>
      13                 :            : #include <getopt.h>
      14                 :            : #include <sys/file.h>
      15                 :            : #include <dirent.h>
      16                 :            : #include <fcntl.h>
      17                 :            : #include <fnmatch.h>
      18                 :            : #include <stddef.h>
      19                 :            : #include <errno.h>
      20                 :            : #include <limits.h>
      21                 :            : #include <sys/mman.h>
      22                 :            : #include <sys/stat.h>
      23                 :            : #if defined(RTE_ARCH_X86)
      24                 :            : #include <sys/io.h>
      25                 :            : #endif
      26                 :            : #include <linux/version.h>
      27                 :            : 
      28                 :            : #include <rte_common.h>
      29                 :            : #include <rte_debug.h>
      30                 :            : #include <rte_memory.h>
      31                 :            : #include <rte_launch.h>
      32                 :            : #include <rte_eal.h>
      33                 :            : #include <rte_eal_memconfig.h>
      34                 :            : #include <rte_errno.h>
      35                 :            : #include <rte_lcore.h>
      36                 :            : #include <rte_service_component.h>
      37                 :            : #include <rte_log.h>
      38                 :            : #include <rte_string_fns.h>
      39                 :            : #include <rte_cpuflags.h>
      40                 :            : #include <rte_bus.h>
      41                 :            : #include <rte_version.h>
      42                 :            : #include <malloc_heap.h>
      43                 :            : #include <rte_vfio.h>
      44                 :            : 
      45                 :            : #include <telemetry_internal.h>
      46                 :            : #include "eal_private.h"
      47                 :            : #include "eal_thread.h"
      48                 :            : #include "eal_internal_cfg.h"
      49                 :            : #include "eal_filesystem.h"
      50                 :            : #include "eal_hugepages.h"
      51                 :            : #include "eal_memcfg.h"
      52                 :            : #include "eal_trace.h"
      53                 :            : #include "eal_options.h"
      54                 :            : #include "eal_vfio.h"
      55                 :            : #include "hotplug_mp.h"
      56                 :            : #include "log_internal.h"
      57                 :            : 
      58                 :            : #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
      59                 :            : 
      60                 :            : #define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10)
      61                 :            : 
      62                 :            : #define KERNEL_IOMMU_GROUPS_PATH "/sys/kernel/iommu_groups"
      63                 :            : 
      64                 :            : /* define fd variable here, because file needs to be kept open for the
      65                 :            :  * duration of the program, as we hold a write lock on it in the primary proc */
      66                 :            : static int mem_cfg_fd = -1;
      67                 :            : 
      68                 :            : static struct flock wr_lock = {
      69                 :            :                 .l_type = F_WRLCK,
      70                 :            :                 .l_whence = SEEK_SET,
      71                 :            :                 .l_start = offsetof(struct rte_mem_config, memsegs),
      72                 :            :                 .l_len = RTE_SIZEOF_FIELD(struct rte_mem_config, memsegs),
      73                 :            : };
      74                 :            : 
      75                 :            : /* internal configuration (per-core) */
      76                 :            : struct lcore_config lcore_config[RTE_MAX_LCORE];
      77                 :            : 
      78                 :            : /* used by rte_rdtsc() */
      79                 :            : int rte_cycles_vmware_tsc_map;
      80                 :            : 
      81                 :            : 
      82                 :            : int
      83                 :        157 : eal_clean_runtime_dir(void)
      84                 :            : {
      85                 :        157 :         const char *runtime_dir = rte_eal_get_runtime_dir();
      86                 :            :         DIR *dir;
      87                 :            :         struct dirent *dirent;
      88                 :            :         int dir_fd, fd, lck_result;
      89                 :            :         static const char * const filters[] = {
      90                 :            :                 "fbarray_*",
      91                 :            :                 "mp_socket_*"
      92                 :            :         };
      93                 :            : 
      94                 :            :         /* open directory */
      95                 :        157 :         dir = opendir(runtime_dir);
      96         [ -  + ]:        157 :         if (!dir) {
      97                 :          0 :                 EAL_LOG(ERR, "Unable to open runtime directory %s",
      98                 :            :                                 runtime_dir);
      99                 :          0 :                 goto error;
     100                 :            :         }
     101                 :        157 :         dir_fd = dirfd(dir);
     102                 :            : 
     103                 :            :         /* lock the directory before doing anything, to avoid races */
     104         [ -  + ]:        157 :         if (flock(dir_fd, LOCK_EX) < 0) {
     105                 :          0 :                 EAL_LOG(ERR, "Unable to lock runtime directory %s",
     106                 :            :                         runtime_dir);
     107                 :          0 :                 goto error;
     108                 :            :         }
     109                 :            : 
     110                 :        157 :         dirent = readdir(dir);
     111         [ -  + ]:        157 :         if (!dirent) {
     112                 :          0 :                 EAL_LOG(ERR, "Unable to read runtime directory %s",
     113                 :            :                                 runtime_dir);
     114                 :          0 :                 goto error;
     115                 :            :         }
     116                 :            : 
     117         [ +  + ]:       2102 :         while (dirent != NULL) {
     118                 :            :                 unsigned int f_idx;
     119                 :            :                 bool skip = true;
     120                 :            : 
     121                 :            :                 /* skip files that don't match the patterns */
     122         [ +  + ]:       3613 :                 for (f_idx = 0; f_idx < RTE_DIM(filters); f_idx++) {
     123                 :       2789 :                         const char *filter = filters[f_idx];
     124                 :            : 
     125         [ +  + ]:       2789 :                         if (fnmatch(filter, dirent->d_name, 0) == 0) {
     126                 :            :                                 skip = false;
     127                 :            :                                 break;
     128                 :            :                         }
     129                 :            :                 }
     130         [ +  + ]:       1945 :                 if (skip) {
     131                 :        824 :                         dirent = readdir(dir);
     132                 :        824 :                         continue;
     133                 :            :                 }
     134                 :            : 
     135                 :            :                 /* try and lock the file */
     136                 :       1121 :                 fd = openat(dir_fd, dirent->d_name, O_RDONLY);
     137                 :            : 
     138                 :            :                 /* skip to next file */
     139         [ +  + ]:       1121 :                 if (fd == -1) {
     140                 :         20 :                         dirent = readdir(dir);
     141                 :         20 :                         continue;
     142                 :            :                 }
     143                 :            : 
     144                 :            :                 /* non-blocking lock */
     145                 :       1101 :                 lck_result = flock(fd, LOCK_EX | LOCK_NB);
     146                 :            : 
     147                 :            :                 /* if lock succeeds, remove the file */
     148         [ +  + ]:       1101 :                 if (lck_result != -1)
     149                 :        144 :                         unlinkat(dir_fd, dirent->d_name, 0);
     150                 :       1101 :                 close(fd);
     151                 :       1101 :                 dirent = readdir(dir);
     152                 :            :         }
     153                 :            : 
     154                 :            :         /* closedir closes dir_fd and drops the lock */
     155                 :        157 :         closedir(dir);
     156                 :        157 :         return 0;
     157                 :            : 
     158                 :          0 : error:
     159         [ #  # ]:          0 :         if (dir)
     160                 :          0 :                 closedir(dir);
     161                 :            : 
     162                 :          0 :         EAL_LOG(ERR, "Error while clearing runtime dir: %s",
     163                 :            :                 strerror(errno));
     164                 :            : 
     165                 :          0 :         return -1;
     166                 :            : }
     167                 :            : 
     168                 :            : 
     169                 :            : /* create memory configuration in shared/mmap memory. Take out
     170                 :            :  * a write lock on the memsegs, so we can auto-detect primary/secondary.
     171                 :            :  * This means we never close the file while running (auto-close on exit).
     172                 :            :  * We also don't lock the whole file, so that in future we can use read-locks
     173                 :            :  * on other parts, e.g. memzones, to detect if there are running secondary
     174                 :            :  * processes. */
     175                 :            : static int
     176                 :        147 : rte_eal_config_create(void)
     177                 :            : {
     178                 :        147 :         struct rte_config *config = rte_eal_get_configuration();
     179                 :        147 :         size_t page_sz = sysconf(_SC_PAGE_SIZE);
     180                 :            :         size_t cfg_len = sizeof(*config->mem_config);
     181                 :        147 :         size_t cfg_len_aligned = RTE_ALIGN(cfg_len, page_sz);
     182                 :            :         void *rte_mem_cfg_addr, *mapped_mem_cfg_addr;
     183                 :            :         int retval;
     184                 :            :         const struct internal_config *internal_conf =
     185                 :        147 :                 eal_get_internal_configuration();
     186                 :            : 
     187                 :        147 :         const char *pathname = eal_runtime_config_path();
     188                 :            : 
     189         [ +  + ]:        147 :         if (internal_conf->no_shconf)
     190                 :            :                 return 0;
     191                 :            : 
     192                 :            :         /* map the config before hugepage address so that we don't waste a page */
     193         [ +  + ]:        140 :         if (internal_conf->base_virtaddr != 0)
     194                 :          1 :                 rte_mem_cfg_addr = (void *)
     195                 :          1 :                         RTE_ALIGN_FLOOR(internal_conf->base_virtaddr -
     196                 :            :                         sizeof(struct rte_mem_config), page_sz);
     197                 :            :         else
     198                 :            :                 rte_mem_cfg_addr = NULL;
     199                 :            : 
     200         [ +  - ]:        140 :         if (mem_cfg_fd < 0){
     201                 :        140 :                 mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0600);
     202         [ -  + ]:        140 :                 if (mem_cfg_fd < 0) {
     203                 :          0 :                         EAL_LOG(ERR, "Cannot open '%s' for rte_mem_config",
     204                 :            :                                 pathname);
     205                 :          0 :                         return -1;
     206                 :            :                 }
     207                 :            :         }
     208                 :            : 
     209                 :        140 :         retval = ftruncate(mem_cfg_fd, cfg_len);
     210         [ -  + ]:        140 :         if (retval < 0){
     211                 :          0 :                 close(mem_cfg_fd);
     212                 :          0 :                 mem_cfg_fd = -1;
     213                 :          0 :                 EAL_LOG(ERR, "Cannot resize '%s' for rte_mem_config",
     214                 :            :                         pathname);
     215                 :          0 :                 return -1;
     216                 :            :         }
     217                 :            : 
     218                 :        140 :         retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock);
     219         [ -  + ]:        140 :         if (retval < 0){
     220                 :          0 :                 close(mem_cfg_fd);
     221                 :          0 :                 mem_cfg_fd = -1;
     222                 :          0 :                 EAL_LOG(ERR, "Cannot create lock on '%s'. Is another primary "
     223                 :            :                         "process running?", pathname);
     224                 :          0 :                 return -1;
     225                 :            :         }
     226                 :            : 
     227                 :            :         /* reserve space for config */
     228                 :        140 :         rte_mem_cfg_addr = eal_get_virtual_area(rte_mem_cfg_addr,
     229                 :            :                         &cfg_len_aligned, page_sz, 0, 0);
     230         [ -  + ]:        140 :         if (rte_mem_cfg_addr == NULL) {
     231                 :          0 :                 EAL_LOG(ERR, "Cannot mmap memory for rte_config");
     232                 :          0 :                 close(mem_cfg_fd);
     233                 :          0 :                 mem_cfg_fd = -1;
     234                 :          0 :                 return -1;
     235                 :            :         }
     236                 :            : 
     237                 :            :         /* remap the actual file into the space we've just reserved */
     238                 :        140 :         mapped_mem_cfg_addr = mmap(rte_mem_cfg_addr,
     239                 :            :                         cfg_len_aligned, PROT_READ | PROT_WRITE,
     240                 :            :                         MAP_SHARED | MAP_FIXED, mem_cfg_fd, 0);
     241         [ -  + ]:        140 :         if (mapped_mem_cfg_addr == MAP_FAILED) {
     242                 :          0 :                 munmap(rte_mem_cfg_addr, cfg_len);
     243                 :          0 :                 close(mem_cfg_fd);
     244                 :          0 :                 mem_cfg_fd = -1;
     245                 :          0 :                 EAL_LOG(ERR, "Cannot remap memory for rte_config");
     246                 :          0 :                 return -1;
     247                 :            :         }
     248                 :            : 
     249                 :        140 :         memcpy(rte_mem_cfg_addr, config->mem_config, sizeof(struct rte_mem_config));
     250                 :        140 :         config->mem_config = rte_mem_cfg_addr;
     251                 :            : 
     252                 :            :         /* store address of the config in the config itself so that secondary
     253                 :            :          * processes could later map the config into this exact location
     254                 :            :          */
     255                 :        140 :         config->mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
     256                 :        140 :         config->mem_config->dma_maskbits = 0;
     257                 :            : 
     258                 :        140 :         return 0;
     259                 :            : }
     260                 :            : 
     261                 :            : /* attach to an existing shared memory config */
     262                 :            : static int
     263                 :         23 : rte_eal_config_attach(void)
     264                 :            : {
     265                 :         23 :         struct rte_config *config = rte_eal_get_configuration();
     266                 :            :         struct rte_mem_config *mem_config;
     267                 :            :         const struct internal_config *internal_conf =
     268                 :         23 :                 eal_get_internal_configuration();
     269                 :            : 
     270                 :         23 :         const char *pathname = eal_runtime_config_path();
     271                 :            : 
     272         [ +  - ]:         23 :         if (internal_conf->no_shconf)
     273                 :            :                 return 0;
     274                 :            : 
     275         [ +  + ]:         23 :         if (mem_cfg_fd < 0){
     276                 :         22 :                 mem_cfg_fd = open(pathname, O_RDWR);
     277         [ +  + ]:         22 :                 if (mem_cfg_fd < 0) {
     278                 :          1 :                         EAL_LOG(ERR, "Cannot open '%s' for rte_mem_config",
     279                 :            :                                 pathname);
     280                 :          1 :                         return -1;
     281                 :            :                 }
     282                 :            :         }
     283                 :            : 
     284                 :            :         /* map it as read-only first */
     285                 :         22 :         mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
     286                 :            :                         PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
     287         [ -  + ]:         22 :         if (mem_config == MAP_FAILED) {
     288                 :          0 :                 close(mem_cfg_fd);
     289                 :          0 :                 mem_cfg_fd = -1;
     290                 :          0 :                 EAL_LOG(ERR, "Cannot mmap memory for rte_config! error %i (%s)",
     291                 :            :                         errno, strerror(errno));
     292                 :          0 :                 return -1;
     293                 :            :         }
     294                 :            : 
     295                 :         22 :         config->mem_config = mem_config;
     296                 :            : 
     297                 :         22 :         return 0;
     298                 :            : }
     299                 :            : 
     300                 :            : /* reattach the shared config at exact memory location primary process has it */
     301                 :            : static int
     302                 :         22 : rte_eal_config_reattach(void)
     303                 :            : {
     304                 :         22 :         struct rte_config *config = rte_eal_get_configuration();
     305                 :            :         struct rte_mem_config *mem_config;
     306                 :            :         void *rte_mem_cfg_addr;
     307                 :            :         const struct internal_config *internal_conf =
     308                 :         22 :                 eal_get_internal_configuration();
     309                 :            : 
     310         [ +  - ]:         22 :         if (internal_conf->no_shconf)
     311                 :            :                 return 0;
     312                 :            : 
     313                 :            :         /* save the address primary process has mapped shared config to */
     314                 :         22 :         rte_mem_cfg_addr =
     315                 :         22 :                 (void *) (uintptr_t) config->mem_config->mem_cfg_addr;
     316                 :            : 
     317                 :            :         /* unmap original config */
     318                 :         22 :         munmap(config->mem_config, sizeof(struct rte_mem_config));
     319                 :            : 
     320                 :            :         /* remap the config at proper address */
     321                 :         22 :         mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
     322                 :            :                         sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
     323                 :            :                         mem_cfg_fd, 0);
     324                 :            : 
     325                 :         22 :         close(mem_cfg_fd);
     326                 :         22 :         mem_cfg_fd = -1;
     327                 :            : 
     328         [ -  + ]:         22 :         if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr) {
     329         [ #  # ]:          0 :                 if (mem_config != MAP_FAILED) {
     330                 :            :                         /* errno is stale, don't use */
     331                 :          0 :                         EAL_LOG(ERR, "Cannot mmap memory for rte_config at [%p], got [%p]"
     332                 :            :                                 " - please use '--" OPT_BASE_VIRTADDR
     333                 :            :                                 "' option", rte_mem_cfg_addr, mem_config);
     334                 :          0 :                         munmap(mem_config, sizeof(struct rte_mem_config));
     335                 :          0 :                         return -1;
     336                 :            :                 }
     337                 :          0 :                 EAL_LOG(ERR, "Cannot mmap memory for rte_config! error %i (%s)",
     338                 :            :                         errno, strerror(errno));
     339                 :          0 :                 return -1;
     340                 :            :         }
     341                 :            : 
     342                 :         22 :         config->mem_config = mem_config;
     343                 :            : 
     344                 :         22 :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :            : /* Detect if we are a primary or a secondary process */
     348                 :            : enum rte_proc_type_t
     349                 :          3 : eal_proc_type_detect(void)
     350                 :            : {
     351                 :            :         enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
     352                 :          3 :         const char *pathname = eal_runtime_config_path();
     353                 :            :         const struct internal_config *internal_conf =
     354                 :          3 :                 eal_get_internal_configuration();
     355                 :            : 
     356                 :            :         /* if there no shared config, there can be no secondary processes */
     357         [ +  + ]:          3 :         if (!internal_conf->no_shconf) {
     358                 :            :                 /* if we can open the file but not get a write-lock we are a
     359                 :            :                  * secondary process. NOTE: if we get a file handle back, we
     360                 :            :                  * keep that open and don't close it to prevent a race condition
     361                 :            :                  * between multiple opens.
     362                 :            :                  */
     363   [ +  +  +  - ]:          3 :                 if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) &&
     364                 :          1 :                                 (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0))
     365                 :            :                         ptype = RTE_PROC_SECONDARY;
     366                 :            :         }
     367                 :            : 
     368                 :          3 :         EAL_LOG(INFO, "Auto-detected process type: %s",
     369                 :            :                         ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
     370                 :            : 
     371                 :          3 :         return ptype;
     372                 :            : }
     373                 :            : 
     374                 :            : /* Sets up rte_config structure with the pointer to shared memory config.*/
     375                 :            : static int
     376                 :        170 : rte_config_init(void)
     377                 :            : {
     378                 :        170 :         struct rte_config *config = rte_eal_get_configuration();
     379                 :            :         const struct internal_config *internal_conf =
     380                 :        170 :                 eal_get_internal_configuration();
     381                 :            : 
     382                 :        170 :         config->process_type = internal_conf->process_type;
     383                 :            : 
     384   [ +  +  -  - ]:        170 :         switch (config->process_type) {
     385                 :        147 :         case RTE_PROC_PRIMARY:
     386         [ +  - ]:        147 :                 if (rte_eal_config_create() < 0)
     387                 :            :                         return -1;
     388                 :        147 :                 eal_mcfg_update_from_internal();
     389                 :        147 :                 break;
     390                 :         23 :         case RTE_PROC_SECONDARY:
     391         [ +  + ]:         23 :                 if (rte_eal_config_attach() < 0)
     392                 :            :                         return -1;
     393                 :         22 :                 eal_mcfg_wait_complete();
     394         [ -  + ]:         22 :                 if (eal_mcfg_check_version() < 0) {
     395                 :          0 :                         EAL_LOG(ERR, "Primary and secondary process DPDK version mismatch");
     396                 :          0 :                         return -1;
     397                 :            :                 }
     398         [ +  - ]:         22 :                 if (rte_eal_config_reattach() < 0)
     399                 :            :                         return -1;
     400         [ -  + ]:         22 :                 if (!__rte_mp_enable()) {
     401                 :          0 :                         EAL_LOG(ERR, "Primary process refused secondary attachment");
     402                 :          0 :                         return -1;
     403                 :            :                 }
     404                 :         22 :                 eal_mcfg_update_internal();
     405                 :         22 :                 break;
     406                 :          0 :         case RTE_PROC_AUTO:
     407                 :            :         case RTE_PROC_INVALID:
     408                 :          0 :                 EAL_LOG(ERR, "Invalid process type %d",
     409                 :            :                         config->process_type);
     410                 :          0 :                 return -1;
     411                 :            :         }
     412                 :            : 
     413                 :            :         return 0;
     414                 :            : }
     415                 :            : 
     416                 :            : /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */
     417                 :            : static void
     418                 :        164 : eal_hugedirs_unlock(void)
     419                 :            : {
     420                 :            :         int i;
     421                 :            :         struct internal_config *internal_conf =
     422                 :        164 :                 eal_get_internal_configuration();
     423                 :            : 
     424         [ +  + ]:        656 :         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
     425                 :            :         {
     426                 :            :                 /* skip uninitialized */
     427         [ +  + ]:        492 :                 if (internal_conf->hugepage_info[i].lock_descriptor < 0)
     428                 :        438 :                         continue;
     429                 :            :                 /* unlock hugepage file */
     430                 :         54 :                 flock(internal_conf->hugepage_info[i].lock_descriptor, LOCK_UN);
     431                 :         54 :                 close(internal_conf->hugepage_info[i].lock_descriptor);
     432                 :            :                 /* reset the field */
     433                 :         54 :                 internal_conf->hugepage_info[i].lock_descriptor = -1;
     434                 :            :         }
     435                 :        164 : }
     436                 :            : 
     437                 :            : /* display usage */
     438                 :            : static void
     439                 :         52 : eal_usage(const char *prgname)
     440                 :            : {
     441                 :         52 :         rte_usage_hook_t hook = eal_get_application_usage_hook();
     442                 :            : 
     443                 :            :         printf("\nUsage: %s ", prgname);
     444                 :         52 :         eal_common_usage();
     445                 :            :         printf("EAL Linux options:\n"
     446                 :            :                "  --"OPT_SOCKET_MEM"        Memory to allocate on sockets (comma separated values)\n"
     447                 :            :                "  --"OPT_SOCKET_LIMIT"      Limit memory allocation on sockets (comma separated values)\n"
     448                 :            :                "  --"OPT_HUGE_DIR"          Directory where hugetlbfs is mounted\n"
     449                 :            :                "  --"OPT_FILE_PREFIX"       Prefix for hugepage filenames\n"
     450                 :            :                "  --"OPT_CREATE_UIO_DEV"    Create /dev/uioX (usually done by hotplug)\n"
     451                 :            :                "  --"OPT_VFIO_INTR"         Interrupt mode for VFIO (legacy|msi|msix)\n"
     452                 :            :                "  --"OPT_VFIO_VF_TOKEN"     VF token (UUID) shared between SR-IOV PF and VFs\n"
     453                 :            :                "  --"OPT_LEGACY_MEM"        Legacy memory mode (no dynamic allocation, contiguous segments)\n"
     454                 :            :                "  --"OPT_SINGLE_FILE_SEGMENTS" Put all hugepage memory in single files\n"
     455                 :            :                "  --"OPT_MATCH_ALLOCATIONS" Free hugepages exactly as allocated\n"
     456                 :            :                "  --"OPT_HUGE_WORKER_STACK"[=size]\n"
     457                 :            :                "                      Allocate worker thread stacks from hugepage memory.\n"
     458                 :            :                "                      Size is in units of kbytes and defaults to system\n"
     459                 :            :                "                      thread stack size if not specified.\n"
     460                 :            :                "\n");
     461                 :            :         /* Allow the application to print its usage message too if hook is set */
     462         [ -  + ]:         52 :         if (hook) {
     463                 :            :                 printf("===== Application Usage =====\n\n");
     464                 :          0 :                 (hook)(prgname);
     465                 :            :         }
     466                 :         52 : }
     467                 :            : 
     468                 :            : static int
     469                 :         10 : eal_parse_socket_arg(char *strval, volatile uint64_t *socket_arg)
     470                 :            : {
     471                 :            :         char * arg[RTE_MAX_NUMA_NODES];
     472                 :            :         char *end;
     473                 :            :         int arg_num, i, len;
     474                 :            : 
     475                 :         10 :         len = strnlen(strval, SOCKET_MEM_STRLEN);
     476         [ -  + ]:         10 :         if (len == SOCKET_MEM_STRLEN) {
     477                 :          0 :                 EAL_LOG(ERR, "--socket-mem is too long");
     478                 :          0 :                 return -1;
     479                 :            :         }
     480                 :            : 
     481                 :            :         /* all other error cases will be caught later */
     482         [ +  + ]:         10 :         if (!isdigit(strval[len-1]))
     483                 :            :                 return -1;
     484                 :            : 
     485                 :            :         /* split the optarg into separate socket values */
     486                 :          7 :         arg_num = rte_strsplit(strval, len,
     487                 :            :                         arg, RTE_MAX_NUMA_NODES, ',');
     488                 :            : 
     489                 :            :         /* if split failed, or 0 arguments */
     490         [ +  - ]:          7 :         if (arg_num <= 0)
     491                 :            :                 return -1;
     492                 :            : 
     493                 :            :         /* parse each defined socket option */
     494                 :          7 :         errno = 0;
     495         [ +  + ]:         19 :         for (i = 0; i < arg_num; i++) {
     496                 :            :                 uint64_t val;
     497                 :         13 :                 end = NULL;
     498                 :         13 :                 val = strtoull(arg[i], &end, 10);
     499                 :            : 
     500                 :            :                 /* check for invalid input */
     501         [ +  - ]:         13 :                 if ((errno != 0)  ||
     502   [ +  -  +  -  :         13 :                                 (arg[i][0] == '\0') || (end == NULL) || (*end != '\0'))
                   +  + ]
     503                 :            :                         return -1;
     504                 :         12 :                 val <<= 20;
     505                 :         12 :                 socket_arg[i] = val;
     506                 :            :         }
     507                 :            : 
     508                 :            :         return 0;
     509                 :            : }
     510                 :            : 
     511                 :            : static int
     512                 :          4 : eal_parse_vfio_intr(const char *mode)
     513                 :            : {
     514                 :            :         struct internal_config *internal_conf =
     515                 :          4 :                 eal_get_internal_configuration();
     516                 :            :         unsigned i;
     517                 :            :         static struct {
     518                 :            :                 const char *name;
     519                 :            :                 enum rte_intr_mode value;
     520                 :            :         } map[] = {
     521                 :            :                 { "legacy", RTE_INTR_MODE_LEGACY },
     522                 :            :                 { "msi", RTE_INTR_MODE_MSI },
     523                 :            :                 { "msix", RTE_INTR_MODE_MSIX },
     524                 :            :         };
     525                 :            : 
     526         [ +  + ]:         10 :         for (i = 0; i < RTE_DIM(map); i++) {
     527         [ +  + ]:          9 :                 if (!strcmp(mode, map[i].name)) {
     528                 :          3 :                         internal_conf->vfio_intr_mode = map[i].value;
     529                 :          3 :                         return 0;
     530                 :            :                 }
     531                 :            :         }
     532                 :            :         return -1;
     533                 :            : }
     534                 :            : 
     535                 :            : static int
     536                 :          0 : eal_parse_vfio_vf_token(const char *vf_token)
     537                 :            : {
     538                 :          0 :         struct internal_config *cfg = eal_get_internal_configuration();
     539                 :            :         rte_uuid_t uuid;
     540                 :            : 
     541         [ #  # ]:          0 :         if (!rte_uuid_parse(vf_token, uuid)) {
     542                 :          0 :                 rte_uuid_copy(cfg->vfio_vf_token, uuid);
     543                 :          0 :                 return 0;
     544                 :            :         }
     545                 :            : 
     546                 :            :         return -1;
     547                 :            : }
     548                 :            : 
     549                 :            : /* Parse the arguments for --log-level only */
     550                 :            : static void
     551                 :        235 : eal_log_level_parse(int argc, char **argv)
     552                 :            : {
     553                 :            :         int opt;
     554                 :            :         char **argvopt;
     555                 :            :         int option_index;
     556                 :        235 :         const int old_optind = optind;
     557                 :        235 :         const int old_optopt = optopt;
     558                 :        235 :         char * const old_optarg = optarg;
     559                 :            :         struct internal_config *internal_conf =
     560                 :        235 :                 eal_get_internal_configuration();
     561                 :            : 
     562                 :            :         argvopt = argv;
     563                 :        235 :         optind = 1;
     564                 :            : 
     565                 :        986 :         while ((opt = getopt_long(argc, argvopt, eal_short_options,
     566         [ +  + ]:        751 :                                   eal_long_options, &option_index)) != EOF) {
     567                 :            : 
     568                 :            :                 int ret;
     569                 :            : 
     570                 :            :                 /* getopt is not happy, stop right now */
     571         [ +  + ]:        524 :                 if (opt == '?')
     572                 :            :                         break;
     573                 :            : 
     574                 :            :                 ret = (opt == OPT_LOG_LEVEL_NUM) ?
     575         [ +  - ]:        516 :                         eal_parse_common_option(opt, optarg, internal_conf) : 0;
     576                 :            : 
     577                 :            :                 /* common parser is not happy */
     578         [ #  # ]:          0 :                 if (ret < 0)
     579                 :            :                         break;
     580                 :            :         }
     581                 :            : 
     582                 :            :         /* restore getopt lib */
     583                 :        235 :         optind = old_optind;
     584                 :        235 :         optopt = old_optopt;
     585                 :        235 :         optarg = old_optarg;
     586                 :        235 : }
     587                 :            : 
     588                 :            : static int
     589                 :          4 : eal_parse_huge_worker_stack(const char *arg)
     590                 :            : {
     591                 :          4 :         struct internal_config *cfg = eal_get_internal_configuration();
     592                 :            : 
     593   [ +  +  -  + ]:          6 :         if (arg == NULL || arg[0] == '\0') {
     594                 :            :                 pthread_attr_t attr;
     595                 :            :                 int ret;
     596                 :            : 
     597         [ -  + ]:          2 :                 if (pthread_attr_init(&attr) != 0) {
     598                 :          0 :                         EAL_LOG(ERR, "Could not retrieve default stack size");
     599                 :          0 :                         return -1;
     600                 :            :                 }
     601                 :          2 :                 ret = pthread_attr_getstacksize(&attr, &cfg->huge_worker_stack_size);
     602                 :          2 :                 pthread_attr_destroy(&attr);
     603         [ -  + ]:          2 :                 if (ret != 0) {
     604                 :          0 :                         EAL_LOG(ERR, "Could not retrieve default stack size");
     605                 :          0 :                         return -1;
     606                 :            :                 }
     607                 :            :         } else {
     608                 :            :                 unsigned long stack_size;
     609                 :            :                 char *end;
     610                 :            : 
     611                 :          2 :                 errno = 0;
     612                 :          2 :                 stack_size = strtoul(arg, &end, 10);
     613   [ +  -  +  -  :          2 :                 if (errno || end == NULL || stack_size == 0 ||
                   -  + ]
     614                 :            :                                 stack_size >= (size_t)-1 / 1024)
     615                 :          0 :                         return -1;
     616                 :            : 
     617                 :          2 :                 cfg->huge_worker_stack_size = stack_size * 1024;
     618                 :            :         }
     619                 :            : 
     620                 :          4 :         EAL_LOG(DEBUG, "Each worker thread will use %zu kB of DPDK memory as stack",
     621                 :            :                 cfg->huge_worker_stack_size / 1024);
     622                 :          4 :         return 0;
     623                 :            : }
     624                 :            : 
     625                 :            : /* Parse the argument given in the command line of the application */
     626                 :            : static int
     627                 :        235 : eal_parse_args(int argc, char **argv)
     628                 :            : {
     629                 :            :         int opt, ret;
     630                 :            :         char **argvopt;
     631                 :            :         int option_index;
     632                 :        235 :         char *prgname = argv[0];
     633                 :        235 :         const int old_optind = optind;
     634                 :        235 :         const int old_optopt = optopt;
     635                 :        235 :         char * const old_optarg = optarg;
     636                 :            :         struct internal_config *internal_conf =
     637                 :        235 :                 eal_get_internal_configuration();
     638                 :            : 
     639                 :            :         argvopt = argv;
     640                 :        235 :         optind = 1;
     641                 :            : 
     642                 :        714 :         while ((opt = getopt_long(argc, argvopt, eal_short_options,
     643         [ +  + ]:        714 :                                   eal_long_options, &option_index)) != EOF) {
     644                 :            : 
     645                 :            :                 /* getopt didn't recognise the option */
     646         [ +  + ]:        524 :                 if (opt == '?') {
     647                 :          8 :                         eal_usage(prgname);
     648                 :            :                         ret = -1;
     649                 :          8 :                         goto out;
     650                 :            :                 }
     651                 :            : 
     652                 :            :                 /* eal_log_level_parse() already handled this option */
     653         [ -  + ]:        516 :                 if (opt == OPT_LOG_LEVEL_NUM)
     654                 :          0 :                         continue;
     655                 :            : 
     656                 :        516 :                 ret = eal_parse_common_option(opt, optarg, internal_conf);
     657                 :            :                 /* common parser is not happy */
     658         [ +  + ]:        516 :                 if (ret < 0) {
     659                 :         32 :                         eal_usage(prgname);
     660                 :            :                         ret = -1;
     661                 :         32 :                         goto out;
     662                 :            :                 }
     663                 :            :                 /* common parser handled this option */
     664         [ +  + ]:        484 :                 if (ret == 0)
     665                 :        341 :                         continue;
     666                 :            : 
     667   [ -  +  +  +  :        143 :                 switch (opt) {
          -  +  -  +  -  
                -  +  - ]
     668                 :          0 :                 case OPT_HELP_NUM:
     669                 :          0 :                         eal_usage(prgname);
     670                 :          0 :                         exit(EXIT_SUCCESS);
     671                 :            : 
     672                 :          5 :                 case OPT_HUGE_DIR_NUM:
     673                 :            :                 {
     674                 :          5 :                         char *hdir = strdup(optarg);
     675         [ -  + ]:          5 :                         if (hdir == NULL)
     676                 :          0 :                                 EAL_LOG(ERR, "Could not store hugepage directory");
     677                 :            :                         else {
     678                 :            :                                 /* free old hugepage dir */
     679                 :          5 :                                 free(internal_conf->hugepage_dir);
     680                 :          5 :                                 internal_conf->hugepage_dir = hdir;
     681                 :            :                         }
     682                 :            :                         break;
     683                 :            :                 }
     684                 :        119 :                 case OPT_FILE_PREFIX_NUM:
     685                 :            :                 {
     686                 :        119 :                         char *prefix = strdup(optarg);
     687         [ -  + ]:        119 :                         if (prefix == NULL)
     688                 :          0 :                                 EAL_LOG(ERR, "Could not store file prefix");
     689                 :            :                         else {
     690                 :            :                                 /* free old prefix */
     691                 :        119 :                                 free(internal_conf->hugefile_prefix);
     692                 :        119 :                                 internal_conf->hugefile_prefix = prefix;
     693                 :            :                         }
     694                 :            :                         break;
     695                 :            :                 }
     696                 :         10 :                 case OPT_SOCKET_MEM_NUM:
     697         [ +  + ]:         10 :                         if (eal_parse_socket_arg(optarg,
     698                 :         10 :                                         internal_conf->socket_mem) < 0) {
     699                 :          4 :                                 EAL_LOG(ERR, "invalid parameters for --"
     700                 :            :                                                 OPT_SOCKET_MEM);
     701                 :          4 :                                 eal_usage(prgname);
     702                 :            :                                 ret = -1;
     703                 :          4 :                                 goto out;
     704                 :            :                         }
     705                 :          6 :                         internal_conf->force_sockets = 1;
     706                 :          6 :                         break;
     707                 :            : 
     708                 :          0 :                 case OPT_SOCKET_LIMIT_NUM:
     709         [ #  # ]:          0 :                         if (eal_parse_socket_arg(optarg,
     710                 :          0 :                                         internal_conf->socket_limit) < 0) {
     711                 :          0 :                                 EAL_LOG(ERR, "invalid parameters for --"
     712                 :            :                                                 OPT_SOCKET_LIMIT);
     713                 :          0 :                                 eal_usage(prgname);
     714                 :            :                                 ret = -1;
     715                 :          0 :                                 goto out;
     716                 :            :                         }
     717                 :          0 :                         internal_conf->force_socket_limits = 1;
     718                 :          0 :                         break;
     719                 :            : 
     720                 :          4 :                 case OPT_VFIO_INTR_NUM:
     721         [ +  + ]:          4 :                         if (eal_parse_vfio_intr(optarg) < 0) {
     722                 :          1 :                                 EAL_LOG(ERR, "invalid parameters for --"
     723                 :            :                                                 OPT_VFIO_INTR);
     724                 :          1 :                                 eal_usage(prgname);
     725                 :            :                                 ret = -1;
     726                 :          1 :                                 goto out;
     727                 :            :                         }
     728                 :            :                         break;
     729                 :            : 
     730                 :          0 :                 case OPT_VFIO_VF_TOKEN_NUM:
     731         [ #  # ]:          0 :                         if (eal_parse_vfio_vf_token(optarg) < 0) {
     732                 :          0 :                                 EAL_LOG(ERR, "invalid parameters for --"
     733                 :            :                                                 OPT_VFIO_VF_TOKEN);
     734                 :          0 :                                 eal_usage(prgname);
     735                 :            :                                 ret = -1;
     736                 :          0 :                                 goto out;
     737                 :            :                         }
     738                 :            :                         break;
     739                 :            : 
     740                 :          1 :                 case OPT_CREATE_UIO_DEV_NUM:
     741                 :          1 :                         internal_conf->create_uio_dev = 1;
     742                 :          1 :                         break;
     743                 :            : 
     744                 :          0 :                 case OPT_MBUF_POOL_OPS_NAME_NUM:
     745                 :            :                 {
     746                 :          0 :                         char *ops_name = strdup(optarg);
     747         [ #  # ]:          0 :                         if (ops_name == NULL)
     748                 :          0 :                                 EAL_LOG(ERR, "Could not store mbuf pool ops name");
     749                 :            :                         else {
     750                 :            :                                 /* free old ops name */
     751                 :          0 :                                 free(internal_conf->user_mbuf_pool_ops_name);
     752                 :            : 
     753                 :          0 :                                 internal_conf->user_mbuf_pool_ops_name =
     754                 :            :                                                 ops_name;
     755                 :            :                         }
     756                 :            :                         break;
     757                 :            :                 }
     758                 :          0 :                 case OPT_MATCH_ALLOCATIONS_NUM:
     759                 :          0 :                         internal_conf->match_allocations = 1;
     760                 :          0 :                         break;
     761                 :            : 
     762                 :          4 :                 case OPT_HUGE_WORKER_STACK_NUM:
     763         [ -  + ]:          4 :                         if (eal_parse_huge_worker_stack(optarg) < 0) {
     764                 :          0 :                                 EAL_LOG(ERR, "invalid parameter for --"
     765                 :            :                                         OPT_HUGE_WORKER_STACK);
     766                 :          0 :                                 eal_usage(prgname);
     767                 :            :                                 ret = -1;
     768                 :          0 :                                 goto out;
     769                 :            :                         }
     770                 :            :                         break;
     771                 :            : 
     772                 :          0 :                 default:
     773   [ #  #  #  # ]:          0 :                         if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
     774                 :          0 :                                 EAL_LOG(ERR, "Option %c is not supported "
     775                 :            :                                         "on Linux", opt);
     776         [ #  # ]:          0 :                         } else if (opt >= OPT_LONG_MIN_NUM &&
     777                 :            :                                    opt < OPT_LONG_MAX_NUM) {
     778                 :          0 :                                 EAL_LOG(ERR, "Option %s is not supported "
     779                 :            :                                         "on Linux",
     780                 :            :                                         eal_long_options[option_index].name);
     781                 :            :                         } else {
     782                 :          0 :                                 EAL_LOG(ERR, "Option %d is not supported "
     783                 :            :                                         "on Linux", opt);
     784                 :            :                         }
     785                 :          0 :                         eal_usage(prgname);
     786                 :            :                         ret = -1;
     787                 :          0 :                         goto out;
     788                 :            :                 }
     789                 :            :         }
     790                 :            : 
     791                 :            :         /* create runtime data directory. In no_shconf mode, skip any errors */
     792         [ -  + ]:        190 :         if (eal_create_runtime_dir() < 0) {
     793         [ #  # ]:          0 :                 if (internal_conf->no_shconf == 0) {
     794                 :          0 :                         EAL_LOG(ERR, "Cannot create runtime directory");
     795                 :            :                         ret = -1;
     796                 :          0 :                         goto out;
     797                 :            :                 } else
     798                 :          0 :                         EAL_LOG(WARNING, "No DPDK runtime directory created");
     799                 :            :         }
     800                 :            : 
     801         [ -  + ]:        190 :         if (eal_adjust_config(internal_conf) != 0) {
     802                 :            :                 ret = -1;
     803                 :          0 :                 goto out;
     804                 :            :         }
     805                 :            : 
     806                 :            :         /* sanity checks */
     807         [ +  + ]:        190 :         if (eal_check_common_options(internal_conf) != 0) {
     808                 :          7 :                 eal_usage(prgname);
     809                 :            :                 ret = -1;
     810                 :          7 :                 goto out;
     811                 :            :         }
     812                 :            : 
     813         [ +  - ]:        183 :         if (optind >= 0)
     814                 :        183 :                 argv[optind-1] = prgname;
     815                 :        183 :         ret = optind-1;
     816                 :            : 
     817                 :        235 : out:
     818                 :            :         /* restore getopt lib */
     819                 :        235 :         optind = old_optind;
     820                 :        235 :         optopt = old_optopt;
     821                 :        235 :         optarg = old_optarg;
     822                 :            : 
     823                 :        235 :         return ret;
     824                 :            : }
     825                 :            : 
     826                 :            : static int
     827                 :        164 : check_socket(const struct rte_memseg_list *msl, void *arg)
     828                 :            : {
     829                 :            :         int *socket_id = arg;
     830                 :            : 
     831         [ +  - ]:        164 :         if (msl->external)
     832                 :            :                 return 0;
     833                 :            : 
     834                 :        164 :         return *socket_id == msl->socket_id;
     835                 :            : }
     836                 :            : 
     837                 :            : static void
     838                 :        164 : eal_check_mem_on_local_socket(void)
     839                 :            : {
     840                 :            :         int socket_id;
     841                 :        164 :         const struct rte_config *config = rte_eal_get_configuration();
     842                 :            : 
     843                 :        164 :         socket_id = rte_lcore_to_socket_id(config->main_lcore);
     844                 :            : 
     845         [ -  + ]:        164 :         if (rte_memseg_list_walk(check_socket, &socket_id) == 0)
     846                 :          0 :                 EAL_LOG(WARNING, "WARNING: Main core has no memory on local socket!");
     847                 :        164 : }
     848                 :            : 
     849                 :            : static int
     850                 :        117 : sync_func(__rte_unused void *arg)
     851                 :            : {
     852                 :        117 :         return 0;
     853                 :            : }
     854                 :            : 
     855                 :            : /*
     856                 :            :  * Request iopl privilege for all RPL, returns 0 on success
     857                 :            :  * iopl() call is mostly for the i386 architecture. For other architectures,
     858                 :            :  * return -1 to indicate IO privilege can't be changed in this way.
     859                 :            :  */
     860                 :            : int
     861                 :        235 : rte_eal_iopl_init(void)
     862                 :            : {
     863                 :            : #if defined(RTE_ARCH_X86)
     864         [ -  + ]:        235 :         if (iopl(3) != 0)
     865                 :          0 :                 return -1;
     866                 :            : #endif
     867                 :            :         return 0;
     868                 :            : }
     869                 :            : 
     870                 :            : #ifdef VFIO_PRESENT
     871                 :            : static int rte_eal_vfio_setup(void)
     872                 :            : {
     873         [ +  - ]:        167 :         if (rte_vfio_enable("vfio"))
     874                 :            :                 return -1;
     875                 :            : 
     876                 :            :         return 0;
     877                 :            : }
     878                 :            : #endif
     879                 :            : 
     880                 :         60 : static void rte_eal_init_alert(const char *msg)
     881                 :            : {
     882                 :         60 :         fprintf(stderr, "EAL: FATAL: %s\n", msg);
     883                 :         60 :         EAL_LOG(ERR, "%s", msg);
     884                 :         60 : }
     885                 :            : 
     886                 :            : /*
     887                 :            :  * On Linux 3.6+, even if VFIO is not loaded, whenever IOMMU is enabled in the
     888                 :            :  * BIOS and in the kernel, /sys/kernel/iommu_groups path will contain kernel
     889                 :            :  * IOMMU groups. If IOMMU is not enabled, that path would be empty.
     890                 :            :  * Therefore, checking if the path is empty will tell us if IOMMU is enabled.
     891                 :            :  */
     892                 :            : static bool
     893                 :         79 : is_iommu_enabled(void)
     894                 :            : {
     895                 :         79 :         DIR *dir = opendir(KERNEL_IOMMU_GROUPS_PATH);
     896                 :            :         struct dirent *d;
     897                 :            :         int n = 0;
     898                 :            : 
     899                 :            :         /* if directory doesn't exist, assume IOMMU is not enabled */
     900         [ +  - ]:         79 :         if (dir == NULL)
     901                 :            :                 return false;
     902                 :            : 
     903         [ +  + ]:        237 :         while ((d = readdir(dir)) != NULL) {
     904                 :            :                 /* skip dot and dot-dot */
     905         [ +  - ]:        158 :                 if (++n > 2)
     906                 :            :                         break;
     907                 :            :         }
     908                 :         79 :         closedir(dir);
     909                 :            : 
     910                 :         79 :         return n > 2;
     911                 :            : }
     912                 :            : 
     913                 :            : static __rte_noreturn void *
     914                 :        117 : eal_worker_thread_loop(void *arg)
     915                 :            : {
     916                 :        117 :         eal_thread_loop(arg);
     917                 :            : }
     918                 :            : 
     919                 :            : static int
     920                 :        117 : eal_worker_thread_create(unsigned int lcore_id)
     921                 :            : {
     922                 :            :         pthread_attr_t *attrp = NULL;
     923                 :            :         void *stack_ptr = NULL;
     924                 :            :         pthread_attr_t attr;
     925                 :            :         size_t stack_size;
     926                 :            :         int ret = -1;
     927                 :            : 
     928                 :        117 :         stack_size = eal_get_internal_configuration()->huge_worker_stack_size;
     929         [ -  + ]:        117 :         if (stack_size != 0) {
     930                 :            :                 /* Allocate NUMA aware stack memory and set pthread attributes */
     931                 :          0 :                 stack_ptr = rte_zmalloc_socket("lcore_stack", stack_size,
     932                 :          0 :                         RTE_CACHE_LINE_SIZE, rte_lcore_to_socket_id(lcore_id));
     933         [ #  # ]:          0 :                 if (stack_ptr == NULL) {
     934                 :          0 :                         rte_eal_init_alert("Cannot allocate worker lcore stack memory");
     935                 :          0 :                         rte_errno = ENOMEM;
     936                 :          0 :                         goto out;
     937                 :            :                 }
     938                 :            : 
     939         [ #  # ]:          0 :                 if (pthread_attr_init(&attr) != 0) {
     940                 :          0 :                         rte_eal_init_alert("Cannot init pthread attributes");
     941                 :          0 :                         rte_errno = EFAULT;
     942                 :          0 :                         goto out;
     943                 :            :                 }
     944                 :            :                 attrp = &attr;
     945                 :            : 
     946         [ #  # ]:          0 :                 if (pthread_attr_setstack(attrp, stack_ptr, stack_size) != 0) {
     947                 :          0 :                         rte_eal_init_alert("Cannot set pthread stack attributes");
     948                 :          0 :                         rte_errno = EFAULT;
     949                 :          0 :                         goto out;
     950                 :            :                 }
     951                 :            :         }
     952                 :            : 
     953         [ -  + ]:        117 :         if (pthread_create((pthread_t *)&lcore_config[lcore_id].thread_id.opaque_id,
     954                 :        117 :                         attrp, eal_worker_thread_loop, (void *)(uintptr_t)lcore_id) == 0)
     955                 :            :                 ret = 0;
     956                 :            : 
     957                 :          0 : out:
     958         [ -  + ]:        117 :         if (ret != 0)
     959                 :          0 :                 rte_free(stack_ptr);
     960         [ -  + ]:        117 :         if (attrp != NULL)
     961                 :          0 :                 pthread_attr_destroy(attrp);
     962                 :        117 :         return ret;
     963                 :            : }
     964                 :            : 
     965                 :            : /* Launch threads, called at application init(). */
     966                 :            : int
     967                 :        237 : rte_eal_init(int argc, char **argv)
     968                 :            : {
     969                 :            :         int i, fctret, ret;
     970                 :            :         static RTE_ATOMIC(uint32_t) run_once;
     971                 :            :         uint32_t has_run = 0;
     972                 :            :         char cpuset[RTE_CPU_AFFINITY_STR_LEN];
     973                 :            :         char thread_name[RTE_THREAD_NAME_SIZE];
     974                 :            :         bool phys_addrs;
     975                 :        237 :         const struct rte_config *config = rte_eal_get_configuration();
     976                 :            :         struct internal_config *internal_conf =
     977                 :        237 :                 eal_get_internal_configuration();
     978                 :            : 
     979                 :            :         /* checks if the machine is adequate */
     980         [ -  + ]:        237 :         if (!rte_cpu_is_supported()) {
     981                 :          0 :                 rte_eal_init_alert("unsupported cpu type.");
     982                 :          0 :                 rte_errno = ENOTSUP;
     983                 :          0 :                 return -1;
     984                 :            :         }
     985                 :            : 
     986         [ +  + ]:        237 :         if (!rte_atomic_compare_exchange_strong_explicit(&run_once, &has_run, 1,
     987                 :            :                                         rte_memory_order_relaxed, rte_memory_order_relaxed)) {
     988                 :          2 :                 rte_eal_init_alert("already called initialization.");
     989                 :          2 :                 rte_errno = EALREADY;
     990                 :          2 :                 return -1;
     991                 :            :         }
     992                 :            : 
     993                 :        235 :         eal_reset_internal_config(internal_conf);
     994                 :            : 
     995                 :            :         /* set log level as early as possible */
     996                 :        235 :         eal_log_level_parse(argc, argv);
     997                 :            : 
     998                 :            :         /* clone argv to report out later in telemetry */
     999                 :        235 :         eal_save_args(argc, argv);
    1000                 :            : 
    1001         [ -  + ]:        235 :         if (rte_eal_cpu_init() < 0) {
    1002                 :          0 :                 rte_eal_init_alert("Cannot detect lcores.");
    1003                 :          0 :                 rte_errno = ENOTSUP;
    1004                 :          0 :                 return -1;
    1005                 :            :         }
    1006                 :            : 
    1007                 :        235 :         fctret = eal_parse_args(argc, argv);
    1008         [ +  + ]:        235 :         if (fctret < 0) {
    1009                 :         52 :                 rte_eal_init_alert("Invalid 'command line' arguments.");
    1010                 :         52 :                 rte_errno = EINVAL;
    1011                 :         52 :                 rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1012                 :         52 :                 return -1;
    1013                 :            :         }
    1014                 :            : 
    1015         [ -  + ]:        183 :         if (eal_plugins_init() < 0) {
    1016                 :          0 :                 rte_eal_init_alert("Cannot init plugins");
    1017                 :          0 :                 rte_errno = EINVAL;
    1018                 :          0 :                 rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1019                 :          0 :                 return -1;
    1020                 :            :         }
    1021                 :            : 
    1022         [ -  + ]:        183 :         if (eal_trace_init() < 0) {
    1023                 :          0 :                 rte_eal_init_alert("Cannot init trace");
    1024                 :          0 :                 rte_errno = EFAULT;
    1025                 :          0 :                 return -1;
    1026                 :            :         }
    1027                 :            : 
    1028         [ +  + ]:        183 :         if (eal_option_device_parse()) {
    1029                 :         13 :                 rte_errno = ENODEV;
    1030                 :         13 :                 rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1031                 :         13 :                 return -1;
    1032                 :            :         }
    1033                 :            : 
    1034         [ +  + ]:        170 :         if (rte_config_init() < 0) {
    1035                 :          1 :                 rte_eal_init_alert("Cannot init config");
    1036                 :          1 :                 return -1;
    1037                 :            :         }
    1038                 :            : 
    1039         [ -  + ]:        169 :         if (rte_eal_intr_init() < 0) {
    1040                 :          0 :                 rte_eal_init_alert("Cannot init interrupt-handling thread");
    1041                 :          0 :                 return -1;
    1042                 :            :         }
    1043                 :            : 
    1044         [ -  + ]:        169 :         if (rte_eal_alarm_init() < 0) {
    1045                 :          0 :                 rte_eal_init_alert("Cannot init alarm");
    1046                 :            :                 /* rte_eal_alarm_init sets rte_errno on failure. */
    1047                 :          0 :                 return -1;
    1048                 :            :         }
    1049                 :            : 
    1050                 :            :         /* Put mp channel init before bus scan so that we can init the vdev
    1051                 :            :          * bus through mp channel in the secondary process before the bus scan.
    1052                 :            :          */
    1053   [ +  +  -  + ]:        169 :         if (rte_mp_channel_init() < 0 && rte_errno != ENOTSUP) {
    1054                 :          0 :                 rte_eal_init_alert("failed to init mp channel");
    1055         [ #  # ]:          0 :                 if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
    1056                 :          0 :                         rte_errno = EFAULT;
    1057                 :          0 :                         return -1;
    1058                 :            :                 }
    1059                 :            :         }
    1060                 :            : 
    1061         [ -  + ]:        169 :         if (rte_bus_scan()) {
    1062                 :          0 :                 rte_eal_init_alert("Cannot scan the buses for devices");
    1063                 :          0 :                 rte_errno = ENODEV;
    1064                 :          0 :                 rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1065                 :          0 :                 return -1;
    1066                 :            :         }
    1067                 :            : 
    1068                 :        169 :         phys_addrs = rte_eal_using_phys_addrs() != 0;
    1069                 :            : 
    1070                 :            :         /* if no EAL option "--iova-mode=<pa|va>", use bus IOVA scheme */
    1071         [ +  - ]:        169 :         if (internal_conf->iova_mode == RTE_IOVA_DC) {
    1072                 :            :                 /* autodetect the IOVA mapping mode */
    1073                 :        169 :                 enum rte_iova_mode iova_mode = rte_bus_get_iommu_class();
    1074                 :            : 
    1075         [ +  + ]:        169 :                 if (iova_mode == RTE_IOVA_DC) {
    1076                 :        168 :                         EAL_LOG(DEBUG, "Buses did not request a specific IOVA mode.");
    1077                 :            : 
    1078                 :            :                         if (!RTE_IOVA_IN_MBUF) {
    1079                 :            :                                 iova_mode = RTE_IOVA_VA;
    1080                 :            :                                 EAL_LOG(DEBUG, "IOVA as VA mode is forced by build option.");
    1081         [ +  + ]:        168 :                         } else if (!phys_addrs) {
    1082                 :            :                                 /* if we have no access to physical addresses,
    1083                 :            :                                  * pick IOVA as VA mode.
    1084                 :            :                                  */
    1085                 :            :                                 iova_mode = RTE_IOVA_VA;
    1086                 :         89 :                                 EAL_LOG(DEBUG, "Physical addresses are unavailable, selecting IOVA as VA mode.");
    1087         [ -  + ]:         79 :                         } else if (is_iommu_enabled()) {
    1088                 :            :                                 /* we have an IOMMU, pick IOVA as VA mode */
    1089                 :            :                                 iova_mode = RTE_IOVA_VA;
    1090                 :          0 :                                 EAL_LOG(DEBUG, "IOMMU is available, selecting IOVA as VA mode.");
    1091                 :            :                         } else {
    1092                 :            :                                 /* physical addresses available, and no IOMMU
    1093                 :            :                                  * found, so pick IOVA as PA.
    1094                 :            :                                  */
    1095                 :            :                                 iova_mode = RTE_IOVA_PA;
    1096                 :         79 :                                 EAL_LOG(DEBUG, "IOMMU is not available, selecting IOVA as PA mode.");
    1097                 :            :                         }
    1098                 :            :                 }
    1099                 :        169 :                 rte_eal_get_configuration()->iova_mode = iova_mode;
    1100                 :            :         } else {
    1101                 :          0 :                 rte_eal_get_configuration()->iova_mode =
    1102                 :          0 :                         internal_conf->iova_mode;
    1103                 :            :         }
    1104                 :            : 
    1105   [ +  +  -  + ]:        169 :         if (rte_eal_iova_mode() == RTE_IOVA_PA && !phys_addrs) {
    1106                 :          0 :                 rte_eal_init_alert("Cannot use IOVA as 'PA' since physical addresses are not available");
    1107                 :          0 :                 rte_errno = EINVAL;
    1108                 :          0 :                 return -1;
    1109                 :            :         }
    1110                 :            : 
    1111                 :        169 :         if (rte_eal_iova_mode() == RTE_IOVA_PA && !RTE_IOVA_IN_MBUF) {
    1112                 :            :                 rte_eal_init_alert("Cannot use IOVA as 'PA' as it is disabled during build");
    1113                 :            :                 rte_errno = EINVAL;
    1114                 :            :                 return -1;
    1115                 :            :         }
    1116                 :            : 
    1117         [ +  + ]:        259 :         EAL_LOG(INFO, "Selected IOVA mode '%s'",
    1118                 :            :                 rte_eal_iova_mode() == RTE_IOVA_PA ? "PA" : "VA");
    1119                 :            : 
    1120         [ +  + ]:        169 :         if (internal_conf->no_hugetlbfs == 0) {
    1121                 :            :                 /* rte_config isn't initialized yet */
    1122                 :         79 :                 ret = internal_conf->process_type == RTE_PROC_PRIMARY ?
    1123         [ +  + ]:         79 :                                 eal_hugepage_info_init() :
    1124                 :         22 :                                 eal_hugepage_info_read();
    1125         [ +  + ]:         79 :                 if (ret < 0) {
    1126                 :          2 :                         rte_eal_init_alert("Cannot get hugepage information.");
    1127                 :          2 :                         rte_errno = EACCES;
    1128                 :          2 :                         rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1129                 :          2 :                         return -1;
    1130                 :            :                 }
    1131                 :            :         }
    1132                 :            : 
    1133   [ +  +  +  + ]:        167 :         if (internal_conf->memory == 0 && internal_conf->force_sockets == 0) {
    1134         [ +  + ]:         67 :                 if (internal_conf->no_hugetlbfs)
    1135                 :          7 :                         internal_conf->memory = MEMSIZE_IF_NO_HUGE_PAGE;
    1136                 :            :         }
    1137                 :            : 
    1138         [ -  + ]:        167 :         if (internal_conf->vmware_tsc_map == 1) {
    1139                 :            : #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
    1140                 :            :                 rte_cycles_vmware_tsc_map = 1;
    1141                 :            :                 EAL_LOG(DEBUG, "Using VMWARE TSC MAP, "
    1142                 :            :                                 "you must have monitor_control.pseudo_perfctr = TRUE");
    1143                 :            : #else
    1144                 :          0 :                 EAL_LOG(WARNING, "Ignoring --vmware-tsc-map because "
    1145                 :            :                                 "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set");
    1146                 :            : #endif
    1147                 :            :         }
    1148                 :            : 
    1149         [ -  + ]:        167 :         if (eal_log_init(program_invocation_short_name,
    1150                 :        167 :                          internal_conf->syslog_facility) < 0) {
    1151                 :          0 :                 rte_eal_init_alert("Cannot init logging.");
    1152                 :          0 :                 rte_errno = ENOMEM;
    1153                 :          0 :                 rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1154                 :          0 :                 return -1;
    1155                 :            :         }
    1156                 :            : 
    1157                 :            : #ifdef VFIO_PRESENT
    1158                 :            :         if (rte_eal_vfio_setup() < 0) {
    1159                 :          0 :                 rte_eal_init_alert("Cannot init VFIO");
    1160                 :          0 :                 rte_errno = EAGAIN;
    1161                 :          0 :                 rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
    1162                 :          0 :                 return -1;
    1163                 :            :         }
    1164                 :            : #endif
    1165                 :            :         /* in secondary processes, memory init may allocate additional fbarrays
    1166                 :            :          * not present in primary processes, so to avoid any potential issues,
    1167                 :            :          * initialize memzones first.
    1168                 :            :          */
    1169         [ -  + ]:        167 :         if (rte_eal_memzone_init() < 0) {
    1170                 :          0 :                 rte_eal_init_alert("Cannot init memzone");
    1171                 :          0 :                 rte_errno = ENODEV;
    1172                 :          0 :                 return -1;
    1173                 :            :         }
    1174                 :            : 
    1175                 :        167 :         rte_mcfg_mem_read_lock();
    1176                 :            : 
    1177         [ +  + ]:        167 :         if (rte_eal_memory_init() < 0) {
    1178                 :          3 :                 rte_mcfg_mem_read_unlock();
    1179                 :          3 :                 rte_eal_init_alert("Cannot init memory");
    1180                 :          3 :                 rte_errno = ENOMEM;
    1181                 :          3 :                 return -1;
    1182                 :            :         }
    1183                 :            : 
    1184                 :            :         /* the directories are locked during eal_hugepage_info_init */
    1185                 :        164 :         eal_hugedirs_unlock();
    1186                 :            : 
    1187         [ -  + ]:        164 :         if (rte_eal_malloc_heap_init() < 0) {
    1188                 :          0 :                 rte_mcfg_mem_read_unlock();
    1189                 :          0 :                 rte_eal_init_alert("Cannot init malloc heap");
    1190                 :          0 :                 rte_errno = ENODEV;
    1191                 :          0 :                 return -1;
    1192                 :            :         }
    1193                 :            : 
    1194                 :        164 :         rte_mcfg_mem_read_unlock();
    1195                 :            : 
    1196         [ -  + ]:        164 :         if (rte_eal_malloc_heap_populate() < 0) {
    1197                 :          0 :                 rte_eal_init_alert("Cannot init malloc heap");
    1198                 :          0 :                 rte_errno = ENODEV;
    1199                 :          0 :                 return -1;
    1200                 :            :         }
    1201                 :            : 
    1202                 :            :         /* register multi-process action callbacks for hotplug after memory init */
    1203         [ -  + ]:        164 :         if (eal_mp_dev_hotplug_init() < 0) {
    1204                 :          0 :                 rte_eal_init_alert("failed to register mp callback for hotplug");
    1205                 :          0 :                 return -1;
    1206                 :            :         }
    1207                 :            : 
    1208         [ -  + ]:        164 :         if (rte_eal_tailqs_init() < 0) {
    1209                 :          0 :                 rte_eal_init_alert("Cannot init tail queues for objects");
    1210                 :          0 :                 rte_errno = EFAULT;
    1211                 :          0 :                 return -1;
    1212                 :            :         }
    1213                 :            : 
    1214         [ -  + ]:        164 :         if (rte_eal_timer_init() < 0) {
    1215                 :          0 :                 rte_eal_init_alert("Cannot init HPET or TSC timers");
    1216                 :          0 :                 rte_errno = ENOTSUP;
    1217                 :          0 :                 return -1;
    1218                 :            :         }
    1219                 :            : 
    1220                 :        164 :         eal_check_mem_on_local_socket();
    1221                 :            : 
    1222         [ -  + ]:        164 :         if (rte_thread_set_affinity_by_id(rte_thread_self(),
    1223                 :        164 :                         &lcore_config[config->main_lcore].cpuset) != 0) {
    1224                 :          0 :                 rte_eal_init_alert("Cannot set affinity");
    1225                 :          0 :                 rte_errno = EINVAL;
    1226                 :          0 :                 return -1;
    1227                 :            :         }
    1228                 :        164 :         __rte_thread_init(config->main_lcore,
    1229                 :        164 :                 &lcore_config[config->main_lcore].cpuset);
    1230                 :            : 
    1231                 :        164 :         ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
    1232         [ -  + ]:        164 :         EAL_LOG(DEBUG, "Main lcore %u is ready (tid=%zx;cpuset=[%s%s])",
    1233                 :            :                 config->main_lcore, (uintptr_t)pthread_self(), cpuset,
    1234                 :            :                 ret == 0 ? "" : "...");
    1235                 :            : 
    1236         [ +  + ]:        281 :         RTE_LCORE_FOREACH_WORKER(i) {
    1237                 :            : 
    1238                 :            :                 /*
    1239                 :            :                  * create communication pipes between main thread
    1240                 :            :                  * and children
    1241                 :            :                  */
    1242         [ -  + ]:        117 :                 if (pipe(lcore_config[i].pipe_main2worker) < 0)
    1243                 :          0 :                         rte_panic("Cannot create pipe\n");
    1244         [ -  + ]:        117 :                 if (pipe(lcore_config[i].pipe_worker2main) < 0)
    1245                 :          0 :                         rte_panic("Cannot create pipe\n");
    1246                 :            : 
    1247                 :        117 :                 lcore_config[i].state = WAIT;
    1248                 :            : 
    1249                 :            :                 /* create a thread for each lcore */
    1250                 :        117 :                 ret = eal_worker_thread_create(i);
    1251         [ -  + ]:        117 :                 if (ret != 0)
    1252                 :          0 :                         rte_panic("Cannot create thread\n");
    1253                 :            : 
    1254                 :            :                 /* Set thread_name for aid in debugging. */
    1255                 :            :                 snprintf(thread_name, sizeof(thread_name),
    1256                 :            :                         "dpdk-worker%d", i);
    1257                 :        117 :                 rte_thread_set_name(lcore_config[i].thread_id, thread_name);
    1258                 :            : 
    1259                 :        117 :                 ret = rte_thread_set_affinity_by_id(lcore_config[i].thread_id,
    1260                 :        117 :                         &lcore_config[i].cpuset);
    1261         [ -  + ]:        117 :                 if (ret != 0)
    1262                 :          0 :                         rte_panic("Cannot set affinity\n");
    1263                 :            :         }
    1264                 :            : 
    1265                 :            :         /*
    1266                 :            :          * Launch a dummy function on all worker lcores, so that main lcore
    1267                 :            :          * knows they are all ready when this function returns.
    1268                 :            :          */
    1269                 :        164 :         rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MAIN);
    1270                 :        164 :         rte_eal_mp_wait_lcore();
    1271                 :            : 
    1272                 :            :         /* initialize services so vdevs register service during bus_probe. */
    1273                 :        164 :         ret = rte_service_init();
    1274         [ -  + ]:        164 :         if (ret) {
    1275                 :          0 :                 rte_eal_init_alert("rte_service_init() failed");
    1276                 :          0 :                 rte_errno = -ret;
    1277                 :          0 :                 return -1;
    1278                 :            :         }
    1279                 :            : 
    1280                 :            :         /* Probe all the buses and devices/drivers on them */
    1281         [ -  + ]:        164 :         if (rte_bus_probe()) {
    1282                 :          0 :                 rte_eal_init_alert("Cannot probe devices");
    1283                 :          0 :                 rte_errno = ENOTSUP;
    1284                 :          0 :                 return -1;
    1285                 :            :         }
    1286                 :            : 
    1287                 :            : #ifdef VFIO_PRESENT
    1288                 :            :         /* Register mp action after probe() so that we got enough info */
    1289   [ +  -  +  - ]:        164 :         if (rte_vfio_is_enabled("vfio") && vfio_mp_sync_setup() < 0)
    1290                 :            :                 return -1;
    1291                 :            : #endif
    1292                 :            : 
    1293                 :            :         /* initialize default service/lcore mappings and start running. Ignore
    1294                 :            :          * -ENOTSUP, as it indicates no service coremask passed to EAL.
    1295                 :            :          */
    1296                 :        164 :         ret = rte_service_start_with_defaults();
    1297         [ -  + ]:        164 :         if (ret < 0 && ret != -ENOTSUP) {
    1298                 :          0 :                 rte_errno = -ret;
    1299                 :          0 :                 return -1;
    1300                 :            :         }
    1301                 :            : 
    1302                 :            :         /*
    1303                 :            :          * Clean up unused files in runtime directory. We do this at the end of
    1304                 :            :          * init and not at the beginning because we want to clean stuff up
    1305                 :            :          * whether we are primary or secondary process, but we cannot remove
    1306                 :            :          * primary process' files because secondary should be able to run even
    1307                 :            :          * if primary process is dead.
    1308                 :            :          *
    1309                 :            :          * In no_shconf mode, no runtime directory is created in the first
    1310                 :            :          * place, so no cleanup needed.
    1311                 :            :          */
    1312   [ +  +  -  + ]:        164 :         if (!internal_conf->no_shconf && eal_clean_runtime_dir() < 0) {
    1313                 :          0 :                 rte_eal_init_alert("Cannot clear runtime directory");
    1314                 :          0 :                 return -1;
    1315                 :            :         }
    1316   [ +  +  +  - ]:        164 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY && !internal_conf->no_telemetry) {
    1317         [ +  - ]:        144 :                 if (rte_telemetry_init(rte_eal_get_runtime_dir(),
    1318                 :            :                                 rte_version(),
    1319                 :            :                                 &internal_conf->ctrl_cpuset) != 0)
    1320                 :            :                         return -1;
    1321                 :            :         }
    1322                 :            : 
    1323                 :        164 :         eal_mcfg_complete();
    1324                 :            : 
    1325                 :        164 :         return fctret;
    1326                 :            : }
    1327                 :            : 
    1328                 :            : static int
    1329                 :   42591381 : mark_freeable(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
    1330                 :            :                 void *arg __rte_unused)
    1331                 :            : {
    1332                 :            :         /* ms is const, so find this memseg */
    1333                 :            :         struct rte_memseg *found;
    1334                 :            : 
    1335         [ +  - ]:   42591381 :         if (msl->external)
    1336                 :            :                 return 0;
    1337                 :            : 
    1338                 :   42591381 :         found = rte_mem_virt2memseg(ms->addr, msl);
    1339                 :            : 
    1340                 :   42591381 :         found->flags &= ~RTE_MEMSEG_FLAG_DO_NOT_FREE;
    1341                 :            : 
    1342                 :   42591381 :         return 0;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : int
    1346                 :        235 : rte_eal_cleanup(void)
    1347                 :            : {
    1348                 :            :         static RTE_ATOMIC(uint32_t) run_once;
    1349                 :            :         uint32_t has_run = 0;
    1350                 :            : 
    1351         [ -  + ]:        235 :         if (!rte_atomic_compare_exchange_strong_explicit(&run_once, &has_run, 1,
    1352                 :            :                                         rte_memory_order_relaxed, rte_memory_order_relaxed)) {
    1353                 :          0 :                 EAL_LOG(WARNING, "Already called cleanup");
    1354                 :          0 :                 rte_errno = EALREADY;
    1355                 :          0 :                 return -1;
    1356                 :            :         }
    1357                 :            : 
    1358                 :            :         /* if we're in a primary process, we need to mark hugepages as freeable
    1359                 :            :          * so that finalization can release them back to the system.
    1360                 :            :          */
    1361                 :            :         struct internal_config *internal_conf =
    1362                 :        235 :                 eal_get_internal_configuration();
    1363                 :            : 
    1364         [ +  + ]:        235 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
    1365         [ +  + ]:        212 :                         internal_conf->hugepage_file.unlink_existing)
    1366                 :        211 :                 rte_memseg_walk(mark_freeable, NULL);
    1367                 :            : 
    1368                 :        235 :         rte_service_finalize();
    1369                 :            : #ifdef VFIO_PRESENT
    1370                 :        235 :         vfio_mp_sync_cleanup();
    1371                 :            : #endif
    1372                 :        235 :         rte_mp_channel_cleanup();
    1373                 :        235 :         eal_bus_cleanup();
    1374                 :        235 :         rte_trace_save();
    1375                 :        235 :         eal_trace_fini();
    1376                 :        235 :         eal_mp_dev_hotplug_cleanup();
    1377                 :        235 :         rte_eal_alarm_cleanup();
    1378                 :            :         /* after this point, any DPDK pointers will become dangling */
    1379                 :        235 :         rte_eal_memory_detach();
    1380                 :        235 :         rte_eal_malloc_heap_cleanup();
    1381                 :        235 :         eal_cleanup_config(internal_conf);
    1382                 :        235 :         rte_eal_log_cleanup();
    1383                 :        235 :         return 0;
    1384                 :            : }
    1385                 :            : 
    1386                 :          0 : int rte_eal_create_uio_dev(void)
    1387                 :            : {
    1388                 :            :         const struct internal_config *internal_conf =
    1389                 :          0 :                 eal_get_internal_configuration();
    1390                 :            : 
    1391                 :          0 :         return internal_conf->create_uio_dev;
    1392                 :            : }
    1393                 :            : 
    1394                 :            : enum rte_intr_mode
    1395                 :          0 : rte_eal_vfio_intr_mode(void)
    1396                 :            : {
    1397                 :            :         const struct internal_config *internal_conf =
    1398                 :          0 :                 eal_get_internal_configuration();
    1399                 :            : 
    1400                 :          0 :         return internal_conf->vfio_intr_mode;
    1401                 :            : }
    1402                 :            : 
    1403                 :            : void
    1404                 :          0 : rte_eal_vfio_get_vf_token(rte_uuid_t vf_token)
    1405                 :            : {
    1406                 :          0 :         struct internal_config *cfg = eal_get_internal_configuration();
    1407                 :            : 
    1408                 :          0 :         rte_uuid_copy(vf_token, cfg->vfio_vf_token);
    1409                 :          0 : }
    1410                 :            : 
    1411                 :            : int
    1412                 :        331 : rte_eal_check_module(const char *module_name)
    1413                 :            : {
    1414                 :            :         char sysfs_mod_name[PATH_MAX];
    1415                 :            :         struct stat st;
    1416                 :            :         int n;
    1417                 :            : 
    1418         [ +  - ]:        331 :         if (NULL == module_name)
    1419                 :            :                 return -1;
    1420                 :            : 
    1421                 :            :         /* Check if there is sysfs mounted */
    1422         [ -  + ]:        331 :         if (stat("/sys/module", &st) != 0) {
    1423                 :          0 :                 EAL_LOG(DEBUG, "sysfs is not mounted! error %i (%s)",
    1424                 :            :                         errno, strerror(errno));
    1425                 :          0 :                 return -1;
    1426                 :            :         }
    1427                 :            : 
    1428                 :            :         /* A module might be built-in, therefore try sysfs */
    1429                 :            :         n = snprintf(sysfs_mod_name, PATH_MAX, "/sys/module/%s", module_name);
    1430         [ -  + ]:        331 :         if (n < 0 || n > PATH_MAX) {
    1431                 :          0 :                 EAL_LOG(DEBUG, "Could not format module path");
    1432                 :          0 :                 return -1;
    1433                 :            :         }
    1434                 :            : 
    1435         [ -  + ]:        331 :         if (stat(sysfs_mod_name, &st) != 0) {
    1436                 :          0 :                 EAL_LOG(DEBUG, "Module %s not found! error %i (%s)",
    1437                 :            :                         sysfs_mod_name, errno, strerror(errno));
    1438                 :          0 :                 return 0;
    1439                 :            :         }
    1440                 :            : 
    1441                 :            :         /* Module has been found */
    1442                 :            :         return 1;
    1443                 :            : }

Generated by: LCOV version 1.14