xref: /dpdk/lib/eal/unix/eal_unix_memory.c (revision 99a2dd955fba6e4cc23b77d590a033650ced9c45)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Dmitry Kozlyuk
3  */
4 
5 #include <string.h>
6 #include <sys/mman.h>
7 #include <unistd.h>
8 
9 #include <rte_eal_paging.h>
10 #include <rte_errno.h>
11 #include <rte_log.h>
12 
13 #include "eal_private.h"
14 
15 #ifdef RTE_EXEC_ENV_LINUX
16 #define EAL_DONTDUMP MADV_DONTDUMP
17 #define EAL_DODUMP   MADV_DODUMP
18 #elif defined RTE_EXEC_ENV_FREEBSD
19 #define EAL_DONTDUMP MADV_NOCORE
20 #define EAL_DODUMP   MADV_CORE
21 #else
22 #error "madvise doesn't support this OS"
23 #endif
24 
25 static void *
26 mem_map(void *requested_addr, size_t size, int prot, int flags,
27 	int fd, size_t offset)
28 {
29 	void *virt = mmap(requested_addr, size, prot, flags, fd, offset);
30 	if (virt == MAP_FAILED) {
31 		RTE_LOG(DEBUG, EAL,
32 			"Cannot mmap(%p, 0x%zx, 0x%x, 0x%x, %d, 0x%zx): %s\n",
33 			requested_addr, size, prot, flags, fd, offset,
34 			strerror(errno));
35 		rte_errno = errno;
36 		return NULL;
37 	}
38 	return virt;
39 }
40 
41 static int
42 mem_unmap(void *virt, size_t size)
43 {
44 	int ret = munmap(virt, size);
45 	if (ret < 0) {
46 		RTE_LOG(DEBUG, EAL, "Cannot munmap(%p, 0x%zx): %s\n",
47 			virt, size, strerror(errno));
48 		rte_errno = errno;
49 	}
50 	return ret;
51 }
52 
53 void *
54 eal_mem_reserve(void *requested_addr, size_t size, int flags)
55 {
56 	int sys_flags = MAP_PRIVATE | MAP_ANONYMOUS;
57 
58 	if (flags & EAL_RESERVE_HUGEPAGES) {
59 #ifdef MAP_HUGETLB
60 		sys_flags |= MAP_HUGETLB;
61 #else
62 		rte_errno = ENOTSUP;
63 		return NULL;
64 #endif
65 	}
66 
67 	if (flags & EAL_RESERVE_FORCE_ADDRESS)
68 		sys_flags |= MAP_FIXED;
69 
70 	return mem_map(requested_addr, size, PROT_NONE, sys_flags, -1, 0);
71 }
72 
73 void
74 eal_mem_free(void *virt, size_t size)
75 {
76 	mem_unmap(virt, size);
77 }
78 
79 int
80 eal_mem_set_dump(void *virt, size_t size, bool dump)
81 {
82 	int flags = dump ? EAL_DODUMP : EAL_DONTDUMP;
83 	int ret = madvise(virt, size, flags);
84 	if (ret) {
85 		RTE_LOG(DEBUG, EAL, "madvise(%p, %#zx, %d) failed: %s\n",
86 				virt, size, flags, strerror(rte_errno));
87 		rte_errno = errno;
88 	}
89 	return ret;
90 }
91 
92 static int
93 mem_rte_to_sys_prot(int prot)
94 {
95 	int sys_prot = PROT_NONE;
96 
97 	if (prot & RTE_PROT_READ)
98 		sys_prot |= PROT_READ;
99 	if (prot & RTE_PROT_WRITE)
100 		sys_prot |= PROT_WRITE;
101 	if (prot & RTE_PROT_EXECUTE)
102 		sys_prot |= PROT_EXEC;
103 
104 	return sys_prot;
105 }
106 
107 void *
108 rte_mem_map(void *requested_addr, size_t size, int prot, int flags,
109 	int fd, size_t offset)
110 {
111 	int sys_flags = 0;
112 	int sys_prot;
113 
114 	sys_prot = mem_rte_to_sys_prot(prot);
115 
116 	if (flags & RTE_MAP_SHARED)
117 		sys_flags |= MAP_SHARED;
118 	if (flags & RTE_MAP_ANONYMOUS)
119 		sys_flags |= MAP_ANONYMOUS;
120 	if (flags & RTE_MAP_PRIVATE)
121 		sys_flags |= MAP_PRIVATE;
122 	if (flags & RTE_MAP_FORCE_ADDRESS)
123 		sys_flags |= MAP_FIXED;
124 
125 	return mem_map(requested_addr, size, sys_prot, sys_flags, fd, offset);
126 }
127 
128 int
129 rte_mem_unmap(void *virt, size_t size)
130 {
131 	return mem_unmap(virt, size);
132 }
133 
134 size_t
135 rte_mem_page_size(void)
136 {
137 	static size_t page_size;
138 
139 	if (!page_size)
140 		page_size = sysconf(_SC_PAGESIZE);
141 
142 	return page_size;
143 }
144 
145 int
146 rte_mem_lock(const void *virt, size_t size)
147 {
148 	int ret = mlock(virt, size);
149 	if (ret)
150 		rte_errno = errno;
151 	return ret;
152 }
153