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