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