eal: fix memory config allocation for multi-process
authorAnatoly Burakov <anatoly.burakov@intel.com>
Thu, 24 Oct 2019 12:36:50 +0000 (13:36 +0100)
committerDavid Marchand <david.marchand@redhat.com>
Sat, 26 Oct 2019 16:03:26 +0000 (18:03 +0200)
Currently, mem config will be mapped without using the virtual
area reservation infrastructure, which means it will be mapped
at an arbitrary location. This may cause failures to map the
shared config in secondary process due to things like PCI
whitelist arguments allocating memory in a space where the
primary has allocated the shared mem config.

Fix this by using virtual area reservation to reserve space for
the mem config, thereby avoiding the problem and reserving the
shared config (hopefully) far away from any normal memory
allocations.

Cc: stable@dpdk.org
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
lib/librte_eal/freebsd/eal/eal.c
lib/librte_eal/linux/eal/eal.c

index 14e1713..7c23d47 100644 (file)
@@ -218,7 +218,10 @@ eal_parse_sysfs_value(const char *filename, unsigned long *val)
 static int
 rte_eal_config_create(void)
 {
-       void *rte_mem_cfg_addr;
+       size_t page_sz = sysconf(_SC_PAGE_SIZE);
+       size_t cfg_len = sizeof(*rte_config.mem_config);
+       size_t cfg_len_aligned = RTE_ALIGN(cfg_len, page_sz);
+       void *rte_mem_cfg_addr, *mapped_mem_cfg_addr;
        int retval;
 
        const char *pathname = eal_runtime_config_path();
@@ -230,7 +233,7 @@ rte_eal_config_create(void)
        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));
+                       sizeof(struct rte_mem_config), page_sz);
        else
                rte_mem_cfg_addr = NULL;
 
@@ -243,7 +246,7 @@ rte_eal_config_create(void)
                }
        }
 
-       retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
+       retval = ftruncate(mem_cfg_fd, cfg_len);
        if (retval < 0){
                close(mem_cfg_fd);
                mem_cfg_fd = -1;
@@ -261,16 +264,28 @@ rte_eal_config_create(void)
                return -1;
        }
 
-       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){
+       /* reserve space for config */
+       rte_mem_cfg_addr = eal_get_virtual_area(rte_mem_cfg_addr,
+                       &cfg_len_aligned, page_sz, 0, 0);
+       if (rte_mem_cfg_addr == NULL) {
                RTE_LOG(ERR, EAL, "Cannot mmap memory for rte_config\n");
                close(mem_cfg_fd);
                mem_cfg_fd = -1;
                return -1;
        }
+
+       /* remap the actual file into the space we've just reserved */
+       mapped_mem_cfg_addr = mmap(rte_mem_cfg_addr,
+                       cfg_len_aligned, PROT_READ | PROT_WRITE,
+                       MAP_SHARED | MAP_FIXED, mem_cfg_fd, 0);
+       if (mapped_mem_cfg_addr == MAP_FAILED) {
+               RTE_LOG(ERR, EAL, "Cannot remap memory for rte_config\n");
+               munmap(rte_mem_cfg_addr, cfg_len);
+               close(mem_cfg_fd);
+               mem_cfg_fd = -1;
+               return -1;
+       }
+
        memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
        rte_config.mem_config = rte_mem_cfg_addr;
 
index aae67b2..d0adf7c 100644 (file)
@@ -306,7 +306,10 @@ eal_parse_sysfs_value(const char *filename, unsigned long *val)
 static int
 rte_eal_config_create(void)
 {
-       void *rte_mem_cfg_addr;
+       size_t page_sz = sysconf(_SC_PAGE_SIZE);
+       size_t cfg_len = sizeof(*rte_config.mem_config);
+       size_t cfg_len_aligned = RTE_ALIGN(cfg_len, page_sz);
+       void *rte_mem_cfg_addr, *mapped_mem_cfg_addr;
        int retval;
 
        const char *pathname = eal_runtime_config_path();
@@ -318,7 +321,7 @@ rte_eal_config_create(void)
        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));
+                       sizeof(struct rte_mem_config), page_sz);
        else
                rte_mem_cfg_addr = NULL;
 
@@ -331,7 +334,7 @@ rte_eal_config_create(void)
                }
        }
 
-       retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
+       retval = ftruncate(mem_cfg_fd, cfg_len);
        if (retval < 0){
                close(mem_cfg_fd);
                mem_cfg_fd = -1;
@@ -349,13 +352,25 @@ rte_eal_config_create(void)
                return -1;
        }
 
-       rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config),
-                               PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
+       /* reserve space for config */
+       rte_mem_cfg_addr = eal_get_virtual_area(rte_mem_cfg_addr,
+                       &cfg_len_aligned, page_sz, 0, 0);
+       if (rte_mem_cfg_addr == NULL) {
+               RTE_LOG(ERR, EAL, "Cannot mmap memory for rte_config\n");
+               close(mem_cfg_fd);
+               mem_cfg_fd = -1;
+               return -1;
+       }
 
-       if (rte_mem_cfg_addr == MAP_FAILED){
+       /* remap the actual file into the space we've just reserved */
+       mapped_mem_cfg_addr = mmap(rte_mem_cfg_addr,
+                       cfg_len_aligned, PROT_READ | PROT_WRITE,
+                       MAP_SHARED | MAP_FIXED, mem_cfg_fd, 0);
+       if (mapped_mem_cfg_addr == MAP_FAILED) {
+               munmap(rte_mem_cfg_addr, cfg_len);
                close(mem_cfg_fd);
                mem_cfg_fd = -1;
-               RTE_LOG(ERR, EAL, "Cannot mmap memory for rte_config\n");
+               RTE_LOG(ERR, EAL, "Cannot remap memory for rte_config\n");
                return -1;
        }