83c94eb1ca208e25fe485b8b48884aff7ac6e572
[dpdk.git] / test / test / test_memzone.c
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 #include <inttypes.h>
8 #include <sys/queue.h>
9
10 #include <rte_random.h>
11 #include <rte_cycles.h>
12 #include <rte_memory.h>
13 #include <rte_memzone.h>
14 #include <rte_eal.h>
15 #include <rte_eal_memconfig.h>
16 #include <rte_common.h>
17 #include <rte_string_fns.h>
18 #include <rte_errno.h>
19 #include <rte_malloc.h>
20 #include "../../lib/librte_eal/common/malloc_elem.h"
21
22 #include "test.h"
23
24 /*
25  * Memzone
26  * =======
27  *
28  * - Search for three reserved zones or reserve them if they do not exist:
29  *
30  *   - One is on any socket id.
31  *   - The second is on socket 0.
32  *   - The last one is on socket 1 (if socket 1 exists).
33  *
34  * - Check that the zones exist.
35  *
36  * - Check that the zones are cache-aligned.
37  *
38  * - Check that zones do not overlap.
39  *
40  * - Check that the zones are on the correct socket id.
41  *
42  * - Check that a lookup of the first zone returns the same pointer.
43  *
44  * - Check that it is not possible to create another zone with the
45  *   same name as an existing zone.
46  *
47  * - Check flags for specific huge page size reservation
48  */
49
50 /* Test if memory overlaps: return 1 if true, or 0 if false. */
51 static int
52 is_memory_overlap(rte_iova_t ptr1, size_t len1, rte_iova_t ptr2, size_t len2)
53 {
54         if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1)
55                 return 1;
56         else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2)
57                 return 1;
58         return 0;
59 }
60
61 static int
62 test_memzone_invalid_alignment(void)
63 {
64         const struct rte_memzone * mz;
65
66         mz = rte_memzone_lookup("invalid_alignment");
67         if (mz != NULL) {
68                 printf("Zone with invalid alignment has been reserved\n");
69                 return -1;
70         }
71
72         mz = rte_memzone_reserve_aligned("invalid_alignment", 100,
73                         SOCKET_ID_ANY, 0, 100);
74         if (mz != NULL) {
75                 printf("Zone with invalid alignment has been reserved\n");
76                 return -1;
77         }
78         return 0;
79 }
80
81 static int
82 test_memzone_reserving_zone_size_bigger_than_the_maximum(void)
83 {
84         const struct rte_memzone * mz;
85
86         mz = rte_memzone_lookup("zone_size_bigger_than_the_maximum");
87         if (mz != NULL) {
88                 printf("zone_size_bigger_than_the_maximum has been reserved\n");
89                 return -1;
90         }
91
92         mz = rte_memzone_reserve("zone_size_bigger_than_the_maximum", (size_t)-1,
93                         SOCKET_ID_ANY, 0);
94         if (mz != NULL) {
95                 printf("It is impossible to reserve such big a memzone\n");
96                 return -1;
97         }
98
99         return 0;
100 }
101
102 static int
103 test_memzone_reserve_flags(void)
104 {
105         const struct rte_memzone *mz;
106         const struct rte_memseg *ms;
107         int hugepage_2MB_avail = 0;
108         int hugepage_1GB_avail = 0;
109         int hugepage_16MB_avail = 0;
110         int hugepage_16GB_avail = 0;
111         const size_t size = 100;
112         int i = 0;
113         ms = rte_eal_get_physmem_layout();
114         for (i = 0; i < RTE_MAX_MEMSEG; i++) {
115                 if (ms[i].hugepage_sz == RTE_PGSIZE_2M)
116                         hugepage_2MB_avail = 1;
117                 if (ms[i].hugepage_sz == RTE_PGSIZE_1G)
118                         hugepage_1GB_avail = 1;
119                 if (ms[i].hugepage_sz == RTE_PGSIZE_16M)
120                         hugepage_16MB_avail = 1;
121                 if (ms[i].hugepage_sz == RTE_PGSIZE_16G)
122                         hugepage_16GB_avail = 1;
123         }
124         /* Display the availability of 2MB ,1GB, 16MB, 16GB pages */
125         if (hugepage_2MB_avail)
126                 printf("2MB Huge pages available\n");
127         if (hugepage_1GB_avail)
128                 printf("1GB Huge pages available\n");
129         if (hugepage_16MB_avail)
130                 printf("16MB Huge pages available\n");
131         if (hugepage_16GB_avail)
132                 printf("16GB Huge pages available\n");
133         /*
134          * If 2MB pages available, check that a small memzone is correctly
135          * reserved from 2MB huge pages when requested by the RTE_MEMZONE_2MB flag.
136          * Also check that RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an
137          * available page size (i.e 1GB ) when 2MB pages are unavailable.
138          */
139         if (hugepage_2MB_avail) {
140                 mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY,
141                                 RTE_MEMZONE_2MB);
142                 if (mz == NULL) {
143                         printf("MEMZONE FLAG 2MB\n");
144                         return -1;
145                 }
146                 if (mz->hugepage_sz != RTE_PGSIZE_2M) {
147                         printf("hugepage_sz not equal 2M\n");
148                         return -1;
149                 }
150                 if (rte_memzone_free(mz)) {
151                         printf("Fail memzone free\n");
152                         return -1;
153                 }
154
155                 mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY,
156                                 RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY);
157                 if (mz == NULL) {
158                         printf("MEMZONE FLAG 2MB\n");
159                         return -1;
160                 }
161                 if (mz->hugepage_sz != RTE_PGSIZE_2M) {
162                         printf("hugepage_sz not equal 2M\n");
163                         return -1;
164                 }
165                 if (rte_memzone_free(mz)) {
166                         printf("Fail memzone free\n");
167                         return -1;
168                 }
169
170                 /* Check if 1GB huge pages are unavailable, that function fails unless
171                  * HINT flag is indicated
172                  */
173                 if (!hugepage_1GB_avail) {
174                         mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY,
175                                         RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY);
176                         if (mz == NULL) {
177                                 printf("MEMZONE FLAG 1GB & HINT\n");
178                                 return -1;
179                         }
180                         if (mz->hugepage_sz != RTE_PGSIZE_2M) {
181                                 printf("hugepage_sz not equal 2M\n");
182                                 return -1;
183                         }
184                         if (rte_memzone_free(mz)) {
185                                 printf("Fail memzone free\n");
186                                 return -1;
187                         }
188
189                         mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY,
190                                         RTE_MEMZONE_1GB);
191                         if (mz != NULL) {
192                                 printf("MEMZONE FLAG 1GB\n");
193                                 return -1;
194                         }
195                 }
196         }
197
198         /*As with 2MB tests above for 1GB huge page requests*/
199         if (hugepage_1GB_avail) {
200                 mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY,
201                                 RTE_MEMZONE_1GB);
202                 if (mz == NULL) {
203                         printf("MEMZONE FLAG 1GB\n");
204                         return -1;
205                 }
206                 if (mz->hugepage_sz != RTE_PGSIZE_1G) {
207                         printf("hugepage_sz not equal 1G\n");
208                         return -1;
209                 }
210                 if (rte_memzone_free(mz)) {
211                         printf("Fail memzone free\n");
212                         return -1;
213                 }
214
215                 mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY,
216                                 RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY);
217                 if (mz == NULL) {
218                         printf("MEMZONE FLAG 1GB\n");
219                         return -1;
220                 }
221                 if (mz->hugepage_sz != RTE_PGSIZE_1G) {
222                         printf("hugepage_sz not equal 1G\n");
223                         return -1;
224                 }
225                 if (rte_memzone_free(mz)) {
226                         printf("Fail memzone free\n");
227                         return -1;
228                 }
229
230                 /* Check if 1GB huge pages are unavailable, that function fails unless
231                  * HINT flag is indicated
232                  */
233                 if (!hugepage_2MB_avail) {
234                         mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY,
235                                         RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY);
236                         if (mz == NULL){
237                                 printf("MEMZONE FLAG 2MB & HINT\n");
238                                 return -1;
239                         }
240                         if (mz->hugepage_sz != RTE_PGSIZE_1G) {
241                                 printf("hugepage_sz not equal 1G\n");
242                                 return -1;
243                         }
244                         if (rte_memzone_free(mz)) {
245                                 printf("Fail memzone free\n");
246                                 return -1;
247                         }
248                         mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY,
249                                         RTE_MEMZONE_2MB);
250                         if (mz != NULL) {
251                                 printf("MEMZONE FLAG 2MB\n");
252                                 return -1;
253                         }
254                         if (rte_memzone_free(mz)) {
255                                 printf("Fail memzone free\n");
256                                 return -1;
257                         }
258                 }
259
260                 if (hugepage_2MB_avail && hugepage_1GB_avail) {
261                         mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY,
262                                                                 RTE_MEMZONE_2MB|RTE_MEMZONE_1GB);
263                         if (mz == NULL) {
264                                 printf("BOTH SIZES SET\n");
265                                 return -1;
266                         }
267                         if (mz->hugepage_sz != RTE_PGSIZE_1G &&
268                                         mz->hugepage_sz != RTE_PGSIZE_2M) {
269                                 printf("Wrong size when both sizes set\n");
270                                 return -1;
271                         }
272                         if (rte_memzone_free(mz)) {
273                                 printf("Fail memzone free\n");
274                                 return -1;
275                         }
276                 }
277         }
278         /*
279          * This option is for IBM Power. If 16MB pages available, check
280          * that a small memzone is correctly reserved from 16MB huge pages
281          * when requested by the RTE_MEMZONE_16MB flag. Also check that
282          * RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an available
283          * page size (i.e 16GB ) when 16MB pages are unavailable.
284          */
285         if (hugepage_16MB_avail) {
286                 mz = rte_memzone_reserve("flag_zone_16M", size, SOCKET_ID_ANY,
287                                 RTE_MEMZONE_16MB);
288                 if (mz == NULL) {
289                         printf("MEMZONE FLAG 16MB\n");
290                         return -1;
291                 }
292                 if (mz->hugepage_sz != RTE_PGSIZE_16M) {
293                         printf("hugepage_sz not equal 16M\n");
294                         return -1;
295                 }
296                 if (rte_memzone_free(mz)) {
297                         printf("Fail memzone free\n");
298                         return -1;
299                 }
300
301                 mz = rte_memzone_reserve("flag_zone_16M_HINT", size,
302                 SOCKET_ID_ANY, RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY);
303                 if (mz == NULL) {
304                         printf("MEMZONE FLAG 16MB\n");
305                         return -1;
306                 }
307                 if (mz->hugepage_sz != RTE_PGSIZE_16M) {
308                         printf("hugepage_sz not equal 16M\n");
309                         return -1;
310                 }
311                 if (rte_memzone_free(mz)) {
312                         printf("Fail memzone free\n");
313                         return -1;
314                 }
315
316                 /* Check if 1GB huge pages are unavailable, that function fails
317                  * unless HINT flag is indicated
318                  */
319                 if (!hugepage_16GB_avail) {
320                         mz = rte_memzone_reserve("flag_zone_16G_HINT", size,
321                                 SOCKET_ID_ANY,
322                                 RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY);
323                         if (mz == NULL) {
324                                 printf("MEMZONE FLAG 16GB & HINT\n");
325                                 return -1;
326                         }
327                         if (mz->hugepage_sz != RTE_PGSIZE_16M) {
328                                 printf("hugepage_sz not equal 16M\n");
329                                 return -1;
330                         }
331                         if (rte_memzone_free(mz)) {
332                                 printf("Fail memzone free\n");
333                                 return -1;
334                         }
335
336                         mz = rte_memzone_reserve("flag_zone_16G", size,
337                                 SOCKET_ID_ANY, RTE_MEMZONE_16GB);
338                         if (mz != NULL) {
339                                 printf("MEMZONE FLAG 16GB\n");
340                                 return -1;
341                         }
342                 }
343         }
344         /*As with 16MB tests above for 16GB huge page requests*/
345         if (hugepage_16GB_avail) {
346                 mz = rte_memzone_reserve("flag_zone_16G", size, SOCKET_ID_ANY,
347                                 RTE_MEMZONE_16GB);
348                 if (mz == NULL) {
349                         printf("MEMZONE FLAG 16GB\n");
350                         return -1;
351                 }
352                 if (mz->hugepage_sz != RTE_PGSIZE_16G) {
353                         printf("hugepage_sz not equal 16G\n");
354                         return -1;
355                 }
356                 if (rte_memzone_free(mz)) {
357                         printf("Fail memzone free\n");
358                         return -1;
359                 }
360
361                 mz = rte_memzone_reserve("flag_zone_16G_HINT", size,
362                 SOCKET_ID_ANY, RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY);
363                 if (mz == NULL) {
364                         printf("MEMZONE FLAG 16GB\n");
365                         return -1;
366                 }
367                 if (mz->hugepage_sz != RTE_PGSIZE_16G) {
368                         printf("hugepage_sz not equal 16G\n");
369                         return -1;
370                 }
371                 if (rte_memzone_free(mz)) {
372                         printf("Fail memzone free\n");
373                         return -1;
374                 }
375
376                 /* Check if 1GB huge pages are unavailable, that function fails
377                  * unless HINT flag is indicated
378                  */
379                 if (!hugepage_16MB_avail) {
380                         mz = rte_memzone_reserve("flag_zone_16M_HINT", size,
381                                 SOCKET_ID_ANY,
382                                 RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY);
383                         if (mz == NULL) {
384                                 printf("MEMZONE FLAG 16MB & HINT\n");
385                                 return -1;
386                         }
387                         if (mz->hugepage_sz != RTE_PGSIZE_16G) {
388                                 printf("hugepage_sz not equal 16G\n");
389                                 return -1;
390                         }
391                         if (rte_memzone_free(mz)) {
392                                 printf("Fail memzone free\n");
393                                 return -1;
394                         }
395                         mz = rte_memzone_reserve("flag_zone_16M", size,
396                                 SOCKET_ID_ANY, RTE_MEMZONE_16MB);
397                         if (mz != NULL) {
398                                 printf("MEMZONE FLAG 16MB\n");
399                                 return -1;
400                         }
401                 }
402
403                 if (hugepage_16MB_avail && hugepage_16GB_avail) {
404                         mz = rte_memzone_reserve("flag_zone_16M_HINT", size,
405                                 SOCKET_ID_ANY,
406                                 RTE_MEMZONE_16MB|RTE_MEMZONE_16GB);
407                         if (mz == NULL) {
408                                 printf("BOTH SIZES SET\n");
409                                 return -1;
410                         }
411                         if (mz->hugepage_sz != RTE_PGSIZE_16G &&
412                                         mz->hugepage_sz != RTE_PGSIZE_16M) {
413                                 printf("Wrong size when both sizes set\n");
414                                 return -1;
415                         }
416                         if (rte_memzone_free(mz)) {
417                                 printf("Fail memzone free\n");
418                                 return -1;
419                         }
420                 }
421         }
422         return 0;
423 }
424
425
426 /* Find the heap with the greatest free block size */
427 static size_t
428 find_max_block_free_size(const unsigned _align)
429 {
430         struct rte_malloc_socket_stats stats;
431         unsigned i, align = _align;
432         size_t len = 0;
433
434         for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
435                 rte_malloc_get_socket_stats(i, &stats);
436                 if (stats.greatest_free_size > len)
437                         len = stats.greatest_free_size;
438         }
439
440         if (align < RTE_CACHE_LINE_SIZE)
441                 align = RTE_CACHE_LINE_ROUNDUP(align+1);
442
443         if (len <= MALLOC_ELEM_OVERHEAD + align)
444                 return 0;
445
446         return len - MALLOC_ELEM_OVERHEAD - align;
447 }
448
449 static int
450 test_memzone_reserve_max(void)
451 {
452         const struct rte_memzone *mz;
453         size_t maxlen;
454
455         maxlen = find_max_block_free_size(0);
456
457         if (maxlen == 0) {
458                 printf("There is no space left!\n");
459                 return 0;
460         }
461
462         mz = rte_memzone_reserve("max_zone", 0, SOCKET_ID_ANY, 0);
463         if (mz == NULL){
464                 printf("Failed to reserve a big chunk of memory - %s\n",
465                                 rte_strerror(rte_errno));
466                 rte_dump_physmem_layout(stdout);
467                 rte_memzone_dump(stdout);
468                 return -1;
469         }
470
471         if (mz->len != maxlen) {
472                 printf("Memzone reserve with 0 size did not return bigest block\n");
473                 printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len);
474                 rte_dump_physmem_layout(stdout);
475                 rte_memzone_dump(stdout);
476                 return -1;
477         }
478
479         if (rte_memzone_free(mz)) {
480                 printf("Fail memzone free\n");
481                 return -1;
482         }
483
484         return 0;
485 }
486
487 static int
488 test_memzone_reserve_max_aligned(void)
489 {
490         const struct rte_memzone *mz;
491         size_t maxlen = 0;
492
493         /* random alignment */
494         rte_srand((unsigned)rte_rdtsc());
495         const unsigned align = 1 << ((rte_rand() % 8) + 5); /* from 128 up to 4k alignment */
496
497         maxlen = find_max_block_free_size(align);
498
499         if (maxlen == 0) {
500                 printf("There is no space left for biggest %u-aligned memzone!\n", align);
501                 return 0;
502         }
503
504         mz = rte_memzone_reserve_aligned("max_zone_aligned", 0,
505                         SOCKET_ID_ANY, 0, align);
506         if (mz == NULL){
507                 printf("Failed to reserve a big chunk of memory - %s\n",
508                                 rte_strerror(rte_errno));
509                 rte_dump_physmem_layout(stdout);
510                 rte_memzone_dump(stdout);
511                 return -1;
512         }
513
514         if (mz->len != maxlen) {
515                 printf("Memzone reserve with 0 size and alignment %u did not return"
516                                 " bigest block\n", align);
517                 printf("Expected size = %zu, actual size = %zu\n",
518                                 maxlen, mz->len);
519                 rte_dump_physmem_layout(stdout);
520                 rte_memzone_dump(stdout);
521                 return -1;
522         }
523
524         if (rte_memzone_free(mz)) {
525                 printf("Fail memzone free\n");
526                 return -1;
527         }
528
529         return 0;
530 }
531
532 static int
533 test_memzone_aligned(void)
534 {
535         const struct rte_memzone *memzone_aligned_32;
536         const struct rte_memzone *memzone_aligned_128;
537         const struct rte_memzone *memzone_aligned_256;
538         const struct rte_memzone *memzone_aligned_512;
539         const struct rte_memzone *memzone_aligned_1024;
540
541         /* memzone that should automatically be adjusted to align on 64 bytes */
542         memzone_aligned_32 = rte_memzone_reserve_aligned("aligned_32", 100,
543                                 SOCKET_ID_ANY, 0, 32);
544
545         /* memzone that is supposed to be aligned on a 128 byte boundary */
546         memzone_aligned_128 = rte_memzone_reserve_aligned("aligned_128", 100,
547                                 SOCKET_ID_ANY, 0, 128);
548
549         /* memzone that is supposed to be aligned on a 256 byte boundary */
550         memzone_aligned_256 = rte_memzone_reserve_aligned("aligned_256", 100,
551                                 SOCKET_ID_ANY, 0, 256);
552
553         /* memzone that is supposed to be aligned on a 512 byte boundary */
554         memzone_aligned_512 = rte_memzone_reserve_aligned("aligned_512", 100,
555                                 SOCKET_ID_ANY, 0, 512);
556
557         /* memzone that is supposed to be aligned on a 1024 byte boundary */
558         memzone_aligned_1024 = rte_memzone_reserve_aligned("aligned_1024", 100,
559                                 SOCKET_ID_ANY, 0, 1024);
560
561         printf("check alignments and lengths\n");
562         if (memzone_aligned_32 == NULL) {
563                 printf("Unable to reserve 64-byte aligned memzone!\n");
564                 return -1;
565         }
566         if ((memzone_aligned_32->iova & RTE_CACHE_LINE_MASK) != 0)
567                 return -1;
568         if (((uintptr_t) memzone_aligned_32->addr & RTE_CACHE_LINE_MASK) != 0)
569                 return -1;
570         if ((memzone_aligned_32->len & RTE_CACHE_LINE_MASK) != 0)
571                 return -1;
572
573         if (memzone_aligned_128 == NULL) {
574                 printf("Unable to reserve 128-byte aligned memzone!\n");
575                 return -1;
576         }
577         if ((memzone_aligned_128->iova & 127) != 0)
578                 return -1;
579         if (((uintptr_t) memzone_aligned_128->addr & 127) != 0)
580                 return -1;
581         if ((memzone_aligned_128->len & RTE_CACHE_LINE_MASK) != 0)
582                 return -1;
583
584         if (memzone_aligned_256 == NULL) {
585                 printf("Unable to reserve 256-byte aligned memzone!\n");
586                 return -1;
587         }
588         if ((memzone_aligned_256->iova & 255) != 0)
589                 return -1;
590         if (((uintptr_t) memzone_aligned_256->addr & 255) != 0)
591                 return -1;
592         if ((memzone_aligned_256->len & RTE_CACHE_LINE_MASK) != 0)
593                 return -1;
594
595         if (memzone_aligned_512 == NULL) {
596                 printf("Unable to reserve 512-byte aligned memzone!\n");
597                 return -1;
598         }
599         if ((memzone_aligned_512->iova & 511) != 0)
600                 return -1;
601         if (((uintptr_t) memzone_aligned_512->addr & 511) != 0)
602                 return -1;
603         if ((memzone_aligned_512->len & RTE_CACHE_LINE_MASK) != 0)
604                 return -1;
605
606         if (memzone_aligned_1024 == NULL) {
607                 printf("Unable to reserve 1024-byte aligned memzone!\n");
608                 return -1;
609         }
610         if ((memzone_aligned_1024->iova & 1023) != 0)
611                 return -1;
612         if (((uintptr_t) memzone_aligned_1024->addr & 1023) != 0)
613                 return -1;
614         if ((memzone_aligned_1024->len & RTE_CACHE_LINE_MASK) != 0)
615                 return -1;
616
617         /* check that zones don't overlap */
618         printf("check overlapping\n");
619         if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
620                                         memzone_aligned_128->iova, memzone_aligned_128->len))
621                 return -1;
622         if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
623                                         memzone_aligned_256->iova, memzone_aligned_256->len))
624                 return -1;
625         if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
626                                         memzone_aligned_512->iova, memzone_aligned_512->len))
627                 return -1;
628         if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
629                                         memzone_aligned_1024->iova, memzone_aligned_1024->len))
630                 return -1;
631         if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len,
632                                         memzone_aligned_256->iova, memzone_aligned_256->len))
633                 return -1;
634         if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len,
635                                         memzone_aligned_512->iova, memzone_aligned_512->len))
636                 return -1;
637         if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len,
638                                         memzone_aligned_1024->iova, memzone_aligned_1024->len))
639                 return -1;
640         if (is_memory_overlap(memzone_aligned_256->iova, memzone_aligned_256->len,
641                                         memzone_aligned_512->iova, memzone_aligned_512->len))
642                 return -1;
643         if (is_memory_overlap(memzone_aligned_256->iova, memzone_aligned_256->len,
644                                         memzone_aligned_1024->iova, memzone_aligned_1024->len))
645                 return -1;
646         if (is_memory_overlap(memzone_aligned_512->iova, memzone_aligned_512->len,
647                                         memzone_aligned_1024->iova, memzone_aligned_1024->len))
648                 return -1;
649
650         /* free all used zones */
651         if (rte_memzone_free(memzone_aligned_32)) {
652                 printf("Fail memzone free\n");
653                 return -1;
654         }
655         if (rte_memzone_free(memzone_aligned_128)) {
656                 printf("Fail memzone free\n");
657                 return -1;
658         }
659         if (rte_memzone_free(memzone_aligned_256)) {
660                 printf("Fail memzone free\n");
661                 return -1;
662         }
663         if (rte_memzone_free(memzone_aligned_512)) {
664                 printf("Fail memzone free\n");
665                 return -1;
666         }
667         if (rte_memzone_free(memzone_aligned_1024)) {
668                 printf("Fail memzone free\n");
669                 return -1;
670         }
671         return 0;
672 }
673
674 static int
675 check_memzone_bounded(const char *name, uint32_t len,  uint32_t align,
676         uint32_t bound)
677 {
678         const struct rte_memzone *mz;
679         rte_iova_t bmask;
680
681         bmask = ~((rte_iova_t)bound - 1);
682
683         if ((mz = rte_memzone_reserve_bounded(name, len, SOCKET_ID_ANY, 0,
684                         align, bound)) == NULL) {
685                 printf("%s(%s): memzone creation failed\n",
686                         __func__, name);
687                 return -1;
688         }
689
690         if ((mz->iova & ((rte_iova_t)align - 1)) != 0) {
691                 printf("%s(%s): invalid phys addr alignment\n",
692                         __func__, mz->name);
693                 return -1;
694         }
695
696         if (((uintptr_t) mz->addr & ((uintptr_t)align - 1)) != 0) {
697                 printf("%s(%s): invalid virtual addr alignment\n",
698                         __func__, mz->name);
699                 return -1;
700         }
701
702         if ((mz->len & RTE_CACHE_LINE_MASK) != 0 || mz->len < len ||
703                         mz->len < RTE_CACHE_LINE_SIZE) {
704                 printf("%s(%s): invalid length\n",
705                         __func__, mz->name);
706                 return -1;
707         }
708
709         if ((mz->iova & bmask) !=
710                         ((mz->iova + mz->len - 1) & bmask)) {
711                 printf("%s(%s): invalid memzone boundary %u crossed\n",
712                         __func__, mz->name, bound);
713                 return -1;
714         }
715
716         if (rte_memzone_free(mz)) {
717                 printf("Fail memzone free\n");
718                 return -1;
719         }
720
721         return 0;
722 }
723
724 static int
725 test_memzone_bounded(void)
726 {
727         const struct rte_memzone *memzone_err;
728         const char *name;
729         int rc;
730
731         /* should fail as boundary is not power of two */
732         name = "bounded_error_31";
733         if ((memzone_err = rte_memzone_reserve_bounded(name,
734                         100, SOCKET_ID_ANY, 0, 32, UINT32_MAX)) != NULL) {
735                 printf("%s(%s)created a memzone with invalid boundary "
736                         "conditions\n", __func__, memzone_err->name);
737                 return -1;
738         }
739
740         /* should fail as len is greater then boundary */
741         name = "bounded_error_32";
742         if ((memzone_err = rte_memzone_reserve_bounded(name,
743                         100, SOCKET_ID_ANY, 0, 32, 32)) != NULL) {
744                 printf("%s(%s)created a memzone with invalid boundary "
745                         "conditions\n", __func__, memzone_err->name);
746                 return -1;
747         }
748
749         if ((rc = check_memzone_bounded("bounded_128", 100, 128, 128)) != 0)
750                 return rc;
751
752         if ((rc = check_memzone_bounded("bounded_256", 100, 256, 128)) != 0)
753                 return rc;
754
755         if ((rc = check_memzone_bounded("bounded_1K", 100, 64, 1024)) != 0)
756                 return rc;
757
758         if ((rc = check_memzone_bounded("bounded_1K_MAX", 0, 64, 1024)) != 0)
759                 return rc;
760
761         return 0;
762 }
763
764 static int
765 test_memzone_free(void)
766 {
767         const struct rte_memzone *mz[RTE_MAX_MEMZONE];
768         int i;
769         char name[20];
770
771         mz[0] = rte_memzone_reserve("tempzone0", 2000, SOCKET_ID_ANY, 0);
772         mz[1] = rte_memzone_reserve("tempzone1", 4000, SOCKET_ID_ANY, 0);
773
774         if (mz[0] > mz[1])
775                 return -1;
776         if (!rte_memzone_lookup("tempzone0"))
777                 return -1;
778         if (!rte_memzone_lookup("tempzone1"))
779                 return -1;
780
781         if (rte_memzone_free(mz[0])) {
782                 printf("Fail memzone free - tempzone0\n");
783                 return -1;
784         }
785         if (rte_memzone_lookup("tempzone0")) {
786                 printf("Found previously free memzone - tempzone0\n");
787                 return -1;
788         }
789         mz[2] = rte_memzone_reserve("tempzone2", 2000, SOCKET_ID_ANY, 0);
790
791         if (mz[2] > mz[1]) {
792                 printf("tempzone2 should have gotten the free entry from tempzone0\n");
793                 return -1;
794         }
795         if (rte_memzone_free(mz[2])) {
796                 printf("Fail memzone free - tempzone2\n");
797                 return -1;
798         }
799         if (rte_memzone_lookup("tempzone2")) {
800                 printf("Found previously free memzone - tempzone2\n");
801                 return -1;
802         }
803         if (rte_memzone_free(mz[1])) {
804                 printf("Fail memzone free - tempzone1\n");
805                 return -1;
806         }
807         if (rte_memzone_lookup("tempzone1")) {
808                 printf("Found previously free memzone - tempzone1\n");
809                 return -1;
810         }
811
812         i = 0;
813         do {
814                 snprintf(name, sizeof(name), "tempzone%u", i);
815                 mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0);
816         } while (mz[i++] != NULL);
817
818         if (rte_memzone_free(mz[0])) {
819                 printf("Fail memzone free - tempzone0\n");
820                 return -1;
821         }
822         mz[0] = rte_memzone_reserve("tempzone0new", 0, SOCKET_ID_ANY, 0);
823
824         if (mz[0] == NULL) {
825                 printf("Fail to create memzone - tempzone0new - when MAX memzones were "
826                                 "created and one was free\n");
827                 return -1;
828         }
829
830         for (i = i - 2; i >= 0; i--) {
831                 if (rte_memzone_free(mz[i])) {
832                         printf("Fail memzone free - tempzone%d\n", i);
833                         return -1;
834                 }
835         }
836
837         return 0;
838 }
839
840 static int
841 test_memzone_basic(void)
842 {
843         const struct rte_memzone *memzone1;
844         const struct rte_memzone *memzone2;
845         const struct rte_memzone *memzone3;
846         const struct rte_memzone *memzone4;
847         const struct rte_memzone *mz;
848
849         memzone1 = rte_memzone_reserve("testzone1", 100,
850                                 SOCKET_ID_ANY, 0);
851
852         memzone2 = rte_memzone_reserve("testzone2", 1000,
853                                 0, 0);
854
855         memzone3 = rte_memzone_reserve("testzone3", 1000,
856                                 1, 0);
857
858         memzone4 = rte_memzone_reserve("testzone4", 1024,
859                                 SOCKET_ID_ANY, 0);
860
861         /* memzone3 may be NULL if we don't have NUMA */
862         if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL)
863                 return -1;
864
865         rte_memzone_dump(stdout);
866
867         /* check cache-line alignments */
868         printf("check alignments and lengths\n");
869
870         if ((memzone1->iova & RTE_CACHE_LINE_MASK) != 0)
871                 return -1;
872         if ((memzone2->iova & RTE_CACHE_LINE_MASK) != 0)
873                 return -1;
874         if (memzone3 != NULL && (memzone3->iova & RTE_CACHE_LINE_MASK) != 0)
875                 return -1;
876         if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0)
877                 return -1;
878         if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0)
879                 return -1;
880         if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 ||
881                         memzone3->len == 0))
882                 return -1;
883         if (memzone4->len != 1024)
884                 return -1;
885
886         /* check that zones don't overlap */
887         printf("check overlapping\n");
888
889         if (is_memory_overlap(memzone1->iova, memzone1->len,
890                         memzone2->iova, memzone2->len))
891                 return -1;
892         if (memzone3 != NULL &&
893                         is_memory_overlap(memzone1->iova, memzone1->len,
894                                         memzone3->iova, memzone3->len))
895                 return -1;
896         if (memzone3 != NULL &&
897                         is_memory_overlap(memzone2->iova, memzone2->len,
898                                         memzone3->iova, memzone3->len))
899                 return -1;
900
901         printf("check socket ID\n");
902
903         /* memzone2 must be on socket id 0 and memzone3 on socket 1 */
904         if (memzone2->socket_id != 0)
905                 return -1;
906         if (memzone3 != NULL && memzone3->socket_id != 1)
907                 return -1;
908
909         printf("test zone lookup\n");
910         mz = rte_memzone_lookup("testzone1");
911         if (mz != memzone1)
912                 return -1;
913
914         printf("test duplcate zone name\n");
915         mz = rte_memzone_reserve("testzone1", 100,
916                         SOCKET_ID_ANY, 0);
917         if (mz != NULL)
918                 return -1;
919
920         if (rte_memzone_free(memzone1)) {
921                 printf("Fail memzone free - memzone1\n");
922                 return -1;
923         }
924         if (rte_memzone_free(memzone2)) {
925                 printf("Fail memzone free - memzone2\n");
926                 return -1;
927         }
928         if (memzone3 && rte_memzone_free(memzone3)) {
929                 printf("Fail memzone free - memzone3\n");
930                 return -1;
931         }
932         if (rte_memzone_free(memzone4)) {
933                 printf("Fail memzone free - memzone4\n");
934                 return -1;
935         }
936
937         return 0;
938 }
939
940 static int memzone_walk_called;
941 static void memzone_walk_clb(const struct rte_memzone *mz __rte_unused,
942                              void *arg __rte_unused)
943 {
944         memzone_walk_called = 1;
945 }
946
947 static int
948 test_memzone(void)
949 {
950         printf("test basic memzone API\n");
951         if (test_memzone_basic() < 0)
952                 return -1;
953
954         printf("test free memzone\n");
955         if (test_memzone_free() < 0)
956                 return -1;
957
958         printf("test reserving memzone with bigger size than the maximum\n");
959         if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0)
960                 return -1;
961
962         printf("test memzone_reserve flags\n");
963         if (test_memzone_reserve_flags() < 0)
964                 return -1;
965
966         printf("test alignment for memzone_reserve\n");
967         if (test_memzone_aligned() < 0)
968                 return -1;
969
970         printf("test boundary alignment for memzone_reserve\n");
971         if (test_memzone_bounded() < 0)
972                 return -1;
973
974         printf("test invalid alignment for memzone_reserve\n");
975         if (test_memzone_invalid_alignment() < 0)
976                 return -1;
977
978         printf("test reserving the largest size memzone possible\n");
979         if (test_memzone_reserve_max() < 0)
980                 return -1;
981
982         printf("test reserving the largest size aligned memzone possible\n");
983         if (test_memzone_reserve_max_aligned() < 0)
984                 return -1;
985
986         printf("check memzone cleanup\n");
987         rte_memzone_walk(memzone_walk_clb, NULL);
988         if (memzone_walk_called) {
989                 printf("there are some memzones left after test\n");
990                 rte_memzone_dump(stdout);
991                 return -1;
992         }
993
994         return 0;
995 }
996
997 REGISTER_TEST_COMMAND(memzone_autotest, test_memzone);