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