kvargs: add in doc
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal.c
index 1ddfb65..d572bda 100644 (file)
@@ -2,6 +2,7 @@
  *   BSD LICENSE
  * 
  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2012-2013 6WIND S.A.
  *   All rights reserved.
  * 
  *   Redistribution and use in source and binary forms, with or without
@@ -41,6 +42,8 @@
 #include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
+#include <fcntl.h>
+#include <dlfcn.h>
 #include <stddef.h>
 #include <errno.h>
 #include <limits.h>
@@ -48,8 +51,6 @@
 #include <sys/mman.h>
 #include <sys/queue.h>
 #include <sys/io.h>
-#include <sys/user.h>
-#include <linux/binfmts.h>
 
 #include <rte_common.h>
 #include <rte_debug.h>
@@ -92,6 +93,7 @@
 #define OPT_USE_DEVICE  "use-device"
 #define OPT_SYSLOG      "syslog"
 #define OPT_BASE_VIRTADDR   "base-virtaddr"
+#define OPT_XEN_DOM0    "xen-dom0"
 
 #define RTE_EAL_BLACKLIST_SIZE 0x100
 
 
 #define BITS_PER_HEX 4
 
-#define GET_BLACKLIST_FIELD(in, fd, lim, dlm)                   \
-{                                                               \
-       unsigned long val;                                      \
-       char *end;                                              \
-       errno = 0;                                              \
-       val = strtoul((in), &end, 16);                          \
-       if (errno != 0 || end[0] != (dlm) || val > (lim))       \
-               return (-EINVAL);                               \
-       (fd) = (typeof (fd))val;                                \
-       (in) = end + 1;                                         \
-}
-
 /* Allow the application to print its usage message too if set */
 static rte_usage_hook_t        rte_application_usage_hook = NULL;
+
+TAILQ_HEAD(shared_driver_list, shared_driver);
+
+/* Definition for shared object drivers. */
+struct shared_driver {
+       TAILQ_ENTRY(shared_driver) next;
+
+       char    name[PATH_MAX];
+       void*   lib_handle;
+};
+
+/* List of external loadable drivers */
+static struct shared_driver_list solib_list =
+TAILQ_HEAD_INITIALIZER(solib_list);
+
 /* early configuration structure, when memory config is not mmapped */
 static struct rte_mem_config early_mem_config;
 
@@ -330,11 +335,14 @@ eal_usage(const char *prgname)
               "  -c COREMASK  : A hexadecimal bitmask of cores to run on\n"
               "  -n NUM       : Number of memory channels\n"
                   "  -v           : Display version information on startup\n"
+              "  -d LIB.so    : add driver (can be used multiple times)\n"
               "  -b <domain:bus:devid.func>: to prevent EAL from using specified "
            "PCI device\n"
               "                 (multiple -b options are allowed)\n"
               "  -m MB        : memory to allocate (see also --"OPT_SOCKET_MEM")\n"
               "  -r NUM       : force number of memory ranks (don't detect)\n"
+              "  --"OPT_XEN_DOM0" : support application running on Xen Domain0 "
+                          "without hugetlbfs\n"
               "  --"OPT_SYSLOG"     : set syslog facility\n"
               "  --"OPT_SOCKET_MEM" : memory to allocate on specific \n"
                   "                 sockets (use comma separated values)\n"
@@ -409,7 +417,7 @@ eal_parse_coremask(const char *coremask)
        if (coremask[0] == '0' && ((coremask[1] == 'x')
                ||  (coremask[1] == 'X')) )
                coremask += 2;
-       i = strnlen(coremask, MAX_ARG_STRLEN);
+       i = strnlen(coremask, PATH_MAX);
        while ((i > 0) && isblank(coremask[i - 1]))
                i--;
        if (i == 0)
@@ -440,6 +448,8 @@ eal_parse_coremask(const char *coremask)
                cfg->lcore_role[idx] = ROLE_OFF;
        if(count == 0)
                return -1;
+       /* Update the count of enabled logical cores of the EAL configuration */
+       cfg->lcore_count = count;
        return 0;
 }
 
@@ -627,8 +637,10 @@ eal_parse_args(int argc, char **argv)
                {OPT_USE_DEVICE, 1, 0, 0},
                {OPT_SYSLOG, 1, NULL, 0},
                {OPT_BASE_VIRTADDR, 1, 0, 0},
+               {OPT_XEN_DOM0, 0, 0, 0},
                {0, 0, 0, 0}
        };
+       struct shared_driver *solib;
 
        argvopt = argv;
 
@@ -639,6 +651,7 @@ eal_parse_args(int argc, char **argv)
        internal_config.hugepage_dir = NULL;
        internal_config.force_sockets = 0;
        internal_config.syslog_facility = LOG_DAEMON;
+       internal_config.xen_dom0_support = 0;
 #ifdef RTE_LIBEAL_USE_HPET
        internal_config.no_hpet = 0;
 #else
@@ -655,7 +668,7 @@ eal_parse_args(int argc, char **argv)
        internal_config.vmware_tsc_map = 0;
        internal_config.base_virtaddr = 0;
 
-       while ((opt = getopt_long(argc, argvopt, "b:c:m:n:r:v",
+       while ((opt = getopt_long(argc, argvopt, "b:c:d:m:n:r:v",
                                  lgopts, &option_index)) != EOF) {
 
                switch (opt) {
@@ -676,6 +689,18 @@ eal_parse_args(int argc, char **argv)
                        }
                        coremask_ok = 1;
                        break;
+               /* force loading of external driver */
+               case 'd':
+                       solib = malloc(sizeof(*solib));
+                       if (solib == NULL) {
+                               RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
+                               return -1;
+                       }
+                       memset(solib, 0, sizeof(*solib));
+                       strncpy(solib->name, optarg, PATH_MAX-1);
+                       solib->name[PATH_MAX-1] = 0;
+                       TAILQ_INSERT_TAIL(&solib_list, solib, next);
+                       break;
                /* size of memory */
                case 'm':
                        internal_config.memory = atoi(optarg);
@@ -714,6 +739,16 @@ eal_parse_args(int argc, char **argv)
                        if (!strcmp(lgopts[option_index].name, OPT_NO_HUGE)) {
                                internal_config.no_hugetlbfs = 1;
                        }
+                       if (!strcmp(lgopts[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");
+                               return -1;
+               #endif 
+                       }
                        else if (!strcmp(lgopts[option_index].name, OPT_NO_PCI)) {
                                internal_config.no_pci = 1;
                        }
@@ -810,7 +845,13 @@ eal_parse_args(int argc, char **argv)
                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 no blacklist, parse a whitelist */
        if (blacklist_index > 0) {
                if (eal_dev_whitelist_exists()) {
@@ -889,6 +930,7 @@ 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);
+       struct shared_driver *solib = NULL;
 
        if (!rte_atomic32_test_and_set(&run_once))
                return -1;
@@ -898,12 +940,16 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_log_early_init() < 0)
                rte_panic("Cannot init early logs\n");
 
+       if (rte_eal_cpu_init() < 0)
+               rte_panic("Cannot detect lcores\n");
+
        fctret = eal_parse_args(argc, argv);
        if (fctret < 0)
                exit(1);
 
        if (internal_config.no_hugetlbfs == 0 &&
                        internal_config.process_type != RTE_PROC_SECONDARY &&
+                       internal_config.xen_dom0_support == 0 &&
                        eal_hugepage_info_init() < 0)
                rte_panic("Cannot get hugepage information\n");
 
@@ -932,9 +978,6 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_iopl_init() == 0)
                rte_config.flags |= EAL_FLG_HIGH_IOPL;
        
-       if (rte_eal_cpu_init() < 0)
-               rte_panic("Cannot detect lcores\n");
-
        if (rte_eal_pci_init() < 0)
                rte_panic("Cannot init PCI\n");
 
@@ -972,9 +1015,6 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_timer_init() < 0)
                rte_panic("Cannot init HPET or TSC timers\n");
 
-       RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
-               rte_config.master_lcore, (int)thread_id);
-
        eal_check_mem_on_local_socket();
 
        rte_eal_mcfg_complete();
@@ -982,6 +1022,21 @@ rte_eal_init(int argc, char **argv)
        if (rte_eal_non_pci_ethdev_init() < 0)
                rte_panic("Cannot init non-PCI eth_devs\n");
 
+       TAILQ_FOREACH(solib, &solib_list, next) {
+               solib->lib_handle = dlopen(solib->name, RTLD_NOW);
+               if ((solib->lib_handle == NULL) && (solib->name[0] != '/')) {
+                       /* relative path: try again with "./" prefix */
+                       char sopath[PATH_MAX];
+                       snprintf(sopath, sizeof(sopath), "./%s", solib->name);
+                       solib->lib_handle = dlopen(sopath, RTLD_NOW);
+               }
+               if (solib->lib_handle == NULL)
+                       RTE_LOG(WARNING, EAL, "%s\n", dlerror());
+       }
+
+       RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
+               rte_config.master_lcore, (int)thread_id);
+
        RTE_LCORE_FOREACH_SLAVE(i) {
 
                /*