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_lcore.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 if (rte_malloc_get_socket_stats(socket_id, &stats) < 0) 479 return 0; 480 481 len = stats.greatest_free_size; 482 overhead = MALLOC_ELEM_OVERHEAD; 483 484 if (len == 0) 485 return 0; 486 487 align = RTE_CACHE_LINE_ROUNDUP(align); 488 overhead += align; 489 490 if (len < overhead) 491 return 0; 492 493 return len - overhead; 494 } 495 496 static int 497 test_memzone_reserve_max(void) 498 { 499 unsigned int i; 500 501 for (i = 0; i < rte_socket_count(); i++) { 502 const struct rte_memzone *mz; 503 size_t maxlen; 504 int socket; 505 506 socket = rte_socket_id_by_idx(i); 507 maxlen = find_max_block_free_size(0, socket); 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, 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", 527 maxlen, mz->len); 528 rte_dump_physmem_layout(stdout); 529 rte_memzone_dump(stdout); 530 return -1; 531 } 532 533 if (rte_memzone_free(mz)) { 534 printf("Fail memzone free\n"); 535 return -1; 536 } 537 } 538 539 return 0; 540 } 541 542 static int 543 test_memzone_reserve_max_aligned(void) 544 { 545 unsigned int i; 546 547 for (i = 0; i < rte_socket_count(); i++) { 548 const struct rte_memzone *mz; 549 size_t maxlen, minlen = 0; 550 int socket; 551 552 socket = rte_socket_id_by_idx(i); 553 554 /* random alignment */ 555 rte_srand((unsigned int)rte_rdtsc()); 556 const unsigned int align = 1 << ((rte_rand() % 8) + 5); /* from 128 up to 4k alignment */ 557 558 /* memzone size may be between size and size - align */ 559 minlen = find_max_block_free_size(align, socket); 560 maxlen = find_max_block_free_size(0, socket); 561 562 if (minlen == 0 || maxlen == 0) { 563 printf("There is no space left for biggest %u-aligned memzone!\n", 564 align); 565 return 0; 566 } 567 568 mz = rte_memzone_reserve_aligned( 569 TEST_MEMZONE_NAME("max_zone_aligned"), 570 0, socket, 0, align); 571 if (mz == NULL) { 572 printf("Failed to reserve a big chunk of memory - %s\n", 573 rte_strerror(rte_errno)); 574 rte_dump_physmem_layout(stdout); 575 rte_memzone_dump(stdout); 576 return -1; 577 } 578 if (mz->addr != RTE_PTR_ALIGN(mz->addr, align)) { 579 printf("Memzone reserve with 0 size and alignment %u did not return aligned block\n", 580 align); 581 rte_dump_physmem_layout(stdout); 582 rte_memzone_dump(stdout); 583 return -1; 584 } 585 586 if (mz->len < minlen || mz->len > maxlen) { 587 printf("Memzone reserve with 0 size and alignment %u did not return" 588 " bigest block\n", align); 589 printf("Expected size = %zu-%zu, actual size = %zu\n", 590 minlen, maxlen, mz->len); 591 rte_dump_physmem_layout(stdout); 592 rte_memzone_dump(stdout); 593 return -1; 594 } 595 596 if (rte_memzone_free(mz)) { 597 printf("Fail memzone free\n"); 598 return -1; 599 } 600 } 601 return 0; 602 } 603 604 static int 605 test_memzone_aligned(void) 606 { 607 const struct rte_memzone *memzone_aligned_32; 608 const struct rte_memzone *memzone_aligned_128; 609 const struct rte_memzone *memzone_aligned_256; 610 const struct rte_memzone *memzone_aligned_512; 611 const struct rte_memzone *memzone_aligned_1024; 612 613 /* memzone that should automatically be adjusted to align on 64 bytes */ 614 memzone_aligned_32 = rte_memzone_reserve_aligned( 615 TEST_MEMZONE_NAME("aligned_32"), 100, SOCKET_ID_ANY, 0, 616 32); 617 618 /* memzone that is supposed to be aligned on a 128 byte boundary */ 619 memzone_aligned_128 = rte_memzone_reserve_aligned( 620 TEST_MEMZONE_NAME("aligned_128"), 100, SOCKET_ID_ANY, 0, 621 128); 622 623 /* memzone that is supposed to be aligned on a 256 byte boundary */ 624 memzone_aligned_256 = rte_memzone_reserve_aligned( 625 TEST_MEMZONE_NAME("aligned_256"), 100, SOCKET_ID_ANY, 0, 626 256); 627 628 /* memzone that is supposed to be aligned on a 512 byte boundary */ 629 memzone_aligned_512 = rte_memzone_reserve_aligned( 630 TEST_MEMZONE_NAME("aligned_512"), 100, SOCKET_ID_ANY, 0, 631 512); 632 633 /* memzone that is supposed to be aligned on a 1024 byte boundary */ 634 memzone_aligned_1024 = rte_memzone_reserve_aligned( 635 TEST_MEMZONE_NAME("aligned_1024"), 100, SOCKET_ID_ANY, 636 0, 1024); 637 638 printf("check alignments and lengths\n"); 639 if (memzone_aligned_32 == NULL) { 640 printf("Unable to reserve 64-byte aligned memzone!\n"); 641 return -1; 642 } 643 if ((memzone_aligned_32->iova & RTE_CACHE_LINE_MASK) != 0) 644 return -1; 645 if (((uintptr_t) memzone_aligned_32->addr & RTE_CACHE_LINE_MASK) != 0) 646 return -1; 647 if ((memzone_aligned_32->len & RTE_CACHE_LINE_MASK) != 0) 648 return -1; 649 650 if (memzone_aligned_128 == NULL) { 651 printf("Unable to reserve 128-byte aligned memzone!\n"); 652 return -1; 653 } 654 if ((memzone_aligned_128->iova & 127) != 0) 655 return -1; 656 if (((uintptr_t) memzone_aligned_128->addr & 127) != 0) 657 return -1; 658 if ((memzone_aligned_128->len & RTE_CACHE_LINE_MASK) != 0) 659 return -1; 660 661 if (memzone_aligned_256 == NULL) { 662 printf("Unable to reserve 256-byte aligned memzone!\n"); 663 return -1; 664 } 665 if ((memzone_aligned_256->iova & 255) != 0) 666 return -1; 667 if (((uintptr_t) memzone_aligned_256->addr & 255) != 0) 668 return -1; 669 if ((memzone_aligned_256->len & RTE_CACHE_LINE_MASK) != 0) 670 return -1; 671 672 if (memzone_aligned_512 == NULL) { 673 printf("Unable to reserve 512-byte aligned memzone!\n"); 674 return -1; 675 } 676 if ((memzone_aligned_512->iova & 511) != 0) 677 return -1; 678 if (((uintptr_t) memzone_aligned_512->addr & 511) != 0) 679 return -1; 680 if ((memzone_aligned_512->len & RTE_CACHE_LINE_MASK) != 0) 681 return -1; 682 683 if (memzone_aligned_1024 == NULL) { 684 printf("Unable to reserve 1024-byte aligned memzone!\n"); 685 return -1; 686 } 687 if ((memzone_aligned_1024->iova & 1023) != 0) 688 return -1; 689 if (((uintptr_t) memzone_aligned_1024->addr & 1023) != 0) 690 return -1; 691 if ((memzone_aligned_1024->len & RTE_CACHE_LINE_MASK) != 0) 692 return -1; 693 694 /* check that zones don't overlap */ 695 printf("check overlapping\n"); 696 if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len, 697 memzone_aligned_128->iova, memzone_aligned_128->len)) 698 return -1; 699 if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len, 700 memzone_aligned_256->iova, memzone_aligned_256->len)) 701 return -1; 702 if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len, 703 memzone_aligned_512->iova, memzone_aligned_512->len)) 704 return -1; 705 if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len, 706 memzone_aligned_1024->iova, memzone_aligned_1024->len)) 707 return -1; 708 if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len, 709 memzone_aligned_256->iova, memzone_aligned_256->len)) 710 return -1; 711 if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len, 712 memzone_aligned_512->iova, memzone_aligned_512->len)) 713 return -1; 714 if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len, 715 memzone_aligned_1024->iova, memzone_aligned_1024->len)) 716 return -1; 717 if (is_memory_overlap(memzone_aligned_256->iova, memzone_aligned_256->len, 718 memzone_aligned_512->iova, memzone_aligned_512->len)) 719 return -1; 720 if (is_memory_overlap(memzone_aligned_256->iova, memzone_aligned_256->len, 721 memzone_aligned_1024->iova, memzone_aligned_1024->len)) 722 return -1; 723 if (is_memory_overlap(memzone_aligned_512->iova, memzone_aligned_512->len, 724 memzone_aligned_1024->iova, memzone_aligned_1024->len)) 725 return -1; 726 727 /* free all used zones */ 728 if (rte_memzone_free(memzone_aligned_32)) { 729 printf("Fail memzone free\n"); 730 return -1; 731 } 732 if (rte_memzone_free(memzone_aligned_128)) { 733 printf("Fail memzone free\n"); 734 return -1; 735 } 736 if (rte_memzone_free(memzone_aligned_256)) { 737 printf("Fail memzone free\n"); 738 return -1; 739 } 740 if (rte_memzone_free(memzone_aligned_512)) { 741 printf("Fail memzone free\n"); 742 return -1; 743 } 744 if (rte_memzone_free(memzone_aligned_1024)) { 745 printf("Fail memzone free\n"); 746 return -1; 747 } 748 return 0; 749 } 750 751 static int 752 check_memzone_bounded(const char *name, uint32_t len, uint32_t align, 753 uint32_t bound) 754 { 755 const struct rte_memzone *mz; 756 rte_iova_t bmask; 757 758 bmask = ~((rte_iova_t)bound - 1); 759 760 if ((mz = rte_memzone_reserve_bounded(name, len, SOCKET_ID_ANY, 0, 761 align, bound)) == NULL) { 762 printf("%s(%s): memzone creation failed\n", 763 __func__, name); 764 return -1; 765 } 766 767 if ((mz->iova & ((rte_iova_t)align - 1)) != 0) { 768 printf("%s(%s): invalid phys addr alignment\n", 769 __func__, mz->name); 770 return -1; 771 } 772 773 if (((uintptr_t) mz->addr & ((uintptr_t)align - 1)) != 0) { 774 printf("%s(%s): invalid virtual addr alignment\n", 775 __func__, mz->name); 776 return -1; 777 } 778 779 if ((mz->len & RTE_CACHE_LINE_MASK) != 0 || mz->len < len || 780 mz->len < RTE_CACHE_LINE_SIZE) { 781 printf("%s(%s): invalid length\n", 782 __func__, mz->name); 783 return -1; 784 } 785 786 if ((mz->iova & bmask) != 787 ((mz->iova + mz->len - 1) & bmask)) { 788 printf("%s(%s): invalid memzone boundary %u crossed\n", 789 __func__, mz->name, bound); 790 return -1; 791 } 792 793 if (rte_memzone_free(mz)) { 794 printf("Fail memzone free\n"); 795 return -1; 796 } 797 798 return 0; 799 } 800 801 static int 802 test_memzone_bounded(void) 803 { 804 const struct rte_memzone *memzone_err; 805 int rc; 806 807 /* should fail as boundary is not power of two */ 808 memzone_err = rte_memzone_reserve_bounded( 809 TEST_MEMZONE_NAME("bounded_error_31"), 100, 810 SOCKET_ID_ANY, 0, 32, UINT32_MAX); 811 if (memzone_err != NULL) { 812 printf("%s(%s)created a memzone with invalid boundary " 813 "conditions\n", __func__, memzone_err->name); 814 return -1; 815 } 816 817 /* should fail as len is greater then boundary */ 818 memzone_err = rte_memzone_reserve_bounded( 819 TEST_MEMZONE_NAME("bounded_error_32"), 100, 820 SOCKET_ID_ANY, 0, 32, 32); 821 if (memzone_err != NULL) { 822 printf("%s(%s)created a memzone with invalid boundary " 823 "conditions\n", __func__, memzone_err->name); 824 return -1; 825 } 826 827 rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_128"), 100, 128, 828 128); 829 if (rc != 0) 830 return rc; 831 832 rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_256"), 100, 256, 833 128); 834 if (rc != 0) 835 return rc; 836 837 rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_1K"), 100, 64, 838 1024); 839 if (rc != 0) 840 return rc; 841 842 rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_1K_MAX"), 0, 64, 843 1024); 844 if (rc != 0) 845 return rc; 846 847 return 0; 848 } 849 850 static int 851 test_memzone_free(void) 852 { 853 const struct rte_memzone *mz[RTE_MAX_MEMZONE + 1]; 854 int i; 855 char name[20]; 856 857 mz[0] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone0"), 2000, 858 SOCKET_ID_ANY, 0); 859 mz[1] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone1"), 4000, 860 SOCKET_ID_ANY, 0); 861 862 if (mz[0] > mz[1]) 863 return -1; 864 if (!rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone0"))) 865 return -1; 866 if (!rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone1"))) 867 return -1; 868 869 if (rte_memzone_free(mz[0])) { 870 printf("Fail memzone free - tempzone0\n"); 871 return -1; 872 } 873 if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone0"))) { 874 printf("Found previously free memzone - tempzone0\n"); 875 return -1; 876 } 877 mz[2] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone2"), 2000, 878 SOCKET_ID_ANY, 0); 879 880 if (mz[2] > mz[1]) { 881 printf("tempzone2 should have gotten the free entry from tempzone0\n"); 882 return -1; 883 } 884 if (rte_memzone_free(mz[2])) { 885 printf("Fail memzone free - tempzone2\n"); 886 return -1; 887 } 888 if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone2"))) { 889 printf("Found previously free memzone - tempzone2\n"); 890 return -1; 891 } 892 if (rte_memzone_free(mz[1])) { 893 printf("Fail memzone free - tempzone1\n"); 894 return -1; 895 } 896 if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone1"))) { 897 printf("Found previously free memzone - tempzone1\n"); 898 return -1; 899 } 900 901 i = 0; 902 do { 903 snprintf(name, sizeof(name), TEST_MEMZONE_NAME("tempzone%u"), 904 i); 905 mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0); 906 } while (mz[i++] != NULL); 907 908 if (rte_memzone_free(mz[0])) { 909 printf("Fail memzone free - tempzone0\n"); 910 return -1; 911 } 912 mz[0] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone0new"), 0, 913 SOCKET_ID_ANY, 0); 914 915 if (mz[0] == NULL) { 916 printf("Fail to create memzone - tempzone0new - when MAX memzones were " 917 "created and one was free\n"); 918 return -1; 919 } 920 921 for (i = i - 2; i >= 0; i--) { 922 if (rte_memzone_free(mz[i])) { 923 printf("Fail memzone free - tempzone%d\n", i); 924 return -1; 925 } 926 } 927 928 return 0; 929 } 930 931 static int test_memzones_left; 932 static int memzone_walk_cnt; 933 static void memzone_walk_clb(const struct rte_memzone *mz, 934 void *arg __rte_unused) 935 { 936 memzone_walk_cnt++; 937 if (!strncmp(TEST_MEMZONE_NAME(""), mz->name, RTE_MEMZONE_NAMESIZE)) 938 test_memzones_left++; 939 } 940 941 static int 942 test_memzone_basic(void) 943 { 944 const struct rte_memzone *memzone1; 945 const struct rte_memzone *memzone2; 946 const struct rte_memzone *memzone3; 947 const struct rte_memzone *memzone4; 948 const struct rte_memzone *mz; 949 int memzone_cnt_after, memzone_cnt_expected; 950 int memzone_cnt_before; 951 952 memzone_walk_cnt = 0; 953 test_memzones_left = 0; 954 rte_memzone_walk(memzone_walk_clb, NULL); 955 memzone_cnt_before = memzone_walk_cnt; 956 957 memzone1 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone1"), 100, 958 SOCKET_ID_ANY, 0); 959 960 memzone2 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone2"), 1000, 961 0, 0); 962 963 memzone3 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone3"), 1000, 964 1, 0); 965 966 memzone4 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone4"), 1024, 967 SOCKET_ID_ANY, 0); 968 969 /* memzone3 may be NULL if we don't have NUMA */ 970 if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL) 971 return -1; 972 973 /* check how many memzones we are expecting */ 974 memzone_cnt_expected = memzone_cnt_before + 975 (memzone1 != NULL) + (memzone2 != NULL) + 976 (memzone3 != NULL) + (memzone4 != NULL); 977 978 memzone_walk_cnt = 0; 979 test_memzones_left = 0; 980 rte_memzone_walk(memzone_walk_clb, NULL); 981 memzone_cnt_after = memzone_walk_cnt; 982 983 if (memzone_cnt_after != memzone_cnt_expected) 984 return -1; 985 986 987 rte_memzone_dump(stdout); 988 989 /* check cache-line alignments */ 990 printf("check alignments and lengths\n"); 991 992 if ((memzone1->iova & RTE_CACHE_LINE_MASK) != 0) 993 return -1; 994 if ((memzone2->iova & RTE_CACHE_LINE_MASK) != 0) 995 return -1; 996 if (memzone3 != NULL && (memzone3->iova & RTE_CACHE_LINE_MASK) != 0) 997 return -1; 998 if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0) 999 return -1; 1000 if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0) 1001 return -1; 1002 if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 || 1003 memzone3->len == 0)) 1004 return -1; 1005 if (memzone4->len != 1024) 1006 return -1; 1007 1008 /* check that zones don't overlap */ 1009 printf("check overlapping\n"); 1010 1011 if (is_memory_overlap(memzone1->iova, memzone1->len, 1012 memzone2->iova, memzone2->len)) 1013 return -1; 1014 if (memzone3 != NULL && 1015 is_memory_overlap(memzone1->iova, memzone1->len, 1016 memzone3->iova, memzone3->len)) 1017 return -1; 1018 if (memzone3 != NULL && 1019 is_memory_overlap(memzone2->iova, memzone2->len, 1020 memzone3->iova, memzone3->len)) 1021 return -1; 1022 1023 printf("check socket ID\n"); 1024 1025 /* memzone2 must be on socket id 0 and memzone3 on socket 1 */ 1026 if (memzone2->socket_id != 0) 1027 return -1; 1028 if (memzone3 != NULL && memzone3->socket_id != 1) 1029 return -1; 1030 1031 printf("test zone lookup\n"); 1032 mz = rte_memzone_lookup(TEST_MEMZONE_NAME("testzone1")); 1033 if (mz != memzone1) 1034 return -1; 1035 1036 printf("test duplcate zone name\n"); 1037 mz = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone1"), 100, 1038 SOCKET_ID_ANY, 0); 1039 if (mz != NULL) 1040 return -1; 1041 1042 if (rte_memzone_free(memzone1)) { 1043 printf("Fail memzone free - memzone1\n"); 1044 return -1; 1045 } 1046 if (rte_memzone_free(memzone2)) { 1047 printf("Fail memzone free - memzone2\n"); 1048 return -1; 1049 } 1050 if (memzone3 && rte_memzone_free(memzone3)) { 1051 printf("Fail memzone free - memzone3\n"); 1052 return -1; 1053 } 1054 if (rte_memzone_free(memzone4)) { 1055 printf("Fail memzone free - memzone4\n"); 1056 return -1; 1057 } 1058 1059 memzone_walk_cnt = 0; 1060 test_memzones_left = 0; 1061 rte_memzone_walk(memzone_walk_clb, NULL); 1062 memzone_cnt_after = memzone_walk_cnt; 1063 if (memzone_cnt_after != memzone_cnt_before) 1064 return -1; 1065 1066 return 0; 1067 } 1068 1069 static int 1070 test_memzone(void) 1071 { 1072 /* take note of how many memzones were allocated before running */ 1073 int memzone_cnt; 1074 1075 memzone_walk_cnt = 0; 1076 test_memzones_left = 0; 1077 rte_memzone_walk(memzone_walk_clb, NULL); 1078 memzone_cnt = memzone_walk_cnt; 1079 1080 printf("test basic memzone API\n"); 1081 if (test_memzone_basic() < 0) 1082 return -1; 1083 1084 printf("test free memzone\n"); 1085 if (test_memzone_free() < 0) 1086 return -1; 1087 1088 printf("test reserving memzone with bigger size than the maximum\n"); 1089 if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0) 1090 return -1; 1091 1092 printf("test memzone_reserve flags\n"); 1093 if (test_memzone_reserve_flags() < 0) 1094 return -1; 1095 1096 printf("test alignment for memzone_reserve\n"); 1097 if (test_memzone_aligned() < 0) 1098 return -1; 1099 1100 printf("test boundary alignment for memzone_reserve\n"); 1101 if (test_memzone_bounded() < 0) 1102 return -1; 1103 1104 printf("test invalid alignment for memzone_reserve\n"); 1105 if (test_memzone_invalid_alignment() < 0) 1106 return -1; 1107 1108 printf("test reserving the largest size memzone possible\n"); 1109 if (test_memzone_reserve_max() < 0) 1110 return -1; 1111 1112 printf("test reserving the largest size aligned memzone possible\n"); 1113 if (test_memzone_reserve_max_aligned() < 0) 1114 return -1; 1115 1116 printf("check memzone cleanup\n"); 1117 memzone_walk_cnt = 0; 1118 test_memzones_left = 0; 1119 rte_memzone_walk(memzone_walk_clb, NULL); 1120 if (memzone_walk_cnt != memzone_cnt || test_memzones_left > 0) { 1121 printf("there are some memzones left after test\n"); 1122 rte_memzone_dump(stdout); 1123 return -1; 1124 } 1125 1126 return 0; 1127 } 1128 1129 REGISTER_TEST_COMMAND(memzone_autotest, test_memzone); 1130