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