1 /*- 2 * Copyright (c) 2018 VMware, Inc. 3 * 4 * SPDX-License-Identifier: (BSD-2-Clause OR GPL-2.0) 5 */ 6 7 /* This file implements defines and helper functions. */ 8 9 #include <sys/cdefs.h> 10 __FBSDID("$FreeBSD$"); 11 12 #include <sys/malloc.h> 13 #include <sys/proc.h> 14 #include <sys/uio.h> 15 16 #include <machine/bus.h> 17 18 #include "vmci.h" 19 #include "vmci_defs.h" 20 #include "vmci_kernel_defs.h" 21 #include "vmci_kernel_if.h" 22 #include "vmci_queue.h" 23 24 struct vmci_queue_kernel_if { 25 size_t num_pages; /* Num pages incl. header. */ 26 struct vmci_dma_alloc *dmas; /* For dma alloc. */ 27 }; 28 29 /* 30 *------------------------------------------------------------------------------ 31 * 32 * vmci_init_lock 33 * 34 * Initializes the lock. Must be called before use. 35 * 36 * Results: 37 * Always VMCI_SUCCESS. 38 * 39 * Side effects: 40 * Thread can block. 41 * 42 *------------------------------------------------------------------------------ 43 */ 44 45 int 46 vmci_init_lock(vmci_lock *lock, char *name) 47 { 48 49 mtx_init(lock, name, NULL, MTX_DEF | MTX_NOWITNESS); 50 return (VMCI_SUCCESS); 51 } 52 53 /* 54 *------------------------------------------------------------------------------ 55 * 56 * vmci_cleanup_lock 57 * 58 * Cleanup the lock. Must be called before deallocating lock. 59 * 60 * Results: 61 * None 62 * 63 * Side effects: 64 * Deletes kernel lock state 65 * 66 *------------------------------------------------------------------------------ 67 */ 68 69 void 70 vmci_cleanup_lock(vmci_lock *lock) 71 { 72 73 mtx_destroy(lock); 74 } 75 76 /* 77 *------------------------------------------------------------------------------ 78 * 79 * vmci_grab_lock 80 * 81 * Grabs the given lock. 82 * 83 * Results: 84 * None 85 * 86 * Side effects: 87 * Thread can block. 88 * 89 *------------------------------------------------------------------------------ 90 */ 91 92 void 93 vmci_grab_lock(vmci_lock *lock) 94 { 95 96 mtx_lock(lock); 97 } 98 99 /* 100 *------------------------------------------------------------------------------ 101 * 102 * vmci_release_lock 103 * 104 * Releases the given lock. 105 * 106 * Results: 107 * None 108 * 109 * Side effects: 110 * A thread blocked on this lock may wake up. 111 * 112 *------------------------------------------------------------------------------ 113 */ 114 115 void 116 vmci_release_lock(vmci_lock *lock) 117 { 118 119 mtx_unlock(lock); 120 } 121 122 /* 123 *------------------------------------------------------------------------------ 124 * 125 * vmci_grab_lock_bh 126 * 127 * Grabs the given lock. 128 * 129 * Results: 130 * None 131 * 132 * Side effects: 133 * None. 134 * 135 *------------------------------------------------------------------------------ 136 */ 137 138 void 139 vmci_grab_lock_bh(vmci_lock *lock) 140 { 141 142 mtx_lock(lock); 143 } 144 145 /* 146 *------------------------------------------------------------------------------ 147 * 148 * vmci_release_lock_bh 149 * 150 * Releases the given lock. 151 * 152 * Results: 153 * None 154 * 155 * Side effects: 156 * None. 157 * 158 *------------------------------------------------------------------------------ 159 */ 160 161 void 162 vmci_release_lock_bh(vmci_lock *lock) 163 { 164 165 mtx_unlock(lock); 166 } 167 168 /* 169 *------------------------------------------------------------------------------ 170 * 171 * vmci_alloc_kernel_mem 172 * 173 * Allocate physically contiguous memory for the VMCI driver. 174 * 175 * Results: 176 * The address allocated or NULL on error. 177 * 178 * 179 * Side effects: 180 * Memory may be allocated. 181 * 182 *------------------------------------------------------------------------------ 183 */ 184 185 void * 186 vmci_alloc_kernel_mem(size_t size, int flags) 187 { 188 void *ptr; 189 190 if ((flags & VMCI_MEMORY_ATOMIC) != 0) 191 ptr = contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 0xFFFFFFFF, 192 8, 1024 * 1024); 193 else 194 ptr = contigmalloc(size, M_DEVBUF, M_WAITOK, 0, 0xFFFFFFFF, 195 8, 1024 * 1024); 196 197 return (ptr); 198 } 199 200 /* 201 *------------------------------------------------------------------------------ 202 * 203 * vmci_free_kernel_mem 204 * 205 * Free kernel memory allocated for the VMCI driver. 206 * 207 * Results: 208 * None. 209 * 210 * Side effects: 211 * Memory is freed. 212 * 213 *------------------------------------------------------------------------------ 214 */ 215 216 void 217 vmci_free_kernel_mem(void *ptr, size_t size) 218 { 219 220 contigfree(ptr, size, M_DEVBUF); 221 } 222 223 /* 224 *------------------------------------------------------------------------------ 225 * 226 * vmci_can_schedule_delayed_work -- 227 * 228 * Checks to see if the given platform supports delayed work callbacks. 229 * 230 * Results: 231 * true if it does. false otherwise. 232 * 233 * Side effects: 234 * None. 235 * 236 *------------------------------------------------------------------------------ 237 */ 238 239 bool 240 vmci_can_schedule_delayed_work(void) 241 { 242 243 return (true); 244 } 245 246 /* 247 *------------------------------------------------------------------------------ 248 * 249 * vmci_schedule_delayed_work -- 250 * 251 * Schedule the specified callback. 252 * 253 * Results: 254 * Zero on success, error code otherwise. 255 * 256 * Side effects: 257 * None. 258 * 259 *------------------------------------------------------------------------------ 260 */ 261 262 int 263 vmci_schedule_delayed_work(vmci_work_fn *work_fn, void *data) 264 { 265 266 return (vmci_schedule_delayed_work_fn(work_fn, data)); 267 } 268 269 /* 270 *------------------------------------------------------------------------------ 271 * 272 * vmci_create_event -- 273 * 274 * Results: 275 * None. 276 * 277 * Side effects: 278 * None. 279 * 280 *------------------------------------------------------------------------------ 281 */ 282 283 void 284 vmci_create_event(vmci_event *event) 285 { 286 287 sema_init(event, 0, "vmci_event"); 288 } 289 290 /* 291 *------------------------------------------------------------------------------ 292 * 293 * vmci_destroy_event -- 294 * 295 * Results: 296 * None. 297 * 298 * Side effects: 299 * None. 300 * 301 *------------------------------------------------------------------------------ 302 */ 303 304 void 305 vmci_destroy_event(vmci_event *event) 306 { 307 308 if (mtx_owned(&event->sema_mtx)) 309 sema_destroy(event); 310 } 311 312 /* 313 *------------------------------------------------------------------------------ 314 * 315 * vmci_signal_event -- 316 * 317 * Results: 318 * None. 319 * 320 * Side effects: 321 * None. 322 * 323 *------------------------------------------------------------------------------ 324 */ 325 326 void 327 vmci_signal_event(vmci_event *event) 328 { 329 330 sema_post(event); 331 } 332 333 /* 334 *------------------------------------------------------------------------------ 335 * 336 * vmci_wait_on_event -- 337 * 338 * Results: 339 * None. 340 * 341 * Side effects: 342 * None. 343 * 344 *------------------------------------------------------------------------------ 345 */ 346 347 void 348 vmci_wait_on_event(vmci_event *event, vmci_event_release_cb release_cb, 349 void *client_data) 350 { 351 352 release_cb(client_data); 353 sema_wait(event); 354 } 355 356 /* 357 *------------------------------------------------------------------------------ 358 * 359 * vmci_mutex_init -- 360 * 361 * Initializes the mutex. Must be called before use. 362 * 363 * Results: 364 * Success. 365 * 366 * Side effects: 367 * None. 368 * 369 *------------------------------------------------------------------------------ 370 */ 371 372 int 373 vmci_mutex_init(vmci_mutex *mutex, char *name) 374 { 375 376 mtx_init(mutex, name, NULL, MTX_DEF | MTX_NOWITNESS); 377 return (VMCI_SUCCESS); 378 } 379 380 /* 381 *------------------------------------------------------------------------------ 382 * 383 * vmci_mutex_destroy -- 384 * 385 * Destroys the mutex. 386 * 387 * Results: 388 * None. 389 * 390 * Side effects: 391 * None. 392 * 393 *------------------------------------------------------------------------------ 394 */ 395 396 void 397 vmci_mutex_destroy(vmci_mutex *mutex) 398 { 399 400 mtx_destroy(mutex); 401 } 402 403 /* 404 *------------------------------------------------------------------------------ 405 * 406 * vmci_mutex_acquire -- 407 * 408 * Acquires the mutex. 409 * 410 * Results: 411 * None. 412 * 413 * Side effects: 414 * Thread may block. 415 * 416 *------------------------------------------------------------------------------ 417 */ 418 419 void 420 vmci_mutex_acquire(vmci_mutex *mutex) 421 { 422 423 mtx_lock(mutex); 424 } 425 426 /* 427 *------------------------------------------------------------------------------ 428 * 429 * vmci_mutex_release -- 430 * 431 * Releases the mutex. 432 * 433 * Results: 434 * None. 435 * 436 * Side effects: 437 * May wake up the thread blocking on this mutex. 438 * 439 *------------------------------------------------------------------------------ 440 */ 441 442 void 443 vmci_mutex_release(vmci_mutex *mutex) 444 { 445 446 mtx_unlock(mutex); 447 } 448 449 /* 450 *------------------------------------------------------------------------------ 451 * 452 * vmci_alloc_queue -- 453 * 454 * Allocates kernel queue pages of specified size with IOMMU mappings, plus 455 * space for the queue structure/kernel interface and the queue header. 456 * 457 * Results: 458 * Pointer to the queue on success, NULL otherwise. 459 * 460 * Side effects: 461 * Memory is allocated. 462 * 463 *------------------------------------------------------------------------------ 464 */ 465 466 void * 467 vmci_alloc_queue(uint64_t size, uint32_t flags) 468 { 469 struct vmci_queue *queue; 470 size_t i; 471 const size_t num_pages = CEILING(size, PAGE_SIZE) + 1; 472 const size_t dmas_size = num_pages * sizeof(struct vmci_dma_alloc); 473 const size_t queue_size = 474 sizeof(*queue) + sizeof(*(queue->kernel_if)) + dmas_size; 475 476 /* Size should be enforced by vmci_qpair_alloc(), double-check here. */ 477 if (size > VMCI_MAX_GUEST_QP_MEMORY) { 478 ASSERT(false); 479 return (NULL); 480 } 481 482 queue = malloc(queue_size, M_DEVBUF, M_NOWAIT); 483 if (!queue) 484 return (NULL); 485 486 queue->q_header = NULL; 487 queue->saved_header = NULL; 488 queue->kernel_if = (struct vmci_queue_kernel_if *)(queue + 1); 489 queue->kernel_if->num_pages = num_pages; 490 queue->kernel_if->dmas = (struct vmci_dma_alloc *)(queue->kernel_if + 491 1); 492 for (i = 0; i < num_pages; i++) { 493 vmci_dma_malloc(PAGE_SIZE, 1, &queue->kernel_if->dmas[i]); 494 if (!queue->kernel_if->dmas[i].dma_vaddr) { 495 /* Size excl. the header. */ 496 vmci_free_queue(queue, i * PAGE_SIZE); 497 return (NULL); 498 } 499 } 500 501 /* Queue header is the first page. */ 502 queue->q_header = (void *)queue->kernel_if->dmas[0].dma_vaddr; 503 504 return ((void *)queue); 505 } 506 507 /* 508 *------------------------------------------------------------------------------ 509 * 510 * vmci_free_queue -- 511 * 512 * Frees kernel VA space for a given queue and its queue header, and frees 513 * physical data pages. 514 * 515 * Results: 516 * None. 517 * 518 * Side effects: 519 * Memory is freed. 520 * 521 *------------------------------------------------------------------------------ 522 */ 523 524 void 525 vmci_free_queue(void *q, uint64_t size) 526 { 527 struct vmci_queue *queue = q; 528 529 if (queue) { 530 const size_t num_pages = CEILING(size, PAGE_SIZE) + 1; 531 uint64_t i; 532 533 /* Given size doesn't include header, so add in a page here. */ 534 for (i = 0; i < num_pages; i++) 535 vmci_dma_free(&queue->kernel_if->dmas[i]); 536 free(queue, M_DEVBUF); 537 } 538 } 539 540 /* 541 *------------------------------------------------------------------------------ 542 * 543 * vmci_alloc_ppn_set -- 544 * 545 * Allocates two list of PPNs --- one for the pages in the produce queue, 546 * and the other for the pages in the consume queue. Intializes the list of 547 * PPNs with the page frame numbers of the KVA for the two queues (and the 548 * queue headers). 549 * 550 * Results: 551 * Success or failure. 552 * 553 * Side effects: 554 * Memory may be allocated. 555 * 556 *----------------------------------------------------------------------------- 557 */ 558 559 int 560 vmci_alloc_ppn_set(void *prod_q, uint64_t num_produce_pages, void *cons_q, 561 uint64_t num_consume_pages, struct ppn_set *ppn_set) 562 { 563 struct vmci_queue *consume_q = cons_q; 564 struct vmci_queue *produce_q = prod_q; 565 vmci_ppn_list consume_ppns; 566 vmci_ppn_list produce_ppns; 567 uint64_t i; 568 569 if (!produce_q || !num_produce_pages || !consume_q || 570 !num_consume_pages || !ppn_set) 571 return (VMCI_ERROR_INVALID_ARGS); 572 573 if (ppn_set->initialized) 574 return (VMCI_ERROR_ALREADY_EXISTS); 575 576 produce_ppns = 577 vmci_alloc_kernel_mem(num_produce_pages * sizeof(*produce_ppns), 578 VMCI_MEMORY_NORMAL); 579 if (!produce_ppns) 580 return (VMCI_ERROR_NO_MEM); 581 582 consume_ppns = 583 vmci_alloc_kernel_mem(num_consume_pages * sizeof(*consume_ppns), 584 VMCI_MEMORY_NORMAL); 585 if (!consume_ppns) { 586 vmci_free_kernel_mem(produce_ppns, 587 num_produce_pages * sizeof(*produce_ppns)); 588 return (VMCI_ERROR_NO_MEM); 589 } 590 591 for (i = 0; i < num_produce_pages; i++) { 592 unsigned long pfn; 593 594 produce_ppns[i] = 595 pfn = produce_q->kernel_if->dmas[i].dma_paddr >> PAGE_SHIFT; 596 597 /* 598 * Fail allocation if PFN isn't supported by hypervisor. 599 */ 600 601 if (sizeof(pfn) > 602 sizeof(*produce_ppns) && pfn != produce_ppns[i]) 603 goto ppn_error; 604 } 605 for (i = 0; i < num_consume_pages; i++) { 606 unsigned long pfn; 607 608 consume_ppns[i] = 609 pfn = consume_q->kernel_if->dmas[i].dma_paddr >> PAGE_SHIFT; 610 611 /* 612 * Fail allocation if PFN isn't supported by hypervisor. 613 */ 614 615 if (sizeof(pfn) > 616 sizeof(*consume_ppns) && pfn != consume_ppns[i]) 617 goto ppn_error; 618 619 } 620 621 ppn_set->num_produce_pages = num_produce_pages; 622 ppn_set->num_consume_pages = num_consume_pages; 623 ppn_set->produce_ppns = produce_ppns; 624 ppn_set->consume_ppns = consume_ppns; 625 ppn_set->initialized = true; 626 return (VMCI_SUCCESS); 627 628 ppn_error: 629 vmci_free_kernel_mem(produce_ppns, num_produce_pages * 630 sizeof(*produce_ppns)); 631 vmci_free_kernel_mem(consume_ppns, num_consume_pages * 632 sizeof(*consume_ppns)); 633 return (VMCI_ERROR_INVALID_ARGS); 634 } 635 636 /* 637 *------------------------------------------------------------------------------ 638 * 639 * vmci_free_ppn_set -- 640 * 641 * Frees the two list of PPNs for a queue pair. 642 * 643 * Results: 644 * None. 645 * 646 * Side effects: 647 * None. 648 * 649 *------------------------------------------------------------------------------ 650 */ 651 652 void 653 vmci_free_ppn_set(struct ppn_set *ppn_set) 654 { 655 656 ASSERT(ppn_set); 657 if (ppn_set->initialized) { 658 /* Do not call these functions on NULL inputs. */ 659 ASSERT(ppn_set->produce_ppns && ppn_set->consume_ppns); 660 vmci_free_kernel_mem(ppn_set->produce_ppns, 661 ppn_set->num_produce_pages * 662 sizeof(*ppn_set->produce_ppns)); 663 vmci_free_kernel_mem(ppn_set->consume_ppns, 664 ppn_set->num_consume_pages * 665 sizeof(*ppn_set->consume_ppns)); 666 } 667 memset(ppn_set, 0, sizeof(*ppn_set)); 668 } 669 670 /* 671 *------------------------------------------------------------------------------ 672 * 673 * vmci_populate_ppn_list -- 674 * 675 * Populates the list of PPNs in the hypercall structure with the PPNS 676 * of the produce queue and the consume queue. 677 * 678 * Results: 679 * VMCI_SUCCESS. 680 * 681 * Side effects: 682 * None. 683 * 684 *------------------------------------------------------------------------------ 685 */ 686 687 int 688 vmci_populate_ppn_list(uint8_t *call_buf, const struct ppn_set *ppn_set) 689 { 690 691 ASSERT(call_buf && ppn_set && ppn_set->initialized); 692 memcpy(call_buf, ppn_set->produce_ppns, 693 ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns)); 694 memcpy(call_buf + ppn_set->num_produce_pages * 695 sizeof(*ppn_set->produce_ppns), ppn_set->consume_ppns, 696 ppn_set->num_consume_pages * sizeof(*ppn_set->consume_ppns)); 697 698 return (VMCI_SUCCESS); 699 } 700 701 /* 702 *------------------------------------------------------------------------------ 703 * 704 * vmci_memcpy_{to,from}iovec -- 705 * 706 * These helper routines will copy the specified bytes to/from memory that's 707 * specified as a struct iovec. The routines can not verify the correctness 708 * of the struct iovec's contents. 709 * 710 * Results: 711 * None. 712 * 713 * Side effects: 714 * None. 715 * 716 *------------------------------------------------------------------------------ 717 */ 718 719 static inline void 720 vmci_memcpy_toiovec(struct iovec *iov, uint8_t *src, size_t len) 721 { 722 723 while (len > 0) { 724 if (iov->iov_len) { 725 size_t to_copy = MIN(iov->iov_len, len); 726 memcpy(iov->iov_base, src, to_copy); 727 src += to_copy; 728 len -= to_copy; 729 iov->iov_base = (void *)((uintptr_t) iov->iov_base + 730 to_copy); 731 iov->iov_len -= to_copy; 732 } 733 iov++; 734 } 735 } 736 737 static inline void 738 vmci_memcpy_fromiovec(uint8_t *dst, struct iovec *iov, size_t len) 739 { 740 741 while (len > 0) { 742 if (iov->iov_len) { 743 size_t to_copy = MIN(iov->iov_len, len); 744 memcpy(dst, iov->iov_base, to_copy); 745 dst += to_copy; 746 len -= to_copy; 747 iov->iov_base = (void *)((uintptr_t) iov->iov_base + 748 to_copy); 749 iov->iov_len -= to_copy; 750 } 751 iov++; 752 } 753 } 754 755 /* 756 *------------------------------------------------------------------------------ 757 * 758 * __vmci_memcpy_to_queue -- 759 * 760 * Copies from a given buffer or iovector to a VMCI Queue. Assumes that 761 * offset + size does not wrap around in the queue. 762 * 763 * Results: 764 * Zero on success, negative error code on failure. 765 * 766 * Side effects: 767 * None. 768 * 769 *------------------------------------------------------------------------------ 770 */ 771 772 #pragma GCC diagnostic ignored "-Wcast-qual" 773 static int 774 __vmci_memcpy_to_queue(struct vmci_queue *queue, uint64_t queue_offset, 775 const void *src, size_t size, bool is_iovec) 776 { 777 struct vmci_queue_kernel_if *kernel_if = queue->kernel_if; 778 size_t bytes_copied = 0; 779 780 while (bytes_copied < size) { 781 const uint64_t page_index = 782 (queue_offset + bytes_copied) / PAGE_SIZE; 783 const size_t page_offset = 784 (queue_offset + bytes_copied) & (PAGE_SIZE - 1); 785 void *va; 786 size_t to_copy; 787 788 /* Skip header. */ 789 va = (void *)kernel_if->dmas[page_index + 1].dma_vaddr; 790 791 ASSERT(va); 792 /* 793 * Fill up the page if we have enough payload, or else 794 * copy the remaining bytes. 795 */ 796 to_copy = MIN(PAGE_SIZE - page_offset, size - bytes_copied); 797 798 if (is_iovec) { 799 struct iovec *iov = (struct iovec *)src; 800 801 /* The iovec will track bytes_copied internally. */ 802 vmci_memcpy_fromiovec((uint8_t *)va + page_offset, 803 iov, to_copy); 804 } else 805 memcpy((uint8_t *)va + page_offset, 806 (uint8_t *)src + bytes_copied, to_copy); 807 bytes_copied += to_copy; 808 } 809 810 return (VMCI_SUCCESS); 811 } 812 813 /* 814 *------------------------------------------------------------------------------ 815 * 816 * __vmci_memcpy_from_queue -- 817 * 818 * Copies to a given buffer or iovector from a VMCI Queue. Assumes that 819 * offset + size does not wrap around in the queue. 820 * 821 * Results: 822 * Zero on success, negative error code on failure. 823 * 824 * Side effects: 825 * None. 826 * 827 *------------------------------------------------------------------------------ 828 */ 829 830 static int 831 __vmci_memcpy_from_queue(void *dest, const struct vmci_queue *queue, 832 uint64_t queue_offset, size_t size, bool is_iovec) 833 { 834 struct vmci_queue_kernel_if *kernel_if = queue->kernel_if; 835 size_t bytes_copied = 0; 836 837 while (bytes_copied < size) { 838 const uint64_t page_index = 839 (queue_offset + bytes_copied) / PAGE_SIZE; 840 const size_t page_offset = 841 (queue_offset + bytes_copied) & (PAGE_SIZE - 1); 842 void *va; 843 size_t to_copy; 844 845 /* Skip header. */ 846 va = (void *)kernel_if->dmas[page_index + 1].dma_vaddr; 847 848 ASSERT(va); 849 /* 850 * Fill up the page if we have enough payload, or else 851 * copy the remaining bytes. 852 */ 853 to_copy = MIN(PAGE_SIZE - page_offset, size - bytes_copied); 854 855 if (is_iovec) { 856 struct iovec *iov = (struct iovec *)dest; 857 858 /* The iovec will track bytesCopied internally. */ 859 vmci_memcpy_toiovec(iov, (uint8_t *)va + 860 page_offset, to_copy); 861 } else 862 memcpy((uint8_t *)dest + bytes_copied, 863 (uint8_t *)va + page_offset, to_copy); 864 865 bytes_copied += to_copy; 866 } 867 868 return (VMCI_SUCCESS); 869 } 870 871 /* 872 *------------------------------------------------------------------------------ 873 * 874 * vmci_memcpy_to_queue -- 875 * 876 * Copies from a given buffer to a VMCI Queue. 877 * 878 * Results: 879 * Zero on success, negative error code on failure. 880 * 881 * Side effects: 882 * None. 883 * 884 *------------------------------------------------------------------------------ 885 */ 886 887 int 888 vmci_memcpy_to_queue(struct vmci_queue *queue, uint64_t queue_offset, 889 const void *src, size_t src_offset, size_t size, int buf_type, 890 bool can_block) 891 { 892 893 ASSERT(can_block); 894 895 return (__vmci_memcpy_to_queue(queue, queue_offset, 896 (uint8_t *)src + src_offset, size, false)); 897 } 898 899 /* 900 *------------------------------------------------------------------------------ 901 * 902 * vmci_memcpy_from_queue -- 903 * 904 * Copies to a given buffer from a VMCI Queue. 905 * 906 * Results: 907 * Zero on success, negative error code on failure. 908 * 909 * Side effects: 910 * None. 911 * 912 *------------------------------------------------------------------------------ 913 */ 914 915 int 916 vmci_memcpy_from_queue(void *dest, size_t dest_offset, 917 const struct vmci_queue *queue, uint64_t queue_offset, size_t size, 918 int buf_type, bool can_block) 919 { 920 921 ASSERT(can_block); 922 923 return (__vmci_memcpy_from_queue((uint8_t *)dest + dest_offset, 924 queue, queue_offset, size, false)); 925 } 926 927 /* 928 *------------------------------------------------------------------------------ 929 * 930 * vmci_memcpy_to_queue_local -- 931 * 932 * Copies from a given buffer to a local VMCI queue. This is the 933 * same as a regular copy. 934 * 935 * Results: 936 * Zero on success, negative error code on failure. 937 * 938 * Side effects: 939 * None. 940 * 941 *------------------------------------------------------------------------------ 942 */ 943 944 int 945 vmci_memcpy_to_queue_local(struct vmci_queue *queue, uint64_t queue_offset, 946 const void *src, size_t src_offset, size_t size, int buf_type, 947 bool can_block) 948 { 949 950 ASSERT(can_block); 951 952 return (__vmci_memcpy_to_queue(queue, queue_offset, 953 (uint8_t *)src + src_offset, size, false)); 954 } 955 956 /* 957 *------------------------------------------------------------------------------ 958 * 959 * vmci_memcpy_from_queue_local -- 960 * 961 * Copies to a given buffer from a VMCI Queue. 962 * 963 * Results: 964 * Zero on success, negative error code on failure. 965 * 966 * Side effects: 967 * None. 968 * 969 *------------------------------------------------------------------------------ 970 */ 971 972 int 973 vmci_memcpy_from_queue_local(void *dest, size_t dest_offset, 974 const struct vmci_queue *queue, uint64_t queue_offset, size_t size, 975 int buf_type, bool can_block) 976 { 977 978 ASSERT(can_block); 979 980 return (__vmci_memcpy_from_queue((uint8_t *)dest + dest_offset, 981 queue, queue_offset, size, false)); 982 } 983 984 /*------------------------------------------------------------------------------ 985 * 986 * vmci_memcpy_to_queue_v -- 987 * 988 * Copies from a given iovec from a VMCI Queue. 989 * 990 * Results: 991 * Zero on success, negative error code on failure. 992 * 993 * Side effects: 994 * None. 995 * 996 *------------------------------------------------------------------------------ 997 */ 998 999 int 1000 vmci_memcpy_to_queue_v(struct vmci_queue *queue, uint64_t queue_offset, 1001 const void *src, size_t src_offset, size_t size, int buf_type, 1002 bool can_block) 1003 { 1004 1005 ASSERT(can_block); 1006 1007 /* 1008 * We ignore src_offset because src is really a struct iovec * and will 1009 * maintain offset internally. 1010 */ 1011 return (__vmci_memcpy_to_queue(queue, queue_offset, src, size, 1012 true)); 1013 } 1014 1015 /* 1016 *------------------------------------------------------------------------------ 1017 * 1018 * vmci_memcpy_from_queue_v -- 1019 * 1020 * Copies to a given iovec from a VMCI Queue. 1021 * 1022 * Results: 1023 * Zero on success, negative error code on failure. 1024 * 1025 * Side effects: 1026 * None. 1027 * 1028 *------------------------------------------------------------------------------ 1029 */ 1030 1031 int 1032 vmci_memcpy_from_queue_v(void *dest, size_t dest_offset, 1033 const struct vmci_queue *queue, uint64_t queue_offset, size_t size, 1034 int buf_type, bool can_block) 1035 { 1036 1037 ASSERT(can_block); 1038 1039 /* 1040 * We ignore dest_offset because dest is really a struct iovec * and 1041 * will maintain offset internally. 1042 */ 1043 return (__vmci_memcpy_from_queue(dest, queue, queue_offset, size, 1044 true)); 1045 } 1046 1047 /* 1048 *------------------------------------------------------------------------------ 1049 * 1050 * vmci_read_port_bytes -- 1051 * 1052 * Copy memory from an I/O port to kernel memory. 1053 * 1054 * Results: 1055 * No results. 1056 * 1057 * Side effects: 1058 * None. 1059 * 1060 *------------------------------------------------------------------------------ 1061 */ 1062 1063 void 1064 vmci_read_port_bytes(vmci_io_handle handle, vmci_io_port port, uint8_t *buffer, 1065 size_t buffer_length) 1066 { 1067 1068 insb(port, buffer, buffer_length); 1069 } 1070