Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Intel Corporation
3 : : */
4 : :
5 : : #define ALLOW_INTERNAL_API
6 : :
7 : : #include "test.h"
8 : :
9 : : #include <errno.h>
10 : : #include <stdio.h>
11 : : #include <stdlib.h>
12 : : #include <string.h>
13 : : #include <fcntl.h>
14 : :
15 : : #ifndef RTE_EXEC_ENV_LINUX
16 : : static int
17 : : test_external_mem(void)
18 : : {
19 : : printf("external_mem only supported on Linux, skipping test\n");
20 : : return TEST_SKIPPED;
21 : : }
22 : :
23 : : #else
24 : :
25 : : #include <sys/mman.h>
26 : : #include <sys/wait.h>
27 : :
28 : : #include <rte_common.h>
29 : : #include <rte_debug.h>
30 : : #include <rte_eal.h>
31 : : #include <rte_eal_paging.h>
32 : : #include <rte_errno.h>
33 : : #include <rte_malloc.h>
34 : : #include <rte_ring.h>
35 : : #include <rte_string_fns.h>
36 : :
37 : : #define EXTERNAL_MEM_SZ (RTE_PGSIZE_4K << 10) /* 4M of data */
38 : :
39 : : static int
40 : 4 : check_mem(void *addr, rte_iova_t *iova, size_t pgsz, int n_pages)
41 : : {
42 : : int i;
43 : :
44 : : /* check that we can get this memory from EAL now */
45 [ + + ]: 4100 : for (i = 0; i < n_pages; i++) {
46 : : const struct rte_memseg_list *msl;
47 : : const struct rte_memseg *ms;
48 : 4096 : void *cur = RTE_PTR_ADD(addr, pgsz * i);
49 : : rte_iova_t expected_iova;
50 : :
51 : 4096 : msl = rte_mem_virt2memseg_list(cur);
52 [ - + ]: 4096 : if (!msl->external) {
53 : : printf("%s():%i: Memseg list is not marked as external\n",
54 : : __func__, __LINE__);
55 : 0 : return -1;
56 : : }
57 : :
58 : 4096 : ms = rte_mem_virt2memseg(cur, msl);
59 [ - + ]: 4096 : if (ms == NULL) {
60 : : printf("%s():%i: Failed to retrieve memseg for external mem\n",
61 : : __func__, __LINE__);
62 : 0 : return -1;
63 : : }
64 [ - + ]: 4096 : if (ms->addr != cur) {
65 : : printf("%s():%i: VA mismatch\n", __func__, __LINE__);
66 : 0 : return -1;
67 : : }
68 [ + + ]: 4096 : expected_iova = (iova == NULL) ? RTE_BAD_IOVA : iova[i];
69 [ - + ]: 4096 : if (ms->iova != expected_iova) {
70 : : printf("%s():%i: IOVA mismatch\n", __func__, __LINE__);
71 : 0 : return -1;
72 : : }
73 : : }
74 : : return 0;
75 : : }
76 : :
77 : : static int
78 : 2 : test_malloc_invalid_param(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
79 : : int n_pages)
80 : : {
81 : : static const char * const names[] = {
82 : : NULL, /* NULL name */
83 : : "", /* empty name */
84 : : "this heap name is definitely way too long to be valid"
85 : : };
86 : : const char *valid_name = "valid heap name";
87 : : unsigned int i;
88 : :
89 : : /* check invalid name handling */
90 [ + + ]: 8 : for (i = 0; i < RTE_DIM(names); i++) {
91 : 6 : const char *name = names[i];
92 : :
93 : : /* these calls may fail for other reasons, so check errno */
94 [ + - - + ]: 6 : if (rte_malloc_heap_create(name) >= 0 || rte_errno != EINVAL) {
95 : : printf("%s():%i: Created heap with invalid name\n",
96 : : __func__, __LINE__);
97 : 0 : goto fail;
98 : : }
99 : :
100 [ + - - + ]: 6 : if (rte_malloc_heap_destroy(name) >= 0 || rte_errno != EINVAL) {
101 : : printf("%s():%i: Destroyed heap with invalid name\n",
102 : : __func__, __LINE__);
103 : 0 : goto fail;
104 : : }
105 : :
106 [ + - ]: 6 : if (rte_malloc_heap_get_socket(name) >= 0 ||
107 [ - + ]: 6 : rte_errno != EINVAL) {
108 : : printf("%s():%i: Found socket for heap with invalid name\n",
109 : : __func__, __LINE__);
110 : 0 : goto fail;
111 : : }
112 : :
113 [ + - ]: 6 : if (rte_malloc_heap_memory_add(name, addr, len,
114 [ - + ]: 6 : NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
115 : : printf("%s():%i: Added memory to heap with invalid name\n",
116 : : __func__, __LINE__);
117 : 0 : goto fail;
118 : : }
119 [ + - ]: 6 : if (rte_malloc_heap_memory_remove(name, addr, len) >= 0 ||
120 [ - + ]: 6 : rte_errno != EINVAL) {
121 : : printf("%s():%i: Removed memory from heap with invalid name\n",
122 : : __func__, __LINE__);
123 : 0 : goto fail;
124 : : }
125 : :
126 [ + - ]: 6 : if (rte_malloc_heap_memory_attach(name, addr, len) >= 0 ||
127 [ - + ]: 6 : rte_errno != EINVAL) {
128 : : printf("%s():%i: Attached memory to heap with invalid name\n",
129 : : __func__, __LINE__);
130 : 0 : goto fail;
131 : : }
132 [ + - ]: 6 : if (rte_malloc_heap_memory_detach(name, addr, len) >= 0 ||
133 [ - + ]: 6 : rte_errno != EINVAL) {
134 : : printf("%s():%i: Detached memory from heap with invalid name\n",
135 : : __func__, __LINE__);
136 : 0 : goto fail;
137 : : }
138 : : }
139 : :
140 : : /* do same as above, but with a valid heap name */
141 : :
142 : : /* skip create call */
143 [ + - - + ]: 2 : if (rte_malloc_heap_destroy(valid_name) >= 0 || rte_errno != ENOENT) {
144 : : printf("%s():%i: Destroyed heap with invalid name\n",
145 : : __func__, __LINE__);
146 : 0 : goto fail;
147 : : }
148 [ + - ]: 2 : if (rte_malloc_heap_get_socket(valid_name) >= 0 ||
149 [ - + ]: 2 : rte_errno != ENOENT) {
150 : : printf("%s():%i: Found socket for heap with invalid name\n",
151 : : __func__, __LINE__);
152 : 0 : goto fail;
153 : : }
154 : :
155 : : /* these calls may fail for other reasons, so check errno */
156 [ + - ]: 2 : if (rte_malloc_heap_memory_add(valid_name, addr, len,
157 [ - + ]: 2 : NULL, 0, pgsz) >= 0 || rte_errno != ENOENT) {
158 : : printf("%s():%i: Added memory to non-existent heap\n",
159 : : __func__, __LINE__);
160 : 0 : goto fail;
161 : : }
162 [ + - ]: 2 : if (rte_malloc_heap_memory_remove(valid_name, addr, len) >= 0 ||
163 [ - + ]: 2 : rte_errno != ENOENT) {
164 : : printf("%s():%i: Removed memory from non-existent heap\n",
165 : : __func__, __LINE__);
166 : 0 : goto fail;
167 : : }
168 : :
169 [ + - ]: 2 : if (rte_malloc_heap_memory_attach(valid_name, addr, len) >= 0 ||
170 [ - + ]: 2 : rte_errno != ENOENT) {
171 : : printf("%s():%i: Attached memory to non-existent heap\n",
172 : : __func__, __LINE__);
173 : 0 : goto fail;
174 : : }
175 [ + - ]: 2 : if (rte_malloc_heap_memory_detach(valid_name, addr, len) >= 0 ||
176 [ - + ]: 2 : rte_errno != ENOENT) {
177 : : printf("%s():%i: Detached memory from non-existent heap\n",
178 : : __func__, __LINE__);
179 : 0 : goto fail;
180 : : }
181 : :
182 : : /* create a valid heap but test other invalid parameters */
183 [ - + ]: 2 : if (rte_malloc_heap_create(valid_name) != 0) {
184 : : printf("%s():%i: Failed to create valid heap\n",
185 : : __func__, __LINE__);
186 : 0 : goto fail;
187 : : }
188 : :
189 : : /* zero length */
190 [ + - ]: 2 : if (rte_malloc_heap_memory_add(valid_name, addr, 0,
191 [ - + ]: 2 : NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
192 : : printf("%s():%i: Added memory with invalid parameters\n",
193 : : __func__, __LINE__);
194 : 0 : goto fail;
195 : : }
196 : :
197 [ + - ]: 2 : if (rte_malloc_heap_memory_remove(valid_name, addr, 0) >= 0 ||
198 [ - + ]: 2 : rte_errno != EINVAL) {
199 : : printf("%s():%i: Removed memory with invalid parameters\n",
200 : : __func__, __LINE__);
201 : 0 : goto fail;
202 : : }
203 : :
204 [ + - ]: 2 : if (rte_malloc_heap_memory_attach(valid_name, addr, 0) >= 0 ||
205 [ - + ]: 2 : rte_errno != EINVAL) {
206 : : printf("%s():%i: Attached memory with invalid parameters\n",
207 : : __func__, __LINE__);
208 : 0 : goto fail;
209 : : }
210 [ + - ]: 2 : if (rte_malloc_heap_memory_detach(valid_name, addr, 0) >= 0 ||
211 [ - + ]: 2 : rte_errno != EINVAL) {
212 : : printf("%s():%i: Detached memory with invalid parameters\n",
213 : : __func__, __LINE__);
214 : 0 : goto fail;
215 : : }
216 : :
217 : : /* zero address */
218 [ + - ]: 2 : if (rte_malloc_heap_memory_add(valid_name, NULL, len,
219 [ - + ]: 2 : NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
220 : : printf("%s():%i: Added memory with invalid parameters\n",
221 : : __func__, __LINE__);
222 : 0 : goto fail;
223 : : }
224 : :
225 [ + - ]: 2 : if (rte_malloc_heap_memory_remove(valid_name, NULL, len) >= 0 ||
226 [ - + ]: 2 : rte_errno != EINVAL) {
227 : : printf("%s():%i: Removed memory with invalid parameters\n",
228 : : __func__, __LINE__);
229 : 0 : goto fail;
230 : : }
231 : :
232 [ + - ]: 2 : if (rte_malloc_heap_memory_attach(valid_name, NULL, len) >= 0 ||
233 [ - + ]: 2 : rte_errno != EINVAL) {
234 : : printf("%s():%i: Attached memory with invalid parameters\n",
235 : : __func__, __LINE__);
236 : 0 : goto fail;
237 : : }
238 [ + - ]: 2 : if (rte_malloc_heap_memory_detach(valid_name, NULL, len) >= 0 ||
239 [ - + ]: 2 : rte_errno != EINVAL) {
240 : : printf("%s():%i: Detached memory with invalid parameters\n",
241 : : __func__, __LINE__);
242 : 0 : goto fail;
243 : : }
244 : :
245 : : /* the following tests are only valid if IOVA table is not NULL */
246 [ + + ]: 2 : if (iova != NULL) {
247 : : /* wrong page count */
248 [ + - ]: 1 : if (rte_malloc_heap_memory_add(valid_name, addr, len,
249 [ - + ]: 1 : iova, 0, pgsz) >= 0 || rte_errno != EINVAL) {
250 : : printf("%s():%i: Added memory with invalid parameters\n",
251 : : __func__, __LINE__);
252 : 0 : goto fail;
253 : : }
254 [ + - ]: 1 : if (rte_malloc_heap_memory_add(valid_name, addr, len,
255 : 1 : iova, n_pages - 1, pgsz) >= 0 ||
256 [ - + ]: 1 : rte_errno != EINVAL) {
257 : : printf("%s():%i: Added memory with invalid parameters\n",
258 : : __func__, __LINE__);
259 : 0 : goto fail;
260 : : }
261 [ + - ]: 1 : if (rte_malloc_heap_memory_add(valid_name, addr, len,
262 : 1 : iova, n_pages + 1, pgsz) >= 0 ||
263 [ - + ]: 1 : rte_errno != EINVAL) {
264 : : printf("%s():%i: Added memory with invalid parameters\n",
265 : : __func__, __LINE__);
266 : 0 : goto fail;
267 : : }
268 : : }
269 : :
270 : : /* tests passed, destroy heap */
271 [ - + ]: 2 : if (rte_malloc_heap_destroy(valid_name) != 0) {
272 : : printf("%s():%i: Failed to destroy valid heap\n",
273 : : __func__, __LINE__);
274 : 0 : goto fail;
275 : : }
276 : : return 0;
277 : 0 : fail:
278 : 0 : rte_malloc_heap_destroy(valid_name);
279 : 0 : return -1;
280 : : }
281 : :
282 : : static int
283 : 2 : test_malloc_basic(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
284 : : int n_pages)
285 : : {
286 : : const char *heap_name = "heap";
287 : : void *ptr = NULL;
288 : : int socket_id;
289 : : const struct rte_memzone *mz = NULL, *contig_mz = NULL;
290 : :
291 : : /* create heap */
292 [ - + ]: 2 : if (rte_malloc_heap_create(heap_name) != 0) {
293 : : printf("%s():%i: Failed to create malloc heap\n",
294 : : __func__, __LINE__);
295 : 0 : goto fail;
296 : : }
297 : :
298 : : /* get socket ID corresponding to this heap */
299 : 2 : socket_id = rte_malloc_heap_get_socket(heap_name);
300 [ - + ]: 2 : if (socket_id < 0) {
301 : : printf("%s():%i: cannot find socket for external heap\n",
302 : : __func__, __LINE__);
303 : 0 : goto fail;
304 : : }
305 : :
306 : : /* heap is empty, so any allocation should fail */
307 : 2 : ptr = rte_malloc_socket("EXTMEM", 64, 0, socket_id);
308 [ - + ]: 2 : if (ptr != NULL) {
309 : : printf("%s():%i: Allocated from empty heap\n", __func__,
310 : : __LINE__);
311 : 0 : goto fail;
312 : : }
313 : :
314 : : /* add memory to heap */
315 [ - + ]: 2 : if (rte_malloc_heap_memory_add(heap_name, addr, len,
316 : : iova, n_pages, pgsz) != 0) {
317 : : printf("%s():%i: Failed to add memory to heap\n",
318 : : __func__, __LINE__);
319 : 0 : goto fail;
320 : : }
321 : :
322 : : /* check if memory is accessible from EAL */
323 [ - + ]: 2 : if (check_mem(addr, iova, pgsz, n_pages) < 0)
324 : 0 : goto fail;
325 : :
326 : : /* allocate - this now should succeed */
327 : 2 : ptr = rte_malloc_socket("EXTMEM", 64, 0, socket_id);
328 [ - + ]: 2 : if (ptr == NULL) {
329 : : printf("%s():%i: Failed to allocate from external heap\n",
330 : : __func__, __LINE__);
331 : 0 : goto fail;
332 : : }
333 : :
334 : : /* check if address is in expected range */
335 [ + - - + ]: 2 : if (ptr < addr || ptr >= RTE_PTR_ADD(addr, len)) {
336 : : printf("%s():%i: Allocated from unexpected address space\n",
337 : : __func__, __LINE__);
338 : 0 : goto fail;
339 : : }
340 : :
341 : : /* we've allocated something - removing memory should fail */
342 [ + - ]: 2 : if (rte_malloc_heap_memory_remove(heap_name, addr, len) >= 0 ||
343 [ - + ]: 2 : rte_errno != EBUSY) {
344 : : printf("%s():%i: Removing memory succeeded when memory is not free\n",
345 : : __func__, __LINE__);
346 : 0 : goto fail;
347 : : }
348 [ + - - + ]: 2 : if (rte_malloc_heap_destroy(heap_name) >= 0 || rte_errno != EBUSY) {
349 : : printf("%s():%i: Destroying heap succeeded when memory is not free\n",
350 : : __func__, __LINE__);
351 : 0 : goto fail;
352 : : }
353 : :
354 : : /* try allocating a memzone */
355 : 2 : mz = rte_memzone_reserve("heap_test", pgsz * 2, socket_id, 0);
356 [ - + ]: 2 : if (mz == NULL) {
357 : : printf("%s():%i: Failed to reserve memzone\n",
358 : : __func__, __LINE__);
359 : 0 : goto fail;
360 : : }
361 : : /* try allocating an IOVA-contiguous memzone - this should succeed
362 : : * if we've set up a contiguous IOVA table, and fail if we haven't.
363 : : */
364 : 2 : contig_mz = rte_memzone_reserve("heap_test_contig", pgsz * 2, socket_id,
365 : : RTE_MEMZONE_IOVA_CONTIG);
366 [ - + ]: 2 : if ((iova == NULL) != (contig_mz == NULL)) {
367 : : printf("%s():%i: Failed to reserve memzone\n",
368 : : __func__, __LINE__);
369 : 0 : goto fail;
370 : : }
371 : :
372 : 2 : rte_malloc_dump_stats(stdout, NULL);
373 : 2 : rte_malloc_dump_heaps(stdout);
374 : :
375 : : /* free memory - removing it should now succeed */
376 : 2 : rte_free(ptr);
377 : : ptr = NULL;
378 : :
379 : 2 : rte_memzone_free(mz);
380 : : mz = NULL;
381 : 2 : rte_memzone_free(contig_mz);
382 : : contig_mz = NULL;
383 : :
384 [ - + ]: 2 : if (rte_malloc_heap_memory_remove(heap_name, addr, len) != 0) {
385 : : printf("%s():%i: Removing memory from heap failed\n",
386 : : __func__, __LINE__);
387 : 0 : goto fail;
388 : : }
389 [ - + ]: 2 : if (rte_malloc_heap_destroy(heap_name) != 0) {
390 : : printf("%s():%i: Destroying heap failed\n",
391 : : __func__, __LINE__);
392 : 0 : goto fail;
393 : : }
394 : :
395 : : return 0;
396 : 0 : fail:
397 : 0 : rte_memzone_free(contig_mz);
398 : 0 : rte_memzone_free(mz);
399 : 0 : rte_free(ptr);
400 : : /* even if something failed, attempt to clean up */
401 : 0 : rte_malloc_heap_memory_remove(heap_name, addr, len);
402 : 0 : rte_malloc_heap_destroy(heap_name);
403 : :
404 : 0 : return -1;
405 : : }
406 : :
407 : : static int
408 : 2 : test_extmem_invalid_param(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
409 : : int n_pages)
410 : : {
411 : : /* these calls may fail for other reasons, so check errno */
412 [ + - ]: 2 : if (rte_extmem_unregister(addr, len) >= 0 ||
413 [ - + ]: 2 : rte_errno != ENOENT) {
414 : : printf("%s():%i: Unregistered non-existent memory\n",
415 : : __func__, __LINE__);
416 : 0 : return -1;
417 : : }
418 : :
419 [ + - ]: 2 : if (rte_extmem_attach(addr, len) >= 0 ||
420 [ - + ]: 2 : rte_errno != ENOENT) {
421 : : printf("%s():%i: Attached to non-existent memory\n",
422 : : __func__, __LINE__);
423 : 0 : return -1;
424 : : }
425 [ + - ]: 2 : if (rte_extmem_attach(addr, len) >= 0 ||
426 [ - + ]: 2 : rte_errno != ENOENT) {
427 : : printf("%s():%i: Detached from non-existent memory\n",
428 : : __func__, __LINE__);
429 : 0 : return -1;
430 : : }
431 : :
432 : : /* zero length */
433 [ + - ]: 2 : if (rte_extmem_register(addr, 0, NULL, 0, pgsz) >= 0 ||
434 [ - + ]: 2 : rte_errno != EINVAL) {
435 : : printf("%s():%i: Registered memory with invalid parameters\n",
436 : : __func__, __LINE__);
437 : 0 : return -1;
438 : : }
439 : :
440 [ + - ]: 2 : if (rte_extmem_unregister(addr, 0) >= 0 ||
441 [ - + ]: 2 : rte_errno != EINVAL) {
442 : : printf("%s():%i: Unregistered memory with invalid parameters\n",
443 : : __func__, __LINE__);
444 : 0 : return -1;
445 : : }
446 : :
447 [ + - ]: 2 : if (rte_extmem_attach(addr, 0) >= 0 ||
448 [ - + ]: 2 : rte_errno != EINVAL) {
449 : : printf("%s():%i: Attached memory with invalid parameters\n",
450 : : __func__, __LINE__);
451 : 0 : return -1;
452 : : }
453 [ + - ]: 2 : if (rte_extmem_attach(addr, 0) >= 0 ||
454 [ - + ]: 2 : rte_errno != EINVAL) {
455 : : printf("%s():%i: Detached memory with invalid parameters\n",
456 : : __func__, __LINE__);
457 : 0 : return -1;
458 : : }
459 : :
460 : : /* zero address */
461 [ + - ]: 2 : if (rte_extmem_register(NULL, len, NULL, 0, pgsz) >= 0 ||
462 [ - + ]: 2 : rte_errno != EINVAL) {
463 : : printf("%s():%i: Registered memory with invalid parameters\n",
464 : : __func__, __LINE__);
465 : 0 : return -1;
466 : : }
467 : :
468 [ + - ]: 2 : if (rte_extmem_unregister(NULL, len) >= 0 ||
469 [ - + ]: 2 : rte_errno != EINVAL) {
470 : : printf("%s():%i: Unregistered memory with invalid parameters\n",
471 : : __func__, __LINE__);
472 : 0 : return -1;
473 : : }
474 : :
475 [ + - ]: 2 : if (rte_extmem_attach(NULL, len) >= 0 ||
476 [ - + ]: 2 : rte_errno != EINVAL) {
477 : : printf("%s():%i: Attached memory with invalid parameters\n",
478 : : __func__, __LINE__);
479 : 0 : return -1;
480 : : }
481 [ + - ]: 2 : if (rte_extmem_attach(NULL, len) >= 0 ||
482 [ - + ]: 2 : rte_errno != EINVAL) {
483 : : printf("%s():%i: Detached memory with invalid parameters\n",
484 : : __func__, __LINE__);
485 : 0 : return -1;
486 : : }
487 : :
488 : : /* the following tests are only valid if IOVA table is not NULL */
489 [ + + ]: 2 : if (iova != NULL) {
490 : : /* wrong page count */
491 [ + - ]: 1 : if (rte_extmem_register(addr, len,
492 [ - + ]: 1 : iova, 0, pgsz) >= 0 || rte_errno != EINVAL) {
493 : : printf("%s():%i: Registered memory with invalid parameters\n",
494 : : __func__, __LINE__);
495 : 0 : return -1;
496 : : }
497 [ + - ]: 1 : if (rte_extmem_register(addr, len,
498 : 1 : iova, n_pages - 1, pgsz) >= 0 ||
499 [ - + ]: 1 : rte_errno != EINVAL) {
500 : : printf("%s():%i: Registered memory with invalid parameters\n",
501 : : __func__, __LINE__);
502 : 0 : return -1;
503 : : }
504 [ + - ]: 1 : if (rte_extmem_register(addr, len,
505 : 1 : iova, n_pages + 1, pgsz) >= 0 ||
506 [ - + ]: 1 : rte_errno != EINVAL) {
507 : : printf("%s():%i: Registered memory with invalid parameters\n",
508 : : __func__, __LINE__);
509 : 0 : return -1;
510 : : }
511 : : }
512 : :
513 : : return 0;
514 : : }
515 : :
516 : : static int
517 : 2 : test_extmem_basic(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
518 : : int n_pages)
519 : : {
520 : : /* register memory */
521 [ - + ]: 2 : if (rte_extmem_register(addr, len, iova, n_pages, pgsz) != 0) {
522 : : printf("%s():%i: Failed to register memory\n",
523 : : __func__, __LINE__);
524 : 0 : goto fail;
525 : : }
526 : :
527 : : /* check if memory is accessible from EAL */
528 [ - + ]: 2 : if (check_mem(addr, iova, pgsz, n_pages) < 0)
529 : 0 : goto fail;
530 : :
531 [ - + ]: 2 : if (rte_extmem_unregister(addr, len) != 0) {
532 : : printf("%s():%i: Removing memory from heap failed\n",
533 : : __func__, __LINE__);
534 : 0 : goto fail;
535 : : }
536 : :
537 : : return 0;
538 : 0 : fail:
539 : : /* even if something failed, attempt to clean up */
540 : 0 : rte_extmem_unregister(addr, len);
541 : :
542 : 0 : return -1;
543 : : }
544 : :
545 : : /* we need to test attach/detach in secondary processes. */
546 : : static int
547 : 1 : test_external_mem(void)
548 : 1 : {
549 : 1 : size_t pgsz = rte_mem_page_size();
550 : : size_t len = EXTERNAL_MEM_SZ;
551 : 1 : rte_iova_t iova[len / pgsz];
552 : : void *addr;
553 : : int ret, n_pages;
554 : : int i;
555 : :
556 : : /* create external memory area */
557 : 1 : n_pages = RTE_DIM(iova);
558 : 1 : addr = mmap(NULL, len, PROT_WRITE | PROT_READ,
559 : : MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
560 [ - + ]: 1 : if (addr == MAP_FAILED) {
561 : : printf("%s():%i: Failed to create dummy memory area\n",
562 : : __func__, __LINE__);
563 : 0 : return -1;
564 : : }
565 [ + + ]: 1025 : for (i = 0; i < n_pages; i++) {
566 : : /* arbitrary IOVA */
567 : 1024 : rte_iova_t tmp = 0x100000000 + i * pgsz;
568 : 1024 : iova[i] = tmp;
569 : : }
570 : :
571 : : /* test external heap memory */
572 : 1 : ret = test_malloc_invalid_param(addr, len, pgsz, iova, n_pages);
573 : 1 : ret |= test_malloc_basic(addr, len, pgsz, iova, n_pages);
574 : : /* when iova table is NULL, everything should still work */
575 : 1 : ret |= test_malloc_invalid_param(addr, len, pgsz, NULL, n_pages);
576 : 1 : ret |= test_malloc_basic(addr, len, pgsz, NULL, n_pages);
577 : :
578 : : /* test non-heap memory */
579 : 1 : ret |= test_extmem_invalid_param(addr, len, pgsz, iova, n_pages);
580 : 1 : ret |= test_extmem_basic(addr, len, pgsz, iova, n_pages);
581 : : /* when iova table is NULL, everything should still work */
582 : 1 : ret |= test_extmem_invalid_param(addr, len, pgsz, NULL, n_pages);
583 : 1 : ret |= test_extmem_basic(addr, len, pgsz, NULL, n_pages);
584 : :
585 : 1 : munmap(addr, len);
586 : :
587 : 1 : return ret;
588 : : }
589 : :
590 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
591 : :
592 : 302 : REGISTER_FAST_TEST(external_mem_autotest, NOHUGE_SKIP, ASAN_OK, test_external_mem);
|