1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 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 "spdk/stdinc.h" 35 36 #include "spdk_internal/mock.h" 37 38 #include "spdk/env.h" 39 #include "spdk/queue.h" 40 #include "spdk/util.h" 41 42 static uint32_t g_ut_num_cores; 43 static bool *g_ut_cores; 44 45 void allocate_cores(uint32_t num_cores); 46 void free_cores(void); 47 48 DEFINE_STUB(spdk_process_is_primary, bool, (void), true) 49 DEFINE_STUB(spdk_memzone_lookup, void *, (const char *name), NULL) 50 DEFINE_STUB_V(spdk_pci_driver_register, (const char *name, struct spdk_pci_id *id_table, 51 uint32_t flags)); 52 DEFINE_STUB(spdk_pci_nvme_get_driver, struct spdk_pci_driver *, (void), NULL) 53 DEFINE_STUB(spdk_pci_ioat_get_driver, struct spdk_pci_driver *, (void), NULL) 54 DEFINE_STUB(spdk_pci_virtio_get_driver, struct spdk_pci_driver *, (void), NULL) 55 DEFINE_STUB(spdk_env_thread_launch_pinned, int, (uint32_t core, thread_start_fn fn, void *arg), 0); 56 DEFINE_STUB_V(spdk_env_thread_wait_all, (void)); 57 DEFINE_STUB_V(spdk_env_opts_init, (struct spdk_env_opts *opts)); 58 DEFINE_STUB(spdk_env_init, int, (const struct spdk_env_opts *opts), 0); 59 DEFINE_STUB_V(spdk_env_fini, (void)); 60 61 void 62 allocate_cores(uint32_t num_cores) 63 { 64 uint32_t i; 65 66 g_ut_num_cores = num_cores; 67 68 g_ut_cores = calloc(num_cores, sizeof(bool)); 69 assert(g_ut_cores != NULL); 70 71 for (i = 0; i < num_cores; i++) { 72 g_ut_cores[i] = true; 73 } 74 } 75 76 void 77 free_cores(void) 78 { 79 free(g_ut_cores); 80 g_ut_cores = NULL; 81 g_ut_num_cores = 0; 82 } 83 84 static uint32_t 85 ut_get_next_core(uint32_t i) 86 { 87 i++; 88 89 while (i < g_ut_num_cores) { 90 if (!g_ut_cores[i]) { 91 i++; 92 continue; 93 } 94 break; 95 } 96 97 if (i < g_ut_num_cores) { 98 return i; 99 } else { 100 return UINT32_MAX; 101 } 102 } 103 104 uint32_t 105 spdk_env_get_first_core(void) 106 { 107 return ut_get_next_core(-1); 108 } 109 110 uint32_t 111 spdk_env_get_next_core(uint32_t prev_core) 112 { 113 return ut_get_next_core(prev_core); 114 } 115 116 uint32_t 117 spdk_env_get_core_count(void) 118 { 119 return g_ut_num_cores; 120 } 121 122 uint32_t 123 spdk_env_get_last_core(void) 124 { 125 uint32_t i; 126 uint32_t last_core = UINT32_MAX; 127 128 SPDK_ENV_FOREACH_CORE(i) { 129 last_core = i; 130 } 131 132 return last_core; 133 } 134 135 DEFINE_RETURN_MOCK(spdk_env_get_current_core, uint32_t); 136 uint32_t 137 spdk_env_get_current_core(void) 138 { 139 HANDLE_RETURN_MOCK(spdk_env_get_current_core); 140 141 return UINT32_MAX; 142 } 143 144 DEFINE_RETURN_MOCK(spdk_env_get_socket_id, uint32_t); 145 uint32_t 146 spdk_env_get_socket_id(uint32_t core) 147 { 148 HANDLE_RETURN_MOCK(spdk_env_get_socket_id); 149 150 return SPDK_ENV_SOCKET_ID_ANY; 151 } 152 153 /* 154 * These mocks don't use the DEFINE_STUB macros because 155 * their default implementation is more complex. 156 */ 157 158 DEFINE_RETURN_MOCK(spdk_memzone_reserve, void *); 159 void * 160 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) 161 { 162 HANDLE_RETURN_MOCK(spdk_memzone_reserve); 163 164 return malloc(len); 165 } 166 167 DEFINE_RETURN_MOCK(spdk_memzone_reserve_aligned, void *); 168 void * 169 spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id, 170 unsigned flags, unsigned align) 171 { 172 HANDLE_RETURN_MOCK(spdk_memzone_reserve_aligned); 173 174 return malloc(len); 175 } 176 177 DEFINE_RETURN_MOCK(spdk_malloc, void *); 178 void * 179 spdk_malloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags) 180 { 181 HANDLE_RETURN_MOCK(spdk_malloc); 182 183 void *buf = NULL; 184 185 if (align == 0) { 186 align = 8; 187 } 188 189 if (posix_memalign(&buf, align, size)) { 190 return NULL; 191 } 192 if (phys_addr) { 193 *phys_addr = (uint64_t)buf; 194 } 195 196 return buf; 197 } 198 199 DEFINE_RETURN_MOCK(spdk_zmalloc, void *); 200 void * 201 spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags) 202 { 203 HANDLE_RETURN_MOCK(spdk_zmalloc); 204 205 void *buf = spdk_malloc(size, align, phys_addr, -1, 1); 206 207 if (buf != NULL) { 208 memset(buf, 0, size); 209 } 210 return buf; 211 } 212 213 DEFINE_RETURN_MOCK(spdk_dma_malloc, void *); 214 void * 215 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr) 216 { 217 HANDLE_RETURN_MOCK(spdk_dma_malloc); 218 219 return spdk_malloc(size, align, phys_addr, -1, 1); 220 } 221 222 DEFINE_RETURN_MOCK(spdk_realloc, void *); 223 void * 224 spdk_realloc(void *buf, size_t size, size_t align) 225 { 226 HANDLE_RETURN_MOCK(spdk_realloc); 227 228 return realloc(buf, size); 229 } 230 231 DEFINE_RETURN_MOCK(spdk_dma_zmalloc, void *); 232 void * 233 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr) 234 { 235 HANDLE_RETURN_MOCK(spdk_dma_zmalloc); 236 237 return spdk_zmalloc(size, align, phys_addr, -1, 1); 238 } 239 240 DEFINE_RETURN_MOCK(spdk_dma_malloc_socket, void *); 241 void * 242 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id) 243 { 244 HANDLE_RETURN_MOCK(spdk_dma_malloc_socket); 245 246 return spdk_dma_malloc(size, align, phys_addr); 247 } 248 249 DEFINE_RETURN_MOCK(spdk_dma_zmalloc_socket, void *); 250 void * 251 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id) 252 { 253 HANDLE_RETURN_MOCK(spdk_dma_zmalloc_socket); 254 255 return spdk_dma_zmalloc(size, align, phys_addr); 256 } 257 258 DEFINE_RETURN_MOCK(spdk_dma_realloc, void *); 259 void * 260 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr) 261 { 262 HANDLE_RETURN_MOCK(spdk_dma_realloc); 263 264 return realloc(buf, size); 265 } 266 267 void 268 spdk_free(void *buf) 269 { 270 /* fix for false-positives in *certain* static analysis tools. */ 271 assert((uintptr_t)buf != UINTPTR_MAX); 272 free(buf); 273 } 274 275 void 276 spdk_dma_free(void *buf) 277 { 278 return spdk_free(buf); 279 } 280 281 #ifndef UNIT_TEST_NO_VTOPHYS 282 DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t); 283 uint64_t 284 spdk_vtophys(const void *buf, uint64_t *size) 285 { 286 HANDLE_RETURN_MOCK(spdk_vtophys); 287 288 return (uintptr_t)buf; 289 } 290 #endif 291 292 void 293 spdk_memzone_dump(FILE *f) 294 { 295 return; 296 } 297 298 DEFINE_RETURN_MOCK(spdk_memzone_free, int); 299 int 300 spdk_memzone_free(const char *name) 301 { 302 HANDLE_RETURN_MOCK(spdk_memzone_free); 303 304 return 0; 305 } 306 307 struct test_mempool { 308 size_t count; 309 size_t ele_size; 310 }; 311 312 DEFINE_RETURN_MOCK(spdk_mempool_create, struct spdk_mempool *); 313 struct spdk_mempool * 314 spdk_mempool_create(const char *name, size_t count, 315 size_t ele_size, size_t cache_size, int socket_id) 316 { 317 struct test_mempool *mp; 318 319 HANDLE_RETURN_MOCK(spdk_mempool_create); 320 321 mp = calloc(1, sizeof(*mp)); 322 if (mp == NULL) { 323 return NULL; 324 } 325 326 mp->count = count; 327 mp->ele_size = ele_size; 328 329 return (struct spdk_mempool *)mp; 330 } 331 332 void 333 spdk_mempool_free(struct spdk_mempool *_mp) 334 { 335 struct test_mempool *mp = (struct test_mempool *)_mp; 336 337 free(mp); 338 } 339 340 DEFINE_RETURN_MOCK(spdk_mempool_get, void *); 341 void * 342 spdk_mempool_get(struct spdk_mempool *_mp) 343 { 344 struct test_mempool *mp = (struct test_mempool *)_mp; 345 size_t ele_size = 0x10000; 346 void *buf; 347 348 HANDLE_RETURN_MOCK(spdk_mempool_get); 349 350 if (mp && mp->count == 0) { 351 return NULL; 352 } 353 354 if (mp) { 355 ele_size = mp->ele_size; 356 } 357 358 if (posix_memalign(&buf, 64, spdk_align32pow2(ele_size))) { 359 return NULL; 360 } else { 361 if (mp) { 362 mp->count--; 363 } 364 return buf; 365 } 366 } 367 368 int 369 spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count) 370 { 371 struct test_mempool *test_mp = (struct test_mempool *)mp; 372 373 if (test_mp && test_mp->count < count) { 374 return -1; 375 } 376 377 for (size_t i = 0; i < count; i++) { 378 ele_arr[i] = spdk_mempool_get(mp); 379 if (ele_arr[i] == NULL) { 380 return -1; 381 } 382 } 383 return 0; 384 } 385 386 void 387 spdk_mempool_put(struct spdk_mempool *_mp, void *ele) 388 { 389 struct test_mempool *mp = (struct test_mempool *)_mp; 390 391 if (mp) { 392 mp->count++; 393 } 394 free(ele); 395 } 396 397 void 398 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count) 399 { 400 for (size_t i = 0; i < count; i++) { 401 spdk_mempool_put(mp, ele_arr[i]); 402 } 403 } 404 405 DEFINE_RETURN_MOCK(spdk_mempool_count, size_t); 406 size_t 407 spdk_mempool_count(const struct spdk_mempool *_mp) 408 { 409 struct test_mempool *mp = (struct test_mempool *)_mp; 410 411 HANDLE_RETURN_MOCK(spdk_mempool_count); 412 413 if (mp) { 414 return mp->count; 415 } else { 416 return 1024; 417 } 418 } 419 420 struct spdk_ring_ele { 421 void *ele; 422 TAILQ_ENTRY(spdk_ring_ele) link; 423 }; 424 425 struct spdk_ring { 426 TAILQ_HEAD(, spdk_ring_ele) elements; 427 pthread_mutex_t lock; 428 size_t count; 429 }; 430 431 DEFINE_RETURN_MOCK(spdk_ring_create, struct spdk_ring *); 432 struct spdk_ring * 433 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id) 434 { 435 struct spdk_ring *ring; 436 437 HANDLE_RETURN_MOCK(spdk_ring_create); 438 439 ring = calloc(1, sizeof(*ring)); 440 if (!ring) { 441 return NULL; 442 } 443 444 if (pthread_mutex_init(&ring->lock, NULL)) { 445 free(ring); 446 return NULL; 447 } 448 449 TAILQ_INIT(&ring->elements); 450 return ring; 451 } 452 453 void 454 spdk_ring_free(struct spdk_ring *ring) 455 { 456 struct spdk_ring_ele *ele, *tmp; 457 458 if (!ring) { 459 return; 460 } 461 462 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) { 463 free(ele); 464 } 465 466 pthread_mutex_destroy(&ring->lock); 467 free(ring); 468 } 469 470 DEFINE_RETURN_MOCK(spdk_ring_enqueue, size_t); 471 size_t 472 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count, 473 size_t *free_space) 474 { 475 struct spdk_ring_ele *ele; 476 size_t i; 477 478 HANDLE_RETURN_MOCK(spdk_ring_enqueue); 479 480 pthread_mutex_lock(&ring->lock); 481 482 for (i = 0; i < count; i++) { 483 ele = calloc(1, sizeof(*ele)); 484 if (!ele) { 485 break; 486 } 487 488 ele->ele = objs[i]; 489 TAILQ_INSERT_TAIL(&ring->elements, ele, link); 490 ring->count++; 491 } 492 493 pthread_mutex_unlock(&ring->lock); 494 return i; 495 } 496 497 DEFINE_RETURN_MOCK(spdk_ring_dequeue, size_t); 498 size_t 499 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count) 500 { 501 struct spdk_ring_ele *ele, *tmp; 502 size_t i = 0; 503 504 HANDLE_RETURN_MOCK(spdk_ring_dequeue); 505 506 if (count == 0) { 507 return 0; 508 } 509 510 pthread_mutex_lock(&ring->lock); 511 512 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) { 513 TAILQ_REMOVE(&ring->elements, ele, link); 514 ring->count--; 515 objs[i] = ele->ele; 516 free(ele); 517 i++; 518 if (i >= count) { 519 break; 520 } 521 } 522 523 pthread_mutex_unlock(&ring->lock); 524 return i; 525 526 } 527 528 529 DEFINE_RETURN_MOCK(spdk_ring_count, size_t); 530 size_t 531 spdk_ring_count(struct spdk_ring *ring) 532 { 533 HANDLE_RETURN_MOCK(spdk_ring_count); 534 return ring->count; 535 } 536 537 DEFINE_RETURN_MOCK(spdk_get_ticks, uint64_t); 538 uint64_t 539 spdk_get_ticks(void) 540 { 541 HANDLE_RETURN_MOCK(spdk_get_ticks); 542 543 return ut_spdk_get_ticks; 544 } 545 546 DEFINE_RETURN_MOCK(spdk_get_ticks_hz, uint64_t); 547 uint64_t 548 spdk_get_ticks_hz(void) 549 { 550 HANDLE_RETURN_MOCK(spdk_get_ticks_hz); 551 552 return 1000000; 553 } 554 555 void 556 spdk_delay_us(unsigned int us) 557 { 558 /* spdk_get_ticks_hz is 1000000, meaning 1 tick per us. */ 559 ut_spdk_get_ticks += us; 560 } 561 562 #ifndef UNIT_TEST_NO_PCI_ADDR 563 DEFINE_RETURN_MOCK(spdk_pci_addr_parse, int); 564 int 565 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf) 566 { 567 unsigned domain, bus, dev, func; 568 569 HANDLE_RETURN_MOCK(spdk_pci_addr_parse); 570 571 if (addr == NULL || bdf == NULL) { 572 return -EINVAL; 573 } 574 575 if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) || 576 (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) { 577 /* Matched a full address - all variables are initialized */ 578 } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) { 579 func = 0; 580 } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) || 581 (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) { 582 domain = 0; 583 } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) || 584 (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) { 585 domain = 0; 586 func = 0; 587 } else { 588 return -EINVAL; 589 } 590 591 if (bus > 0xFF || dev > 0x1F || func > 7) { 592 return -EINVAL; 593 } 594 595 addr->domain = domain; 596 addr->bus = bus; 597 addr->dev = dev; 598 addr->func = func; 599 600 return 0; 601 } 602 603 DEFINE_RETURN_MOCK(spdk_pci_addr_fmt, int); 604 int 605 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr) 606 { 607 int rc; 608 609 HANDLE_RETURN_MOCK(spdk_pci_addr_fmt); 610 611 rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x", 612 addr->domain, addr->bus, 613 addr->dev, addr->func); 614 615 if (rc > 0 && (size_t)rc < sz) { 616 return 0; 617 } 618 619 return -1; 620 } 621 622 DEFINE_RETURN_MOCK(spdk_pci_addr_compare, int); 623 int 624 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2) 625 { 626 HANDLE_RETURN_MOCK(spdk_pci_addr_compare); 627 628 if (a1->domain > a2->domain) { 629 return 1; 630 } else if (a1->domain < a2->domain) { 631 return -1; 632 } else if (a1->bus > a2->bus) { 633 return 1; 634 } else if (a1->bus < a2->bus) { 635 return -1; 636 } else if (a1->dev > a2->dev) { 637 return 1; 638 } else if (a1->dev < a2->dev) { 639 return -1; 640 } else if (a1->func > a2->func) { 641 return 1; 642 } else if (a1->func < a2->func) { 643 return -1; 644 } 645 646 return 0; 647 } 648 #endif 649