Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2010-2014 Intel Corporation 3 : : */ 4 : : 5 : : #include <stdio.h> 6 : : #include <stdint.h> 7 : : 8 : : #include <rte_eal.h> 9 : : #include <rte_errno.h> 10 : : #include <rte_memory.h> 11 : : #include <rte_malloc.h> 12 : : #include <rte_common.h> 13 : : #include <rte_memzone.h> 14 : : 15 : : #include "test.h" 16 : : 17 : : /* 18 : : * Memory 19 : : * ====== 20 : : * 21 : : * - Dump the mapped memory. The python-expect script checks that at 22 : : * least one line is dumped. 23 : : * 24 : : * - Check that memory size is different than 0. 25 : : * 26 : : * - Try to read all memory; it should not segfault. 27 : : */ 28 : : 29 : : /* 30 : : * ASan complains about accessing unallocated memory. 31 : : * See: https://bugs.dpdk.org/show_bug.cgi?id=880 32 : : */ 33 : : __rte_no_asan 34 : : static int 35 : 1 : check_mem(const struct rte_memseg_list *msl __rte_unused, 36 : : const struct rte_memseg *ms, void *arg __rte_unused) 37 : : { 38 : 1 : volatile uint8_t *mem = (volatile uint8_t *) ms->addr; 39 : 1 : size_t i, max = ms->len; 40 : : 41 [ + + ]: 2097153 : for (i = 0; i < max; i++, mem++) 42 : 2097152 : *mem; 43 : 1 : return 0; 44 : : } 45 : : 46 : : static int 47 : 1 : check_seg_fds(const struct rte_memseg_list *msl, const struct rte_memseg *ms, 48 : : void *arg __rte_unused) 49 : : { 50 : : size_t offset; 51 : : int ret; 52 : : 53 : : /* skip external segments */ 54 [ + - ]: 1 : if (msl->external) 55 : : return 0; 56 : : 57 : : /* try segment fd first. we're in a callback, so thread-unsafe */ 58 : 1 : ret = rte_memseg_get_fd_thread_unsafe(ms); 59 [ - + ]: 1 : if (ret < 0) { 60 : : /* ENOTSUP means segment is valid, but there is not support for 61 : : * segment fd API (e.g. on FreeBSD). 62 : : */ 63 [ # # ]: 0 : if (rte_errno == ENOTSUP) 64 : : return 1; 65 : : /* all other errors are treated as failures */ 66 : 0 : return -1; 67 : : } 68 : : 69 : : /* we're able to get memseg fd - try getting its offset */ 70 : 1 : ret = rte_memseg_get_fd_offset_thread_unsafe(ms, &offset); 71 [ - + ]: 1 : if (ret < 0) { 72 [ # # ]: 0 : if (rte_errno == ENOTSUP) 73 : : return 1; 74 : 0 : return -1; 75 : : } 76 : : return 0; 77 : : } 78 : : 79 : : static int 80 : 1 : check_malloc_virt2iova(void) 81 : : { 82 : : const size_t alloc_sz = 128; 83 : : const size_t off = 32; 84 : : struct rte_memseg *ms; 85 : : char *p; 86 : : rte_iova_t iova, iova_off; 87 : : 88 : 1 : p = rte_malloc("memory_autotest", alloc_sz, RTE_CACHE_LINE_SIZE); 89 [ - + ]: 1 : if (p == NULL) { 90 : : printf("rte_malloc failed\n"); 91 : 0 : return -1; 92 : : } 93 : : 94 : 1 : iova = rte_mem_virt2iova(p); 95 [ - + ]: 1 : if (iova == RTE_BAD_IOVA) { 96 : : printf("rte_mem_virt2iova failed for rte_malloc pointer\n"); 97 : 0 : rte_free(p); 98 : 0 : return -1; 99 : : } 100 : : 101 : 1 : ms = rte_mem_virt2memseg(p, NULL); 102 [ - + ]: 1 : if (ms == NULL) { 103 : : printf("failed to resolve memseg for rte_malloc pointer\n"); 104 : 0 : rte_free(p); 105 : 0 : return -1; 106 : : } 107 : : 108 [ + - ]: 1 : if (rte_eal_iova_mode() == RTE_IOVA_PA) { 109 [ + - + - ]: 1 : if (ms->iova == RTE_BAD_IOVA || iova < ms->iova || 110 [ - + ]: 1 : iova >= ms->iova + ms->len) { 111 : : printf("translated iova is outside memseg range\n"); 112 : 0 : rte_free(p); 113 : 0 : return -1; 114 : : } 115 : : 116 : 1 : phys_addr_t physaddr = rte_mem_virt2phy(p); 117 [ - + ]: 1 : if (physaddr == RTE_BAD_PHYS_ADDR || physaddr != iova) { 118 : : printf("rte_mem_virt2phy failed for rte_malloc pointer\n"); 119 : 0 : rte_free(p); 120 : 0 : return -1; 121 : : } 122 [ # # ]: 0 : } else if (rte_eal_iova_mode() == RTE_IOVA_VA) { 123 [ # # ]: 0 : if (iova != (uintptr_t)p) { 124 : : printf("rte_mem_virt2iova did not return VA in VA mode\n"); 125 : 0 : rte_free(p); 126 : 0 : return -1; 127 : : } 128 : : } 129 : : 130 : 1 : iova_off = rte_mem_virt2iova(p + off); 131 [ + - - + ]: 1 : if (iova_off == RTE_BAD_IOVA || iova_off != iova + off) { 132 : : printf("translated iova for interior pointer is invalid\n"); 133 : 0 : rte_free(p); 134 : 0 : return -1; 135 : : } 136 : : 137 : 1 : rte_free(p); 138 : 1 : return 0; 139 : : } 140 : : 141 : : static int 142 : 1 : test_memory(void) 143 : : { 144 : : uint64_t s; 145 : : int ret; 146 : : 147 : : /* 148 : : * dump the mapped memory: the python-expect script checks 149 : : * that at least one line is dumped 150 : : */ 151 : : printf("Dump memory layout\n"); 152 : 1 : rte_dump_physmem_layout(stdout); 153 : : 154 : : /* check that memory size is != 0 */ 155 : 1 : s = rte_eal_get_physmem_size(); 156 [ - + ]: 1 : if (s == 0) { 157 : : printf("No memory detected\n"); 158 : 0 : return -1; 159 : : } 160 : : 161 : : /* try to read memory (should not segfault) */ 162 : 1 : rte_memseg_walk(check_mem, NULL); 163 : : 164 : : /* check segment fd support */ 165 : 1 : ret = rte_memseg_walk(check_seg_fds, NULL); 166 [ - + ]: 1 : if (ret == 1) { 167 : : printf("Segment fd API is unsupported\n"); 168 [ - + ]: 1 : } else if (ret == -1) { 169 : : printf("Error getting segment fd's\n"); 170 : 0 : return -1; 171 : : } 172 : : 173 : 1 : ret = check_malloc_virt2iova(); 174 : : if (ret < 0) 175 : : return ret; 176 : : 177 : : return 0; 178 : : } 179 : : 180 : 301 : REGISTER_FAST_TEST(memory_autotest, NOHUGE_SKIP, ASAN_OK, test_memory);