LCOV - code coverage report
Current view: top level - lib/eal/linux - eal.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 287 444 64.6 %
Date: 2025-11-01 17:50:34 Functions: 19 22 86.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 145 224 64.7 %

           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_eal_paging.h>
      35                 :            : #include <rte_errno.h>
      36                 :            : #include <rte_lcore.h>
      37                 :            : #include <rte_service_component.h>
      38                 :            : #include <rte_log.h>
      39                 :            : #include <rte_string_fns.h>
      40                 :            : #include <rte_cpuflags.h>
      41                 :            : #include <rte_bus.h>
      42                 :            : #include <rte_version.h>
      43                 :            : #include <malloc_heap.h>
      44                 :            : #include <rte_vfio.h>
      45                 :            : 
      46                 :            : #include <telemetry_internal.h>
      47                 :            : #include <eal_export.h>
      48                 :            : #include "eal_private.h"
      49                 :            : #include "eal_thread.h"
      50                 :            : #include "eal_lcore_var.h"
      51                 :            : #include "eal_internal_cfg.h"
      52                 :            : #include "eal_filesystem.h"
      53                 :            : #include "eal_hugepages.h"
      54                 :            : #include "eal_memcfg.h"
      55                 :            : #include "eal_trace.h"
      56                 :            : #include "eal_options.h"
      57                 :            : #include "eal_vfio.h"
      58                 :            : #include "hotplug_mp.h"
      59                 :            : #include "log_internal.h"
      60                 :            : 
      61                 :            : #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
      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                 :            : RTE_EXPORT_SYMBOL(rte_cycles_vmware_tsc_map)
      80                 :            : int rte_cycles_vmware_tsc_map;
      81                 :            : 
      82                 :            : 
      83                 :            : int
      84                 :        174 : eal_clean_runtime_dir(void)
      85                 :            : {
      86                 :        174 :         const char *runtime_dir = rte_eal_get_runtime_dir();
      87                 :            :         DIR *dir;
      88                 :            :         struct dirent *dirent;
      89                 :            :         int dir_fd, fd, lck_result;
      90                 :            :         static const char * const filters[] = {
      91                 :            :                 "fbarray_*",
      92                 :            :                 "mp_socket_*"
      93                 :            :         };
      94                 :            : 
      95                 :            :         /* open directory */
      96                 :        174 :         dir = opendir(runtime_dir);
      97         [ -  + ]:        174 :         if (!dir) {
      98                 :          0 :                 EAL_LOG(ERR, "Unable to open runtime directory %s",
      99                 :            :                                 runtime_dir);
     100                 :          0 :                 goto error;
     101                 :            :         }
     102                 :        174 :         dir_fd = dirfd(dir);
     103                 :            : 
     104                 :            :         /* lock the directory before doing anything, to avoid races */
     105         [ -  + ]:        174 :         if (flock(dir_fd, LOCK_EX) < 0) {
     106                 :          0 :                 EAL_LOG(ERR, "Unable to lock runtime directory %s",
     107                 :            :                         runtime_dir);
     108                 :          0 :                 goto error;
     109                 :            :         }
     110                 :            : 
     111                 :        174 :         dirent = readdir(dir);
     112         [ -  + ]:        174 :         if (!dirent) {
     113                 :          0 :                 EAL_LOG(ERR, "Unable to read runtime directory %s",
     114                 :            :                                 runtime_dir);
     115                 :          0 :                 goto error;
     116                 :            :         }
     117                 :            : 
     118         [ +  + ]:       2338 :         while (dirent != NULL) {
     119                 :            :                 unsigned int f_idx;
     120                 :            :                 bool skip = true;
     121                 :            : 
     122                 :            :                 /* skip files that don't match the patterns */
     123         [ +  + ]:       4017 :                 for (f_idx = 0; f_idx < RTE_DIM(filters); f_idx++) {
     124                 :       3103 :                         const char *filter = filters[f_idx];
     125                 :            : 
     126         [ +  + ]:       3103 :                         if (fnmatch(filter, dirent->d_name, 0) == 0) {
     127                 :            :                                 skip = false;
     128                 :            :                                 break;
     129                 :            :                         }
     130                 :            :                 }
     131         [ +  + ]:       2164 :                 if (skip) {
     132                 :        914 :                         dirent = readdir(dir);
     133                 :        914 :                         continue;
     134                 :            :                 }
     135                 :            : 
     136                 :            :                 /* try and lock the file */
     137                 :       1250 :                 fd = openat(dir_fd, dirent->d_name, O_RDONLY);
     138                 :            : 
     139                 :            :                 /* skip to next file */
     140         [ +  + ]:       1250 :                 if (fd == -1) {
     141                 :         25 :                         dirent = readdir(dir);
     142                 :         25 :                         continue;
     143                 :            :                 }
     144                 :            : 
     145                 :            :                 /* non-blocking lock */
     146                 :       1225 :                 lck_result = flock(fd, LOCK_EX | LOCK_NB);
     147                 :            : 
     148                 :            :                 /* if lock succeeds, remove the file */
     149         [ +  + ]:       1225 :                 if (lck_result != -1)
     150                 :        145 :                         unlinkat(dir_fd, dirent->d_name, 0);
     151                 :       1225 :                 close(fd);
     152                 :       1225 :                 dirent = readdir(dir);
     153                 :            :         }
     154                 :            : 
     155                 :            :         /* closedir closes dir_fd and drops the lock */
     156                 :        174 :         closedir(dir);
     157                 :        174 :         return 0;
     158                 :            : 
     159                 :          0 : error:
     160         [ #  # ]:          0 :         if (dir)
     161                 :          0 :                 closedir(dir);
     162                 :            : 
     163                 :          0 :         EAL_LOG(ERR, "Error while clearing runtime dir: %s",
     164                 :            :                 strerror(errno));
     165                 :            : 
     166                 :          0 :         return -1;
     167                 :            : }
     168                 :            : 
     169                 :            : 
     170                 :            : /* create memory configuration in shared/mmap memory. Take out
     171                 :            :  * a write lock on the memsegs, so we can auto-detect primary/secondary.
     172                 :            :  * This means we never close the file while running (auto-close on exit).
     173                 :            :  * We also don't lock the whole file, so that in future we can use read-locks
     174                 :            :  * on other parts, e.g. memzones, to detect if there are running secondary
     175                 :            :  * processes. */
     176                 :            : static int
     177                 :        159 : rte_eal_config_create(void)
     178                 :            : {
     179                 :        159 :         struct rte_config *config = rte_eal_get_configuration();
     180                 :        159 :         size_t page_sz = rte_mem_page_size();
     181                 :            :         size_t cfg_len = sizeof(*config->mem_config);
     182                 :        159 :         size_t cfg_len_aligned = RTE_ALIGN(cfg_len, page_sz);
     183                 :            :         void *rte_mem_cfg_addr, *mapped_mem_cfg_addr;
     184                 :            :         int retval;
     185                 :            :         const struct internal_config *internal_conf =
     186                 :        159 :                 eal_get_internal_configuration();
     187                 :            : 
     188                 :        159 :         const char *pathname = eal_runtime_config_path();
     189                 :            : 
     190         [ +  + ]:        159 :         if (internal_conf->no_shconf)
     191                 :            :                 return 0;
     192                 :            : 
     193                 :            :         /* map the config before hugepage address so that we don't waste a page */
     194         [ +  + ]:        152 :         if (internal_conf->base_virtaddr != 0)
     195                 :          1 :                 rte_mem_cfg_addr = (void *)
     196                 :          1 :                         RTE_ALIGN_FLOOR(internal_conf->base_virtaddr -
     197                 :            :                         sizeof(struct rte_mem_config), page_sz);
     198                 :            :         else
     199                 :            :                 rte_mem_cfg_addr = NULL;
     200                 :            : 
     201         [ +  - ]:        152 :         if (mem_cfg_fd < 0){
     202                 :        152 :                 mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0600);
     203         [ -  + ]:        152 :                 if (mem_cfg_fd < 0) {
     204                 :          0 :                         EAL_LOG(ERR, "Cannot open '%s' for rte_mem_config",
     205                 :            :                                 pathname);
     206                 :          0 :                         return -1;
     207                 :            :                 }
     208                 :            :         }
     209                 :            : 
     210                 :        152 :         retval = ftruncate(mem_cfg_fd, cfg_len);
     211         [ -  + ]:        152 :         if (retval < 0){
     212                 :          0 :                 close(mem_cfg_fd);
     213                 :          0 :                 mem_cfg_fd = -1;
     214                 :          0 :                 EAL_LOG(ERR, "Cannot resize '%s' for rte_mem_config",
     215                 :            :                         pathname);
     216                 :          0 :                 return -1;
     217                 :            :         }
     218                 :            : 
     219                 :        152 :         retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock);
     220         [ -  + ]:        152 :         if (retval < 0){
     221                 :          0 :                 close(mem_cfg_fd);
     222                 :          0 :                 mem_cfg_fd = -1;
     223                 :          0 :                 EAL_LOG(ERR, "Cannot create lock on '%s'. Is another primary "
     224                 :            :                         "process running?", pathname);
     225                 :          0 :                 return -1;
     226                 :            :         }
     227                 :            : 
     228                 :            :         /* reserve space for config */
     229                 :        152 :         rte_mem_cfg_addr = eal_get_virtual_area(rte_mem_cfg_addr,
     230                 :            :                         &cfg_len_aligned, page_sz, 0, 0);
     231         [ -  + ]:        152 :         if (rte_mem_cfg_addr == NULL) {
     232                 :          0 :                 EAL_LOG(ERR, "Cannot mmap memory for rte_config");
     233                 :          0 :                 close(mem_cfg_fd);
     234                 :          0 :                 mem_cfg_fd = -1;
     235                 :          0 :                 return -1;
     236                 :            :         }
     237                 :            : 
     238                 :            :         /* remap the actual file into the space we've just reserved */
     239                 :        152 :         mapped_mem_cfg_addr = mmap(rte_mem_cfg_addr,
     240                 :            :                         cfg_len_aligned, PROT_READ | PROT_WRITE,
     241                 :            :                         MAP_SHARED | MAP_FIXED, mem_cfg_fd, 0);
     242         [ -  + ]:        152 :         if (mapped_mem_cfg_addr == MAP_FAILED) {
     243                 :          0 :                 munmap(rte_mem_cfg_addr, cfg_len);
     244                 :          0 :                 close(mem_cfg_fd);
     245                 :          0 :                 mem_cfg_fd = -1;
     246                 :          0 :                 EAL_LOG(ERR, "Cannot remap memory for rte_config");
     247                 :          0 :                 return -1;
     248                 :            :         }
     249                 :            : 
     250                 :        152 :         memcpy(rte_mem_cfg_addr, config->mem_config, sizeof(struct rte_mem_config));
     251                 :        152 :         config->mem_config = rte_mem_cfg_addr;
     252                 :            : 
     253                 :            :         /* store address of the config in the config itself so that secondary
     254                 :            :          * processes could later map the config into this exact location
     255                 :            :          */
     256                 :        152 :         config->mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
     257                 :        152 :         config->mem_config->dma_maskbits = 0;
     258                 :            : 
     259                 :        152 :         return 0;
     260                 :            : }
     261                 :            : 
     262                 :            : /* attach to an existing shared memory config */
     263                 :            : static int
     264                 :         28 : rte_eal_config_attach(void)
     265                 :            : {
     266                 :         28 :         struct rte_config *config = rte_eal_get_configuration();
     267                 :            :         struct rte_mem_config *mem_config;
     268                 :            :         const struct internal_config *internal_conf =
     269                 :         28 :                 eal_get_internal_configuration();
     270                 :            : 
     271                 :         28 :         const char *pathname = eal_runtime_config_path();
     272                 :            : 
     273         [ +  - ]:         28 :         if (internal_conf->no_shconf)
     274                 :            :                 return 0;
     275                 :            : 
     276         [ +  + ]:         28 :         if (mem_cfg_fd < 0){
     277                 :         27 :                 mem_cfg_fd = open(pathname, O_RDWR);
     278         [ +  + ]:         27 :                 if (mem_cfg_fd < 0) {
     279                 :          1 :                         EAL_LOG(ERR, "Cannot open '%s' for rte_mem_config",
     280                 :            :                                 pathname);
     281                 :          1 :                         return -1;
     282                 :            :                 }
     283                 :            :         }
     284                 :            : 
     285                 :            :         /* map it as read-only first */
     286                 :         27 :         mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
     287                 :            :                         PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
     288         [ -  + ]:         27 :         if (mem_config == MAP_FAILED) {
     289                 :          0 :                 close(mem_cfg_fd);
     290                 :          0 :                 mem_cfg_fd = -1;
     291                 :          0 :                 EAL_LOG(ERR, "Cannot mmap memory for rte_config! error %i (%s)",
     292                 :            :                         errno, strerror(errno));
     293                 :          0 :                 return -1;
     294                 :            :         }
     295                 :            : 
     296                 :         27 :         config->mem_config = mem_config;
     297                 :            : 
     298                 :         27 :         return 0;
     299                 :            : }
     300                 :            : 
     301                 :            : /* reattach the shared config at exact memory location primary process has it */
     302                 :            : static int
     303                 :         27 : rte_eal_config_reattach(void)
     304                 :            : {
     305                 :         27 :         struct rte_config *config = rte_eal_get_configuration();
     306                 :            :         struct rte_mem_config *mem_config;
     307                 :            :         void *rte_mem_cfg_addr;
     308                 :            :         const struct internal_config *internal_conf =
     309                 :         27 :                 eal_get_internal_configuration();
     310                 :            : 
     311         [ +  - ]:         27 :         if (internal_conf->no_shconf)
     312                 :            :                 return 0;
     313                 :            : 
     314                 :            :         /* save the address primary process has mapped shared config to */
     315                 :         27 :         rte_mem_cfg_addr =
     316                 :         27 :                 (void *) (uintptr_t) config->mem_config->mem_cfg_addr;
     317                 :            : 
     318                 :            :         /* unmap original config */
     319                 :         27 :         munmap(config->mem_config, sizeof(struct rte_mem_config));
     320                 :            : 
     321                 :            :         /* remap the config at proper address */
     322                 :         27 :         mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
     323                 :            :                         sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
     324                 :            :                         mem_cfg_fd, 0);
     325                 :            : 
     326                 :         27 :         close(mem_cfg_fd);
     327                 :         27 :         mem_cfg_fd = -1;
     328                 :            : 
     329         [ -  + ]:         27 :         if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr) {
     330         [ #  # ]:          0 :                 if (mem_config != MAP_FAILED) {
     331                 :            :                         /* errno is stale, don't use */
     332                 :          0 :                         EAL_LOG(ERR, "Cannot mmap memory for rte_config at [%p], got [%p] - please use '--base-virtaddr' option",
     333                 :            :                                  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                 :         27 :         config->mem_config = mem_config;
     343                 :            : 
     344                 :         27 :         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                 :        187 : rte_config_init(void)
     377                 :            : {
     378                 :        187 :         struct rte_config *config = rte_eal_get_configuration();
     379                 :            :         const struct internal_config *internal_conf =
     380                 :        187 :                 eal_get_internal_configuration();
     381                 :            : 
     382                 :        187 :         config->process_type = internal_conf->process_type;
     383                 :            : 
     384   [ +  +  -  - ]:        187 :         switch (config->process_type) {
     385                 :        159 :         case RTE_PROC_PRIMARY:
     386         [ +  - ]:        159 :                 if (rte_eal_config_create() < 0)
     387                 :            :                         return -1;
     388                 :        159 :                 eal_mcfg_update_from_internal();
     389                 :        159 :                 break;
     390                 :         28 :         case RTE_PROC_SECONDARY:
     391         [ +  + ]:         28 :                 if (rte_eal_config_attach() < 0)
     392                 :            :                         return -1;
     393                 :         27 :                 eal_mcfg_wait_complete();
     394         [ -  + ]:         27 :                 if (eal_mcfg_check_version() < 0) {
     395                 :          0 :                         EAL_LOG(ERR, "Primary and secondary process DPDK version mismatch");
     396                 :          0 :                         return -1;
     397                 :            :                 }
     398         [ +  - ]:         27 :                 if (rte_eal_config_reattach() < 0)
     399                 :            :                         return -1;
     400         [ -  + ]:         27 :                 if (!__rte_mp_enable()) {
     401                 :          0 :                         EAL_LOG(ERR, "Primary process refused secondary attachment");
     402                 :          0 :                         return -1;
     403                 :            :                 }
     404                 :         27 :                 eal_mcfg_update_internal();
     405                 :         27 :                 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                 :        181 : eal_hugedirs_unlock(void)
     419                 :            : {
     420                 :            :         int i;
     421                 :            :         struct internal_config *internal_conf =
     422                 :        181 :                 eal_get_internal_configuration();
     423                 :            : 
     424         [ +  + ]:        724 :         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
     425                 :            :         {
     426                 :            :                 /* skip uninitialized */
     427         [ +  + ]:        543 :                 if (internal_conf->hugepage_info[i].lock_descriptor < 0)
     428                 :        487 :                         continue;
     429                 :            :                 /* unlock hugepage file */
     430                 :         56 :                 flock(internal_conf->hugepage_info[i].lock_descriptor, LOCK_UN);
     431                 :         56 :                 close(internal_conf->hugepage_info[i].lock_descriptor);
     432                 :            :                 /* reset the field */
     433                 :         56 :                 internal_conf->hugepage_info[i].lock_descriptor = -1;
     434                 :            :         }
     435                 :        181 : }
     436                 :            : 
     437                 :            : static int
     438                 :        181 : check_socket(const struct rte_memseg_list *msl, void *arg)
     439                 :            : {
     440                 :            :         int *socket_id = arg;
     441                 :            : 
     442         [ +  - ]:        181 :         if (msl->external)
     443                 :            :                 return 0;
     444                 :            : 
     445                 :        181 :         return *socket_id == msl->socket_id;
     446                 :            : }
     447                 :            : 
     448                 :            : static void
     449                 :        181 : eal_check_mem_on_local_socket(void)
     450                 :            : {
     451                 :            :         int socket_id;
     452                 :        181 :         const struct rte_config *config = rte_eal_get_configuration();
     453                 :            : 
     454                 :        181 :         socket_id = rte_lcore_to_socket_id(config->main_lcore);
     455                 :            : 
     456         [ -  + ]:        181 :         if (rte_memseg_list_walk(check_socket, &socket_id) == 0)
     457                 :          0 :                 EAL_LOG(WARNING, "WARNING: Main core has no memory on local socket!");
     458                 :        181 : }
     459                 :            : 
     460                 :            : static int
     461                 :        124 : sync_func(__rte_unused void *arg)
     462                 :            : {
     463                 :        124 :         return 0;
     464                 :            : }
     465                 :            : 
     466                 :            : /*
     467                 :            :  * Request iopl privilege for all RPL, returns 0 on success
     468                 :            :  * iopl() call is mostly for the i386 architecture. For other architectures,
     469                 :            :  * return -1 to indicate IO privilege can't be changed in this way.
     470                 :            :  */
     471                 :            : RTE_EXPORT_SYMBOL(rte_eal_iopl_init)
     472                 :            : int
     473                 :        253 : rte_eal_iopl_init(void)
     474                 :            : {
     475                 :            : #if defined(RTE_ARCH_X86)
     476         [ -  + ]:        253 :         if (iopl(3) != 0)
     477                 :          0 :                 return -1;
     478                 :            : #endif
     479                 :            :         return 0;
     480                 :            : }
     481                 :            : 
     482                 :         54 : static void rte_eal_init_alert(const char *msg)
     483                 :            : {
     484                 :         54 :         EAL_LOG(ALERT, "%s", msg);
     485                 :         54 : }
     486                 :            : 
     487                 :            : /*
     488                 :            :  * On Linux 3.6+, even if VFIO is not loaded, whenever IOMMU is enabled in the
     489                 :            :  * BIOS and in the kernel, /sys/kernel/iommu_groups path will contain kernel
     490                 :            :  * IOMMU groups. If IOMMU is not enabled, that path would be empty.
     491                 :            :  * Therefore, checking if the path is empty will tell us if IOMMU is enabled.
     492                 :            :  */
     493                 :            : static bool
     494                 :         86 : is_iommu_enabled(void)
     495                 :            : {
     496                 :         86 :         DIR *dir = opendir(KERNEL_IOMMU_GROUPS_PATH);
     497                 :            :         struct dirent *d;
     498                 :            :         int n = 0;
     499                 :            : 
     500                 :            :         /* if directory doesn't exist, assume IOMMU is not enabled */
     501         [ +  - ]:         86 :         if (dir == NULL)
     502                 :            :                 return false;
     503                 :            : 
     504         [ +  + ]:        258 :         while ((d = readdir(dir)) != NULL) {
     505                 :            :                 /* skip dot and dot-dot */
     506         [ +  - ]:        172 :                 if (++n > 2)
     507                 :            :                         break;
     508                 :            :         }
     509                 :         86 :         closedir(dir);
     510                 :            : 
     511                 :         86 :         return n > 2;
     512                 :            : }
     513                 :            : 
     514                 :            : static __rte_noreturn void *
     515                 :        124 : eal_worker_thread_loop(void *arg)
     516                 :            : {
     517                 :        124 :         eal_thread_loop(arg);
     518                 :            : }
     519                 :            : 
     520                 :            : static int
     521                 :        124 : eal_worker_thread_create(unsigned int lcore_id)
     522                 :            : {
     523                 :            :         pthread_attr_t *attrp = NULL;
     524                 :            :         void *stack_ptr = NULL;
     525                 :            :         pthread_attr_t attr;
     526                 :            :         size_t stack_size;
     527                 :            :         int ret = -1;
     528                 :            : 
     529                 :        124 :         stack_size = eal_get_internal_configuration()->huge_worker_stack_size;
     530         [ -  + ]:        124 :         if (stack_size != 0) {
     531                 :            :                 /* Allocate NUMA aware stack memory and set pthread attributes */
     532                 :          0 :                 stack_ptr = rte_zmalloc_socket("lcore_stack", stack_size,
     533                 :          0 :                         RTE_CACHE_LINE_SIZE, rte_lcore_to_socket_id(lcore_id));
     534         [ #  # ]:          0 :                 if (stack_ptr == NULL) {
     535                 :          0 :                         rte_eal_init_alert("Cannot allocate worker lcore stack memory");
     536                 :          0 :                         rte_errno = ENOMEM;
     537                 :          0 :                         goto out;
     538                 :            :                 }
     539                 :            : 
     540         [ #  # ]:          0 :                 if (pthread_attr_init(&attr) != 0) {
     541                 :          0 :                         rte_eal_init_alert("Cannot init pthread attributes");
     542                 :          0 :                         rte_errno = EFAULT;
     543                 :          0 :                         goto out;
     544                 :            :                 }
     545                 :            :                 attrp = &attr;
     546                 :            : 
     547         [ #  # ]:          0 :                 if (pthread_attr_setstack(attrp, stack_ptr, stack_size) != 0) {
     548                 :          0 :                         rte_eal_init_alert("Cannot set pthread stack attributes");
     549                 :          0 :                         rte_errno = EFAULT;
     550                 :          0 :                         goto out;
     551                 :            :                 }
     552                 :            :         }
     553                 :            : 
     554         [ -  + ]:        124 :         if (pthread_create((pthread_t *)&lcore_config[lcore_id].thread_id.opaque_id,
     555                 :        124 :                         attrp, eal_worker_thread_loop, (void *)(uintptr_t)lcore_id) == 0)
     556                 :            :                 ret = 0;
     557                 :            : 
     558                 :          0 : out:
     559         [ -  + ]:        124 :         if (ret != 0)
     560                 :          0 :                 rte_free(stack_ptr);
     561         [ -  + ]:        124 :         if (attrp != NULL)
     562                 :          0 :                 pthread_attr_destroy(attrp);
     563                 :        124 :         return ret;
     564                 :            : }
     565                 :            : 
     566                 :            : /* Launch threads, called at application init(). */
     567                 :            : RTE_EXPORT_SYMBOL(rte_eal_init)
     568                 :            : int
     569                 :        255 : rte_eal_init(int argc, char **argv)
     570                 :            : {
     571                 :            :         int i, fctret, ret;
     572                 :            :         static RTE_ATOMIC(uint32_t) run_once;
     573                 :            :         uint32_t has_run = 0;
     574                 :            :         char cpuset[RTE_CPU_AFFINITY_STR_LEN];
     575                 :            :         char thread_name[RTE_THREAD_NAME_SIZE];
     576                 :            :         bool phys_addrs;
     577                 :        255 :         const struct rte_config *config = rte_eal_get_configuration();
     578                 :            :         struct internal_config *internal_conf =
     579                 :        255 :                 eal_get_internal_configuration();
     580                 :            : 
     581                 :            :         /* first check if we have been run before */
     582         [ +  + ]:        255 :         if (!rte_atomic_compare_exchange_strong_explicit(&run_once, &has_run, 1,
     583                 :            :                                         rte_memory_order_relaxed, rte_memory_order_relaxed)) {
     584                 :          2 :                 rte_eal_init_alert("already called initialization.");
     585                 :          2 :                 rte_errno = EALREADY;
     586                 :          2 :                 return -1;
     587                 :            :         }
     588                 :            : 
     589                 :            :         /* clone argv to report out later in telemetry */
     590                 :        253 :         eal_save_args(argc, argv);
     591                 :            : 
     592                 :        253 :         fctret = eal_collate_args(argc, argv);
     593         [ +  + ]:        246 :         if (fctret < 0) {
     594                 :          5 :                 rte_eal_init_alert("Invalid command line arguments.");
     595                 :          5 :                 rte_errno = EINVAL;
     596                 :          5 :                 goto err_out;
     597                 :            :         }
     598                 :            : 
     599                 :            :         /* setup log as early as possible */
     600         [ +  + ]:        241 :         if (eal_parse_log_options() < 0) {
     601                 :          3 :                 rte_eal_init_alert("invalid log arguments.");
     602                 :          3 :                 rte_errno = EINVAL;
     603                 :          3 :                 goto err_out;
     604                 :            :         }
     605                 :            : 
     606                 :        238 :         eal_log_init(program_invocation_short_name);
     607                 :            : 
     608                 :            :         /* checks if the machine is adequate */
     609         [ -  + ]:        238 :         if (!rte_cpu_is_supported()) {
     610                 :          0 :                 rte_eal_init_alert("unsupported cpu type.");
     611                 :          0 :                 rte_errno = ENOTSUP;
     612                 :          0 :                 goto err_out;
     613                 :            :         }
     614                 :            : 
     615                 :            :         /* verify if DPDK supported on architecture MMU */
     616         [ -  + ]:        238 :         if (!eal_mmu_supported()) {
     617                 :          0 :                 rte_eal_init_alert("unsupported MMU type.");
     618                 :          0 :                 rte_errno = ENOTSUP;
     619                 :          0 :                 goto err_out;
     620                 :            :         }
     621                 :            : 
     622                 :        238 :         eal_reset_internal_config(internal_conf);
     623                 :            : 
     624         [ -  + ]:        238 :         if (rte_eal_cpu_init() < 0) {
     625                 :          0 :                 rte_eal_init_alert("Cannot detect lcores.");
     626                 :          0 :                 rte_errno = ENOTSUP;
     627                 :          0 :                 goto err_out;
     628                 :            :         }
     629                 :            : 
     630         [ +  + ]:        238 :         if (eal_parse_args() < 0) {
     631                 :         38 :                 rte_eal_init_alert("Error parsing command line arguments.");
     632                 :         38 :                 rte_errno = EINVAL;
     633                 :         38 :                 goto err_out;
     634                 :            :         }
     635                 :            : 
     636         [ -  + ]:        200 :         if (eal_plugins_init() < 0) {
     637                 :          0 :                 rte_eal_init_alert("Cannot init plugins");
     638                 :          0 :                 rte_errno = EINVAL;
     639                 :          0 :                 goto err_out;
     640                 :            :         }
     641                 :            : 
     642         [ -  + ]:        200 :         if (eal_trace_init() < 0) {
     643                 :          0 :                 rte_eal_init_alert("Cannot init trace");
     644                 :          0 :                 rte_errno = EFAULT;
     645                 :          0 :                 goto err_out;
     646                 :            :         }
     647                 :            : 
     648         [ +  + ]:        200 :         if (eal_option_device_parse()) {
     649                 :         13 :                 rte_errno = ENODEV;
     650                 :         13 :                 goto err_out;
     651                 :            :         }
     652                 :            : 
     653         [ +  + ]:        187 :         if (rte_config_init() < 0) {
     654                 :          1 :                 rte_eal_init_alert("Cannot init config");
     655                 :          1 :                 goto err_out;
     656                 :            :         }
     657                 :            : 
     658         [ -  + ]:        186 :         if (rte_eal_intr_init() < 0) {
     659                 :          0 :                 rte_eal_init_alert("Cannot init interrupt-handling thread");
     660                 :          0 :                 goto err_out;
     661                 :            :         }
     662                 :            : 
     663         [ -  + ]:        186 :         if (rte_eal_alarm_init() < 0) {
     664                 :          0 :                 rte_eal_init_alert("Cannot init alarm");
     665                 :            :                 /* rte_eal_alarm_init sets rte_errno on failure. */
     666                 :          0 :                 goto err_out;
     667                 :            :         }
     668                 :            : 
     669                 :            :         /* Put mp channel init before bus scan so that we can init the vdev
     670                 :            :          * bus through mp channel in the secondary process before the bus scan.
     671                 :            :          */
     672   [ +  +  -  + ]:        186 :         if (rte_mp_channel_init() < 0 && rte_errno != ENOTSUP) {
     673                 :          0 :                 rte_eal_init_alert("failed to init mp channel");
     674         [ #  # ]:          0 :                 if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
     675                 :          0 :                         rte_errno = EFAULT;
     676                 :          0 :                         goto err_out;
     677                 :            :                 }
     678                 :            :         }
     679                 :            : 
     680         [ -  + ]:        186 :         if (rte_bus_scan()) {
     681                 :          0 :                 rte_eal_init_alert("Cannot scan the buses for devices");
     682                 :          0 :                 rte_errno = ENODEV;
     683                 :          0 :                 goto err_out;
     684                 :            :         }
     685                 :            : 
     686                 :        186 :         phys_addrs = rte_eal_using_phys_addrs() != 0;
     687                 :            : 
     688                 :            :         /* Always call rte_bus_get_iommu_class() to trigger DMA mask detection and validation */
     689                 :        186 :         enum rte_iova_mode bus_iova_mode = rte_bus_get_iommu_class();
     690                 :            : 
     691                 :            :         /* if no EAL option "--iova-mode=<pa|va>", use bus IOVA scheme */
     692         [ +  - ]:        186 :         if (internal_conf->iova_mode == RTE_IOVA_DC) {
     693                 :            :                 /* autodetect the IOVA mapping mode */
     694                 :            :                 enum rte_iova_mode iova_mode = bus_iova_mode;
     695                 :            : 
     696         [ +  + ]:        186 :                 if (iova_mode == RTE_IOVA_DC) {
     697                 :        185 :                         EAL_LOG(DEBUG, "Buses did not request a specific IOVA mode.");
     698                 :            : 
     699                 :            :                         if (!RTE_IOVA_IN_MBUF) {
     700                 :            :                                 iova_mode = RTE_IOVA_VA;
     701                 :            :                                 EAL_LOG(DEBUG, "IOVA as VA mode is forced by build option.");
     702         [ +  + ]:        185 :                         } else if (!phys_addrs) {
     703                 :            :                                 /* if we have no access to physical addresses,
     704                 :            :                                  * pick IOVA as VA mode.
     705                 :            :                                  */
     706                 :            :                                 iova_mode = RTE_IOVA_VA;
     707                 :         99 :                                 EAL_LOG(DEBUG, "Physical addresses are unavailable, selecting IOVA as VA mode.");
     708         [ -  + ]:         86 :                         } else if (is_iommu_enabled()) {
     709                 :            :                                 /* we have an IOMMU, pick IOVA as VA mode */
     710                 :            :                                 iova_mode = RTE_IOVA_VA;
     711                 :          0 :                                 EAL_LOG(DEBUG, "IOMMU is available, selecting IOVA as VA mode.");
     712                 :            :                         } else {
     713                 :            :                                 /* physical addresses available, and no IOMMU
     714                 :            :                                  * found, so pick IOVA as PA.
     715                 :            :                                  */
     716                 :            :                                 iova_mode = RTE_IOVA_PA;
     717                 :         86 :                                 EAL_LOG(DEBUG, "IOMMU is not available, selecting IOVA as PA mode.");
     718                 :            :                         }
     719                 :            :                 }
     720                 :        186 :                 rte_eal_get_configuration()->iova_mode = iova_mode;
     721                 :            :         } else {
     722                 :          0 :                 rte_eal_get_configuration()->iova_mode =
     723                 :          0 :                         internal_conf->iova_mode;
     724                 :            :         }
     725                 :            : 
     726   [ +  +  -  + ]:        186 :         if (rte_eal_iova_mode() == RTE_IOVA_PA && !phys_addrs) {
     727                 :          0 :                 rte_eal_init_alert("Cannot use IOVA as 'PA' since physical addresses are not available");
     728                 :          0 :                 rte_errno = EINVAL;
     729                 :          0 :                 goto err_out;
     730                 :            :         }
     731                 :            : 
     732                 :        186 :         if (rte_eal_iova_mode() == RTE_IOVA_PA && !RTE_IOVA_IN_MBUF) {
     733                 :            :                 rte_eal_init_alert("Cannot use IOVA as 'PA' as it is disabled during build");
     734                 :            :                 rte_errno = EINVAL;
     735                 :            :                 goto err_out;
     736                 :            :         }
     737                 :            : 
     738         [ +  + ]:        286 :         EAL_LOG(INFO, "Selected IOVA mode '%s'",
     739                 :            :                 rte_eal_iova_mode() == RTE_IOVA_PA ? "PA" : "VA");
     740                 :            : 
     741         [ +  + ]:        186 :         if (internal_conf->no_hugetlbfs == 0) {
     742                 :            :                 /* rte_config isn't initialized yet */
     743                 :         86 :                 ret = internal_conf->process_type == RTE_PROC_PRIMARY ?
     744         [ +  + ]:         86 :                                 eal_hugepage_info_init() :
     745                 :         27 :                                 eal_hugepage_info_read();
     746         [ +  + ]:         86 :                 if (ret < 0) {
     747                 :          2 :                         rte_eal_init_alert("Cannot get hugepage information.");
     748                 :          2 :                         rte_errno = EACCES;
     749                 :          2 :                         goto err_out;
     750                 :            :                 }
     751                 :            :         }
     752                 :            : 
     753   [ +  +  +  + ]:        184 :         if (internal_conf->memory == 0 && internal_conf->force_numa == 0) {
     754         [ +  + ]:         74 :                 if (internal_conf->no_hugetlbfs)
     755                 :          7 :                         internal_conf->memory = MEMSIZE_IF_NO_HUGE_PAGE;
     756                 :            :         }
     757                 :            : 
     758         [ -  + ]:        184 :         if (internal_conf->vmware_tsc_map == 1) {
     759                 :            : #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
     760                 :            :                 rte_cycles_vmware_tsc_map = 1;
     761                 :            :                 EAL_LOG(DEBUG, "Using VMWARE TSC MAP, "
     762                 :            :                                 "you must have monitor_control.pseudo_perfctr = TRUE");
     763                 :            : #else
     764                 :          0 :                 EAL_LOG(WARNING, "Ignoring --vmware-tsc-map because "
     765                 :            :                                 "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set");
     766                 :            : #endif
     767                 :            :         }
     768                 :            : 
     769         [ -  + ]:        184 :         if (rte_vfio_enable("vfio")) {
     770                 :          0 :                 rte_eal_init_alert("Cannot init VFIO");
     771                 :          0 :                 rte_errno = EAGAIN;
     772                 :          0 :                 goto err_out;
     773                 :            :         }
     774                 :            :         /* in secondary processes, memory init may allocate additional fbarrays
     775                 :            :          * not present in primary processes, so to avoid any potential issues,
     776                 :            :          * initialize memzones first.
     777                 :            :          */
     778         [ -  + ]:        184 :         if (rte_eal_memzone_init() < 0) {
     779                 :          0 :                 rte_eal_init_alert("Cannot init memzone");
     780                 :          0 :                 rte_errno = ENODEV;
     781                 :          0 :                 goto err_out;
     782                 :            :         }
     783                 :            : 
     784                 :        184 :         rte_mcfg_mem_read_lock();
     785                 :            : 
     786         [ +  + ]:        184 :         if (rte_eal_memory_init() < 0) {
     787                 :          3 :                 rte_mcfg_mem_read_unlock();
     788                 :          3 :                 rte_eal_init_alert("Cannot init memory");
     789                 :          3 :                 rte_errno = ENOMEM;
     790                 :          3 :                 goto err_out;
     791                 :            :         }
     792                 :            : 
     793                 :            :         /* the directories are locked during eal_hugepage_info_init */
     794                 :        181 :         eal_hugedirs_unlock();
     795                 :            : 
     796         [ -  + ]:        181 :         if (rte_eal_malloc_heap_init() < 0) {
     797                 :          0 :                 rte_mcfg_mem_read_unlock();
     798                 :          0 :                 rte_eal_init_alert("Cannot init malloc heap");
     799                 :          0 :                 rte_errno = ENODEV;
     800                 :          0 :                 goto err_out;
     801                 :            :         }
     802                 :            : 
     803                 :        181 :         rte_mcfg_mem_read_unlock();
     804                 :            : 
     805         [ -  + ]:        181 :         if (rte_eal_malloc_heap_populate() < 0) {
     806                 :          0 :                 rte_eal_init_alert("Cannot init malloc heap");
     807                 :          0 :                 rte_errno = ENODEV;
     808                 :          0 :                 goto err_out;
     809                 :            :         }
     810                 :            : 
     811                 :            :         /* register multi-process action callbacks for hotplug after memory init */
     812         [ -  + ]:        181 :         if (eal_mp_dev_hotplug_init() < 0) {
     813                 :          0 :                 rte_eal_init_alert("failed to register mp callback for hotplug");
     814                 :          0 :                 goto err_out;
     815                 :            :         }
     816                 :            : 
     817         [ -  + ]:        181 :         if (rte_eal_tailqs_init() < 0) {
     818                 :          0 :                 rte_eal_init_alert("Cannot init tail queues for objects");
     819                 :          0 :                 rte_errno = EFAULT;
     820                 :          0 :                 goto err_out;
     821                 :            :         }
     822                 :            : 
     823         [ -  + ]:        181 :         if (rte_eal_timer_init() < 0) {
     824                 :          0 :                 rte_eal_init_alert("Cannot init HPET or TSC timers");
     825                 :          0 :                 rte_errno = ENOTSUP;
     826                 :          0 :                 goto err_out;
     827                 :            :         }
     828                 :            : 
     829                 :        181 :         eal_rand_init();
     830                 :            : 
     831                 :        181 :         eal_check_mem_on_local_socket();
     832                 :            : 
     833         [ -  + ]:        181 :         if (rte_thread_set_affinity_by_id(rte_thread_self(),
     834                 :        181 :                         &lcore_config[config->main_lcore].cpuset) != 0) {
     835                 :          0 :                 rte_eal_init_alert("Cannot set affinity");
     836                 :          0 :                 rte_errno = EINVAL;
     837                 :          0 :                 goto err_out;
     838                 :            :         }
     839                 :        181 :         __rte_thread_init(config->main_lcore,
     840                 :        181 :                 &lcore_config[config->main_lcore].cpuset);
     841                 :            : 
     842                 :        181 :         ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset));
     843         [ -  + ]:        181 :         EAL_LOG(DEBUG, "Main lcore %u is ready (tid=%zx;cpuset=[%s%s])",
     844                 :            :                 config->main_lcore, (uintptr_t)pthread_self(), cpuset,
     845                 :            :                 ret == 0 ? "" : "...");
     846                 :            : 
     847         [ +  + ]:        305 :         RTE_LCORE_FOREACH_WORKER(i) {
     848                 :            : 
     849                 :            :                 /*
     850                 :            :                  * create communication pipes between main thread
     851                 :            :                  * and children
     852                 :            :                  */
     853         [ -  + ]:        124 :                 if (pipe(lcore_config[i].pipe_main2worker) < 0)
     854                 :          0 :                         rte_panic("Cannot create pipe\n");
     855         [ -  + ]:        124 :                 if (pipe(lcore_config[i].pipe_worker2main) < 0)
     856                 :          0 :                         rte_panic("Cannot create pipe\n");
     857                 :            : 
     858                 :        124 :                 lcore_config[i].state = WAIT;
     859                 :            : 
     860                 :            :                 /* create a thread for each lcore */
     861                 :        124 :                 ret = eal_worker_thread_create(i);
     862         [ -  + ]:        124 :                 if (ret != 0)
     863                 :          0 :                         rte_panic("Cannot create thread\n");
     864                 :            : 
     865                 :            :                 /* Set thread_name for aid in debugging. */
     866                 :            :                 snprintf(thread_name, sizeof(thread_name),
     867                 :            :                         "dpdk-worker%d", i);
     868                 :        124 :                 rte_thread_set_name(lcore_config[i].thread_id, thread_name);
     869                 :            : 
     870                 :        124 :                 ret = rte_thread_set_affinity_by_id(lcore_config[i].thread_id,
     871                 :        124 :                         &lcore_config[i].cpuset);
     872         [ -  + ]:        124 :                 if (ret != 0)
     873                 :          0 :                         rte_panic("Cannot set affinity\n");
     874                 :            :         }
     875                 :            : 
     876                 :            :         /*
     877                 :            :          * Launch a dummy function on all worker lcores, so that main lcore
     878                 :            :          * knows they are all ready when this function returns.
     879                 :            :          */
     880                 :        181 :         rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MAIN);
     881                 :        181 :         rte_eal_mp_wait_lcore();
     882                 :            : 
     883                 :            :         /* initialize services so vdevs register service during bus_probe. */
     884                 :        181 :         ret = rte_service_init();
     885         [ -  + ]:        181 :         if (ret) {
     886                 :          0 :                 rte_eal_init_alert("rte_service_init() failed");
     887                 :          0 :                 rte_errno = -ret;
     888                 :          0 :                 goto err_out;
     889                 :            :         }
     890                 :            : 
     891                 :            :         /* Probe all the buses and devices/drivers on them */
     892         [ -  + ]:        181 :         if (rte_bus_probe()) {
     893                 :          0 :                 rte_eal_init_alert("Cannot probe devices");
     894                 :          0 :                 rte_errno = ENOTSUP;
     895                 :          0 :                 goto err_out;
     896                 :            :         }
     897                 :            : 
     898                 :            :         /* initialize default service/lcore mappings and start running. Ignore
     899                 :            :          * -ENOTSUP, as it indicates no service coremask passed to EAL.
     900                 :            :          */
     901                 :        181 :         ret = rte_service_start_with_defaults();
     902         [ -  + ]:        181 :         if (ret < 0 && ret != -ENOTSUP) {
     903                 :          0 :                 rte_errno = -ret;
     904                 :          0 :                 goto err_out;
     905                 :            :         }
     906                 :            : 
     907                 :            :         /*
     908                 :            :          * Clean up unused files in runtime directory. We do this at the end of
     909                 :            :          * init and not at the beginning because we want to clean stuff up
     910                 :            :          * whether we are primary or secondary process, but we cannot remove
     911                 :            :          * primary process' files because secondary should be able to run even
     912                 :            :          * if primary process is dead.
     913                 :            :          *
     914                 :            :          * In no_shconf mode, no runtime directory is created in the first
     915                 :            :          * place, so no cleanup needed.
     916                 :            :          */
     917   [ +  +  -  + ]:        181 :         if (!internal_conf->no_shconf && eal_clean_runtime_dir() < 0) {
     918                 :          0 :                 rte_eal_init_alert("Cannot clear runtime directory");
     919                 :          0 :                 goto err_out;
     920                 :            :         }
     921   [ +  +  +  - ]:        181 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY && !internal_conf->no_telemetry) {
     922         [ -  + ]:        156 :                 if (rte_telemetry_init(rte_eal_get_runtime_dir(),
     923                 :            :                                 rte_version(),
     924                 :            :                                 &internal_conf->ctrl_cpuset) != 0)
     925                 :          0 :                         goto err_out;
     926                 :            :         }
     927                 :            : 
     928                 :        181 :         eal_mcfg_complete();
     929                 :            : 
     930                 :        181 :         return fctret;
     931                 :            : 
     932                 :         65 : err_out:
     933                 :         65 :         rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
     934                 :         65 :         eal_clean_saved_args();
     935                 :         65 :         return -1;
     936                 :            : }
     937                 :            : 
     938                 :            : static int
     939                 :   47834264 : mark_freeable(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
     940                 :            :                 void *arg __rte_unused)
     941                 :            : {
     942                 :            :         /* ms is const, so find this memseg */
     943                 :            :         struct rte_memseg *found;
     944                 :            : 
     945         [ +  - ]:   47834264 :         if (msl->external)
     946                 :            :                 return 0;
     947                 :            : 
     948                 :   47834264 :         found = rte_mem_virt2memseg(ms->addr, msl);
     949                 :            : 
     950                 :   47834264 :         found->flags &= ~RTE_MEMSEG_FLAG_DO_NOT_FREE;
     951                 :            : 
     952                 :   47834264 :         return 0;
     953                 :            : }
     954                 :            : 
     955                 :            : RTE_EXPORT_SYMBOL(rte_eal_cleanup)
     956                 :            : int
     957                 :        246 : rte_eal_cleanup(void)
     958                 :            : {
     959                 :            :         static RTE_ATOMIC(uint32_t) run_once;
     960                 :            :         uint32_t has_run = 0;
     961                 :            : 
     962         [ -  + ]:        246 :         if (!rte_atomic_compare_exchange_strong_explicit(&run_once, &has_run, 1,
     963                 :            :                                         rte_memory_order_relaxed, rte_memory_order_relaxed)) {
     964                 :          0 :                 EAL_LOG(WARNING, "Already called cleanup");
     965                 :          0 :                 rte_errno = EALREADY;
     966                 :          0 :                 return -1;
     967                 :            :         }
     968                 :            : 
     969                 :            :         /* if we're in a primary process, we need to mark hugepages as freeable
     970                 :            :          * so that finalization can release them back to the system.
     971                 :            :          */
     972                 :            :         struct internal_config *internal_conf =
     973                 :        246 :                 eal_get_internal_configuration();
     974                 :            : 
     975         [ +  + ]:        246 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
     976         [ +  + ]:        218 :                         internal_conf->hugepage_file.unlink_existing)
     977                 :        209 :                 rte_memseg_walk(mark_freeable, NULL);
     978                 :            : 
     979                 :        246 :         rte_service_finalize();
     980                 :        246 :         eal_bus_cleanup();
     981                 :        246 :         vfio_mp_sync_cleanup();
     982                 :        246 :         rte_mp_channel_cleanup();
     983                 :        246 :         rte_eal_alarm_cleanup();
     984                 :        246 :         rte_trace_save();
     985                 :        246 :         eal_trace_fini();
     986                 :        246 :         eal_mp_dev_hotplug_cleanup();
     987                 :            :         /* after this point, any DPDK pointers will become dangling */
     988                 :        246 :         rte_eal_memory_detach();
     989                 :        246 :         rte_eal_malloc_heap_cleanup();
     990                 :        246 :         eal_cleanup_config(internal_conf);
     991                 :        246 :         eal_lcore_var_cleanup();
     992                 :        246 :         rte_eal_log_cleanup();
     993                 :        246 :         return 0;
     994                 :            : }
     995                 :            : 
     996                 :            : RTE_EXPORT_SYMBOL(rte_eal_create_uio_dev)
     997                 :          0 : int rte_eal_create_uio_dev(void)
     998                 :            : {
     999                 :            :         const struct internal_config *internal_conf =
    1000                 :          0 :                 eal_get_internal_configuration();
    1001                 :            : 
    1002                 :          0 :         return internal_conf->create_uio_dev;
    1003                 :            : }
    1004                 :            : 
    1005                 :            : RTE_EXPORT_SYMBOL(rte_eal_vfio_intr_mode)
    1006                 :            : enum rte_intr_mode
    1007                 :          0 : rte_eal_vfio_intr_mode(void)
    1008                 :            : {
    1009                 :            :         const struct internal_config *internal_conf =
    1010                 :          0 :                 eal_get_internal_configuration();
    1011                 :            : 
    1012                 :          0 :         return internal_conf->vfio_intr_mode;
    1013                 :            : }
    1014                 :            : 
    1015                 :            : RTE_EXPORT_SYMBOL(rte_eal_vfio_get_vf_token)
    1016                 :            : void
    1017                 :          0 : rte_eal_vfio_get_vf_token(rte_uuid_t vf_token)
    1018                 :            : {
    1019                 :          0 :         struct internal_config *cfg = eal_get_internal_configuration();
    1020                 :            : 
    1021                 :          0 :         rte_uuid_copy(vf_token, cfg->vfio_vf_token);
    1022                 :          0 : }
    1023                 :            : 
    1024                 :            : int
    1025                 :        184 : rte_eal_check_module(const char *module_name)
    1026                 :            : {
    1027                 :            :         char sysfs_mod_name[PATH_MAX];
    1028                 :            :         struct stat st;
    1029                 :            :         int n;
    1030                 :            : 
    1031         [ +  - ]:        184 :         if (NULL == module_name)
    1032                 :            :                 return -1;
    1033                 :            : 
    1034                 :            :         /* Check if there is sysfs mounted */
    1035         [ -  + ]:        184 :         if (stat("/sys/module", &st) != 0) {
    1036                 :          0 :                 EAL_LOG(DEBUG, "sysfs is not mounted! error %i (%s)",
    1037                 :            :                         errno, strerror(errno));
    1038                 :          0 :                 return -1;
    1039                 :            :         }
    1040                 :            : 
    1041                 :            :         /* A module might be built-in, therefore try sysfs */
    1042                 :            :         n = snprintf(sysfs_mod_name, PATH_MAX, "/sys/module/%s", module_name);
    1043         [ -  + ]:        184 :         if (n < 0 || n > PATH_MAX) {
    1044                 :          0 :                 EAL_LOG(DEBUG, "Could not format module path");
    1045                 :          0 :                 return -1;
    1046                 :            :         }
    1047                 :            : 
    1048         [ -  + ]:        184 :         if (stat(sysfs_mod_name, &st) != 0) {
    1049                 :          0 :                 EAL_LOG(DEBUG, "Module %s not found! error %i (%s)",
    1050                 :            :                         sysfs_mod_name, errno, strerror(errno));
    1051                 :          0 :                 return 0;
    1052                 :            :         }
    1053                 :            : 
    1054                 :            :         /* Module has been found */
    1055                 :            :         return 1;
    1056                 :            : }

Generated by: LCOV version 1.14