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