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