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