memory: add --socket-mem option
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without 
8  *   modification, are permitted provided that the following conditions 
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright 
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright 
14  *       notice, this list of conditions and the following disclaimer in 
15  *       the documentation and/or other materials provided with the 
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its 
18  *       contributors may be used to endorse or promote products derived 
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  * 
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 <getopt.h>
43 #include <fcntl.h>
44 #include <stddef.h>
45 #include <errno.h>
46 #include <limits.h>
47 #include <errno.h>
48 #include <sys/mman.h>
49 #include <sys/queue.h>
50
51 #include <rte_common.h>
52 #include <rte_debug.h>
53 #include <rte_memory.h>
54 #include <rte_memzone.h>
55 #include <rte_launch.h>
56 #include <rte_tailq.h>
57 #include <rte_eal.h>
58 #include <rte_per_lcore.h>
59 #include <rte_lcore.h>
60 #include <rte_log.h>
61 #include <rte_random.h>
62 #include <rte_cycles.h>
63 #include <rte_string_fns.h>
64 #include <rte_cpuflags.h>
65 #include <rte_interrupts.h>
66 #include <rte_pci.h>
67 #include <rte_common.h>
68 #include <rte_version.h>
69
70 #include "eal_private.h"
71 #include "eal_thread.h"
72 #include "eal_internal_cfg.h"
73 #include "eal_filesystem.h"
74 #include "eal_hugepages.h"
75
76 #define OPT_HUGE_DIR    "huge-dir"
77 #define OPT_PROC_TYPE   "proc-type"
78 #define OPT_NO_SHCONF   "no-shconf"
79 #define OPT_NO_HPET     "no-hpet"
80 #define OPT_NO_PCI      "no-pci"
81 #define OPT_NO_HUGE     "no-huge"
82 #define OPT_FILE_PREFIX "file-prefix"
83 #define OPT_SOCKET_MEM  "socket-mem"
84
85 #define RTE_EAL_BLACKLIST_SIZE  0x100
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 GET_BLACKLIST_FIELD(in, fd, lim, dlm)                   \
92 {                                                               \
93         unsigned long val;                                      \
94         char *end;                                              \
95         errno = 0;                                              \
96         val = strtoul((in), &end, 16);                          \
97         if (errno != 0 || end[0] != (dlm) || val > (lim))       \
98                 return (-EINVAL);                               \
99         (fd) = (typeof (fd))val;                                \
100         (in) = end + 1;                                         \
101 }
102
103 /* early configuration structure, when memory config is not mmapped */
104 static struct rte_mem_config early_mem_config;
105
106 /* define fd variable here, because file needs to be kept open for the
107  * duration of the program, as we hold a write lock on it in the primary proc */
108 static int mem_cfg_fd = -1;
109
110 static struct flock wr_lock = {
111                 .l_type = F_WRLCK,
112                 .l_whence = SEEK_SET,
113                 .l_start = offsetof(struct rte_mem_config, memseg),
114                 .l_len = sizeof(early_mem_config.memseg),
115 };
116
117 /* Address of global and public configuration */
118 static struct rte_config rte_config = {
119                 .mem_config = &early_mem_config,
120 };
121
122 static struct rte_pci_addr eal_dev_blacklist[RTE_EAL_BLACKLIST_SIZE];
123
124 /* internal configuration (per-core) */
125 struct lcore_config lcore_config[RTE_MAX_LCORE];
126
127 /* internal configuration */
128 struct internal_config internal_config;
129
130 /* Return a pointer to the configuration structure */
131 struct rte_config *
132 rte_eal_get_configuration(void)
133 {
134         return &rte_config;
135 }
136
137 /* parse a sysfs (or other) file containing one integer value */
138 int
139 eal_parse_sysfs_value(const char *filename, unsigned long *val)
140 {
141         FILE *f;
142         char buf[BUFSIZ];
143         char *end = NULL;
144
145         if ((f = fopen(filename, "r")) == NULL) {
146                 RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
147                         __func__, filename);
148                 return -1;
149         }
150
151         if (fgets(buf, sizeof(buf), f) == NULL) {
152                 RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
153                         __func__, filename);
154                 fclose(f);
155                 return -1;
156         }
157         *val = strtoul(buf, &end, 0);
158         if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
159                 RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n",
160                                 __func__, filename);
161                 fclose(f);
162                 return -1;
163         }
164         fclose(f);
165         return 0;
166 }
167
168
169 /* create memory configuration in shared/mmap memory. Take out
170  * a write lock on the memsegs, so we can auto-detect primary/secondary.
171  * This means we never close the file while running (auto-close on exit).
172  * We also don't lock the whole file, so that in future we can use read-locks
173  * on other parts, e.g. memzones, to detect if there are running secondary
174  * processes. */
175 static void
176 rte_eal_config_create(void)
177 {
178         void *rte_mem_cfg_addr;
179         int retval;
180
181         const char *pathname = eal_runtime_config_path();
182
183         if (internal_config.no_shconf)
184                 return;
185
186         if (mem_cfg_fd < 0){
187                 mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
188                 if (mem_cfg_fd < 0)
189                         rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
190         }
191
192         retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
193         if (retval < 0){
194                 close(mem_cfg_fd);
195                 rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname);
196         }
197
198         retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock);
199         if (retval < 0){
200                 close(mem_cfg_fd);
201                 rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary "
202                                 "process running?\n", pathname);
203         }
204
205         rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
206                            PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
207
208         if (rte_mem_cfg_addr == MAP_FAILED){
209                 rte_panic("Cannot mmap memory for rte_config\n");
210         }
211         rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
212         memcpy(rte_config.mem_config, &early_mem_config,
213                         sizeof(early_mem_config));
214 }
215
216 /* attach to an existing shared memory config */
217 static void
218 rte_eal_config_attach(void)
219 {
220         void *rte_mem_cfg_addr;
221         const char *pathname = eal_runtime_config_path();
222
223         if (internal_config.no_shconf)
224                 return;
225
226         if (mem_cfg_fd < 0){
227                 mem_cfg_fd = open(pathname, O_RDONLY);
228                 if (mem_cfg_fd < 0)
229                         rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
230         }
231
232         rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), PROT_READ,
233                         MAP_SHARED, mem_cfg_fd, 0);
234         close(mem_cfg_fd);
235         if (rte_mem_cfg_addr == MAP_FAILED)
236                 rte_panic("Cannot mmap memory for rte_config\n");
237
238         rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
239 }
240
241 /* Detect if we are a primary or a secondary process */
242 static enum rte_proc_type_t
243 eal_proc_type_detect(void)
244 {
245         enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
246         const char *pathname = eal_runtime_config_path();
247
248         /* if we can open the file but not get a write-lock we are a secondary
249          * process. NOTE: if we get a file handle back, we keep that open
250          * and don't close it to prevent a race condition between multiple opens */
251         if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) &&
252                         (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0))
253                 ptype = RTE_PROC_SECONDARY;
254
255         RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n",
256                         ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
257
258         return ptype;
259 }
260
261 /* Sets up rte_config structure with the pointer to shared memory config.*/
262 static void
263 rte_config_init(void)
264 {
265         /* set the magic in configuration structure */
266         rte_config.magic = RTE_MAGIC;
267         rte_config.process_type = (internal_config.process_type == RTE_PROC_AUTO) ?
268                         eal_proc_type_detect() : /* for auto, detect the type */
269                         internal_config.process_type; /* otherwise use what's already set */
270
271         switch (rte_config.process_type){
272         case RTE_PROC_PRIMARY:
273                 rte_eal_config_create();
274                 break;
275         case RTE_PROC_SECONDARY:
276                 rte_eal_config_attach();
277                 break;
278         case RTE_PROC_AUTO:
279         case RTE_PROC_INVALID:
280                 rte_panic("Invalid process type\n");
281         }
282 }
283
284 /* display usage */
285 static void
286 eal_usage(const char *prgname)
287 {
288         printf("\nUsage: %s -c COREMASK -n NUM [-m NB] [-r NUM] [-b <domain:bus:devid.func>]"
289                "[--proc-type primary|secondary|auto] \n\n"
290                "EAL options:\n"
291                "  -c COREMASK  : A hexadecimal bitmask of cores to run on\n"
292                "  -n NUM       : Number of memory channels\n"
293                    "  -v           : Display version information on startup\n"
294                "  -b <domain:bus:devid.func>: to prevent EAL from using specified "
295            "PCI device\n"
296                "                 (multiple -b options are allowed)\n"
297                "  -m MB        : memory to allocate (see also --"OPT_SOCKET_MEM")\n"
298                "  -r NUM       : force number of memory ranks (don't detect)\n"
299                "  --"OPT_SOCKET_MEM" : memory to allocate on specific \n"
300                    "                 sockets (use comma separated values)\n"
301                "  --"OPT_HUGE_DIR"   : directory where hugetlbfs is mounted\n"
302                "  --"OPT_PROC_TYPE"  : type of this process\n"
303                "  --"OPT_FILE_PREFIX": prefix for hugepage filenames\n"
304                "\nEAL options for DEBUG use only:\n"
305                "  --"OPT_NO_HUGE"  : use malloc instead of hugetlbfs\n"
306                "  --"OPT_NO_PCI"   : disable pci\n"
307                "  --"OPT_NO_HPET"  : disable hpet\n"
308                "  --"OPT_NO_SHCONF": no shared config (mmap'd files)\n\n",
309                prgname);
310 }
311
312 /*
313  * Parse the coremask given as argument (hexadecimal string) and fill
314  * the global configuration (core role and core count) with the parsed
315  * value.
316  */
317 static int
318 eal_parse_coremask(const char *coremask)
319 {
320         struct rte_config *cfg = rte_eal_get_configuration();
321         unsigned i;
322         char *end = NULL;
323         unsigned long long cm;
324         unsigned count = 0;
325
326         /* parse hexadecimal string */
327         cm = strtoull(coremask, &end, 16);
328         if ((coremask[0] == '\0') || (end == NULL) || (*end != '\0') || (cm == 0))
329                 return -1;
330
331         RTE_LOG(DEBUG, EAL, "coremask set to %llx\n", cm);
332         /* set core role and core count */
333         for (i = 0; i < RTE_MAX_LCORE; i++) {
334                 if ((1ULL << i) & cm) {
335                         if (count == 0)
336                                 cfg->master_lcore = i;
337                         cfg->lcore_role[i] = ROLE_RTE;
338                         count++;
339                 }
340                 else {
341                         cfg->lcore_role[i] = ROLE_OFF;
342                 }
343         }
344         return 0;
345 }
346
347 static int
348 eal_parse_socket_mem(char *socket_mem)
349 {
350         char * arg[RTE_MAX_NUMA_NODES];
351         char *end;
352         int arg_num, i, len;
353         uint64_t total_mem = 0;
354
355         len = strnlen(socket_mem, SOCKET_MEM_STRLEN);
356         if (len == SOCKET_MEM_STRLEN) {
357                 RTE_LOG(ERR, EAL, "--socket-mem is too long\n");
358                 return -1;
359         }
360
361         /* all other error cases will be caught later */
362         if (!isdigit(socket_mem[len-1]))
363                 return -1;
364
365         /* split the optarg into separate socket values */
366         arg_num = rte_strsplit(socket_mem, len,
367                         arg, RTE_MAX_NUMA_NODES, ',');
368
369         /* if split failed, or 0 arguments */
370         if (arg_num <= 0)
371                 return -1;
372
373         internal_config.force_sockets = 1;
374
375         /* parse each defined socket option */
376         errno = 0;
377         for (i = 0; i < arg_num; i++) {
378                 end = NULL;
379                 internal_config.socket_mem[i] = strtoull(arg[i], &end, 10);
380
381                 /* check for invalid input */
382                 if ((errno != 0)  ||
383                                 (arg[i][0] == '\0') || (end == NULL) || (*end != '\0'))
384                         return -1;
385                 internal_config.socket_mem[i] *= 1024ULL;
386                 internal_config.socket_mem[i] *= 1024ULL;
387                 total_mem += internal_config.socket_mem[i];
388         }
389
390         /* check if we have a positive amount of total memory */
391         if (total_mem == 0)
392                 return -1;
393
394         return 0;
395 }
396
397 static inline uint64_t
398 eal_get_hugepage_mem_size(void)
399 {
400         uint64_t size = 0;
401         unsigned i, j;
402
403         for (i = 0; i < internal_config.num_hugepage_sizes; i++) {
404                 struct hugepage_info *hpi = &internal_config.hugepage_info[i];
405                 if (hpi->hugedir != NULL) {
406                         for (j = 0; j < RTE_MAX_NUMA_NODES; j++) {
407                                 size += hpi->hugepage_sz * hpi->num_pages[j];
408                         }
409                 }
410         }
411
412         return (size);
413 }
414
415 static enum rte_proc_type_t
416 eal_parse_proc_type(const char *arg)
417 {
418         if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
419                 return RTE_PROC_PRIMARY;
420         if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
421                 return RTE_PROC_SECONDARY;
422         if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
423                 return RTE_PROC_AUTO;
424
425         return RTE_PROC_INVALID;
426 }
427
428 static int
429 eal_parse_blacklist(const char *input,  struct rte_pci_addr *dev2bl)
430 {
431         GET_BLACKLIST_FIELD(input, dev2bl->domain, UINT16_MAX, ':');
432         GET_BLACKLIST_FIELD(input, dev2bl->bus, UINT8_MAX, ':');
433         GET_BLACKLIST_FIELD(input, dev2bl->devid, UINT8_MAX, '.');
434         GET_BLACKLIST_FIELD(input, dev2bl->function, UINT8_MAX, 0);
435         return (0);
436 }
437
438 static ssize_t
439 eal_parse_blacklist_opt(const char *optarg, size_t idx)
440 {
441         if (idx >= sizeof (eal_dev_blacklist) / sizeof (eal_dev_blacklist[0])) {
442                 RTE_LOG(ERR, EAL,
443                     "%s - too many devices to blacklist...\n",
444                     optarg);
445                 return (-EINVAL);
446         } else if (eal_parse_blacklist(optarg, eal_dev_blacklist + idx) != 0) {
447                 RTE_LOG(ERR, EAL,
448                     "%s - invalid device to blacklist...\n",
449                     optarg);
450                 return (-EINVAL);
451         }
452
453         idx += 1;
454         return (idx);
455 }
456
457
458 /* Parse the argument given in the command line of the application */
459 static int
460 eal_parse_args(int argc, char **argv)
461 {
462         int opt, ret, i;
463         char **argvopt;
464         int option_index;
465         int coremask_ok = 0;
466         ssize_t blacklist_index = 0;;
467         char *prgname = argv[0];
468         static struct option lgopts[] = {
469                 {OPT_NO_HUGE, 0, 0, 0},
470                 {OPT_NO_PCI, 0, 0, 0},
471                 {OPT_NO_HPET, 0, 0, 0},
472                 {OPT_HUGE_DIR, 1, 0, 0},
473                 {OPT_NO_SHCONF, 0, 0, 0},
474                 {OPT_PROC_TYPE, 1, 0, 0},
475                 {OPT_FILE_PREFIX, 1, 0, 0},
476                 {OPT_SOCKET_MEM, 1, 0, 0},
477                 {0, 0, 0, 0}
478         };
479
480         argvopt = argv;
481
482         internal_config.memory = 0;
483         internal_config.force_nrank = 0;
484         internal_config.force_nchannel = 0;
485         internal_config.hugefile_prefix = HUGEFILE_PREFIX_DEFAULT;
486         internal_config.hugepage_dir = NULL;
487         internal_config.force_sockets = 0;
488 #ifdef RTE_LIBEAL_USE_HPET
489         internal_config.no_hpet = 0;
490 #else
491         internal_config.no_hpet = 1;
492 #endif
493         /* zero out the NUMA config */
494         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
495                 internal_config.socket_mem[i] = 0;
496
497         while ((opt = getopt_long(argc, argvopt, "b:c:m:n:r:v",
498                                   lgopts, &option_index)) != EOF) {
499
500                 switch (opt) {
501                 /* blacklist */
502                 case 'b':
503                         if ((blacklist_index = eal_parse_blacklist_opt(optarg,
504                             blacklist_index)) < 0) {
505                                 eal_usage(prgname);
506                                 return (-1);
507                         }
508                         break;
509                 /* coremask */
510                 case 'c':
511                         if (eal_parse_coremask(optarg) < 0) {
512                                 RTE_LOG(ERR, EAL, "invalid coremask\n");
513                                 eal_usage(prgname);
514                                 return -1;
515                         }
516                         coremask_ok = 1;
517                         break;
518                 /* size of memory */
519                 case 'm':
520                         internal_config.memory = atoi(optarg);
521                         internal_config.memory *= 1024ULL;
522                         internal_config.memory *= 1024ULL;
523                         break;
524                 /* force number of channels */
525                 case 'n':
526                         internal_config.force_nchannel = atoi(optarg);
527                         if (internal_config.force_nchannel == 0 ||
528                             internal_config.force_nchannel > 4) {
529                                 RTE_LOG(ERR, EAL, "invalid channel number\n");
530                                 eal_usage(prgname);
531                                 return -1;
532                         }
533                         break;
534                 /* force number of ranks */
535                 case 'r':
536                         internal_config.force_nrank = atoi(optarg);
537                         if (internal_config.force_nrank == 0 ||
538                             internal_config.force_nrank > 16) {
539                                 RTE_LOG(ERR, EAL, "invalid rank number\n");
540                                 eal_usage(prgname);
541                                 return -1;
542                         }
543                         break;
544                 case 'v':
545                         /* since message is explicitly requested by user, we
546                          * write message at highest log level so it can always be seen
547                          * even if info or warning messages are disabled */
548                         RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
549                         break;
550
551                 /* long options */
552                 case 0:
553                         if (!strcmp(lgopts[option_index].name, OPT_NO_HUGE)) {
554                                 internal_config.no_hugetlbfs = 1;
555                         }
556                         else if (!strcmp(lgopts[option_index].name, OPT_NO_PCI)) {
557                                 internal_config.no_pci = 1;
558                         }
559                         else if (!strcmp(lgopts[option_index].name, OPT_NO_HPET)) {
560                                 internal_config.no_hpet = 1;
561                         }
562                         else if (!strcmp(lgopts[option_index].name, OPT_NO_SHCONF)) {
563                                 internal_config.no_shconf = 1;
564                         }
565                         else if (!strcmp(lgopts[option_index].name, OPT_HUGE_DIR)) {
566                                 internal_config.hugepage_dir = optarg;
567                         }
568                         else if (!strcmp(lgopts[option_index].name, OPT_PROC_TYPE)) {
569                                 internal_config.process_type = eal_parse_proc_type(optarg);
570                         }
571                         else if (!strcmp(lgopts[option_index].name, OPT_FILE_PREFIX)) {
572                                 internal_config.hugefile_prefix = optarg;
573                         }
574                         else if (!strcmp(lgopts[option_index].name, OPT_SOCKET_MEM)) {
575                                 if (eal_parse_socket_mem(optarg) < 0) {
576                                         RTE_LOG(ERR, EAL, "invalid parameters for --"
577                                                         OPT_SOCKET_MEM "\n");
578                                         eal_usage(prgname);
579                                         return -1;
580                                 }
581                         }
582                         break;
583
584                 default:
585                         eal_usage(prgname);
586                         return -1;
587                 }
588         }
589
590         /* sanity checks */
591         if (!coremask_ok) {
592                 RTE_LOG(ERR, EAL, "coremask not specified\n");
593                 eal_usage(prgname);
594                 return -1;
595         }
596         if (internal_config.process_type == RTE_PROC_AUTO){
597                 internal_config.process_type = eal_proc_type_detect();
598         }
599         if (internal_config.process_type == RTE_PROC_INVALID){
600                 RTE_LOG(ERR, EAL, "Invalid process type specified\n");
601                 eal_usage(prgname);
602                 return -1;
603         }
604         if (internal_config.process_type == RTE_PROC_PRIMARY &&
605                         internal_config.force_nchannel == 0) {
606                 RTE_LOG(ERR, EAL, "Number of memory channels (-n) not specified\n");
607                 eal_usage(prgname);
608                 return -1;
609         }
610         if (index(internal_config.hugefile_prefix,'%') != NULL){
611                 RTE_LOG(ERR, EAL, "Invalid char, '%%', in '"OPT_FILE_PREFIX"' option\n");
612                 eal_usage(prgname);
613                 return -1;
614         }
615         if (internal_config.memory > 0 && internal_config.force_sockets == 1) {
616                 RTE_LOG(ERR, EAL, "Options -m and --socket-mem cannot be specified "
617                                 "at the same time\n");
618                 eal_usage(prgname);
619                 return -1;
620         }
621         /* --no-huge doesn't make sense with either -m or --socket-mem */
622         if (internal_config.no_hugetlbfs &&
623                         (internal_config.memory > 0 ||
624                                         internal_config.force_sockets == 1)) {
625                 RTE_LOG(ERR, EAL, "Options -m or --socket-mem cannot be specified "
626                                 "together with --no-huge!\n");
627                 eal_usage(prgname);
628                 return -1;
629         }
630
631         if (blacklist_index > 0)
632                 rte_eal_pci_set_blacklist(eal_dev_blacklist, blacklist_index);
633
634         if (optind >= 0)
635                 argv[optind-1] = prgname;
636
637         /* if no memory amounts were requested, this will result in 0 and
638          * will be overriden later, right after eal_hugepage_info_init() */
639         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
640                 internal_config.memory += internal_config.socket_mem[i];
641
642         ret = optind-1;
643         optind = 0; /* reset getopt lib */
644         return ret;
645 }
646
647 static void
648 eal_check_mem_on_local_socket(void)
649 {
650         const struct rte_memseg *ms;
651         int i, socket_id;
652
653         socket_id = rte_lcore_to_socket_id(rte_config.master_lcore);
654
655         ms = rte_eal_get_physmem_layout();
656
657         for (i = 0; i < RTE_MAX_MEMSEG; i++)
658                 if (ms[i].socket_id == socket_id &&
659                                 ms[i].len > 0)
660                         return;
661
662         RTE_LOG(WARNING, EAL, "WARNING: Master core has no "
663                         "memory on local socket!\n");
664 }
665
666 /* Launch threads, called at application init(). */
667 int
668 rte_eal_init(int argc, char **argv)
669 {
670         int i, fctret, ret;
671         pthread_t thread_id;
672
673         thread_id = pthread_self();
674
675         if (rte_eal_log_early_init() < 0)
676                 rte_panic("Cannot init early logs\n");
677
678         fctret = eal_parse_args(argc, argv);
679         if (fctret < 0)
680                 exit(1);
681
682         if (eal_hugepage_info_init() < 0)
683                 rte_panic("Cannot get hugepage information\n");
684
685         if (internal_config.memory == 0 && internal_config.force_sockets == 0) {
686                 if (internal_config.no_hugetlbfs)
687                         internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
688                 else
689                         internal_config.memory = eal_get_hugepage_mem_size();
690         }
691
692         rte_srand(rte_rdtsc());
693         rte_config_init();
694
695         if (rte_eal_cpu_init() < 0)
696                 rte_panic("Cannot detect lcores\n");
697
698         if (rte_eal_memory_init() < 0)
699                 rte_panic("Cannot init memory\n");
700
701         if (rte_eal_memzone_init() < 0)
702                 rte_panic("Cannot init memzone\n");
703
704         if (rte_eal_tailqs_init() < 0)
705                 rte_panic("Cannot init tail queues for objects\n");
706
707         if (rte_eal_log_init() < 0)
708                 rte_panic("Cannot init logs\n");
709
710         if (rte_eal_alarm_init() < 0)
711                 rte_panic("Cannot init interrupt-handling thread\n");
712
713         if (rte_eal_intr_init() < 0)
714                 rte_panic("Cannot init interrupt-handling thread\n");
715
716         if (rte_eal_hpet_init() < 0)
717                 rte_panic("Cannot init HPET\n");
718
719         if (rte_eal_pci_init() < 0)
720                 rte_panic("Cannot init PCI\n");
721
722         RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
723                 rte_config.master_lcore, (int)thread_id);
724
725         eal_check_mem_on_local_socket();
726
727         RTE_LCORE_FOREACH_SLAVE(i) {
728
729                 /*
730                  * create communication pipes between master thread
731                  * and children
732                  */
733                 if (pipe(lcore_config[i].pipe_master2slave) < 0)
734                         rte_panic("Cannot create pipe\n");
735                 if (pipe(lcore_config[i].pipe_slave2master) < 0)
736                         rte_panic("Cannot create pipe\n");
737
738                 lcore_config[i].state = WAIT;
739
740                 /* create a thread for each lcore */
741                 ret = pthread_create(&lcore_config[i].thread_id, NULL,
742                                      eal_thread_loop, NULL);
743                 if (ret != 0)
744                         rte_panic("Cannot create thread\n");
745         }
746
747         eal_thread_init_master(rte_config.master_lcore);
748
749         return fctret;
750 }
751
752 /* get core role */
753 enum rte_lcore_role_t
754 rte_eal_lcore_role(unsigned lcore_id)
755 {
756         return (rte_config.lcore_role[lcore_id]);
757 }
758
759 enum rte_proc_type_t
760 rte_eal_process_type(void)
761 {
762         return (rte_config.process_type);
763 }
764