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