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