2014-02-10 11:49:10 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
2014-06-04 00:42:50 +01:00
|
|
|
*
|
2016-03-09 13:37:24 +00:00
|
|
|
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
2014-04-25 13:59:41 +02:00
|
|
|
* Copyright(c) 2014 6WIND S.A.
|
2014-02-10 11:49:10 +00:00
|
|
|
* All rights reserved.
|
2014-06-04 00:42:50 +01:00
|
|
|
*
|
2014-02-10 11:49:10 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
2014-06-04 00:42:50 +01:00
|
|
|
*
|
2014-02-10 11:49:10 +00:00
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
2014-06-04 00:42:50 +01:00
|
|
|
*
|
2014-02-10 11:49:10 +00:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
|
|
|
|
#include <rte_common.h>
|
|
|
|
#include <rte_debug.h>
|
|
|
|
#include <rte_memory.h>
|
|
|
|
#include <rte_memzone.h>
|
|
|
|
#include <rte_launch.h>
|
|
|
|
#include <rte_eal.h>
|
|
|
|
#include <rte_eal_memconfig.h>
|
2017-03-22 16:19:27 -04:00
|
|
|
#include <rte_errno.h>
|
2014-02-10 11:49:10 +00:00
|
|
|
#include <rte_per_lcore.h>
|
|
|
|
#include <rte_lcore.h>
|
|
|
|
#include <rte_log.h>
|
|
|
|
#include <rte_random.h>
|
|
|
|
#include <rte_cycles.h>
|
|
|
|
#include <rte_string_fns.h>
|
|
|
|
#include <rte_cpuflags.h>
|
|
|
|
#include <rte_interrupts.h>
|
2017-01-19 14:21:35 +00:00
|
|
|
#include <rte_bus.h>
|
2014-02-10 11:49:10 +00:00
|
|
|
#include <rte_pci.h>
|
2014-07-02 11:14:03 +02:00
|
|
|
#include <rte_dev.h>
|
2014-04-25 13:59:41 +02:00
|
|
|
#include <rte_devargs.h>
|
2014-02-10 11:49:10 +00:00
|
|
|
#include <rte_common.h>
|
|
|
|
#include <rte_version.h>
|
|
|
|
#include <rte_atomic.h>
|
|
|
|
#include <malloc_heap.h>
|
|
|
|
|
|
|
|
#include "eal_private.h"
|
|
|
|
#include "eal_thread.h"
|
|
|
|
#include "eal_internal_cfg.h"
|
|
|
|
#include "eal_filesystem.h"
|
|
|
|
#include "eal_hugepages.h"
|
2014-09-22 10:37:59 +02:00
|
|
|
#include "eal_options.h"
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
#define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
|
|
|
|
|
|
|
|
/* Allow the application to print its usage message too if set */
|
|
|
|
static rte_usage_hook_t rte_application_usage_hook = NULL;
|
|
|
|
/* early configuration structure, when memory config is not mmapped */
|
|
|
|
static struct rte_mem_config early_mem_config;
|
|
|
|
|
|
|
|
/* define fd variable here, because file needs to be kept open for the
|
|
|
|
* duration of the program, as we hold a write lock on it in the primary proc */
|
|
|
|
static int mem_cfg_fd = -1;
|
|
|
|
|
|
|
|
static struct flock wr_lock = {
|
|
|
|
.l_type = F_WRLCK,
|
|
|
|
.l_whence = SEEK_SET,
|
|
|
|
.l_start = offsetof(struct rte_mem_config, memseg),
|
|
|
|
.l_len = sizeof(early_mem_config.memseg),
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Address of global and public configuration */
|
|
|
|
static struct rte_config rte_config = {
|
|
|
|
.mem_config = &early_mem_config,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* internal configuration (per-core) */
|
|
|
|
struct lcore_config lcore_config[RTE_MAX_LCORE];
|
|
|
|
|
|
|
|
/* internal configuration */
|
|
|
|
struct internal_config internal_config;
|
|
|
|
|
|
|
|
/* used by rte_rdtsc() */
|
|
|
|
int rte_cycles_vmware_tsc_map;
|
|
|
|
|
|
|
|
/* Return a pointer to the configuration structure */
|
|
|
|
struct rte_config *
|
|
|
|
rte_eal_get_configuration(void)
|
|
|
|
{
|
|
|
|
return &rte_config;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse a sysfs (or other) file containing one integer value */
|
|
|
|
int
|
|
|
|
eal_parse_sysfs_value(const char *filename, unsigned long *val)
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
char *end = NULL;
|
|
|
|
|
|
|
|
if ((f = fopen(filename, "r")) == NULL) {
|
|
|
|
RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
|
|
|
|
__func__, filename);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fgets(buf, sizeof(buf), f) == NULL) {
|
|
|
|
RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
|
|
|
|
__func__, filename);
|
|
|
|
fclose(f);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*val = strtoul(buf, &end, 0);
|
|
|
|
if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
|
|
|
|
RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n",
|
|
|
|
__func__, filename);
|
|
|
|
fclose(f);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* create memory configuration in shared/mmap memory. Take out
|
|
|
|
* a write lock on the memsegs, so we can auto-detect primary/secondary.
|
|
|
|
* This means we never close the file while running (auto-close on exit).
|
|
|
|
* We also don't lock the whole file, so that in future we can use read-locks
|
|
|
|
* on other parts, e.g. memzones, to detect if there are running secondary
|
|
|
|
* processes. */
|
|
|
|
static void
|
|
|
|
rte_eal_config_create(void)
|
|
|
|
{
|
|
|
|
void *rte_mem_cfg_addr;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
const char *pathname = eal_runtime_config_path();
|
|
|
|
|
|
|
|
if (internal_config.no_shconf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (mem_cfg_fd < 0){
|
|
|
|
mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
|
|
|
|
if (mem_cfg_fd < 0)
|
|
|
|
rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
|
|
|
|
if (retval < 0){
|
|
|
|
close(mem_cfg_fd);
|
|
|
|
rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname);
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock);
|
|
|
|
if (retval < 0){
|
|
|
|
close(mem_cfg_fd);
|
|
|
|
rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary "
|
|
|
|
"process running?\n", pathname);
|
|
|
|
}
|
|
|
|
|
|
|
|
rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
|
|
|
|
PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
|
|
|
|
|
|
|
|
if (rte_mem_cfg_addr == MAP_FAILED){
|
|
|
|
rte_panic("Cannot mmap memory for rte_config\n");
|
|
|
|
}
|
|
|
|
memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
|
|
|
|
rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* attach to an existing shared memory config */
|
|
|
|
static void
|
|
|
|
rte_eal_config_attach(void)
|
|
|
|
{
|
|
|
|
void *rte_mem_cfg_addr;
|
|
|
|
const char *pathname = eal_runtime_config_path();
|
|
|
|
|
|
|
|
if (internal_config.no_shconf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (mem_cfg_fd < 0){
|
|
|
|
mem_cfg_fd = open(pathname, O_RDWR);
|
|
|
|
if (mem_cfg_fd < 0)
|
|
|
|
rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
|
|
|
|
}
|
|
|
|
|
2014-06-04 00:42:50 +01:00
|
|
|
rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
|
2014-02-10 11:49:10 +00:00
|
|
|
PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
|
|
|
|
close(mem_cfg_fd);
|
|
|
|
if (rte_mem_cfg_addr == MAP_FAILED)
|
|
|
|
rte_panic("Cannot mmap memory for rte_config\n");
|
|
|
|
|
|
|
|
rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Detect if we are a primary or a secondary process */
|
2014-11-20 22:57:22 +01:00
|
|
|
enum rte_proc_type_t
|
2014-02-10 11:49:10 +00:00
|
|
|
eal_proc_type_detect(void)
|
|
|
|
{
|
|
|
|
enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
|
|
|
|
const char *pathname = eal_runtime_config_path();
|
|
|
|
|
|
|
|
/* if we can open the file but not get a write-lock we are a secondary
|
|
|
|
* process. NOTE: if we get a file handle back, we keep that open
|
|
|
|
* and don't close it to prevent a race condition between multiple opens */
|
|
|
|
if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) &&
|
|
|
|
(fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0))
|
|
|
|
ptype = RTE_PROC_SECONDARY;
|
|
|
|
|
|
|
|
RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n",
|
|
|
|
ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
|
|
|
|
|
|
|
|
return ptype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sets up rte_config structure with the pointer to shared memory config.*/
|
|
|
|
static void
|
|
|
|
rte_config_init(void)
|
|
|
|
{
|
2014-11-20 22:57:22 +01:00
|
|
|
rte_config.process_type = internal_config.process_type;
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
switch (rte_config.process_type){
|
|
|
|
case RTE_PROC_PRIMARY:
|
|
|
|
rte_eal_config_create();
|
|
|
|
break;
|
|
|
|
case RTE_PROC_SECONDARY:
|
|
|
|
rte_eal_config_attach();
|
|
|
|
rte_eal_mcfg_wait_complete(rte_config.mem_config);
|
|
|
|
break;
|
|
|
|
case RTE_PROC_AUTO:
|
|
|
|
case RTE_PROC_INVALID:
|
|
|
|
rte_panic("Invalid process type\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display usage */
|
|
|
|
static void
|
|
|
|
eal_usage(const char *prgname)
|
|
|
|
{
|
2014-09-22 10:37:59 +02:00
|
|
|
printf("\nUsage: %s ", prgname);
|
|
|
|
eal_common_usage();
|
2014-02-10 11:49:10 +00:00
|
|
|
/* Allow the application to print its usage message too if hook is set */
|
|
|
|
if ( rte_application_usage_hook ) {
|
|
|
|
printf("===== Application Usage =====\n\n");
|
|
|
|
rte_application_usage_hook(prgname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set a per-application usage message */
|
|
|
|
rte_usage_hook_t
|
|
|
|
rte_set_application_usage_hook( rte_usage_hook_t usage_func )
|
|
|
|
{
|
|
|
|
rte_usage_hook_t old_func;
|
|
|
|
|
|
|
|
/* Will be NULL on the first call to denote the last usage routine. */
|
|
|
|
old_func = rte_application_usage_hook;
|
|
|
|
rte_application_usage_hook = usage_func;
|
|
|
|
|
|
|
|
return old_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t
|
|
|
|
eal_get_hugepage_mem_size(void)
|
|
|
|
{
|
|
|
|
uint64_t size = 0;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < internal_config.num_hugepage_sizes; i++) {
|
|
|
|
struct hugepage_info *hpi = &internal_config.hugepage_info[i];
|
|
|
|
if (hpi->hugedir != NULL) {
|
|
|
|
for (j = 0; j < RTE_MAX_NUMA_NODES; j++) {
|
|
|
|
size += hpi->hugepage_sz * hpi->num_pages[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX;
|
|
|
|
}
|
|
|
|
|
2015-06-08 16:55:52 -05:00
|
|
|
/* Parse the arguments for --log-level only */
|
|
|
|
static void
|
|
|
|
eal_log_level_parse(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int opt;
|
|
|
|
char **argvopt;
|
|
|
|
int option_index;
|
2015-10-19 21:13:10 +08:00
|
|
|
const int old_optind = optind;
|
|
|
|
const int old_optopt = optopt;
|
|
|
|
const int old_optreset = optreset;
|
|
|
|
char * const old_optarg = optarg;
|
2015-06-08 16:55:52 -05:00
|
|
|
|
|
|
|
argvopt = argv;
|
2015-10-19 21:13:10 +08:00
|
|
|
optind = 1;
|
|
|
|
optreset = 1;
|
2015-06-08 16:55:52 -05:00
|
|
|
|
|
|
|
eal_reset_internal_config(&internal_config);
|
|
|
|
|
|
|
|
while ((opt = getopt_long(argc, argvopt, eal_short_options,
|
|
|
|
eal_long_options, &option_index)) != EOF) {
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* getopt is not happy, stop right now */
|
|
|
|
if (opt == '?')
|
|
|
|
break;
|
|
|
|
|
|
|
|
ret = (opt == OPT_LOG_LEVEL_NUM) ?
|
|
|
|
eal_parse_common_option(opt, optarg, &internal_config) : 0;
|
|
|
|
|
|
|
|
/* common parser is not happy */
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-19 21:13:10 +08:00
|
|
|
/* restore getopt lib */
|
|
|
|
optind = old_optind;
|
|
|
|
optopt = old_optopt;
|
|
|
|
optreset = old_optreset;
|
|
|
|
optarg = old_optarg;
|
2015-06-08 16:55:52 -05:00
|
|
|
}
|
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
/* Parse the argument given in the command line of the application */
|
|
|
|
static int
|
|
|
|
eal_parse_args(int argc, char **argv)
|
|
|
|
{
|
2014-11-20 22:57:22 +01:00
|
|
|
int opt, ret;
|
2014-02-10 11:49:10 +00:00
|
|
|
char **argvopt;
|
|
|
|
int option_index;
|
|
|
|
char *prgname = argv[0];
|
2015-10-19 21:13:10 +08:00
|
|
|
const int old_optind = optind;
|
|
|
|
const int old_optopt = optopt;
|
|
|
|
const int old_optreset = optreset;
|
|
|
|
char * const old_optarg = optarg;
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
argvopt = argv;
|
2015-10-19 21:13:10 +08:00
|
|
|
optind = 1;
|
|
|
|
optreset = 1;
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2014-09-22 10:37:59 +02:00
|
|
|
while ((opt = getopt_long(argc, argvopt, eal_short_options,
|
|
|
|
eal_long_options, &option_index)) != EOF) {
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2014-09-22 10:37:59 +02:00
|
|
|
/* getopt is not happy, stop right now */
|
2015-01-29 17:51:17 +01:00
|
|
|
if (opt == '?') {
|
|
|
|
eal_usage(prgname);
|
2015-10-19 21:13:10 +08:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
2015-01-29 17:51:17 +01:00
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2014-09-22 10:38:00 +02:00
|
|
|
ret = eal_parse_common_option(opt, optarg, &internal_config);
|
2014-09-22 10:37:59 +02:00
|
|
|
/* common parser is not happy */
|
|
|
|
if (ret < 0) {
|
|
|
|
eal_usage(prgname);
|
2015-10-19 21:13:10 +08:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
2014-09-22 10:37:59 +02:00
|
|
|
}
|
|
|
|
/* common parser handled this option */
|
2014-11-17 10:14:10 +01:00
|
|
|
if (ret == 0)
|
2014-09-22 10:37:59 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (opt) {
|
2015-01-29 17:51:17 +01:00
|
|
|
case 'h':
|
|
|
|
eal_usage(prgname);
|
|
|
|
exit(EXIT_SUCCESS);
|
2014-02-10 11:49:10 +00:00
|
|
|
default:
|
2014-09-22 10:38:00 +02:00
|
|
|
if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
|
2014-09-22 10:37:59 +02:00
|
|
|
RTE_LOG(ERR, EAL, "Option %c is not supported "
|
|
|
|
"on FreeBSD\n", opt);
|
2014-09-22 10:38:00 +02:00
|
|
|
} else if (opt >= OPT_LONG_MIN_NUM &&
|
|
|
|
opt < OPT_LONG_MAX_NUM) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option %s is not supported "
|
|
|
|
"on FreeBSD\n",
|
|
|
|
eal_long_options[option_index].name);
|
2014-09-22 10:37:59 +02:00
|
|
|
} else {
|
|
|
|
RTE_LOG(ERR, EAL, "Option %d is not supported "
|
|
|
|
"on FreeBSD\n", opt);
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
eal_usage(prgname);
|
2015-10-19 21:13:10 +08:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
2014-02-10 11:49:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-19 21:13:10 +08:00
|
|
|
if (eal_adjust_config(&internal_config) != 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2014-11-17 10:14:10 +01:00
|
|
|
/* sanity checks */
|
|
|
|
if (eal_check_common_options(&internal_config) != 0) {
|
2014-04-25 13:59:41 +02:00
|
|
|
eal_usage(prgname);
|
2015-10-19 21:13:10 +08:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
2014-02-10 11:49:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (optind >= 0)
|
|
|
|
argv[optind-1] = prgname;
|
|
|
|
ret = optind-1;
|
2015-10-19 21:13:10 +08:00
|
|
|
|
|
|
|
out:
|
|
|
|
/* restore getopt lib */
|
|
|
|
optind = old_optind;
|
|
|
|
optopt = old_optopt;
|
|
|
|
optreset = old_optreset;
|
|
|
|
optarg = old_optarg;
|
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
eal_check_mem_on_local_socket(void)
|
|
|
|
{
|
|
|
|
const struct rte_memseg *ms;
|
|
|
|
int i, socket_id;
|
|
|
|
|
|
|
|
socket_id = rte_lcore_to_socket_id(rte_config.master_lcore);
|
|
|
|
|
|
|
|
ms = rte_eal_get_physmem_layout();
|
|
|
|
|
|
|
|
for (i = 0; i < RTE_MAX_MEMSEG; i++)
|
|
|
|
if (ms[i].socket_id == socket_id &&
|
|
|
|
ms[i].len > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RTE_LOG(WARNING, EAL, "WARNING: Master core has no "
|
|
|
|
"memory on local socket!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
sync_func(__attribute__((unused)) void *arg)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-04 00:42:50 +01:00
|
|
|
inline static void
|
2014-02-10 11:49:10 +00:00
|
|
|
rte_eal_mcfg_complete(void)
|
|
|
|
{
|
|
|
|
/* ALL shared mem_config related INIT DONE */
|
|
|
|
if (rte_config.process_type == RTE_PROC_PRIMARY)
|
|
|
|
rte_config.mem_config->magic = RTE_MAGIC;
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:59:47 +02:00
|
|
|
/* return non-zero if hugepages are enabled. */
|
|
|
|
int rte_eal_has_hugepages(void)
|
|
|
|
{
|
|
|
|
return !internal_config.no_hugetlbfs;
|
|
|
|
}
|
|
|
|
|
2014-05-02 16:42:52 -07:00
|
|
|
/* Abstraction for port I/0 privilege */
|
2014-08-26 16:11:39 +02:00
|
|
|
int
|
2014-02-10 11:49:10 +00:00
|
|
|
rte_eal_iopl_init(void)
|
|
|
|
{
|
2015-04-16 14:52:07 +03:00
|
|
|
static int fd;
|
2015-02-14 09:59:07 -05:00
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
fd = open("/dev/io", O_RDWR);
|
|
|
|
if (fd < 0)
|
|
|
|
return -1;
|
2015-04-16 14:52:07 +03:00
|
|
|
/* keep fd open for iopl */
|
2014-02-10 11:49:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-22 16:19:27 -04:00
|
|
|
static void rte_eal_init_alert(const char *msg)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "EAL: FATAL: %s\n", msg);
|
|
|
|
RTE_LOG(ERR, EAL, "%s\n", msg);
|
|
|
|
}
|
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
/* Launch threads, called at application init(). */
|
|
|
|
int
|
|
|
|
rte_eal_init(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int i, fctret, ret;
|
|
|
|
pthread_t thread_id;
|
|
|
|
static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
|
2015-02-17 10:08:07 +08:00
|
|
|
char cpuset[RTE_CPU_AFFINITY_STR_LEN];
|
2015-07-28 17:51:44 -07:00
|
|
|
char thread_name[RTE_MAX_THREAD_NAME_LEN];
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2016-09-23 11:47:31 -03:00
|
|
|
/* checks if the machine is adequate */
|
2017-03-22 16:19:28 -04:00
|
|
|
if (!rte_cpu_is_supported()) {
|
|
|
|
rte_eal_init_alert("unsupported cpu type.");
|
|
|
|
rte_errno = ENOTSUP;
|
|
|
|
return -1;
|
|
|
|
}
|
2016-09-23 11:47:31 -03:00
|
|
|
|
2017-03-22 16:19:32 -04:00
|
|
|
if (!rte_atomic32_test_and_set(&run_once)) {
|
|
|
|
rte_eal_init_alert("already called initialization.");
|
|
|
|
rte_errno = EALREADY;
|
2014-02-10 11:49:10 +00:00
|
|
|
return -1;
|
2017-03-22 16:19:32 -04:00
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
thread_id = pthread_self();
|
|
|
|
|
2015-06-08 16:55:52 -05:00
|
|
|
eal_log_level_parse(argc, argv);
|
|
|
|
|
|
|
|
/* set log level as early as possible */
|
|
|
|
rte_set_log_level(internal_config.log_level);
|
|
|
|
|
2017-03-22 16:19:27 -04:00
|
|
|
if (rte_eal_cpu_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot detect lcores.");
|
|
|
|
rte_errno = ENOTSUP;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-10-08 10:43:31 +02:00
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
fctret = eal_parse_args(argc, argv);
|
2017-03-22 16:19:30 -04:00
|
|
|
if (fctret < 0) {
|
|
|
|
rte_eal_init_alert("Invalid 'command line' arguments.");
|
|
|
|
rte_errno = EINVAL;
|
|
|
|
rte_atomic32_clear(&run_once);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
if (internal_config.no_hugetlbfs == 0 &&
|
|
|
|
internal_config.process_type != RTE_PROC_SECONDARY &&
|
2017-03-22 16:19:29 -04:00
|
|
|
eal_hugepage_info_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot get hugepage information.");
|
|
|
|
rte_errno = EACCES;
|
|
|
|
rte_atomic32_clear(&run_once);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
if (internal_config.memory == 0 && internal_config.force_sockets == 0) {
|
|
|
|
if (internal_config.no_hugetlbfs)
|
|
|
|
internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
|
|
|
|
else
|
|
|
|
internal_config.memory = eal_get_hugepage_mem_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (internal_config.vmware_tsc_map == 1) {
|
|
|
|
#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
|
|
|
|
rte_cycles_vmware_tsc_map = 1;
|
|
|
|
RTE_LOG (DEBUG, EAL, "Using VMWARE TSC MAP, "
|
|
|
|
"you must have monitor_control.pseudo_perfctr = TRUE\n");
|
|
|
|
#else
|
|
|
|
RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because "
|
|
|
|
"RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
rte_srand(rte_rdtsc());
|
|
|
|
|
|
|
|
rte_config_init();
|
|
|
|
|
2017-03-22 16:19:33 -04:00
|
|
|
if (rte_eal_memory_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot init memory\n");
|
|
|
|
rte_errno = ENOMEM;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2017-03-22 16:19:31 -04:00
|
|
|
if (rte_eal_memzone_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot init memzone\n");
|
|
|
|
rte_errno = ENODEV;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2017-03-22 16:19:33 -04:00
|
|
|
if (rte_eal_tailqs_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot init tail queues for objects\n");
|
|
|
|
rte_errno = EFAULT;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2017-03-22 16:19:33 -04:00
|
|
|
if (rte_eal_alarm_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot init interrupt-handling thread\n");
|
|
|
|
/* rte_eal_alarm_init sets rte_errno on failure. */
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2017-03-22 16:19:35 -04:00
|
|
|
if (rte_eal_intr_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot init interrupt-handling thread\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
2017-03-22 16:19:34 -04:00
|
|
|
if (rte_eal_timer_init() < 0) {
|
|
|
|
rte_eal_init_alert("Cannot init HPET or TSC timers\n");
|
|
|
|
rte_errno = ENOTSUP;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-10 11:49:10 +00:00
|
|
|
|
|
|
|
if (rte_eal_pci_init() < 0)
|
|
|
|
rte_panic("Cannot init PCI\n");
|
|
|
|
|
|
|
|
eal_check_mem_on_local_socket();
|
|
|
|
|
2015-11-10 16:28:14 +02:00
|
|
|
if (eal_plugins_init() < 0)
|
2017-03-22 16:19:36 -04:00
|
|
|
rte_eal_init_alert("Cannot init plugins\n");
|
2015-11-10 16:28:14 +02:00
|
|
|
|
2015-02-17 10:08:05 +08:00
|
|
|
eal_thread_init_master(rte_config.master_lcore);
|
|
|
|
|
2015-02-17 10:08:07 +08:00
|
|
|
ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN);
|
|
|
|
|
|
|
|
RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%p;cpuset=[%s%s])\n",
|
|
|
|
rte_config.master_lcore, thread_id, cpuset,
|
|
|
|
ret == 0 ? "" : "...");
|
|
|
|
|
2017-01-18 19:35:21 +05:30
|
|
|
if (rte_bus_scan())
|
|
|
|
rte_panic("Cannot scan the buses for devices\n");
|
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
RTE_LCORE_FOREACH_SLAVE(i) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* create communication pipes between master thread
|
|
|
|
* and children
|
|
|
|
*/
|
|
|
|
if (pipe(lcore_config[i].pipe_master2slave) < 0)
|
|
|
|
rte_panic("Cannot create pipe\n");
|
|
|
|
if (pipe(lcore_config[i].pipe_slave2master) < 0)
|
|
|
|
rte_panic("Cannot create pipe\n");
|
|
|
|
|
|
|
|
lcore_config[i].state = WAIT;
|
|
|
|
|
|
|
|
/* create a thread for each lcore */
|
|
|
|
ret = pthread_create(&lcore_config[i].thread_id, NULL,
|
|
|
|
eal_thread_loop, NULL);
|
|
|
|
if (ret != 0)
|
|
|
|
rte_panic("Cannot create thread\n");
|
2015-07-28 17:51:44 -07:00
|
|
|
|
|
|
|
/* Set thread_name for aid in debugging. */
|
|
|
|
snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN,
|
|
|
|
"lcore-slave-%d", i);
|
2016-06-17 14:48:16 +02:00
|
|
|
rte_thread_setname(lcore_config[i].thread_id, thread_name);
|
2014-02-10 11:49:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Launch a dummy function on all slave lcores, so that master lcore
|
|
|
|
* knows they are all ready when this function returns.
|
|
|
|
*/
|
|
|
|
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
|
|
|
|
rte_eal_mp_wait_lcore();
|
|
|
|
|
2017-01-18 19:35:22 +05:30
|
|
|
/* Probe all the buses and devices/drivers on them */
|
|
|
|
if (rte_bus_probe())
|
|
|
|
rte_panic("Cannot probe devices\n");
|
|
|
|
|
2014-06-25 21:07:45 +01:00
|
|
|
/* Probe & Initialize PCI devices */
|
|
|
|
if (rte_eal_pci_probe())
|
2014-08-26 16:12:17 +02:00
|
|
|
rte_panic("Cannot probe PCI\n");
|
2014-06-25 21:07:45 +01:00
|
|
|
|
eal: postpone vdev initialization
Some platform like octeontx may use pci and
vdev based combined device to represent a logical
dpdk functional device.In such case, postponing the
vdev initialization after pci device
initialization will provide the better view of
the pci device resources in the system in
vdev's probe function, and it allows better
functional subsystem registration in vdev probe
function.
As a bonus, This patch fixes a bond device
initialization use case.
example command to reproduce the issue:
./testpmd -c 0x2 --vdev 'eth_bond0,mode=0,
slave=0000:02:00.0,slave=0000:03:00.0' --
--port-topology=chained
root cause:
In existing case(vdev initialization and then pci
initialization), creates three Ethernet ports with
following port ids
0 - Bond device
1 - PCI device 0
2 - PCI devive 1
Since testpmd, calls the configure/start on all the ports on
start up,it will translate to following illegal setup sequence
1)bond device configure/start
1.1) pci device0 stop/configure/start
1.2) pci device1 stop/configure/start
2)pci device 0 configure(illegal setup case,
as device in start state)
The fix changes the initialization sequence and
allow initialization in following valid setup order
1) pcie device 0 configure/start
2) pcie device 1 configure/start
3) bond device 2 configure/start
3.1) pcie device 0/stop/configure/start
3.2) pcie device 1/stop/configure/start
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
2016-11-20 13:30:50 +05:30
|
|
|
if (rte_eal_dev_init() < 0)
|
|
|
|
rte_panic("Cannot init pmd devices\n");
|
|
|
|
|
2016-03-09 13:37:24 +00:00
|
|
|
rte_eal_mcfg_complete();
|
|
|
|
|
2014-02-10 11:49:10 +00:00
|
|
|
return fctret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get core role */
|
|
|
|
enum rte_lcore_role_t
|
|
|
|
rte_eal_lcore_role(unsigned lcore_id)
|
|
|
|
{
|
2015-05-11 17:10:25 +03:00
|
|
|
return rte_config.lcore_role[lcore_id];
|
2014-02-10 11:49:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
enum rte_proc_type_t
|
|
|
|
rte_eal_process_type(void)
|
|
|
|
{
|
2015-05-11 17:10:25 +03:00
|
|
|
return rte_config.process_type;
|
2014-02-10 11:49:10 +00:00
|
|
|
}
|