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 * 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 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 * 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 75 eal_mem_free(void *virt, size_t size) 76 { 77 mem_unmap(virt, size); 78 } 79 80 int 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 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 * 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 130 rte_mem_unmap(void *virt, size_t size) 131 { 132 return mem_unmap(virt, size); 133 } 134 135 size_t 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 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