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