eal: use --base-virtaddr for mapping rte_config as well
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal.c
index faa4c93..ad43914 100644 (file)
@@ -75,6 +75,7 @@
 #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 OPT_BASE_VIRTADDR   "base-virtaddr"
 #define OPT_XEN_DOM0    "xen-dom0"
 #define OPT_CREATE_UIO_DEV "create-uio-dev"
+#define OPT_VFIO_INTR    "vfio-intr"
 
 #define RTE_EAL_BLACKLIST_SIZE 0x100
 
@@ -211,6 +213,14 @@ rte_eal_config_create(void)
        if (internal_config.no_shconf)
                return;
 
+       /* map the config before hugepage address so that we don't waste a page */
+       if (internal_config.base_virtaddr != 0)
+               rte_mem_cfg_addr = (void *)
+                       RTE_ALIGN_FLOOR(internal_config.base_virtaddr -
+                       sizeof(struct rte_mem_config), sysconf(_SC_PAGE_SIZE));
+       else
+               rte_mem_cfg_addr = NULL;
+
        if (mem_cfg_fd < 0){
                mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
                if (mem_cfg_fd < 0)
@@ -230,7 +240,7 @@ rte_eal_config_create(void)
                                "process running?\n", pathname);
        }
 
-       rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
+       rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config),
                                PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
 
        if (rte_mem_cfg_addr == MAP_FAILED){
@@ -238,13 +248,19 @@ rte_eal_config_create(void)
        }
        memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
        rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+
+       /* store address of the config in the config itself so that secondary
+        * processes could later map the config into this exact location */
+       rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
+
 }
 
 /* attach to an existing shared memory config */
 static void
 rte_eal_config_attach(void)
 {
-       void *rte_mem_cfg_addr;
+       struct rte_mem_config *mem_config;
+
        const char *pathname = eal_runtime_config_path();
 
        if (internal_config.no_shconf)
@@ -256,13 +272,40 @@ rte_eal_config_attach(void)
                        rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
        }
 
-       rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
-                               PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
+       /* map it as read-only first */
+       mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
+                       PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
+       if (mem_config == MAP_FAILED)
+               rte_panic("Cannot mmap memory for rte_config\n");
+
+       rte_config.mem_config = mem_config;
+}
+
+/* reattach the shared config at exact memory location primary process has it */
+static void
+rte_eal_config_reattach(void)
+{
+       struct rte_mem_config *mem_config;
+       void *rte_mem_cfg_addr;
+
+       if (internal_config.no_shconf)
+               return;
+
+       /* save the address primary process has mapped shared config to */
+       rte_mem_cfg_addr = (void *) (uintptr_t) rte_config.mem_config->mem_cfg_addr;
+
+       /* unmap original config */
+       munmap(rte_config.mem_config, sizeof(struct rte_mem_config));
+
+       /* remap the config at proper address */
+       mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
+                       sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
+                       mem_cfg_fd, 0);
        close(mem_cfg_fd);
-       if (rte_mem_cfg_addr == MAP_FAILED)
+       if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr)
                rte_panic("Cannot mmap memory for rte_config\n");
 
-       rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+       rte_config.mem_config = mem_config;
 }
 
 /* Detect if we are a primary or a secondary process */
@@ -300,6 +343,7 @@ rte_config_init(void)
        case RTE_PROC_SECONDARY:
                rte_eal_config_attach();
                rte_eal_mcfg_wait_complete(rte_config.mem_config);
+               rte_eal_config_reattach();
                break;
        case RTE_PROC_AUTO:
        case RTE_PROC_INVALID:
@@ -360,6 +404,8 @@ eal_usage(const char *prgname)
               "               (ex: --vdev=eth_pcap0,iface=eth2).\n"
               "  --"OPT_VMWARE_TSC_MAP": use VMware TSC map instead of native RDTSC\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"
               "\nEAL options for DEBUG use only:\n"
               "  --"OPT_NO_HUGE"  : use malloc instead of hugetlbfs\n"
@@ -559,6 +605,7 @@ eal_parse_base_virtaddr(const char *arg)
        char *end;
        uint64_t addr;
 
+       errno = 0;
        addr = strtoull(arg, &end, 16);
 
        /* check for errors */
@@ -578,6 +625,28 @@ eal_parse_base_virtaddr(const char *arg)
        return 0;
 }
 
+static int
+eal_parse_vfio_intr(const char *mode)
+{
+       unsigned i;
+       static struct {
+               const char *name;
+               enum rte_intr_mode value;
+       } map[] = {
+               { "legacy", RTE_INTR_MODE_LEGACY },
+               { "msi", RTE_INTR_MODE_MSI },
+               { "msix", RTE_INTR_MODE_MSIX },
+       };
+
+       for (i = 0; i < RTE_DIM(map); i++) {
+               if (!strcmp(mode, map[i].name)) {
+                       internal_config.vfio_intr_mode = map[i].value;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
 static inline size_t
 eal_get_hugepage_mem_size(void)
 {
@@ -632,6 +701,7 @@ eal_parse_args(int argc, char **argv)
                {OPT_PCI_BLACKLIST, 1, 0, 0},
                {OPT_VDEV, 1, 0, 0},
                {OPT_SYSLOG, 1, NULL, 0},
+               {OPT_VFIO_INTR, 1, NULL, 0},
                {OPT_BASE_VIRTADDR, 1, 0, 0},
                {OPT_XEN_DOM0, 0, 0, 0},
                {OPT_CREATE_UIO_DEV, 1, NULL, 0},
@@ -828,6 +898,14 @@ eal_parse_args(int argc, char **argv)
                                        return -1;
                                }
                        }
+                       else if (!strcmp(lgopts[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(lgopts[option_index].name, OPT_CREATE_UIO_DEV)) {
                                internal_config.create_uio_dev = 1;
                        }
@@ -1062,7 +1140,7 @@ rte_eal_init(int argc, char **argv)
        RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
                rte_config.master_lcore, (int)thread_id);
 
-       if (rte_eal_dev_init() < 0)
+       if (rte_eal_dev_init(PMD_INIT_PRE_PCI_PROBE) < 0)
                rte_panic("Cannot init pmd devices\n");
 
        RTE_LCORE_FOREACH_SLAVE(i) {
@@ -1092,6 +1170,14 @@ rte_eal_init(int argc, char **argv)
        rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
        rte_eal_mp_wait_lcore();
 
+       /* 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");
+
        return fctret;
 }