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