05804dc541d24382ffa2ed3a9be65bbb6f7db6ae
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   Copyright(c) 2012-2014 6WIND S.A.
6  *   All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <unistd.h>
41 #include <pthread.h>
42 #include <syslog.h>
43 #include <getopt.h>
44 #include <sys/file.h>
45 #include <fcntl.h>
46 #include <dlfcn.h>
47 #include <stddef.h>
48 #include <errno.h>
49 #include <limits.h>
50 #include <errno.h>
51 #include <sys/mman.h>
52 #include <sys/queue.h>
53 #include <sys/io.h>
54
55 #include <rte_common.h>
56 #include <rte_debug.h>
57 #include <rte_memory.h>
58 #include <rte_memzone.h>
59 #include <rte_launch.h>
60 #include <rte_tailq.h>
61 #include <rte_eal.h>
62 #include <rte_eal_memconfig.h>
63 #include <rte_per_lcore.h>
64 #include <rte_lcore.h>
65 #include <rte_log.h>
66 #include <rte_random.h>
67 #include <rte_cycles.h>
68 #include <rte_string_fns.h>
69 #include <rte_cpuflags.h>
70 #include <rte_interrupts.h>
71 #include <rte_pci.h>
72 #include <rte_devargs.h>
73 #include <rte_common.h>
74 #include <rte_version.h>
75 #include <rte_atomic.h>
76 #include <malloc_heap.h>
77 #include <rte_eth_ring.h>
78 #include <rte_dev.h>
79
80 #include "eal_private.h"
81 #include "eal_thread.h"
82 #include "eal_internal_cfg.h"
83 #include "eal_filesystem.h"
84 #include "eal_hugepages.h"
85 #include "eal_options.h"
86
87 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
88
89 #define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10)
90
91 #define HIGHEST_RPL 3
92
93 /* Allow the application to print its usage message too if set */
94 static rte_usage_hook_t rte_application_usage_hook = NULL;
95
96 TAILQ_HEAD(shared_driver_list, shared_driver);
97
98 /* Definition for shared object drivers. */
99 struct shared_driver {
100         TAILQ_ENTRY(shared_driver) next;
101
102         char    name[PATH_MAX];
103         void*   lib_handle;
104 };
105
106 /* List of external loadable drivers */
107 static struct shared_driver_list solib_list =
108 TAILQ_HEAD_INITIALIZER(solib_list);
109
110 /* early configuration structure, when memory config is not mmapped */
111 static struct rte_mem_config early_mem_config;
112
113 /* define fd variable here, because file needs to be kept open for the
114  * duration of the program, as we hold a write lock on it in the primary proc */
115 static int mem_cfg_fd = -1;
116
117 static struct flock wr_lock = {
118                 .l_type = F_WRLCK,
119                 .l_whence = SEEK_SET,
120                 .l_start = offsetof(struct rte_mem_config, memseg),
121                 .l_len = sizeof(early_mem_config.memseg),
122 };
123
124 /* Address of global and public configuration */
125 static struct rte_config rte_config = {
126                 .mem_config = &early_mem_config,
127 };
128
129 /* internal configuration (per-core) */
130 struct lcore_config lcore_config[RTE_MAX_LCORE];
131
132 /* internal configuration */
133 struct internal_config internal_config;
134
135 /* used by rte_rdtsc() */
136 int rte_cycles_vmware_tsc_map;
137
138 /* Return a pointer to the configuration structure */
139 struct rte_config *
140 rte_eal_get_configuration(void)
141 {
142         return &rte_config;
143 }
144
145 /* parse a sysfs (or other) file containing one integer value */
146 int
147 eal_parse_sysfs_value(const char *filename, unsigned long *val)
148 {
149         FILE *f;
150         char buf[BUFSIZ];
151         char *end = NULL;
152
153         if ((f = fopen(filename, "r")) == NULL) {
154                 RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
155                         __func__, filename);
156                 return -1;
157         }
158
159         if (fgets(buf, sizeof(buf), f) == NULL) {
160                 RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
161                         __func__, filename);
162                 fclose(f);
163                 return -1;
164         }
165         *val = strtoul(buf, &end, 0);
166         if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
167                 RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n",
168                                 __func__, filename);
169                 fclose(f);
170                 return -1;
171         }
172         fclose(f);
173         return 0;
174 }
175
176
177 /* create memory configuration in shared/mmap memory. Take out
178  * a write lock on the memsegs, so we can auto-detect primary/secondary.
179  * This means we never close the file while running (auto-close on exit).
180  * We also don't lock the whole file, so that in future we can use read-locks
181  * on other parts, e.g. memzones, to detect if there are running secondary
182  * processes. */
183 static void
184 rte_eal_config_create(void)
185 {
186         void *rte_mem_cfg_addr;
187         int retval;
188
189         const char *pathname = eal_runtime_config_path();
190
191         if (internal_config.no_shconf)
192                 return;
193
194         /* map the config before hugepage address so that we don't waste a page */
195         if (internal_config.base_virtaddr != 0)
196                 rte_mem_cfg_addr = (void *)
197                         RTE_ALIGN_FLOOR(internal_config.base_virtaddr -
198                         sizeof(struct rte_mem_config), sysconf(_SC_PAGE_SIZE));
199         else
200                 rte_mem_cfg_addr = NULL;
201
202         if (mem_cfg_fd < 0){
203                 mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
204                 if (mem_cfg_fd < 0)
205                         rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
206         }
207
208         retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
209         if (retval < 0){
210                 close(mem_cfg_fd);
211                 rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname);
212         }
213
214         retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock);
215         if (retval < 0){
216                 close(mem_cfg_fd);
217                 rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary "
218                                 "process running?\n", pathname);
219         }
220
221         rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config),
222                                 PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
223
224         if (rte_mem_cfg_addr == MAP_FAILED){
225                 rte_panic("Cannot mmap memory for rte_config\n");
226         }
227         memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
228         rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
229
230         /* store address of the config in the config itself so that secondary
231          * processes could later map the config into this exact location */
232         rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
233
234 }
235
236 /* attach to an existing shared memory config */
237 static void
238 rte_eal_config_attach(void)
239 {
240         struct rte_mem_config *mem_config;
241
242         const char *pathname = eal_runtime_config_path();
243
244         if (internal_config.no_shconf)
245                 return;
246
247         if (mem_cfg_fd < 0){
248                 mem_cfg_fd = open(pathname, O_RDWR);
249                 if (mem_cfg_fd < 0)
250                         rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
251         }
252
253         /* map it as read-only first */
254         mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
255                         PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
256         if (mem_config == MAP_FAILED)
257                 rte_panic("Cannot mmap memory for rte_config\n");
258
259         rte_config.mem_config = mem_config;
260 }
261
262 /* reattach the shared config at exact memory location primary process has it */
263 static void
264 rte_eal_config_reattach(void)
265 {
266         struct rte_mem_config *mem_config;
267         void *rte_mem_cfg_addr;
268
269         if (internal_config.no_shconf)
270                 return;
271
272         /* save the address primary process has mapped shared config to */
273         rte_mem_cfg_addr = (void *) (uintptr_t) rte_config.mem_config->mem_cfg_addr;
274
275         /* unmap original config */
276         munmap(rte_config.mem_config, sizeof(struct rte_mem_config));
277
278         /* remap the config at proper address */
279         mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
280                         sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
281                         mem_cfg_fd, 0);
282         close(mem_cfg_fd);
283         if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr)
284                 rte_panic("Cannot mmap memory for rte_config\n");
285
286         rte_config.mem_config = mem_config;
287 }
288
289 /* Detect if we are a primary or a secondary process */
290 static enum rte_proc_type_t
291 eal_proc_type_detect(void)
292 {
293         enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
294         const char *pathname = eal_runtime_config_path();
295
296         /* if we can open the file but not get a write-lock we are a secondary
297          * process. NOTE: if we get a file handle back, we keep that open
298          * and don't close it to prevent a race condition between multiple opens */
299         if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) &&
300                         (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0))
301                 ptype = RTE_PROC_SECONDARY;
302
303         RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n",
304                         ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
305
306         return ptype;
307 }
308
309 /* Sets up rte_config structure with the pointer to shared memory config.*/
310 static void
311 rte_config_init(void)
312 {
313         rte_config.process_type = (internal_config.process_type == RTE_PROC_AUTO) ?
314                         eal_proc_type_detect() : /* for auto, detect the type */
315                         internal_config.process_type; /* otherwise use what's already set */
316
317         switch (rte_config.process_type){
318         case RTE_PROC_PRIMARY:
319                 rte_eal_config_create();
320                 break;
321         case RTE_PROC_SECONDARY:
322                 rte_eal_config_attach();
323                 rte_eal_mcfg_wait_complete(rte_config.mem_config);
324                 rte_eal_config_reattach();
325                 break;
326         case RTE_PROC_AUTO:
327         case RTE_PROC_INVALID:
328                 rte_panic("Invalid process type\n");
329         }
330 }
331
332 /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */
333 static void
334 eal_hugedirs_unlock(void)
335 {
336         int i;
337
338         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
339         {
340                 /* skip uninitialized */
341                 if (internal_config.hugepage_info[i].lock_descriptor < 0)
342                         continue;
343                 /* unlock hugepage file */
344                 flock(internal_config.hugepage_info[i].lock_descriptor, LOCK_UN);
345                 close(internal_config.hugepage_info[i].lock_descriptor);
346                 /* reset the field */
347                 internal_config.hugepage_info[i].lock_descriptor = -1;
348         }
349 }
350
351 /* display usage */
352 static void
353 eal_usage(const char *prgname)
354 {
355         printf("\nUsage: %s ", prgname);
356         eal_common_usage();
357         printf("EAL Linux options:\n"
358                "  -d LIB.so    : add driver (can be used multiple times)\n"
359                "  --"OPT_XEN_DOM0" : support application running on Xen Domain0 "
360                            "without hugetlbfs\n"
361                "  --"OPT_SOCKET_MEM" : memory to allocate on specific\n"
362                    "                 sockets (use comma separated values)\n"
363                "  --"OPT_HUGE_DIR"   : directory where hugetlbfs is mounted\n"
364                "  --"OPT_FILE_PREFIX": prefix for hugepage filenames\n"
365                "  --"OPT_BASE_VIRTADDR": specify base virtual address\n"
366                "  --"OPT_VFIO_INTR": specify desired interrupt mode for VFIO "
367                            "(legacy|msi|msix)\n"
368                "  --"OPT_CREATE_UIO_DEV": create /dev/uioX (usually done by hotplug)\n"
369                "\n");
370         /* Allow the application to print its usage message too if hook is set */
371         if ( rte_application_usage_hook ) {
372                 printf("===== Application Usage =====\n\n");
373                 rte_application_usage_hook(prgname);
374         }
375 }
376
377 /* Set a per-application usage message */
378 rte_usage_hook_t
379 rte_set_application_usage_hook( rte_usage_hook_t usage_func )
380 {
381         rte_usage_hook_t        old_func;
382
383         /* Will be NULL on the first call to denote the last usage routine. */
384         old_func                                        = rte_application_usage_hook;
385         rte_application_usage_hook      = usage_func;
386
387         return old_func;
388 }
389
390 static int
391 eal_parse_socket_mem(char *socket_mem)
392 {
393         char * arg[RTE_MAX_NUMA_NODES];
394         char *end;
395         int arg_num, i, len;
396         uint64_t total_mem = 0;
397
398         len = strnlen(socket_mem, SOCKET_MEM_STRLEN);
399         if (len == SOCKET_MEM_STRLEN) {
400                 RTE_LOG(ERR, EAL, "--socket-mem is too long\n");
401                 return -1;
402         }
403
404         /* all other error cases will be caught later */
405         if (!isdigit(socket_mem[len-1]))
406                 return -1;
407
408         /* split the optarg into separate socket values */
409         arg_num = rte_strsplit(socket_mem, len,
410                         arg, RTE_MAX_NUMA_NODES, ',');
411
412         /* if split failed, or 0 arguments */
413         if (arg_num <= 0)
414                 return -1;
415
416         internal_config.force_sockets = 1;
417
418         /* parse each defined socket option */
419         errno = 0;
420         for (i = 0; i < arg_num; i++) {
421                 end = NULL;
422                 internal_config.socket_mem[i] = strtoull(arg[i], &end, 10);
423
424                 /* check for invalid input */
425                 if ((errno != 0)  ||
426                                 (arg[i][0] == '\0') || (end == NULL) || (*end != '\0'))
427                         return -1;
428                 internal_config.socket_mem[i] *= 1024ULL;
429                 internal_config.socket_mem[i] *= 1024ULL;
430                 total_mem += internal_config.socket_mem[i];
431         }
432
433         /* check if we have a positive amount of total memory */
434         if (total_mem == 0)
435                 return -1;
436
437         return 0;
438 }
439
440 static int
441 eal_parse_base_virtaddr(const char *arg)
442 {
443         char *end;
444         uint64_t addr;
445
446         errno = 0;
447         addr = strtoull(arg, &end, 16);
448
449         /* check for errors */
450         if ((errno != 0) || (arg[0] == '\0') || end == NULL || (*end != '\0'))
451                 return -1;
452
453         /* make sure we don't exceed 32-bit boundary on 32-bit target */
454 #ifndef RTE_ARCH_X86_64
455         if (addr >= UINTPTR_MAX)
456                 return -1;
457 #endif
458
459         /* align the addr on 2M boundary */
460         internal_config.base_virtaddr = RTE_PTR_ALIGN_CEIL((uintptr_t)addr,
461                                                            RTE_PGSIZE_2M);
462
463         return 0;
464 }
465
466 static int
467 eal_parse_vfio_intr(const char *mode)
468 {
469         unsigned i;
470         static struct {
471                 const char *name;
472                 enum rte_intr_mode value;
473         } map[] = {
474                 { "legacy", RTE_INTR_MODE_LEGACY },
475                 { "msi", RTE_INTR_MODE_MSI },
476                 { "msix", RTE_INTR_MODE_MSIX },
477         };
478
479         for (i = 0; i < RTE_DIM(map); i++) {
480                 if (!strcmp(mode, map[i].name)) {
481                         internal_config.vfio_intr_mode = map[i].value;
482                         return 0;
483                 }
484         }
485         return -1;
486 }
487
488 static inline size_t
489 eal_get_hugepage_mem_size(void)
490 {
491         uint64_t size = 0;
492         unsigned i, j;
493
494         for (i = 0; i < internal_config.num_hugepage_sizes; i++) {
495                 struct hugepage_info *hpi = &internal_config.hugepage_info[i];
496                 if (hpi->hugedir != NULL) {
497                         for (j = 0; j < RTE_MAX_NUMA_NODES; j++) {
498                                 size += hpi->hugepage_sz * hpi->num_pages[j];
499                         }
500                 }
501         }
502
503         return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX;
504 }
505
506 /* Parse the argument given in the command line of the application */
507 static int
508 eal_parse_args(int argc, char **argv)
509 {
510         int opt, ret, i;
511         char **argvopt;
512         int option_index;
513         int coremask_ok = 0;
514         char *prgname = argv[0];
515         struct shared_driver *solib;
516
517         argvopt = argv;
518
519         internal_config.memory = 0;
520         internal_config.force_nrank = 0;
521         internal_config.force_nchannel = 0;
522         internal_config.hugefile_prefix = HUGEFILE_PREFIX_DEFAULT;
523         internal_config.hugepage_dir = NULL;
524         internal_config.force_sockets = 0;
525         internal_config.syslog_facility = LOG_DAEMON;
526         /* default value from build option */
527         internal_config.log_level = RTE_LOG_LEVEL;
528         internal_config.xen_dom0_support = 0;
529         /* if set to NONE, interrupt mode is determined automatically */
530         internal_config.vfio_intr_mode = RTE_INTR_MODE_NONE;
531 #ifdef RTE_LIBEAL_USE_HPET
532         internal_config.no_hpet = 0;
533 #else
534         internal_config.no_hpet = 1;
535 #endif
536         /* zero out the NUMA config */
537         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
538                 internal_config.socket_mem[i] = 0;
539
540         /* zero out hugedir descriptors */
541         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
542                 internal_config.hugepage_info[i].lock_descriptor = -1;
543
544         internal_config.vmware_tsc_map = 0;
545         internal_config.base_virtaddr = 0;
546
547         while ((opt = getopt_long(argc, argvopt, eal_short_options,
548                                   eal_long_options, &option_index)) != EOF) {
549
550                 int ret;
551
552                 /* getopt is not happy, stop right now */
553                 if (opt == '?')
554                         return -1;
555
556                 ret = eal_parse_common_option(opt, optarg, &internal_config);
557                 /* common parser is not happy */
558                 if (ret < 0) {
559                         eal_usage(prgname);
560                         return -1;
561                 }
562                 /* common parser handled this option */
563                 if (ret == 0) {
564                         /* special case, note that the common parser accepted
565                          * the coremask option */
566                         if (opt == 'c')
567                                 coremask_ok = 1;
568                         continue;
569                 }
570
571                 switch (opt) {
572                 /* force loading of external driver */
573                 case 'd':
574                         solib = malloc(sizeof(*solib));
575                         if (solib == NULL) {
576                                 RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
577                                 return -1;
578                         }
579                         memset(solib, 0, sizeof(*solib));
580                         strncpy(solib->name, optarg, PATH_MAX-1);
581                         solib->name[PATH_MAX-1] = 0;
582                         TAILQ_INSERT_TAIL(&solib_list, solib, next);
583                         break;
584
585                 /* long options */
586                 case OPT_XEN_DOM0_NUM:
587 #ifdef RTE_LIBRTE_XEN_DOM0
588                         internal_config.xen_dom0_support = 1;
589 #else
590                         RTE_LOG(ERR, EAL, "Can't support DPDK app "
591                                 "running on Dom0, please configure"
592                                 " RTE_LIBRTE_XEN_DOM0=y\n");
593                         return -1;
594 #endif
595                         break;
596
597                 case OPT_HUGE_DIR_NUM:
598                         internal_config.hugepage_dir = optarg;
599                         break;
600
601                 case OPT_FILE_PREFIX_NUM:
602                         internal_config.hugefile_prefix = optarg;
603                         break;
604
605                 case OPT_SOCKET_MEM_NUM:
606                         if (eal_parse_socket_mem(optarg) < 0) {
607                                 RTE_LOG(ERR, EAL, "invalid parameters for --"
608                                                 OPT_SOCKET_MEM "\n");
609                                 eal_usage(prgname);
610                                 return -1;
611                         }
612                         break;
613
614                 case OPT_BASE_VIRTADDR_NUM:
615                         if (eal_parse_base_virtaddr(optarg) < 0) {
616                                 RTE_LOG(ERR, EAL, "invalid parameter for --"
617                                                 OPT_BASE_VIRTADDR "\n");
618                                 eal_usage(prgname);
619                                 return -1;
620                         }
621                         break;
622
623                 case OPT_VFIO_INTR_NUM:
624                         if (eal_parse_vfio_intr(optarg) < 0) {
625                                 RTE_LOG(ERR, EAL, "invalid parameters for --"
626                                                 OPT_VFIO_INTR "\n");
627                                 eal_usage(prgname);
628                                 return -1;
629                         }
630                         break;
631
632                 case OPT_CREATE_UIO_DEV_NUM:
633                         internal_config.create_uio_dev = 1;
634                         break;
635
636                 default:
637                         if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
638                                 RTE_LOG(ERR, EAL, "Option %c is not supported "
639                                         "on Linux\n", opt);
640                         } else if (opt >= OPT_LONG_MIN_NUM &&
641                                    opt < OPT_LONG_MAX_NUM) {
642                                 RTE_LOG(ERR, EAL, "Option %s is not supported "
643                                         "on Linux\n",
644                                         eal_long_options[option_index].name);
645                         } else {
646                                 RTE_LOG(ERR, EAL, "Option %d is not supported "
647                                         "on Linux\n", opt);
648                         }
649                         eal_usage(prgname);
650                         return -1;
651                 }
652         }
653
654         /* sanity checks */
655         if (!coremask_ok) {
656                 RTE_LOG(ERR, EAL, "coremask not specified\n");
657                 eal_usage(prgname);
658                 return -1;
659         }
660         if (internal_config.process_type == RTE_PROC_AUTO){
661                 internal_config.process_type = eal_proc_type_detect();
662         }
663         if (internal_config.process_type == RTE_PROC_INVALID){
664                 RTE_LOG(ERR, EAL, "Invalid process type specified\n");
665                 eal_usage(prgname);
666                 return -1;
667         }
668         if (internal_config.process_type == RTE_PROC_PRIMARY &&
669                         internal_config.force_nchannel == 0) {
670                 RTE_LOG(ERR, EAL, "Number of memory channels (-n) not specified\n");
671                 eal_usage(prgname);
672                 return -1;
673         }
674         if (index(internal_config.hugefile_prefix,'%') != NULL){
675                 RTE_LOG(ERR, EAL, "Invalid char, '%%', in '"OPT_FILE_PREFIX"' option\n");
676                 eal_usage(prgname);
677                 return -1;
678         }
679         if (internal_config.memory > 0 && internal_config.force_sockets == 1) {
680                 RTE_LOG(ERR, EAL, "Options -m and --socket-mem cannot be specified "
681                                 "at the same time\n");
682                 eal_usage(prgname);
683                 return -1;
684         }
685         /* --no-huge doesn't make sense with either -m or --socket-mem */
686         if (internal_config.no_hugetlbfs &&
687                         (internal_config.memory > 0 ||
688                                         internal_config.force_sockets == 1)) {
689                 RTE_LOG(ERR, EAL, "Options -m or --socket-mem cannot be specified "
690                                 "together with --no-huge!\n");
691                 eal_usage(prgname);
692                 return -1;
693         }
694         /* --xen-dom0 doesn't make sense with --socket-mem */
695         if (internal_config.xen_dom0_support && internal_config.force_sockets == 1) {
696                 RTE_LOG(ERR, EAL, "Options --socket-mem cannot be specified "
697                                         "together with --xen_dom0!\n");
698                 eal_usage(prgname);
699                 return -1;
700         }
701
702         if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&
703                 rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {
704                 RTE_LOG(ERR, EAL, "Error: blacklist [-b] and whitelist "
705                         "[-w] options cannot be used at the same time\n");
706                 eal_usage(prgname);
707                 return -1;
708         }
709
710         if (optind >= 0)
711                 argv[optind-1] = prgname;
712
713         /* if no memory amounts were requested, this will result in 0 and
714          * will be overriden later, right after eal_hugepage_info_init() */
715         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
716                 internal_config.memory += internal_config.socket_mem[i];
717
718         ret = optind-1;
719         optind = 0; /* reset getopt lib */
720         return ret;
721 }
722
723 static void
724 eal_check_mem_on_local_socket(void)
725 {
726         const struct rte_memseg *ms;
727         int i, socket_id;
728
729         socket_id = rte_lcore_to_socket_id(rte_config.master_lcore);
730
731         ms = rte_eal_get_physmem_layout();
732
733         for (i = 0; i < RTE_MAX_MEMSEG; i++)
734                 if (ms[i].socket_id == socket_id &&
735                                 ms[i].len > 0)
736                         return;
737
738         RTE_LOG(WARNING, EAL, "WARNING: Master core has no "
739                         "memory on local socket!\n");
740 }
741
742 static int
743 sync_func(__attribute__((unused)) void *arg)
744 {
745         return 0;
746 }
747
748 inline static void
749 rte_eal_mcfg_complete(void)
750 {
751         /* ALL shared mem_config related INIT DONE */
752         if (rte_config.process_type == RTE_PROC_PRIMARY)
753                 rte_config.mem_config->magic = RTE_MAGIC;
754 }
755
756 /*
757  * Request iopl privilege for all RPL, returns 0 on success
758  */
759 static int
760 rte_eal_iopl_init(void)
761 {
762         return iopl(HIGHEST_RPL);
763 }
764
765 /* Launch threads, called at application init(). */
766 int
767 rte_eal_init(int argc, char **argv)
768 {
769         int i, fctret, ret;
770         pthread_t thread_id;
771         static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
772         struct shared_driver *solib = NULL;
773         const char *logid;
774
775         if (!rte_atomic32_test_and_set(&run_once))
776                 return -1;
777
778         logid = strrchr(argv[0], '/');
779         logid = strdup(logid ? logid + 1: argv[0]);
780
781         thread_id = pthread_self();
782
783         if (rte_eal_log_early_init() < 0)
784                 rte_panic("Cannot init early logs\n");
785
786         if (rte_eal_cpu_init() < 0)
787                 rte_panic("Cannot detect lcores\n");
788
789         fctret = eal_parse_args(argc, argv);
790         if (fctret < 0)
791                 exit(1);
792
793         /* set log level as early as possible */
794         rte_set_log_level(internal_config.log_level);
795
796         if (internal_config.no_hugetlbfs == 0 &&
797                         internal_config.process_type != RTE_PROC_SECONDARY &&
798                         internal_config.xen_dom0_support == 0 &&
799                         eal_hugepage_info_init() < 0)
800                 rte_panic("Cannot get hugepage information\n");
801
802         if (internal_config.memory == 0 && internal_config.force_sockets == 0) {
803                 if (internal_config.no_hugetlbfs)
804                         internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
805                 else
806                         internal_config.memory = eal_get_hugepage_mem_size();
807         }
808
809         if (internal_config.vmware_tsc_map == 1) {
810 #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
811                 rte_cycles_vmware_tsc_map = 1;
812                 RTE_LOG (DEBUG, EAL, "Using VMWARE TSC MAP, "
813                                 "you must have monitor_control.pseudo_perfctr = TRUE\n");
814 #else
815                 RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because "
816                                 "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n");
817 #endif
818         }
819
820         rte_srand(rte_rdtsc());
821
822         rte_config_init();
823
824         if (rte_eal_iopl_init() == 0)
825                 rte_config.flags |= EAL_FLG_HIGH_IOPL;
826
827         if (rte_eal_pci_init() < 0)
828                 rte_panic("Cannot init PCI\n");
829
830 #ifdef RTE_LIBRTE_IVSHMEM
831         if (rte_eal_ivshmem_init() < 0)
832                 rte_panic("Cannot init IVSHMEM\n");
833 #endif
834
835         if (rte_eal_memory_init() < 0)
836                 rte_panic("Cannot init memory\n");
837
838         /* the directories are locked during eal_hugepage_info_init */
839         eal_hugedirs_unlock();
840
841         if (rte_eal_memzone_init() < 0)
842                 rte_panic("Cannot init memzone\n");
843
844         if (rte_eal_tailqs_init() < 0)
845                 rte_panic("Cannot init tail queues for objects\n");
846
847 #ifdef RTE_LIBRTE_IVSHMEM
848         if (rte_eal_ivshmem_obj_init() < 0)
849                 rte_panic("Cannot init IVSHMEM objects\n");
850 #endif
851
852         if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
853                 rte_panic("Cannot init logs\n");
854
855         if (rte_eal_alarm_init() < 0)
856                 rte_panic("Cannot init interrupt-handling thread\n");
857
858         if (rte_eal_intr_init() < 0)
859                 rte_panic("Cannot init interrupt-handling thread\n");
860
861         if (rte_eal_timer_init() < 0)
862                 rte_panic("Cannot init HPET or TSC timers\n");
863
864         eal_check_mem_on_local_socket();
865
866         rte_eal_mcfg_complete();
867
868         TAILQ_FOREACH(solib, &solib_list, next) {
869                 RTE_LOG(INFO, EAL, "open shared lib %s\n", solib->name);
870                 solib->lib_handle = dlopen(solib->name, RTLD_NOW);
871                 if (solib->lib_handle == NULL)
872                         RTE_LOG(WARNING, EAL, "%s\n", dlerror());
873         }
874
875         eal_thread_init_master(rte_config.master_lcore);
876
877         RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
878                 rte_config.master_lcore, (int)thread_id);
879
880         if (rte_eal_dev_init(PMD_INIT_PRE_PCI_PROBE) < 0)
881                 rte_panic("Cannot init pmd devices\n");
882
883         RTE_LCORE_FOREACH_SLAVE(i) {
884
885                 /*
886                  * create communication pipes between master thread
887                  * and children
888                  */
889                 if (pipe(lcore_config[i].pipe_master2slave) < 0)
890                         rte_panic("Cannot create pipe\n");
891                 if (pipe(lcore_config[i].pipe_slave2master) < 0)
892                         rte_panic("Cannot create pipe\n");
893
894                 lcore_config[i].state = WAIT;
895
896                 /* create a thread for each lcore */
897                 ret = pthread_create(&lcore_config[i].thread_id, NULL,
898                                      eal_thread_loop, NULL);
899                 if (ret != 0)
900                         rte_panic("Cannot create thread\n");
901         }
902
903         /*
904          * Launch a dummy function on all slave lcores, so that master lcore
905          * knows they are all ready when this function returns.
906          */
907         rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
908         rte_eal_mp_wait_lcore();
909
910         /* Probe & Initialize PCI devices */
911         if (rte_eal_pci_probe())
912                         rte_panic("Cannot probe PCI\n");
913
914         /* Initialize any outstanding devices */
915         if (rte_eal_dev_init(PMD_INIT_POST_PCI_PROBE) < 0)
916                 rte_panic("Cannot init pmd devices\n");
917
918         return fctret;
919 }
920
921 /* get core role */
922 enum rte_lcore_role_t
923 rte_eal_lcore_role(unsigned lcore_id)
924 {
925         return (rte_config.lcore_role[lcore_id]);
926 }
927
928 enum rte_proc_type_t
929 rte_eal_process_type(void)
930 {
931         return (rte_config.process_type);
932 }
933
934 int rte_eal_has_hugepages(void)
935 {
936         return ! internal_config.no_hugetlbfs;
937 }