199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson #include <sys/types.h>
599a2dd95SBruce Richardson #include <sys/sysctl.h>
699a2dd95SBruce Richardson #include <sys/mman.h>
799a2dd95SBruce Richardson #include <string.h>
899a2dd95SBruce Richardson
999a2dd95SBruce Richardson #include <rte_log.h>
1099a2dd95SBruce Richardson #include <fcntl.h>
1199a2dd95SBruce Richardson
1299a2dd95SBruce Richardson #include "eal_private.h"
1399a2dd95SBruce Richardson #include "eal_hugepages.h"
1499a2dd95SBruce Richardson #include "eal_internal_cfg.h"
1599a2dd95SBruce Richardson #include "eal_filesystem.h"
1699a2dd95SBruce Richardson
1799a2dd95SBruce Richardson #define CONTIGMEM_DEV "/dev/contigmem"
1899a2dd95SBruce Richardson
1999a2dd95SBruce Richardson /*
2099a2dd95SBruce Richardson * Uses mmap to create a shared memory area for storage of data
2199a2dd95SBruce Richardson * Used in this file to store the hugepage file map on disk
2299a2dd95SBruce Richardson */
2399a2dd95SBruce Richardson static void *
map_shared_memory(const char * filename,const size_t mem_size,int flags)2499a2dd95SBruce Richardson map_shared_memory(const char *filename, const size_t mem_size, int flags)
2599a2dd95SBruce Richardson {
2699a2dd95SBruce Richardson void *retval;
2799a2dd95SBruce Richardson int fd = open(filename, flags, 0600);
2899a2dd95SBruce Richardson if (fd < 0)
2999a2dd95SBruce Richardson return NULL;
3099a2dd95SBruce Richardson if (ftruncate(fd, mem_size) < 0) {
3199a2dd95SBruce Richardson close(fd);
3299a2dd95SBruce Richardson return NULL;
3399a2dd95SBruce Richardson }
3499a2dd95SBruce Richardson retval = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
3599a2dd95SBruce Richardson close(fd);
3666e7ac41SChengwen Feng return retval == MAP_FAILED ? NULL : retval;
3799a2dd95SBruce Richardson }
3899a2dd95SBruce Richardson
3999a2dd95SBruce Richardson static void *
open_shared_memory(const char * filename,const size_t mem_size)4099a2dd95SBruce Richardson open_shared_memory(const char *filename, const size_t mem_size)
4199a2dd95SBruce Richardson {
4299a2dd95SBruce Richardson return map_shared_memory(filename, mem_size, O_RDWR);
4399a2dd95SBruce Richardson }
4499a2dd95SBruce Richardson
4599a2dd95SBruce Richardson static void *
create_shared_memory(const char * filename,const size_t mem_size)4699a2dd95SBruce Richardson create_shared_memory(const char *filename, const size_t mem_size)
4799a2dd95SBruce Richardson {
4899a2dd95SBruce Richardson return map_shared_memory(filename, mem_size, O_RDWR | O_CREAT);
4999a2dd95SBruce Richardson }
5099a2dd95SBruce Richardson
5199a2dd95SBruce Richardson /*
5299a2dd95SBruce Richardson * No hugepage support on freebsd, but we dummy it, using contigmem driver
5399a2dd95SBruce Richardson */
5499a2dd95SBruce Richardson int
eal_hugepage_info_init(void)5599a2dd95SBruce Richardson eal_hugepage_info_init(void)
5699a2dd95SBruce Richardson {
5799a2dd95SBruce Richardson size_t sysctl_size;
5899a2dd95SBruce Richardson int num_buffers, fd, error;
5999a2dd95SBruce Richardson int64_t buffer_size;
6099a2dd95SBruce Richardson struct internal_config *internal_conf =
6199a2dd95SBruce Richardson eal_get_internal_configuration();
6299a2dd95SBruce Richardson
6399a2dd95SBruce Richardson /* re-use the linux "internal config" structure for our memory data */
6499a2dd95SBruce Richardson struct hugepage_info *hpi = &internal_conf->hugepage_info[0];
6599a2dd95SBruce Richardson struct hugepage_info *tmp_hpi;
6699a2dd95SBruce Richardson unsigned int i;
6799a2dd95SBruce Richardson
6899a2dd95SBruce Richardson internal_conf->num_hugepage_sizes = 1;
6999a2dd95SBruce Richardson
7099a2dd95SBruce Richardson sysctl_size = sizeof(num_buffers);
7199a2dd95SBruce Richardson error = sysctlbyname("hw.contigmem.num_buffers", &num_buffers,
7299a2dd95SBruce Richardson &sysctl_size, NULL, 0);
7399a2dd95SBruce Richardson
7499a2dd95SBruce Richardson if (error != 0) {
75*ae67895bSDavid Marchand EAL_LOG(ERR, "could not read sysctl hw.contigmem.num_buffers");
7699a2dd95SBruce Richardson return -1;
7799a2dd95SBruce Richardson }
7899a2dd95SBruce Richardson
7999a2dd95SBruce Richardson sysctl_size = sizeof(buffer_size);
8099a2dd95SBruce Richardson error = sysctlbyname("hw.contigmem.buffer_size", &buffer_size,
8199a2dd95SBruce Richardson &sysctl_size, NULL, 0);
8299a2dd95SBruce Richardson
8399a2dd95SBruce Richardson if (error != 0) {
84*ae67895bSDavid Marchand EAL_LOG(ERR, "could not read sysctl hw.contigmem.buffer_size");
8599a2dd95SBruce Richardson return -1;
8699a2dd95SBruce Richardson }
8799a2dd95SBruce Richardson
8899a2dd95SBruce Richardson fd = open(CONTIGMEM_DEV, O_RDWR);
8999a2dd95SBruce Richardson if (fd < 0) {
90*ae67895bSDavid Marchand EAL_LOG(ERR, "could not open "CONTIGMEM_DEV);
9199a2dd95SBruce Richardson return -1;
9299a2dd95SBruce Richardson }
9347a4f265SBruce Richardson if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
94*ae67895bSDavid Marchand EAL_LOG(ERR, "could not lock memory. Is another DPDK process running?");
9547a4f265SBruce Richardson return -1;
9647a4f265SBruce Richardson }
9799a2dd95SBruce Richardson
9899a2dd95SBruce Richardson if (buffer_size >= 1<<30)
99*ae67895bSDavid Marchand EAL_LOG(INFO, "Contigmem driver has %d buffers, each of size %dGB",
10099a2dd95SBruce Richardson num_buffers, (int)(buffer_size>>30));
10199a2dd95SBruce Richardson else if (buffer_size >= 1<<20)
102*ae67895bSDavid Marchand EAL_LOG(INFO, "Contigmem driver has %d buffers, each of size %dMB",
10399a2dd95SBruce Richardson num_buffers, (int)(buffer_size>>20));
10499a2dd95SBruce Richardson else
105*ae67895bSDavid Marchand EAL_LOG(INFO, "Contigmem driver has %d buffers, each of size %dKB",
10699a2dd95SBruce Richardson num_buffers, (int)(buffer_size>>10));
10799a2dd95SBruce Richardson
10899a2dd95SBruce Richardson strlcpy(hpi->hugedir, CONTIGMEM_DEV, sizeof(hpi->hugedir));
10999a2dd95SBruce Richardson hpi->hugepage_sz = buffer_size;
11099a2dd95SBruce Richardson hpi->num_pages[0] = num_buffers;
11199a2dd95SBruce Richardson hpi->lock_descriptor = fd;
11299a2dd95SBruce Richardson
11399a2dd95SBruce Richardson /* for no shared files mode, do not create shared memory config */
11499a2dd95SBruce Richardson if (internal_conf->no_shconf)
11599a2dd95SBruce Richardson return 0;
11699a2dd95SBruce Richardson
11799a2dd95SBruce Richardson tmp_hpi = create_shared_memory(eal_hugepage_info_path(),
11899a2dd95SBruce Richardson sizeof(internal_conf->hugepage_info));
11999a2dd95SBruce Richardson if (tmp_hpi == NULL ) {
120*ae67895bSDavid Marchand EAL_LOG(ERR, "Failed to create shared memory!");
12199a2dd95SBruce Richardson return -1;
12299a2dd95SBruce Richardson }
12399a2dd95SBruce Richardson
12499a2dd95SBruce Richardson memcpy(tmp_hpi, hpi, sizeof(internal_conf->hugepage_info));
12599a2dd95SBruce Richardson
12699a2dd95SBruce Richardson /* we've copied file descriptors along with everything else, but they
12799a2dd95SBruce Richardson * will be invalid in secondary process, so overwrite them
12899a2dd95SBruce Richardson */
12999a2dd95SBruce Richardson for (i = 0; i < RTE_DIM(internal_conf->hugepage_info); i++) {
13099a2dd95SBruce Richardson struct hugepage_info *tmp = &tmp_hpi[i];
13199a2dd95SBruce Richardson tmp->lock_descriptor = -1;
13299a2dd95SBruce Richardson }
13399a2dd95SBruce Richardson
13499a2dd95SBruce Richardson if (munmap(tmp_hpi, sizeof(internal_conf->hugepage_info)) < 0) {
135*ae67895bSDavid Marchand EAL_LOG(ERR, "Failed to unmap shared memory!");
13699a2dd95SBruce Richardson return -1;
13799a2dd95SBruce Richardson }
13899a2dd95SBruce Richardson
13999a2dd95SBruce Richardson return 0;
14099a2dd95SBruce Richardson }
14199a2dd95SBruce Richardson
14299a2dd95SBruce Richardson /* copy stuff from shared info into internal config */
14399a2dd95SBruce Richardson int
eal_hugepage_info_read(void)14499a2dd95SBruce Richardson eal_hugepage_info_read(void)
14599a2dd95SBruce Richardson {
14699a2dd95SBruce Richardson struct internal_config *internal_conf =
14799a2dd95SBruce Richardson eal_get_internal_configuration();
14899a2dd95SBruce Richardson
14999a2dd95SBruce Richardson struct hugepage_info *hpi = &internal_conf->hugepage_info[0];
15099a2dd95SBruce Richardson struct hugepage_info *tmp_hpi;
15199a2dd95SBruce Richardson
15299a2dd95SBruce Richardson internal_conf->num_hugepage_sizes = 1;
15399a2dd95SBruce Richardson
15499a2dd95SBruce Richardson tmp_hpi = open_shared_memory(eal_hugepage_info_path(),
15599a2dd95SBruce Richardson sizeof(internal_conf->hugepage_info));
15699a2dd95SBruce Richardson if (tmp_hpi == NULL) {
157*ae67895bSDavid Marchand EAL_LOG(ERR, "Failed to open shared memory!");
15899a2dd95SBruce Richardson return -1;
15999a2dd95SBruce Richardson }
16099a2dd95SBruce Richardson
16199a2dd95SBruce Richardson memcpy(hpi, tmp_hpi, sizeof(internal_conf->hugepage_info));
16299a2dd95SBruce Richardson
16399a2dd95SBruce Richardson if (munmap(tmp_hpi, sizeof(internal_conf->hugepage_info)) < 0) {
164*ae67895bSDavid Marchand EAL_LOG(ERR, "Failed to unmap shared memory!");
16599a2dd95SBruce Richardson return -1;
16699a2dd95SBruce Richardson }
16799a2dd95SBruce Richardson return 0;
16899a2dd95SBruce Richardson }
169