1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <stdint.h> 36 #include <inttypes.h> 37 #include <sys/queue.h> 38 39 #include <rte_random.h> 40 #include <rte_cycles.h> 41 #include <rte_memory.h> 42 #include <rte_memzone.h> 43 #include <rte_eal.h> 44 #include <rte_eal_memconfig.h> 45 #include <rte_common.h> 46 #include <rte_string_fns.h> 47 #include <rte_errno.h> 48 #include <rte_malloc.h> 49 #include "../../lib/librte_eal/common/malloc_elem.h" 50 51 #include "test.h" 52 53 /* 54 * Memzone 55 * ======= 56 * 57 * - Search for three reserved zones or reserve them if they do not exist: 58 * 59 * - One is on any socket id. 60 * - The second is on socket 0. 61 * - The last one is on socket 1 (if socket 1 exists). 62 * 63 * - Check that the zones exist. 64 * 65 * - Check that the zones are cache-aligned. 66 * 67 * - Check that zones do not overlap. 68 * 69 * - Check that the zones are on the correct socket id. 70 * 71 * - Check that a lookup of the first zone returns the same pointer. 72 * 73 * - Check that it is not possible to create another zone with the 74 * same name as an existing zone. 75 * 76 * - Check flags for specific huge page size reservation 77 */ 78 79 /* Test if memory overlaps: return 1 if true, or 0 if false. */ 80 static int 81 is_memory_overlap(phys_addr_t ptr1, size_t len1, phys_addr_t ptr2, size_t len2) 82 { 83 if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1) 84 return 1; 85 else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2) 86 return 1; 87 return 0; 88 } 89 90 static int 91 test_memzone_invalid_alignment(void) 92 { 93 const struct rte_memzone * mz; 94 95 mz = rte_memzone_lookup("invalid_alignment"); 96 if (mz != NULL) { 97 printf("Zone with invalid alignment has been reserved\n"); 98 return -1; 99 } 100 101 mz = rte_memzone_reserve_aligned("invalid_alignment", 100, 102 SOCKET_ID_ANY, 0, 100); 103 if (mz != NULL) { 104 printf("Zone with invalid alignment has been reserved\n"); 105 return -1; 106 } 107 return 0; 108 } 109 110 static int 111 test_memzone_reserving_zone_size_bigger_than_the_maximum(void) 112 { 113 const struct rte_memzone * mz; 114 115 mz = rte_memzone_lookup("zone_size_bigger_than_the_maximum"); 116 if (mz != NULL) { 117 printf("zone_size_bigger_than_the_maximum has been reserved\n"); 118 return -1; 119 } 120 121 mz = rte_memzone_reserve("zone_size_bigger_than_the_maximum", (size_t)-1, 122 SOCKET_ID_ANY, 0); 123 if (mz != NULL) { 124 printf("It is impossible to reserve such big a memzone\n"); 125 return -1; 126 } 127 128 return 0; 129 } 130 131 static int 132 test_memzone_reserve_flags(void) 133 { 134 const struct rte_memzone *mz; 135 const struct rte_memseg *ms; 136 int hugepage_2MB_avail = 0; 137 int hugepage_1GB_avail = 0; 138 int hugepage_16MB_avail = 0; 139 int hugepage_16GB_avail = 0; 140 const size_t size = 100; 141 int i = 0; 142 ms = rte_eal_get_physmem_layout(); 143 for (i = 0; i < RTE_MAX_MEMSEG; i++) { 144 if (ms[i].hugepage_sz == RTE_PGSIZE_2M) 145 hugepage_2MB_avail = 1; 146 if (ms[i].hugepage_sz == RTE_PGSIZE_1G) 147 hugepage_1GB_avail = 1; 148 if (ms[i].hugepage_sz == RTE_PGSIZE_16M) 149 hugepage_16MB_avail = 1; 150 if (ms[i].hugepage_sz == RTE_PGSIZE_16G) 151 hugepage_16GB_avail = 1; 152 } 153 /* Display the availability of 2MB ,1GB, 16MB, 16GB pages */ 154 if (hugepage_2MB_avail) 155 printf("2MB Huge pages available\n"); 156 if (hugepage_1GB_avail) 157 printf("1GB Huge pages available\n"); 158 if (hugepage_16MB_avail) 159 printf("16MB Huge pages available\n"); 160 if (hugepage_16GB_avail) 161 printf("16GB Huge pages available\n"); 162 /* 163 * If 2MB pages available, check that a small memzone is correctly 164 * reserved from 2MB huge pages when requested by the RTE_MEMZONE_2MB flag. 165 * Also check that RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an 166 * available page size (i.e 1GB ) when 2MB pages are unavailable. 167 */ 168 if (hugepage_2MB_avail) { 169 mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY, 170 RTE_MEMZONE_2MB); 171 if (mz == NULL) { 172 printf("MEMZONE FLAG 2MB\n"); 173 return -1; 174 } 175 if (mz->hugepage_sz != RTE_PGSIZE_2M) { 176 printf("hugepage_sz not equal 2M\n"); 177 return -1; 178 } 179 180 mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, 181 RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY); 182 if (mz == NULL) { 183 printf("MEMZONE FLAG 2MB\n"); 184 return -1; 185 } 186 if (mz->hugepage_sz != RTE_PGSIZE_2M) { 187 printf("hugepage_sz not equal 2M\n"); 188 return -1; 189 } 190 191 /* Check if 1GB huge pages are unavailable, that function fails unless 192 * HINT flag is indicated 193 */ 194 if (!hugepage_1GB_avail) { 195 mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY, 196 RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY); 197 if (mz == NULL) { 198 printf("MEMZONE FLAG 1GB & HINT\n"); 199 return -1; 200 } 201 if (mz->hugepage_sz != RTE_PGSIZE_2M) { 202 printf("hugepage_sz not equal 2M\n"); 203 return -1; 204 } 205 206 mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY, 207 RTE_MEMZONE_1GB); 208 if (mz != NULL) { 209 printf("MEMZONE FLAG 1GB\n"); 210 return -1; 211 } 212 } 213 } 214 215 /*As with 2MB tests above for 1GB huge page requests*/ 216 if (hugepage_1GB_avail) { 217 mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY, 218 RTE_MEMZONE_1GB); 219 if (mz == NULL) { 220 printf("MEMZONE FLAG 1GB\n"); 221 return -1; 222 } 223 if (mz->hugepage_sz != RTE_PGSIZE_1G) { 224 printf("hugepage_sz not equal 1G\n"); 225 return -1; 226 } 227 228 mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY, 229 RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY); 230 if (mz == NULL) { 231 printf("MEMZONE FLAG 1GB\n"); 232 return -1; 233 } 234 if (mz->hugepage_sz != RTE_PGSIZE_1G) { 235 printf("hugepage_sz not equal 1G\n"); 236 return -1; 237 } 238 239 /* Check if 1GB huge pages are unavailable, that function fails unless 240 * HINT flag is indicated 241 */ 242 if (!hugepage_2MB_avail) { 243 mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, 244 RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY); 245 if (mz == NULL){ 246 printf("MEMZONE FLAG 2MB & HINT\n"); 247 return -1; 248 } 249 if (mz->hugepage_sz != RTE_PGSIZE_1G) { 250 printf("hugepage_sz not equal 1G\n"); 251 return -1; 252 } 253 mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY, 254 RTE_MEMZONE_2MB); 255 if (mz != NULL) { 256 printf("MEMZONE FLAG 2MB\n"); 257 return -1; 258 } 259 } 260 261 if (hugepage_2MB_avail && hugepage_1GB_avail) { 262 mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, 263 RTE_MEMZONE_2MB|RTE_MEMZONE_1GB); 264 if (mz != NULL) { 265 printf("BOTH SIZES SET\n"); 266 return -1; 267 } 268 } 269 } 270 /* 271 * This option is for IBM Power. If 16MB pages available, check 272 * that a small memzone is correctly reserved from 16MB huge pages 273 * when requested by the RTE_MEMZONE_16MB flag. Also check that 274 * RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an available 275 * page size (i.e 16GB ) when 16MB pages are unavailable. 276 */ 277 if (hugepage_16MB_avail) { 278 mz = rte_memzone_reserve("flag_zone_16M", size, SOCKET_ID_ANY, 279 RTE_MEMZONE_16MB); 280 if (mz == NULL) { 281 printf("MEMZONE FLAG 16MB\n"); 282 return -1; 283 } 284 if (mz->hugepage_sz != RTE_PGSIZE_16M) { 285 printf("hugepage_sz not equal 16M\n"); 286 return -1; 287 } 288 289 mz = rte_memzone_reserve("flag_zone_16M_HINT", size, 290 SOCKET_ID_ANY, RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY); 291 if (mz == NULL) { 292 printf("MEMZONE FLAG 2MB\n"); 293 return -1; 294 } 295 if (mz->hugepage_sz != RTE_PGSIZE_16M) { 296 printf("hugepage_sz not equal 16M\n"); 297 return -1; 298 } 299 300 /* Check if 1GB huge pages are unavailable, that function fails 301 * unless HINT flag is indicated 302 */ 303 if (!hugepage_16GB_avail) { 304 mz = rte_memzone_reserve("flag_zone_16G_HINT", size, 305 SOCKET_ID_ANY, 306 RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY); 307 if (mz == NULL) { 308 printf("MEMZONE FLAG 16GB & HINT\n"); 309 return -1; 310 } 311 if (mz->hugepage_sz != RTE_PGSIZE_16M) { 312 printf("hugepage_sz not equal 16M\n"); 313 return -1; 314 } 315 316 mz = rte_memzone_reserve("flag_zone_16G", size, 317 SOCKET_ID_ANY, RTE_MEMZONE_16GB); 318 if (mz != NULL) { 319 printf("MEMZONE FLAG 16GB\n"); 320 return -1; 321 } 322 } 323 } 324 /*As with 16MB tests above for 16GB huge page requests*/ 325 if (hugepage_16GB_avail) { 326 mz = rte_memzone_reserve("flag_zone_16G", size, SOCKET_ID_ANY, 327 RTE_MEMZONE_16GB); 328 if (mz == NULL) { 329 printf("MEMZONE FLAG 16GB\n"); 330 return -1; 331 } 332 if (mz->hugepage_sz != RTE_PGSIZE_16G) { 333 printf("hugepage_sz not equal 16G\n"); 334 return -1; 335 } 336 337 mz = rte_memzone_reserve("flag_zone_16G_HINT", size, 338 SOCKET_ID_ANY, RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY); 339 if (mz == NULL) { 340 printf("MEMZONE FLAG 16GB\n"); 341 return -1; 342 } 343 if (mz->hugepage_sz != RTE_PGSIZE_16G) { 344 printf("hugepage_sz not equal 16G\n"); 345 return -1; 346 } 347 348 /* Check if 1GB huge pages are unavailable, that function fails 349 * unless HINT flag is indicated 350 */ 351 if (!hugepage_16MB_avail) { 352 mz = rte_memzone_reserve("flag_zone_16M_HINT", size, 353 SOCKET_ID_ANY, 354 RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY); 355 if (mz == NULL) { 356 printf("MEMZONE FLAG 16MB & HINT\n"); 357 return -1; 358 } 359 if (mz->hugepage_sz != RTE_PGSIZE_16G) { 360 printf("hugepage_sz not equal 16G\n"); 361 return -1; 362 } 363 mz = rte_memzone_reserve("flag_zone_16M", size, 364 SOCKET_ID_ANY, RTE_MEMZONE_16MB); 365 if (mz != NULL) { 366 printf("MEMZONE FLAG 16MB\n"); 367 return -1; 368 } 369 } 370 371 if (hugepage_16MB_avail && hugepage_16GB_avail) { 372 mz = rte_memzone_reserve("flag_zone_16M_HINT", size, 373 SOCKET_ID_ANY, 374 RTE_MEMZONE_16MB|RTE_MEMZONE_16GB); 375 if (mz != NULL) { 376 printf("BOTH SIZES SET\n"); 377 return -1; 378 } 379 } 380 } 381 return 0; 382 } 383 384 385 /* Find the heap with the greatest free block size */ 386 static size_t 387 find_max_block_free_size(const unsigned _align) 388 { 389 struct rte_malloc_socket_stats stats; 390 unsigned i, align = _align; 391 size_t len = 0; 392 393 for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { 394 rte_malloc_get_socket_stats(i, &stats); 395 if (stats.greatest_free_size > len) 396 len = stats.greatest_free_size; 397 } 398 399 if (align < RTE_CACHE_LINE_SIZE) 400 align = RTE_CACHE_LINE_ROUNDUP(align+1); 401 402 if (len <= MALLOC_ELEM_OVERHEAD + align) 403 return 0; 404 405 return len - MALLOC_ELEM_OVERHEAD - align; 406 } 407 408 static int 409 test_memzone_reserve_max(void) 410 { 411 const struct rte_memzone *mz; 412 size_t maxlen; 413 414 maxlen = find_max_block_free_size(0); 415 416 if (maxlen == 0) { 417 printf("There is no space left!\n"); 418 return 0; 419 } 420 421 mz = rte_memzone_reserve("max_zone", 0, SOCKET_ID_ANY, 0); 422 if (mz == NULL){ 423 printf("Failed to reserve a big chunk of memory - %s\n", 424 rte_strerror(rte_errno)); 425 rte_dump_physmem_layout(stdout); 426 rte_memzone_dump(stdout); 427 return -1; 428 } 429 430 if (mz->len != maxlen) { 431 printf("Memzone reserve with 0 size did not return bigest block\n"); 432 printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len); 433 rte_dump_physmem_layout(stdout); 434 rte_memzone_dump(stdout); 435 return -1; 436 } 437 return 0; 438 } 439 440 static int 441 test_memzone_reserve_max_aligned(void) 442 { 443 const struct rte_memzone *mz; 444 size_t maxlen = 0; 445 446 /* random alignment */ 447 rte_srand((unsigned)rte_rdtsc()); 448 const unsigned align = 1 << ((rte_rand() % 8) + 5); /* from 128 up to 4k alignment */ 449 450 maxlen = find_max_block_free_size(align); 451 452 if (maxlen == 0) { 453 printf("There is no space left for biggest %u-aligned memzone!\n", align); 454 return 0; 455 } 456 457 mz = rte_memzone_reserve_aligned("max_zone_aligned", 0, 458 SOCKET_ID_ANY, 0, align); 459 if (mz == NULL){ 460 printf("Failed to reserve a big chunk of memory - %s\n", 461 rte_strerror(rte_errno)); 462 rte_dump_physmem_layout(stdout); 463 rte_memzone_dump(stdout); 464 return -1; 465 } 466 467 if (mz->len != maxlen) { 468 printf("Memzone reserve with 0 size and alignment %u did not return" 469 " bigest block\n", align); 470 printf("Expected size = %zu, actual size = %zu\n", 471 maxlen, mz->len); 472 rte_dump_physmem_layout(stdout); 473 rte_memzone_dump(stdout); 474 return -1; 475 } 476 return 0; 477 } 478 479 static int 480 test_memzone_aligned(void) 481 { 482 const struct rte_memzone *memzone_aligned_32; 483 const struct rte_memzone *memzone_aligned_128; 484 const struct rte_memzone *memzone_aligned_256; 485 const struct rte_memzone *memzone_aligned_512; 486 const struct rte_memzone *memzone_aligned_1024; 487 488 /* memzone that should automatically be adjusted to align on 64 bytes */ 489 memzone_aligned_32 = rte_memzone_reserve_aligned("aligned_32", 100, 490 SOCKET_ID_ANY, 0, 32); 491 492 /* memzone that is supposed to be aligned on a 128 byte boundary */ 493 memzone_aligned_128 = rte_memzone_reserve_aligned("aligned_128", 100, 494 SOCKET_ID_ANY, 0, 128); 495 496 /* memzone that is supposed to be aligned on a 256 byte boundary */ 497 memzone_aligned_256 = rte_memzone_reserve_aligned("aligned_256", 100, 498 SOCKET_ID_ANY, 0, 256); 499 500 /* memzone that is supposed to be aligned on a 512 byte boundary */ 501 memzone_aligned_512 = rte_memzone_reserve_aligned("aligned_512", 100, 502 SOCKET_ID_ANY, 0, 512); 503 504 /* memzone that is supposed to be aligned on a 1024 byte boundary */ 505 memzone_aligned_1024 = rte_memzone_reserve_aligned("aligned_1024", 100, 506 SOCKET_ID_ANY, 0, 1024); 507 508 printf("check alignments and lengths\n"); 509 if (memzone_aligned_32 == NULL) { 510 printf("Unable to reserve 64-byte aligned memzone!\n"); 511 return -1; 512 } 513 if ((memzone_aligned_32->phys_addr & RTE_CACHE_LINE_MASK) != 0) 514 return -1; 515 if (((uintptr_t) memzone_aligned_32->addr & RTE_CACHE_LINE_MASK) != 0) 516 return -1; 517 if ((memzone_aligned_32->len & RTE_CACHE_LINE_MASK) != 0) 518 return -1; 519 520 if (memzone_aligned_128 == NULL) { 521 printf("Unable to reserve 128-byte aligned memzone!\n"); 522 return -1; 523 } 524 if ((memzone_aligned_128->phys_addr & 127) != 0) 525 return -1; 526 if (((uintptr_t) memzone_aligned_128->addr & 127) != 0) 527 return -1; 528 if ((memzone_aligned_128->len & RTE_CACHE_LINE_MASK) != 0) 529 return -1; 530 531 if (memzone_aligned_256 == NULL) { 532 printf("Unable to reserve 256-byte aligned memzone!\n"); 533 return -1; 534 } 535 if ((memzone_aligned_256->phys_addr & 255) != 0) 536 return -1; 537 if (((uintptr_t) memzone_aligned_256->addr & 255) != 0) 538 return -1; 539 if ((memzone_aligned_256->len & RTE_CACHE_LINE_MASK) != 0) 540 return -1; 541 542 if (memzone_aligned_512 == NULL) { 543 printf("Unable to reserve 512-byte aligned memzone!\n"); 544 return -1; 545 } 546 if ((memzone_aligned_512->phys_addr & 511) != 0) 547 return -1; 548 if (((uintptr_t) memzone_aligned_512->addr & 511) != 0) 549 return -1; 550 if ((memzone_aligned_512->len & RTE_CACHE_LINE_MASK) != 0) 551 return -1; 552 553 if (memzone_aligned_1024 == NULL) { 554 printf("Unable to reserve 1024-byte aligned memzone!\n"); 555 return -1; 556 } 557 if ((memzone_aligned_1024->phys_addr & 1023) != 0) 558 return -1; 559 if (((uintptr_t) memzone_aligned_1024->addr & 1023) != 0) 560 return -1; 561 if ((memzone_aligned_1024->len & RTE_CACHE_LINE_MASK) != 0) 562 return -1; 563 564 /* check that zones don't overlap */ 565 printf("check overlapping\n"); 566 if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, 567 memzone_aligned_128->phys_addr, memzone_aligned_128->len)) 568 return -1; 569 if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, 570 memzone_aligned_256->phys_addr, memzone_aligned_256->len)) 571 return -1; 572 if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, 573 memzone_aligned_512->phys_addr, memzone_aligned_512->len)) 574 return -1; 575 if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, 576 memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) 577 return -1; 578 if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, 579 memzone_aligned_256->phys_addr, memzone_aligned_256->len)) 580 return -1; 581 if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, 582 memzone_aligned_512->phys_addr, memzone_aligned_512->len)) 583 return -1; 584 if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, 585 memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) 586 return -1; 587 if (is_memory_overlap(memzone_aligned_256->phys_addr, memzone_aligned_256->len, 588 memzone_aligned_512->phys_addr, memzone_aligned_512->len)) 589 return -1; 590 if (is_memory_overlap(memzone_aligned_256->phys_addr, memzone_aligned_256->len, 591 memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) 592 return -1; 593 if (is_memory_overlap(memzone_aligned_512->phys_addr, memzone_aligned_512->len, 594 memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) 595 return -1; 596 return 0; 597 } 598 599 static int 600 check_memzone_bounded(const char *name, uint32_t len, uint32_t align, 601 uint32_t bound) 602 { 603 const struct rte_memzone *mz; 604 phys_addr_t bmask; 605 606 bmask = ~((phys_addr_t)bound - 1); 607 608 if ((mz = rte_memzone_reserve_bounded(name, len, SOCKET_ID_ANY, 0, 609 align, bound)) == NULL) { 610 printf("%s(%s): memzone creation failed\n", 611 __func__, name); 612 return -1; 613 } 614 615 if ((mz->phys_addr & ((phys_addr_t)align - 1)) != 0) { 616 printf("%s(%s): invalid phys addr alignment\n", 617 __func__, mz->name); 618 return -1; 619 } 620 621 if (((uintptr_t) mz->addr & ((uintptr_t)align - 1)) != 0) { 622 printf("%s(%s): invalid virtual addr alignment\n", 623 __func__, mz->name); 624 return -1; 625 } 626 627 if ((mz->len & RTE_CACHE_LINE_MASK) != 0 || mz->len < len || 628 mz->len < RTE_CACHE_LINE_SIZE) { 629 printf("%s(%s): invalid length\n", 630 __func__, mz->name); 631 return -1; 632 } 633 634 if ((mz->phys_addr & bmask) != 635 ((mz->phys_addr + mz->len - 1) & bmask)) { 636 printf("%s(%s): invalid memzone boundary %u crossed\n", 637 __func__, mz->name, bound); 638 return -1; 639 } 640 641 return 0; 642 } 643 644 static int 645 test_memzone_bounded(void) 646 { 647 const struct rte_memzone *memzone_err; 648 const char *name; 649 int rc; 650 651 /* should fail as boundary is not power of two */ 652 name = "bounded_error_31"; 653 if ((memzone_err = rte_memzone_reserve_bounded(name, 654 100, SOCKET_ID_ANY, 0, 32, UINT32_MAX)) != NULL) { 655 printf("%s(%s)created a memzone with invalid boundary " 656 "conditions\n", __func__, memzone_err->name); 657 return -1; 658 } 659 660 /* should fail as len is greater then boundary */ 661 name = "bounded_error_32"; 662 if ((memzone_err = rte_memzone_reserve_bounded(name, 663 100, SOCKET_ID_ANY, 0, 32, 32)) != NULL) { 664 printf("%s(%s)created a memzone with invalid boundary " 665 "conditions\n", __func__, memzone_err->name); 666 return -1; 667 } 668 669 if ((rc = check_memzone_bounded("bounded_128", 100, 128, 128)) != 0) 670 return rc; 671 672 if ((rc = check_memzone_bounded("bounded_256", 100, 256, 128)) != 0) 673 return rc; 674 675 if ((rc = check_memzone_bounded("bounded_1K", 100, 64, 1024)) != 0) 676 return rc; 677 678 if ((rc = check_memzone_bounded("bounded_1K_MAX", 0, 64, 1024)) != 0) 679 return rc; 680 681 return 0; 682 } 683 684 static int 685 test_memzone_free(void) 686 { 687 const struct rte_memzone *mz[RTE_MAX_MEMZONE]; 688 int i; 689 char name[20]; 690 691 mz[0] = rte_memzone_reserve("tempzone0", 2000, SOCKET_ID_ANY, 0); 692 mz[1] = rte_memzone_reserve("tempzone1", 4000, SOCKET_ID_ANY, 0); 693 694 if (mz[0] > mz[1]) 695 return -1; 696 if (!rte_memzone_lookup("tempzone0")) 697 return -1; 698 if (!rte_memzone_lookup("tempzone1")) 699 return -1; 700 701 if (rte_memzone_free(mz[0])) { 702 printf("Fail memzone free - tempzone0\n"); 703 return -1; 704 } 705 if (rte_memzone_lookup("tempzone0")) { 706 printf("Found previously free memzone - tempzone0\n"); 707 return -1; 708 } 709 mz[2] = rte_memzone_reserve("tempzone2", 2000, SOCKET_ID_ANY, 0); 710 711 if (mz[2] > mz[1]) { 712 printf("tempzone2 should have gotten the free entry from tempzone0\n"); 713 return -1; 714 } 715 if (rte_memzone_free(mz[2])) { 716 printf("Fail memzone free - tempzone2\n"); 717 return -1; 718 } 719 if (rte_memzone_lookup("tempzone2")) { 720 printf("Found previously free memzone - tempzone2\n"); 721 return -1; 722 } 723 if (rte_memzone_free(mz[1])) { 724 printf("Fail memzone free - tempzone1\n"); 725 return -1; 726 } 727 if (rte_memzone_lookup("tempzone1")) { 728 printf("Found previously free memzone - tempzone1\n"); 729 return -1; 730 } 731 732 i = 0; 733 do { 734 snprintf(name, sizeof(name), "tempzone%u", i); 735 mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0); 736 } while (mz[i++] != NULL); 737 738 if (rte_memzone_free(mz[0])) { 739 printf("Fail memzone free - tempzone0\n"); 740 return -1; 741 } 742 mz[0] = rte_memzone_reserve("tempzone0new", 0, SOCKET_ID_ANY, 0); 743 744 if (mz[0] == NULL) { 745 printf("Fail to create memzone - tempzone0new - when MAX memzones were " 746 "created and one was free\n"); 747 return -1; 748 } 749 750 for (i = i - 2; i >= 0; i--) { 751 if (rte_memzone_free(mz[i])) { 752 printf("Fail memzone free - tempzone%d\n", i); 753 return -1; 754 } 755 } 756 757 return 0; 758 } 759 760 static int 761 test_memzone(void) 762 { 763 const struct rte_memzone *memzone1; 764 const struct rte_memzone *memzone2; 765 const struct rte_memzone *memzone3; 766 const struct rte_memzone *memzone4; 767 const struct rte_memzone *mz; 768 769 memzone1 = rte_memzone_reserve("testzone1", 100, 770 SOCKET_ID_ANY, 0); 771 772 memzone2 = rte_memzone_reserve("testzone2", 1000, 773 0, 0); 774 775 memzone3 = rte_memzone_reserve("testzone3", 1000, 776 1, 0); 777 778 memzone4 = rte_memzone_reserve("testzone4", 1024, 779 SOCKET_ID_ANY, 0); 780 781 /* memzone3 may be NULL if we don't have NUMA */ 782 if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL) 783 return -1; 784 785 rte_memzone_dump(stdout); 786 787 /* check cache-line alignments */ 788 printf("check alignments and lengths\n"); 789 790 if ((memzone1->phys_addr & RTE_CACHE_LINE_MASK) != 0) 791 return -1; 792 if ((memzone2->phys_addr & RTE_CACHE_LINE_MASK) != 0) 793 return -1; 794 if (memzone3 != NULL && (memzone3->phys_addr & RTE_CACHE_LINE_MASK) != 0) 795 return -1; 796 if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0) 797 return -1; 798 if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0) 799 return -1; 800 if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 || 801 memzone3->len == 0)) 802 return -1; 803 if (memzone4->len != 1024) 804 return -1; 805 806 /* check that zones don't overlap */ 807 printf("check overlapping\n"); 808 809 if (is_memory_overlap(memzone1->phys_addr, memzone1->len, 810 memzone2->phys_addr, memzone2->len)) 811 return -1; 812 if (memzone3 != NULL && 813 is_memory_overlap(memzone1->phys_addr, memzone1->len, 814 memzone3->phys_addr, memzone3->len)) 815 return -1; 816 if (memzone3 != NULL && 817 is_memory_overlap(memzone2->phys_addr, memzone2->len, 818 memzone3->phys_addr, memzone3->len)) 819 return -1; 820 821 printf("check socket ID\n"); 822 823 /* memzone2 must be on socket id 0 and memzone3 on socket 1 */ 824 if (memzone2->socket_id != 0) 825 return -1; 826 if (memzone3 != NULL && memzone3->socket_id != 1) 827 return -1; 828 829 printf("test zone lookup\n"); 830 mz = rte_memzone_lookup("testzone1"); 831 if (mz != memzone1) 832 return -1; 833 834 printf("test duplcate zone name\n"); 835 mz = rte_memzone_reserve("testzone1", 100, 836 SOCKET_ID_ANY, 0); 837 if (mz != NULL) 838 return -1; 839 840 printf("test free memzone\n"); 841 if (test_memzone_free() < 0) 842 return -1; 843 844 printf("test reserving memzone with bigger size than the maximum\n"); 845 if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0) 846 return -1; 847 848 printf("test memzone_reserve flags\n"); 849 if (test_memzone_reserve_flags() < 0) 850 return -1; 851 852 printf("test alignment for memzone_reserve\n"); 853 if (test_memzone_aligned() < 0) 854 return -1; 855 856 printf("test boundary alignment for memzone_reserve\n"); 857 if (test_memzone_bounded() < 0) 858 return -1; 859 860 printf("test invalid alignment for memzone_reserve\n"); 861 if (test_memzone_invalid_alignment() < 0) 862 return -1; 863 864 printf("test reserving the largest size memzone possible\n"); 865 if (test_memzone_reserve_max() < 0) 866 return -1; 867 868 printf("test reserving the largest size aligned memzone possible\n"); 869 if (test_memzone_reserve_max_aligned() < 0) 870 return -1; 871 872 return 0; 873 } 874 875 REGISTER_TEST_COMMAND(memzone_autotest, test_memzone); 876