#include <errno.h>
#include <sys/mman.h>
#include <sys/queue.h>
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
#include <sys/io.h>
+#endif
#include <rte_common.h>
#include <rte_debug.h>
#include <rte_memory.h>
#include <rte_memzone.h>
#include <rte_launch.h>
-#include <rte_tailq.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_per_lcore.h>
#include <rte_version.h>
#include <rte_atomic.h>
#include <malloc_heap.h>
-#include <rte_eth_ring.h>
-#include <rte_dev.h>
#include "eal_private.h"
#include "eal_thread.h"
#define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10)
-#define HIGHEST_RPL 3
-
/* Allow the application to print its usage message too if set */
static rte_usage_hook_t rte_application_usage_hook = NULL;
}
/* Detect if we are a primary or a secondary process */
-static enum rte_proc_type_t
+enum rte_proc_type_t
eal_proc_type_detect(void)
{
enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
static void
rte_config_init(void)
{
- rte_config.process_type = (internal_config.process_type == RTE_PROC_AUTO) ?
- eal_proc_type_detect() : /* for auto, detect the type */
- internal_config.process_type; /* otherwise use what's already set */
+ rte_config.process_type = internal_config.process_type;
switch (rte_config.process_type){
case RTE_PROC_PRIMARY:
printf("\nUsage: %s ", prgname);
eal_common_usage();
printf("EAL Linux options:\n"
- " -d LIB.so : add driver (can be used multiple times)\n"
- " --"OPT_XEN_DOM0" : support application running on Xen Domain0 "
- "without hugetlbfs\n"
- " --"OPT_SOCKET_MEM" : memory to allocate on specific\n"
- " sockets (use comma separated values)\n"
- " --"OPT_HUGE_DIR" : directory where hugetlbfs is mounted\n"
- " --"OPT_FILE_PREFIX": prefix for hugepage filenames\n"
- " --"OPT_BASE_VIRTADDR": specify base virtual address\n"
- " --"OPT_VFIO_INTR": specify desired interrupt mode for VFIO "
- "(legacy|msi|msix)\n"
- " --"OPT_CREATE_UIO_DEV": create /dev/uioX (usually done by hotplug)\n"
+ " -d LIB.so Add driver (can be used multiple times)\n"
+ " --"OPT_SOCKET_MEM" Memory to allocate on sockets (comma separated values)\n"
+ " --"OPT_HUGE_DIR" Directory where hugetlbfs is mounted\n"
+ " --"OPT_FILE_PREFIX" Prefix for hugepage filenames\n"
+ " --"OPT_BASE_VIRTADDR" Base virtual address\n"
+ " --"OPT_CREATE_UIO_DEV" Create /dev/uioX (usually done by hotplug)\n"
+ " --"OPT_VFIO_INTR" Interrupt mode for VFIO (legacy|msi|msix)\n"
+ " --"OPT_XEN_DOM0" Support running on Xen dom0 without hugetlbfs\n"
"\n");
/* Allow the application to print its usage message too if hook is set */
if ( rte_application_usage_hook ) {
return -1;
/* make sure we don't exceed 32-bit boundary on 32-bit target */
-#ifndef RTE_ARCH_X86_64
+#ifndef RTE_ARCH_64
if (addr >= UINTPTR_MAX)
return -1;
#endif
- /* align the addr on 2M boundary */
- internal_config.base_virtaddr = RTE_PTR_ALIGN_CEIL((uintptr_t)addr,
- RTE_PGSIZE_2M);
+ /* align the addr on 16M boundary, 16MB is the minimum huge page
+ * size on IBM Power architecture. If the addr is aligned to 16MB,
+ * it can align to 2MB for x86. So this alignment can also be used
+ * on x86 */
+ internal_config.base_virtaddr =
+ RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M);
return 0;
}
return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX;
}
+/* Parse the arguments for --log-level only */
+static void
+eal_log_level_parse(int argc, char **argv)
+{
+ int opt;
+ char **argvopt;
+ int option_index;
+
+ argvopt = argv;
+
+ 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;
+ }
+
+ optind = 0; /* reset getopt lib */
+}
+
/* Parse the argument given in the command line of the application */
static int
eal_parse_args(int argc, char **argv)
{
- int opt, ret, i;
+ int opt, ret;
char **argvopt;
int option_index;
- int coremask_ok = 0;
char *prgname = argv[0];
struct shared_driver *solib;
argvopt = argv;
- internal_config.memory = 0;
- internal_config.force_nrank = 0;
- internal_config.force_nchannel = 0;
- internal_config.hugefile_prefix = HUGEFILE_PREFIX_DEFAULT;
- internal_config.hugepage_dir = NULL;
- internal_config.force_sockets = 0;
- internal_config.syslog_facility = LOG_DAEMON;
- /* default value from build option */
- internal_config.log_level = RTE_LOG_LEVEL;
- internal_config.xen_dom0_support = 0;
- /* if set to NONE, interrupt mode is determined automatically */
- internal_config.vfio_intr_mode = RTE_INTR_MODE_NONE;
-#ifdef RTE_LIBEAL_USE_HPET
- internal_config.no_hpet = 0;
-#else
- internal_config.no_hpet = 1;
-#endif
- /* zero out the NUMA config */
- for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
- internal_config.socket_mem[i] = 0;
-
- /* zero out hugedir descriptors */
- for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
- internal_config.hugepage_info[i].lock_descriptor = -1;
-
- internal_config.vmware_tsc_map = 0;
- internal_config.base_virtaddr = 0;
-
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 == '?')
+ if (opt == '?') {
+ eal_usage(prgname);
return -1;
+ }
- ret = eal_parse_common_option(opt, optarg, option_index,
- &internal_config);
+ ret = eal_parse_common_option(opt, optarg, &internal_config);
/* common parser is not happy */
if (ret < 0) {
eal_usage(prgname);
return -1;
}
/* common parser handled this option */
- if (ret == 0) {
- /* special case, note that the common parser accepted
- * the coremask option */
- if (opt == 'c')
- coremask_ok = 1;
+ if (ret == 0)
continue;
- }
switch (opt) {
+ case 'h':
+ eal_usage(prgname);
+ exit(EXIT_SUCCESS);
+
/* force loading of external driver */
case 'd':
solib = malloc(sizeof(*solib));
break;
/* long options */
- case 0:
- if (!strcmp(eal_long_options[option_index].name, OPT_XEN_DOM0)) {
- #ifdef RTE_LIBRTE_XEN_DOM0
- internal_config.xen_dom0_support = 1;
- #else
- RTE_LOG(ERR, EAL, "Can't support DPDK app "
- "running on Dom0, please configure"
- " RTE_LIBRTE_XEN_DOM0=y\n");
+ case OPT_XEN_DOM0_NUM:
+#ifdef RTE_LIBRTE_XEN_DOM0
+ internal_config.xen_dom0_support = 1;
+#else
+ RTE_LOG(ERR, EAL, "Can't support DPDK app "
+ "running on Dom0, please configure"
+ " RTE_LIBRTE_XEN_DOM0=y\n");
+ return -1;
+#endif
+ break;
+
+ case OPT_HUGE_DIR_NUM:
+ internal_config.hugepage_dir = optarg;
+ break;
+
+ case OPT_FILE_PREFIX_NUM:
+ internal_config.hugefile_prefix = optarg;
+ break;
+
+ case OPT_SOCKET_MEM_NUM:
+ if (eal_parse_socket_mem(optarg) < 0) {
+ RTE_LOG(ERR, EAL, "invalid parameters for --"
+ OPT_SOCKET_MEM "\n");
+ eal_usage(prgname);
return -1;
- #endif
- } else if (!strcmp(eal_long_options[option_index].name, OPT_HUGE_DIR)) {
- internal_config.hugepage_dir = optarg;
- } else if (!strcmp(eal_long_options[option_index].name, OPT_FILE_PREFIX)) {
- internal_config.hugefile_prefix = optarg;
- } else if (!strcmp(eal_long_options[option_index].name, OPT_SOCKET_MEM)) {
- if (eal_parse_socket_mem(optarg) < 0) {
- RTE_LOG(ERR, EAL, "invalid parameters for --"
- OPT_SOCKET_MEM "\n");
- eal_usage(prgname);
- return -1;
- }
- } else if (!strcmp(eal_long_options[option_index].name, OPT_BASE_VIRTADDR)) {
- if (eal_parse_base_virtaddr(optarg) < 0) {
- RTE_LOG(ERR, EAL, "invalid parameter for --"
- OPT_BASE_VIRTADDR "\n");
- eal_usage(prgname);
- return -1;
- }
- } else if (!strcmp(eal_long_options[option_index].name, OPT_VFIO_INTR)) {
- if (eal_parse_vfio_intr(optarg) < 0) {
- RTE_LOG(ERR, EAL, "invalid parameters for --"
- OPT_VFIO_INTR "\n");
- eal_usage(prgname);
- return -1;
- }
- } else if (!strcmp(eal_long_options[option_index].name, OPT_CREATE_UIO_DEV)) {
- internal_config.create_uio_dev = 1;
- } else {
- RTE_LOG(ERR, EAL, "Option %s is not supported "
- "on Linux\n",
- eal_long_options[option_index].name);
+ }
+ break;
+
+ case OPT_BASE_VIRTADDR_NUM:
+ if (eal_parse_base_virtaddr(optarg) < 0) {
+ RTE_LOG(ERR, EAL, "invalid parameter for --"
+ OPT_BASE_VIRTADDR "\n");
+ eal_usage(prgname);
+ return -1;
+ }
+ break;
+
+ case OPT_VFIO_INTR_NUM:
+ if (eal_parse_vfio_intr(optarg) < 0) {
+ RTE_LOG(ERR, EAL, "invalid parameters for --"
+ OPT_VFIO_INTR "\n");
eal_usage(prgname);
return -1;
}
break;
+ case OPT_CREATE_UIO_DEV_NUM:
+ internal_config.create_uio_dev = 1;
+ break;
+
default:
- if (isprint(opt)) {
+ if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
RTE_LOG(ERR, EAL, "Option %c is not supported "
"on Linux\n", opt);
+ } else if (opt >= OPT_LONG_MIN_NUM &&
+ opt < OPT_LONG_MAX_NUM) {
+ RTE_LOG(ERR, EAL, "Option %s is not supported "
+ "on Linux\n",
+ eal_long_options[option_index].name);
} else {
RTE_LOG(ERR, EAL, "Option %d is not supported "
"on Linux\n", opt);
}
}
- /* sanity checks */
- if (!coremask_ok) {
- RTE_LOG(ERR, EAL, "coremask not specified\n");
- eal_usage(prgname);
- return -1;
- }
- if (internal_config.process_type == RTE_PROC_AUTO){
- internal_config.process_type = eal_proc_type_detect();
- }
- if (internal_config.process_type == RTE_PROC_INVALID){
- RTE_LOG(ERR, EAL, "Invalid process type specified\n");
- eal_usage(prgname);
- return -1;
- }
- if (internal_config.process_type == RTE_PROC_PRIMARY &&
- internal_config.force_nchannel == 0) {
- RTE_LOG(ERR, EAL, "Number of memory channels (-n) not specified\n");
- eal_usage(prgname);
+ if (eal_adjust_config(&internal_config) != 0)
return -1;
- }
- if (index(internal_config.hugefile_prefix,'%') != NULL){
- RTE_LOG(ERR, EAL, "Invalid char, '%%', in '"OPT_FILE_PREFIX"' option\n");
- eal_usage(prgname);
- return -1;
- }
- if (internal_config.memory > 0 && internal_config.force_sockets == 1) {
- RTE_LOG(ERR, EAL, "Options -m and --socket-mem cannot be specified "
- "at the same time\n");
- eal_usage(prgname);
- return -1;
- }
- /* --no-huge doesn't make sense with either -m or --socket-mem */
- if (internal_config.no_hugetlbfs &&
- (internal_config.memory > 0 ||
- internal_config.force_sockets == 1)) {
- RTE_LOG(ERR, EAL, "Options -m or --socket-mem cannot be specified "
- "together with --no-huge!\n");
+
+ /* sanity checks */
+ if (eal_check_common_options(&internal_config) != 0) {
eal_usage(prgname);
return -1;
}
+
/* --xen-dom0 doesn't make sense with --socket-mem */
if (internal_config.xen_dom0_support && internal_config.force_sockets == 1) {
- RTE_LOG(ERR, EAL, "Options --socket-mem cannot be specified "
- "together with --xen_dom0!\n");
- eal_usage(prgname);
- return -1;
- }
-
- if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&
- rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {
- RTE_LOG(ERR, EAL, "Error: blacklist [-b] and whitelist "
- "[-w] options cannot be used at the same time\n");
+ RTE_LOG(ERR, EAL, "Options --"OPT_SOCKET_MEM" cannot be specified "
+ "together with --"OPT_XEN_DOM0"\n");
eal_usage(prgname);
return -1;
}
if (optind >= 0)
argv[optind-1] = prgname;
-
- /* if no memory amounts were requested, this will result in 0 and
- * will be overriden later, right after eal_hugepage_info_init() */
- for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
- internal_config.memory += internal_config.socket_mem[i];
-
ret = optind-1;
optind = 0; /* reset getopt lib */
return ret;
/*
* Request iopl privilege for all RPL, returns 0 on success
+ * iopl() call is mostly for the i386 architecture. For other architectures,
+ * return -1 to indicate IO privilege can't be changed in this way.
*/
-static int
+int
rte_eal_iopl_init(void)
{
- return iopl(HIGHEST_RPL);
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+ if (iopl(3) != 0)
+ return -1;
+ return 0;
+#else
+ return -1;
+#endif
}
/* Launch threads, called at application init(). */
static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
struct shared_driver *solib = NULL;
const char *logid;
+ char cpuset[RTE_CPU_AFFINITY_STR_LEN];
if (!rte_atomic32_test_and_set(&run_once))
return -1;
if (rte_eal_log_early_init() < 0)
rte_panic("Cannot init early logs\n");
+ eal_log_level_parse(argc, argv);
+
+ /* set log level as early as possible */
+ rte_set_log_level(internal_config.log_level);
+
if (rte_eal_cpu_init() < 0)
rte_panic("Cannot detect lcores\n");
if (fctret < 0)
exit(1);
- /* set log level as early as possible */
- rte_set_log_level(internal_config.log_level);
-
if (internal_config.no_hugetlbfs == 0 &&
internal_config.process_type != RTE_PROC_SECONDARY &&
internal_config.xen_dom0_support == 0 &&
rte_config_init();
- if (rte_eal_iopl_init() == 0)
- rte_config.flags |= EAL_FLG_HIGH_IOPL;
-
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");
rte_eal_mcfg_complete();
TAILQ_FOREACH(solib, &solib_list, next) {
- RTE_LOG(INFO, EAL, "open shared lib %s\n", solib->name);
+ RTE_LOG(DEBUG, EAL, "open shared lib %s\n", solib->name);
solib->lib_handle = dlopen(solib->name, RTLD_NOW);
if (solib->lib_handle == NULL)
RTE_LOG(WARNING, EAL, "%s\n", dlerror());
eal_thread_init_master(rte_config.master_lcore);
- RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
- rte_config.master_lcore, (int)thread_id);
+ ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN);
- if (rte_eal_dev_init(PMD_INIT_PRE_PCI_PROBE) < 0)
+ RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%x;cpuset=[%s%s])\n",
+ rte_config.master_lcore, (int)thread_id, cpuset,
+ ret == 0 ? "" : "...");
+
+ if (rte_eal_dev_init() < 0)
rte_panic("Cannot init pmd devices\n");
RTE_LCORE_FOREACH_SLAVE(i) {
/* Probe & Initialize PCI devices */
if (rte_eal_pci_probe())
- rte_panic("Cannot probe PCI\n");
-
- /* Initialize any outstanding devices */
- if (rte_eal_dev_init(PMD_INIT_POST_PCI_PROBE) < 0)
- rte_panic("Cannot init pmd devices\n");
+ rte_panic("Cannot probe PCI\n");
return fctret;
}
enum rte_lcore_role_t
rte_eal_lcore_role(unsigned lcore_id)
{
- return (rte_config.lcore_role[lcore_id]);
+ return rte_config.lcore_role[lcore_id];
}
enum rte_proc_type_t
rte_eal_process_type(void)
{
- return (rte_config.process_type);
+ return rte_config.process_type;
}
int rte_eal_has_hugepages(void)
{
return ! internal_config.no_hugetlbfs;
}
+
+int
+rte_eal_check_module(const char *module_name)
+{
+ char mod_name[30]; /* Any module names can be longer than 30 bytes? */
+ int ret = 0;
+ int n;
+
+ if (NULL == module_name)
+ return -1;
+
+ FILE *fd = fopen("/proc/modules", "r");
+ if (NULL == fd) {
+ RTE_LOG(ERR, EAL, "Open /proc/modules failed!"
+ " error %i (%s)\n", errno, strerror(errno));
+ return -1;
+ }
+ while (!feof(fd)) {
+ n = fscanf(fd, "%29s %*[^\n]", mod_name);
+ if ((n == 1) && !strcmp(mod_name, module_name)) {
+ ret = 1;
+ break;
+ }
+ }
+ fclose(fd);
+
+ return ret;
+}