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