eal_memory.c revision 39157ec0
1/*-
2 *   BSD LICENSE
3 *
4 *   Copyright(c) 2010-2014 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#include <sys/mman.h>
34#include <unistd.h>
35#include <sys/types.h>
36#include <sys/sysctl.h>
37#include <inttypes.h>
38#include <fcntl.h>
39
40#include <rte_eal.h>
41#include <rte_eal_memconfig.h>
42#include <rte_log.h>
43#include <rte_string_fns.h>
44#include "eal_private.h"
45#include "eal_internal_cfg.h"
46#include "eal_filesystem.h"
47
48#define EAL_PAGE_SIZE (sysconf(_SC_PAGESIZE))
49
50/*
51 * Get physical address of any mapped virtual address in the current process.
52 */
53phys_addr_t
54rte_mem_virt2phy(const void *virtaddr)
55{
56	/* XXX not implemented. This function is only used by
57	 * rte_mempool_virt2phy() when hugepages are disabled. */
58	(void)virtaddr;
59	return RTE_BAD_PHYS_ADDR;
60}
61
62int
63rte_eal_hugepage_init(void)
64{
65	struct rte_mem_config *mcfg;
66	uint64_t total_mem = 0;
67	void *addr;
68	unsigned i, j, seg_idx = 0;
69
70	/* get pointer to global configuration */
71	mcfg = rte_eal_get_configuration()->mem_config;
72
73	/* for debug purposes, hugetlbfs can be disabled */
74	if (internal_config.no_hugetlbfs) {
75		addr = malloc(internal_config.memory);
76		mcfg->memseg[0].phys_addr = (phys_addr_t)(uintptr_t)addr;
77		mcfg->memseg[0].addr = addr;
78		mcfg->memseg[0].hugepage_sz = RTE_PGSIZE_4K;
79		mcfg->memseg[0].len = internal_config.memory;
80		mcfg->memseg[0].socket_id = 0;
81		return 0;
82	}
83
84	/* map all hugepages and sort them */
85	for (i = 0; i < internal_config.num_hugepage_sizes; i ++){
86		struct hugepage_info *hpi;
87
88		hpi = &internal_config.hugepage_info[i];
89		for (j = 0; j < hpi->num_pages[0]; j++) {
90			struct rte_memseg *seg;
91			uint64_t physaddr;
92			int error;
93			size_t sysctl_size = sizeof(physaddr);
94			char physaddr_str[64];
95
96			addr = mmap(NULL, hpi->hugepage_sz, PROT_READ|PROT_WRITE,
97				    MAP_SHARED, hpi->lock_descriptor,
98				    j * EAL_PAGE_SIZE);
99			if (addr == MAP_FAILED) {
100				RTE_LOG(ERR, EAL, "Failed to mmap buffer %u from %s\n",
101						j, hpi->hugedir);
102				return -1;
103			}
104
105			snprintf(physaddr_str, sizeof(physaddr_str), "hw.contigmem"
106					".physaddr.%d", j);
107			error = sysctlbyname(physaddr_str, &physaddr, &sysctl_size,
108					NULL, 0);
109			if (error < 0) {
110				RTE_LOG(ERR, EAL, "Failed to get physical addr for buffer %u "
111						"from %s\n", j, hpi->hugedir);
112				return -1;
113			}
114
115			seg = &mcfg->memseg[seg_idx++];
116			seg->addr = addr;
117			seg->phys_addr = physaddr;
118			seg->hugepage_sz = hpi->hugepage_sz;
119			seg->len = hpi->hugepage_sz;
120			seg->nchannel = mcfg->nchannel;
121			seg->nrank = mcfg->nrank;
122			seg->socket_id = 0;
123
124			RTE_LOG(INFO, EAL, "Mapped memory segment %u @ %p: physaddr:0x%"
125					PRIx64", len %zu\n",
126					seg_idx, addr, physaddr, hpi->hugepage_sz);
127			if (total_mem >= internal_config.memory ||
128					seg_idx >= RTE_MAX_MEMSEG)
129				break;
130		}
131	}
132	return 0;
133}
134
135int
136rte_eal_hugepage_attach(void)
137{
138	const struct hugepage_info *hpi;
139	int fd_hugepage_info, fd_hugepage = -1;
140	unsigned i = 0;
141	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
142
143	/* Obtain a file descriptor for hugepage_info */
144	fd_hugepage_info = open(eal_hugepage_info_path(), O_RDONLY);
145	if (fd_hugepage_info < 0) {
146		RTE_LOG(ERR, EAL, "Could not open %s\n", eal_hugepage_info_path());
147		return -1;
148	}
149
150	/* Map the shared hugepage_info into the process address spaces */
151	hpi = mmap(NULL, sizeof(struct hugepage_info), PROT_READ, MAP_PRIVATE,
152			fd_hugepage_info, 0);
153	if (hpi == MAP_FAILED) {
154		RTE_LOG(ERR, EAL, "Could not mmap %s\n", eal_hugepage_info_path());
155		goto error;
156	}
157
158	/* Obtain a file descriptor for contiguous memory */
159	fd_hugepage = open(hpi->hugedir, O_RDWR);
160	if (fd_hugepage < 0) {
161		RTE_LOG(ERR, EAL, "Could not open %s\n", hpi->hugedir);
162		goto error;
163	}
164
165	/* Map the contiguous memory into each memory segment */
166	for (i = 0; i < hpi->num_pages[0]; i++) {
167
168		void *addr;
169		struct rte_memseg *seg = &mcfg->memseg[i];
170
171		addr = mmap(seg->addr, hpi->hugepage_sz, PROT_READ|PROT_WRITE,
172			    MAP_SHARED|MAP_FIXED, fd_hugepage,
173			    i * EAL_PAGE_SIZE);
174		if (addr == MAP_FAILED || addr != seg->addr) {
175			RTE_LOG(ERR, EAL, "Failed to mmap buffer %u from %s\n",
176				i, hpi->hugedir);
177			goto error;
178		}
179
180	}
181
182	/* hugepage_info is no longer required */
183	munmap((void *)(uintptr_t)hpi, sizeof(struct hugepage_info));
184	close(fd_hugepage_info);
185	close(fd_hugepage);
186	return 0;
187
188error:
189	if (fd_hugepage_info >= 0)
190		close(fd_hugepage_info);
191	if (fd_hugepage >= 0)
192		close(fd_hugepage);
193	return -1;
194}
195