1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <string.h> 8 #include <inttypes.h> 9 #include <sys/queue.h> 10 11 #include <rte_random.h> 12 #include <rte_cycles.h> 13 #include <rte_memory.h> 14 #include <rte_memzone.h> 15 #include <rte_eal.h> 16 #include <rte_eal_memconfig.h> 17 #include <rte_common.h> 18 #include <rte_string_fns.h> 19 #include <rte_errno.h> 20 #include <rte_malloc.h> 21 #include "../../lib/librte_eal/common/malloc_elem.h" 22 #include "../../lib/librte_eal/common/eal_memcfg.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 rte_malloc_get_socket_stats(socket_id, &stats); 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 932 test_memzone_basic(void) 933 { 934 const struct rte_memzone *memzone1; 935 const struct rte_memzone *memzone2; 936 const struct rte_memzone *memzone3; 937 const struct rte_memzone *memzone4; 938 const struct rte_memzone *mz; 939 int memzone_cnt_after, memzone_cnt_expected; 940 int memzone_cnt_before = 941 rte_eal_get_configuration()->mem_config->memzones.count; 942 943 memzone1 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone1"), 100, 944 SOCKET_ID_ANY, 0); 945 946 memzone2 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone2"), 1000, 947 0, 0); 948 949 memzone3 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone3"), 1000, 950 1, 0); 951 952 memzone4 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone4"), 1024, 953 SOCKET_ID_ANY, 0); 954 955 /* memzone3 may be NULL if we don't have NUMA */ 956 if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL) 957 return -1; 958 959 /* check how many memzones we are expecting */ 960 memzone_cnt_expected = memzone_cnt_before + 961 (memzone1 != NULL) + (memzone2 != NULL) + 962 (memzone3 != NULL) + (memzone4 != NULL); 963 964 memzone_cnt_after = 965 rte_eal_get_configuration()->mem_config->memzones.count; 966 967 if (memzone_cnt_after != memzone_cnt_expected) 968 return -1; 969 970 971 rte_memzone_dump(stdout); 972 973 /* check cache-line alignments */ 974 printf("check alignments and lengths\n"); 975 976 if ((memzone1->iova & RTE_CACHE_LINE_MASK) != 0) 977 return -1; 978 if ((memzone2->iova & RTE_CACHE_LINE_MASK) != 0) 979 return -1; 980 if (memzone3 != NULL && (memzone3->iova & RTE_CACHE_LINE_MASK) != 0) 981 return -1; 982 if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0) 983 return -1; 984 if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0) 985 return -1; 986 if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 || 987 memzone3->len == 0)) 988 return -1; 989 if (memzone4->len != 1024) 990 return -1; 991 992 /* check that zones don't overlap */ 993 printf("check overlapping\n"); 994 995 if (is_memory_overlap(memzone1->iova, memzone1->len, 996 memzone2->iova, memzone2->len)) 997 return -1; 998 if (memzone3 != NULL && 999 is_memory_overlap(memzone1->iova, memzone1->len, 1000 memzone3->iova, memzone3->len)) 1001 return -1; 1002 if (memzone3 != NULL && 1003 is_memory_overlap(memzone2->iova, memzone2->len, 1004 memzone3->iova, memzone3->len)) 1005 return -1; 1006 1007 printf("check socket ID\n"); 1008 1009 /* memzone2 must be on socket id 0 and memzone3 on socket 1 */ 1010 if (memzone2->socket_id != 0) 1011 return -1; 1012 if (memzone3 != NULL && memzone3->socket_id != 1) 1013 return -1; 1014 1015 printf("test zone lookup\n"); 1016 mz = rte_memzone_lookup(TEST_MEMZONE_NAME("testzone1")); 1017 if (mz != memzone1) 1018 return -1; 1019 1020 printf("test duplcate zone name\n"); 1021 mz = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone1"), 100, 1022 SOCKET_ID_ANY, 0); 1023 if (mz != NULL) 1024 return -1; 1025 1026 if (rte_memzone_free(memzone1)) { 1027 printf("Fail memzone free - memzone1\n"); 1028 return -1; 1029 } 1030 if (rte_memzone_free(memzone2)) { 1031 printf("Fail memzone free - memzone2\n"); 1032 return -1; 1033 } 1034 if (memzone3 && rte_memzone_free(memzone3)) { 1035 printf("Fail memzone free - memzone3\n"); 1036 return -1; 1037 } 1038 if (rte_memzone_free(memzone4)) { 1039 printf("Fail memzone free - memzone4\n"); 1040 return -1; 1041 } 1042 1043 memzone_cnt_after = 1044 rte_eal_get_configuration()->mem_config->memzones.count; 1045 if (memzone_cnt_after != memzone_cnt_before) 1046 return -1; 1047 1048 return 0; 1049 } 1050 1051 static int test_memzones_left; 1052 static int memzone_walk_cnt; 1053 static void memzone_walk_clb(const struct rte_memzone *mz, 1054 void *arg __rte_unused) 1055 { 1056 memzone_walk_cnt++; 1057 if (!strncmp(TEST_MEMZONE_NAME(""), mz->name, RTE_MEMZONE_NAMESIZE)) 1058 test_memzones_left++; 1059 } 1060 1061 static int 1062 test_memzone(void) 1063 { 1064 /* take note of how many memzones were allocated before running */ 1065 int memzone_cnt = 1066 rte_eal_get_configuration()->mem_config->memzones.count; 1067 1068 printf("test basic memzone API\n"); 1069 if (test_memzone_basic() < 0) 1070 return -1; 1071 1072 printf("test free memzone\n"); 1073 if (test_memzone_free() < 0) 1074 return -1; 1075 1076 printf("test reserving memzone with bigger size than the maximum\n"); 1077 if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0) 1078 return -1; 1079 1080 printf("test memzone_reserve flags\n"); 1081 if (test_memzone_reserve_flags() < 0) 1082 return -1; 1083 1084 printf("test alignment for memzone_reserve\n"); 1085 if (test_memzone_aligned() < 0) 1086 return -1; 1087 1088 printf("test boundary alignment for memzone_reserve\n"); 1089 if (test_memzone_bounded() < 0) 1090 return -1; 1091 1092 printf("test invalid alignment for memzone_reserve\n"); 1093 if (test_memzone_invalid_alignment() < 0) 1094 return -1; 1095 1096 printf("test reserving the largest size memzone possible\n"); 1097 if (test_memzone_reserve_max() < 0) 1098 return -1; 1099 1100 printf("test reserving the largest size aligned memzone possible\n"); 1101 if (test_memzone_reserve_max_aligned() < 0) 1102 return -1; 1103 1104 printf("check memzone cleanup\n"); 1105 memzone_walk_cnt = 0; 1106 test_memzones_left = 0; 1107 rte_memzone_walk(memzone_walk_clb, NULL); 1108 if (memzone_walk_cnt != memzone_cnt || test_memzones_left > 0) { 1109 printf("there are some memzones left after test\n"); 1110 rte_memzone_dump(stdout); 1111 return -1; 1112 } 1113 1114 return 0; 1115 } 1116 1117 REGISTER_TEST_COMMAND(memzone_autotest, test_memzone); 1118