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