163a93856SMark Peek /*- 23eeb7511SMark Peek * Copyright (c) 2018 VMware, Inc. 363a93856SMark Peek * 48c302b2eSMark Peek * SPDX-License-Identifier: (BSD-2-Clause OR GPL-2.0) 563a93856SMark Peek */ 663a93856SMark Peek 763a93856SMark Peek /* This file implements defines and helper functions. */ 863a93856SMark Peek 963a93856SMark Peek #include <sys/cdefs.h> 1063a93856SMark Peek __FBSDID("$FreeBSD$"); 1163a93856SMark Peek 1263a93856SMark Peek #include <sys/malloc.h> 1363a93856SMark Peek #include <sys/proc.h> 1463a93856SMark Peek #include <sys/uio.h> 1563a93856SMark Peek 1663a93856SMark Peek #include <machine/bus.h> 1763a93856SMark Peek 1863a93856SMark Peek #include "vmci.h" 1963a93856SMark Peek #include "vmci_defs.h" 2063a93856SMark Peek #include "vmci_kernel_defs.h" 2163a93856SMark Peek #include "vmci_kernel_if.h" 2263a93856SMark Peek #include "vmci_queue.h" 2363a93856SMark Peek 2463a93856SMark Peek struct vmci_queue_kernel_if { 2563a93856SMark Peek size_t num_pages; /* Num pages incl. header. */ 2663a93856SMark Peek struct vmci_dma_alloc *dmas; /* For dma alloc. */ 2763a93856SMark Peek }; 2863a93856SMark Peek 2963a93856SMark Peek /* 3063a93856SMark Peek *------------------------------------------------------------------------------ 3163a93856SMark Peek * 3263a93856SMark Peek * vmci_init_lock 3363a93856SMark Peek * 3463a93856SMark Peek * Initializes the lock. Must be called before use. 3563a93856SMark Peek * 3663a93856SMark Peek * Results: 3763a93856SMark Peek * Always VMCI_SUCCESS. 3863a93856SMark Peek * 3963a93856SMark Peek * Side effects: 4063a93856SMark Peek * Thread can block. 4163a93856SMark Peek * 4263a93856SMark Peek *------------------------------------------------------------------------------ 4363a93856SMark Peek */ 4463a93856SMark Peek 4563a93856SMark Peek int 4663a93856SMark Peek vmci_init_lock(vmci_lock *lock, char *name) 4763a93856SMark Peek { 4863a93856SMark Peek 4963a93856SMark Peek mtx_init(lock, name, NULL, MTX_DEF | MTX_NOWITNESS); 5063a93856SMark Peek return (VMCI_SUCCESS); 5163a93856SMark Peek } 5263a93856SMark Peek 5363a93856SMark Peek /* 5463a93856SMark Peek *------------------------------------------------------------------------------ 5563a93856SMark Peek * 5663a93856SMark Peek * vmci_cleanup_lock 5763a93856SMark Peek * 5863a93856SMark Peek * Cleanup the lock. Must be called before deallocating lock. 5963a93856SMark Peek * 6063a93856SMark Peek * Results: 6163a93856SMark Peek * None 6263a93856SMark Peek * 6363a93856SMark Peek * Side effects: 6463a93856SMark Peek * Deletes kernel lock state 6563a93856SMark Peek * 6663a93856SMark Peek *------------------------------------------------------------------------------ 6763a93856SMark Peek */ 6863a93856SMark Peek 6963a93856SMark Peek void 7063a93856SMark Peek vmci_cleanup_lock(vmci_lock *lock) 7163a93856SMark Peek { 7263a93856SMark Peek 730f14bcbeSMark Peek if mtx_initialized(lock) 7463a93856SMark Peek mtx_destroy(lock); 7563a93856SMark Peek } 7663a93856SMark Peek 7763a93856SMark Peek /* 7863a93856SMark Peek *------------------------------------------------------------------------------ 7963a93856SMark Peek * 8063a93856SMark Peek * vmci_grab_lock 8163a93856SMark Peek * 8263a93856SMark Peek * Grabs the given lock. 8363a93856SMark Peek * 8463a93856SMark Peek * Results: 8563a93856SMark Peek * None 8663a93856SMark Peek * 8763a93856SMark Peek * Side effects: 8863a93856SMark Peek * Thread can block. 8963a93856SMark Peek * 9063a93856SMark Peek *------------------------------------------------------------------------------ 9163a93856SMark Peek */ 9263a93856SMark Peek 9363a93856SMark Peek void 9463a93856SMark Peek vmci_grab_lock(vmci_lock *lock) 9563a93856SMark Peek { 9663a93856SMark Peek 9763a93856SMark Peek mtx_lock(lock); 9863a93856SMark Peek } 9963a93856SMark Peek 10063a93856SMark Peek /* 10163a93856SMark Peek *------------------------------------------------------------------------------ 10263a93856SMark Peek * 10363a93856SMark Peek * vmci_release_lock 10463a93856SMark Peek * 10563a93856SMark Peek * Releases the given lock. 10663a93856SMark Peek * 10763a93856SMark Peek * Results: 10863a93856SMark Peek * None 10963a93856SMark Peek * 11063a93856SMark Peek * Side effects: 11163a93856SMark Peek * A thread blocked on this lock may wake up. 11263a93856SMark Peek * 11363a93856SMark Peek *------------------------------------------------------------------------------ 11463a93856SMark Peek */ 11563a93856SMark Peek 11663a93856SMark Peek void 11763a93856SMark Peek vmci_release_lock(vmci_lock *lock) 11863a93856SMark Peek { 11963a93856SMark Peek 12063a93856SMark Peek mtx_unlock(lock); 12163a93856SMark Peek } 12263a93856SMark Peek 12363a93856SMark Peek /* 12463a93856SMark Peek *------------------------------------------------------------------------------ 12563a93856SMark Peek * 12663a93856SMark Peek * vmci_grab_lock_bh 12763a93856SMark Peek * 12863a93856SMark Peek * Grabs the given lock. 12963a93856SMark Peek * 13063a93856SMark Peek * Results: 13163a93856SMark Peek * None 13263a93856SMark Peek * 13363a93856SMark Peek * Side effects: 13463a93856SMark Peek * None. 13563a93856SMark Peek * 13663a93856SMark Peek *------------------------------------------------------------------------------ 13763a93856SMark Peek */ 13863a93856SMark Peek 13963a93856SMark Peek void 14063a93856SMark Peek vmci_grab_lock_bh(vmci_lock *lock) 14163a93856SMark Peek { 14263a93856SMark Peek 14363a93856SMark Peek mtx_lock(lock); 14463a93856SMark Peek } 14563a93856SMark Peek 14663a93856SMark Peek /* 14763a93856SMark Peek *------------------------------------------------------------------------------ 14863a93856SMark Peek * 14963a93856SMark Peek * vmci_release_lock_bh 15063a93856SMark Peek * 15163a93856SMark Peek * Releases the given lock. 15263a93856SMark Peek * 15363a93856SMark Peek * Results: 15463a93856SMark Peek * None 15563a93856SMark Peek * 15663a93856SMark Peek * Side effects: 15763a93856SMark Peek * None. 15863a93856SMark Peek * 15963a93856SMark Peek *------------------------------------------------------------------------------ 16063a93856SMark Peek */ 16163a93856SMark Peek 16263a93856SMark Peek void 16363a93856SMark Peek vmci_release_lock_bh(vmci_lock *lock) 16463a93856SMark Peek { 16563a93856SMark Peek 16663a93856SMark Peek mtx_unlock(lock); 16763a93856SMark Peek } 16863a93856SMark Peek 16963a93856SMark Peek /* 17063a93856SMark Peek *------------------------------------------------------------------------------ 17163a93856SMark Peek * 1720f14bcbeSMark Peek * vmci_initialized_lock 1730f14bcbeSMark Peek * 1740f14bcbeSMark Peek * Returns whether a lock has been initialized. 1750f14bcbeSMark Peek * 1760f14bcbeSMark Peek * Results: 1770f14bcbeSMark Peek * Return 1 if initialized or 0 if unininitialized. 1780f14bcbeSMark Peek * 1790f14bcbeSMark Peek * Side effects: 1800f14bcbeSMark Peek * None 1810f14bcbeSMark Peek * 1820f14bcbeSMark Peek *------------------------------------------------------------------------------ 1830f14bcbeSMark Peek */ 1840f14bcbeSMark Peek 1850f14bcbeSMark Peek int 1860f14bcbeSMark Peek vmci_initialized_lock(vmci_lock *lock) 1870f14bcbeSMark Peek { 1880f14bcbeSMark Peek 1890f14bcbeSMark Peek return mtx_initialized(lock); 1900f14bcbeSMark Peek } 1910f14bcbeSMark Peek 1920f14bcbeSMark Peek /* 1930f14bcbeSMark Peek *------------------------------------------------------------------------------ 1940f14bcbeSMark Peek * 19563a93856SMark Peek * vmci_alloc_kernel_mem 19663a93856SMark Peek * 19763a93856SMark Peek * Allocate physically contiguous memory for the VMCI driver. 19863a93856SMark Peek * 19963a93856SMark Peek * Results: 20063a93856SMark Peek * The address allocated or NULL on error. 20163a93856SMark Peek * 20263a93856SMark Peek * 20363a93856SMark Peek * Side effects: 20463a93856SMark Peek * Memory may be allocated. 20563a93856SMark Peek * 20663a93856SMark Peek *------------------------------------------------------------------------------ 20763a93856SMark Peek */ 20863a93856SMark Peek 20963a93856SMark Peek void * 21063a93856SMark Peek vmci_alloc_kernel_mem(size_t size, int flags) 21163a93856SMark Peek { 21263a93856SMark Peek void *ptr; 21363a93856SMark Peek 21463a93856SMark Peek if ((flags & VMCI_MEMORY_ATOMIC) != 0) 21563a93856SMark Peek ptr = contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 0xFFFFFFFF, 21663a93856SMark Peek 8, 1024 * 1024); 21763a93856SMark Peek else 21863a93856SMark Peek ptr = contigmalloc(size, M_DEVBUF, M_WAITOK, 0, 0xFFFFFFFF, 21963a93856SMark Peek 8, 1024 * 1024); 22063a93856SMark Peek 22163a93856SMark Peek return (ptr); 22263a93856SMark Peek } 22363a93856SMark Peek 22463a93856SMark Peek /* 22563a93856SMark Peek *------------------------------------------------------------------------------ 22663a93856SMark Peek * 22763a93856SMark Peek * vmci_free_kernel_mem 22863a93856SMark Peek * 22963a93856SMark Peek * Free kernel memory allocated for the VMCI driver. 23063a93856SMark Peek * 23163a93856SMark Peek * Results: 23263a93856SMark Peek * None. 23363a93856SMark Peek * 23463a93856SMark Peek * Side effects: 23563a93856SMark Peek * Memory is freed. 23663a93856SMark Peek * 23763a93856SMark Peek *------------------------------------------------------------------------------ 23863a93856SMark Peek */ 23963a93856SMark Peek 24063a93856SMark Peek void 24163a93856SMark Peek vmci_free_kernel_mem(void *ptr, size_t size) 24263a93856SMark Peek { 24363a93856SMark Peek 24463a93856SMark Peek contigfree(ptr, size, M_DEVBUF); 24563a93856SMark Peek } 24663a93856SMark Peek 24763a93856SMark Peek /* 24863a93856SMark Peek *------------------------------------------------------------------------------ 24963a93856SMark Peek * 25063a93856SMark Peek * vmci_can_schedule_delayed_work -- 25163a93856SMark Peek * 25263a93856SMark Peek * Checks to see if the given platform supports delayed work callbacks. 25363a93856SMark Peek * 25463a93856SMark Peek * Results: 25563a93856SMark Peek * true if it does. false otherwise. 25663a93856SMark Peek * 25763a93856SMark Peek * Side effects: 25863a93856SMark Peek * None. 25963a93856SMark Peek * 26063a93856SMark Peek *------------------------------------------------------------------------------ 26163a93856SMark Peek */ 26263a93856SMark Peek 26363a93856SMark Peek bool 26463a93856SMark Peek vmci_can_schedule_delayed_work(void) 26563a93856SMark Peek { 26663a93856SMark Peek 26763a93856SMark Peek return (true); 26863a93856SMark Peek } 26963a93856SMark Peek 27063a93856SMark Peek /* 27163a93856SMark Peek *------------------------------------------------------------------------------ 27263a93856SMark Peek * 27363a93856SMark Peek * vmci_schedule_delayed_work -- 27463a93856SMark Peek * 27563a93856SMark Peek * Schedule the specified callback. 27663a93856SMark Peek * 27763a93856SMark Peek * Results: 27863a93856SMark Peek * Zero on success, error code otherwise. 27963a93856SMark Peek * 28063a93856SMark Peek * Side effects: 28163a93856SMark Peek * None. 28263a93856SMark Peek * 28363a93856SMark Peek *------------------------------------------------------------------------------ 28463a93856SMark Peek */ 28563a93856SMark Peek 28663a93856SMark Peek int 28763a93856SMark Peek vmci_schedule_delayed_work(vmci_work_fn *work_fn, void *data) 28863a93856SMark Peek { 28963a93856SMark Peek 29063a93856SMark Peek return (vmci_schedule_delayed_work_fn(work_fn, data)); 29163a93856SMark Peek } 29263a93856SMark Peek 29363a93856SMark Peek /* 29463a93856SMark Peek *------------------------------------------------------------------------------ 29563a93856SMark Peek * 29663a93856SMark Peek * vmci_create_event -- 29763a93856SMark Peek * 29863a93856SMark Peek * Results: 29963a93856SMark Peek * None. 30063a93856SMark Peek * 30163a93856SMark Peek * Side effects: 30263a93856SMark Peek * None. 30363a93856SMark Peek * 30463a93856SMark Peek *------------------------------------------------------------------------------ 30563a93856SMark Peek */ 30663a93856SMark Peek 30763a93856SMark Peek void 30863a93856SMark Peek vmci_create_event(vmci_event *event) 30963a93856SMark Peek { 31063a93856SMark Peek 31163a93856SMark Peek sema_init(event, 0, "vmci_event"); 31263a93856SMark Peek } 31363a93856SMark Peek 31463a93856SMark Peek /* 31563a93856SMark Peek *------------------------------------------------------------------------------ 31663a93856SMark Peek * 31763a93856SMark Peek * vmci_destroy_event -- 31863a93856SMark Peek * 31963a93856SMark Peek * Results: 32063a93856SMark Peek * None. 32163a93856SMark Peek * 32263a93856SMark Peek * Side effects: 32363a93856SMark Peek * None. 32463a93856SMark Peek * 32563a93856SMark Peek *------------------------------------------------------------------------------ 32663a93856SMark Peek */ 32763a93856SMark Peek 32863a93856SMark Peek void 32963a93856SMark Peek vmci_destroy_event(vmci_event *event) 33063a93856SMark Peek { 33163a93856SMark Peek 33263a93856SMark Peek if (mtx_owned(&event->sema_mtx)) 33363a93856SMark Peek sema_destroy(event); 33463a93856SMark Peek } 33563a93856SMark Peek 33663a93856SMark Peek /* 33763a93856SMark Peek *------------------------------------------------------------------------------ 33863a93856SMark Peek * 33963a93856SMark Peek * vmci_signal_event -- 34063a93856SMark Peek * 34163a93856SMark Peek * Results: 34263a93856SMark Peek * None. 34363a93856SMark Peek * 34463a93856SMark Peek * Side effects: 34563a93856SMark Peek * None. 34663a93856SMark Peek * 34763a93856SMark Peek *------------------------------------------------------------------------------ 34863a93856SMark Peek */ 34963a93856SMark Peek 35063a93856SMark Peek void 35163a93856SMark Peek vmci_signal_event(vmci_event *event) 35263a93856SMark Peek { 35363a93856SMark Peek 35463a93856SMark Peek sema_post(event); 35563a93856SMark Peek } 35663a93856SMark Peek 35763a93856SMark Peek /* 35863a93856SMark Peek *------------------------------------------------------------------------------ 35963a93856SMark Peek * 36063a93856SMark Peek * vmci_wait_on_event -- 36163a93856SMark Peek * 36263a93856SMark Peek * Results: 36363a93856SMark Peek * None. 36463a93856SMark Peek * 36563a93856SMark Peek * Side effects: 36663a93856SMark Peek * None. 36763a93856SMark Peek * 36863a93856SMark Peek *------------------------------------------------------------------------------ 36963a93856SMark Peek */ 37063a93856SMark Peek 37163a93856SMark Peek void 37263a93856SMark Peek vmci_wait_on_event(vmci_event *event, vmci_event_release_cb release_cb, 37363a93856SMark Peek void *client_data) 37463a93856SMark Peek { 37563a93856SMark Peek 37663a93856SMark Peek release_cb(client_data); 37763a93856SMark Peek sema_wait(event); 37863a93856SMark Peek } 37963a93856SMark Peek 38063a93856SMark Peek /* 38163a93856SMark Peek *------------------------------------------------------------------------------ 38263a93856SMark Peek * 38363a93856SMark Peek * vmci_mutex_init -- 38463a93856SMark Peek * 38563a93856SMark Peek * Initializes the mutex. Must be called before use. 38663a93856SMark Peek * 38763a93856SMark Peek * Results: 38863a93856SMark Peek * Success. 38963a93856SMark Peek * 39063a93856SMark Peek * Side effects: 39163a93856SMark Peek * None. 39263a93856SMark Peek * 39363a93856SMark Peek *------------------------------------------------------------------------------ 39463a93856SMark Peek */ 39563a93856SMark Peek 39663a93856SMark Peek int 39763a93856SMark Peek vmci_mutex_init(vmci_mutex *mutex, char *name) 39863a93856SMark Peek { 39963a93856SMark Peek 40063a93856SMark Peek mtx_init(mutex, name, NULL, MTX_DEF | MTX_NOWITNESS); 40163a93856SMark Peek return (VMCI_SUCCESS); 40263a93856SMark Peek } 40363a93856SMark Peek 40463a93856SMark Peek /* 40563a93856SMark Peek *------------------------------------------------------------------------------ 40663a93856SMark Peek * 40763a93856SMark Peek * vmci_mutex_destroy -- 40863a93856SMark Peek * 40963a93856SMark Peek * Destroys the mutex. 41063a93856SMark Peek * 41163a93856SMark Peek * Results: 41263a93856SMark Peek * None. 41363a93856SMark Peek * 41463a93856SMark Peek * Side effects: 41563a93856SMark Peek * None. 41663a93856SMark Peek * 41763a93856SMark Peek *------------------------------------------------------------------------------ 41863a93856SMark Peek */ 41963a93856SMark Peek 42063a93856SMark Peek void 42163a93856SMark Peek vmci_mutex_destroy(vmci_mutex *mutex) 42263a93856SMark Peek { 42363a93856SMark Peek 42463a93856SMark Peek mtx_destroy(mutex); 42563a93856SMark Peek } 42663a93856SMark Peek 42763a93856SMark Peek /* 42863a93856SMark Peek *------------------------------------------------------------------------------ 42963a93856SMark Peek * 43063a93856SMark Peek * vmci_mutex_acquire -- 43163a93856SMark Peek * 43263a93856SMark Peek * Acquires the mutex. 43363a93856SMark Peek * 43463a93856SMark Peek * Results: 43563a93856SMark Peek * None. 43663a93856SMark Peek * 43763a93856SMark Peek * Side effects: 43863a93856SMark Peek * Thread may block. 43963a93856SMark Peek * 44063a93856SMark Peek *------------------------------------------------------------------------------ 44163a93856SMark Peek */ 44263a93856SMark Peek 44363a93856SMark Peek void 44463a93856SMark Peek vmci_mutex_acquire(vmci_mutex *mutex) 44563a93856SMark Peek { 44663a93856SMark Peek 44763a93856SMark Peek mtx_lock(mutex); 44863a93856SMark Peek } 44963a93856SMark Peek 45063a93856SMark Peek /* 45163a93856SMark Peek *------------------------------------------------------------------------------ 45263a93856SMark Peek * 45363a93856SMark Peek * vmci_mutex_release -- 45463a93856SMark Peek * 45563a93856SMark Peek * Releases the mutex. 45663a93856SMark Peek * 45763a93856SMark Peek * Results: 45863a93856SMark Peek * None. 45963a93856SMark Peek * 46063a93856SMark Peek * Side effects: 46163a93856SMark Peek * May wake up the thread blocking on this mutex. 46263a93856SMark Peek * 46363a93856SMark Peek *------------------------------------------------------------------------------ 46463a93856SMark Peek */ 46563a93856SMark Peek 46663a93856SMark Peek void 46763a93856SMark Peek vmci_mutex_release(vmci_mutex *mutex) 46863a93856SMark Peek { 46963a93856SMark Peek 47063a93856SMark Peek mtx_unlock(mutex); 47163a93856SMark Peek } 47263a93856SMark Peek 47363a93856SMark Peek /* 47463a93856SMark Peek *------------------------------------------------------------------------------ 47563a93856SMark Peek * 4760f14bcbeSMark Peek * vmci_mutex_initialized 4770f14bcbeSMark Peek * 4780f14bcbeSMark Peek * Returns whether a mutex has been initialized. 4790f14bcbeSMark Peek * 4800f14bcbeSMark Peek * Results: 4810f14bcbeSMark Peek * Return 1 if initialized or 0 if unininitialized. 4820f14bcbeSMark Peek * 4830f14bcbeSMark Peek * Side effects: 4840f14bcbeSMark Peek * None 4850f14bcbeSMark Peek * 4860f14bcbeSMark Peek *------------------------------------------------------------------------------ 4870f14bcbeSMark Peek */ 4880f14bcbeSMark Peek 4890f14bcbeSMark Peek int 4900f14bcbeSMark Peek vmci_mutex_initialized(vmci_mutex *mutex) 4910f14bcbeSMark Peek { 4920f14bcbeSMark Peek 4930f14bcbeSMark Peek return mtx_initialized(mutex); 4940f14bcbeSMark Peek } 4950f14bcbeSMark Peek /* 4960f14bcbeSMark Peek *------------------------------------------------------------------------------ 4970f14bcbeSMark Peek * 49863a93856SMark Peek * vmci_alloc_queue -- 49963a93856SMark Peek * 50063a93856SMark Peek * Allocates kernel queue pages of specified size with IOMMU mappings, plus 50163a93856SMark Peek * space for the queue structure/kernel interface and the queue header. 50263a93856SMark Peek * 50363a93856SMark Peek * Results: 50463a93856SMark Peek * Pointer to the queue on success, NULL otherwise. 50563a93856SMark Peek * 50663a93856SMark Peek * Side effects: 50763a93856SMark Peek * Memory is allocated. 50863a93856SMark Peek * 50963a93856SMark Peek *------------------------------------------------------------------------------ 51063a93856SMark Peek */ 51163a93856SMark Peek 51263a93856SMark Peek void * 51363a93856SMark Peek vmci_alloc_queue(uint64_t size, uint32_t flags) 51463a93856SMark Peek { 51563a93856SMark Peek struct vmci_queue *queue; 51663a93856SMark Peek size_t i; 51763a93856SMark Peek const size_t num_pages = CEILING(size, PAGE_SIZE) + 1; 51863a93856SMark Peek const size_t dmas_size = num_pages * sizeof(struct vmci_dma_alloc); 51963a93856SMark Peek const size_t queue_size = 52063a93856SMark Peek sizeof(*queue) + sizeof(*(queue->kernel_if)) + dmas_size; 52163a93856SMark Peek 52263a93856SMark Peek /* Size should be enforced by vmci_qpair_alloc(), double-check here. */ 52363a93856SMark Peek if (size > VMCI_MAX_GUEST_QP_MEMORY) { 52463a93856SMark Peek ASSERT(false); 52563a93856SMark Peek return (NULL); 52663a93856SMark Peek } 52763a93856SMark Peek 52863a93856SMark Peek queue = malloc(queue_size, M_DEVBUF, M_NOWAIT); 52963a93856SMark Peek if (!queue) 53063a93856SMark Peek return (NULL); 53163a93856SMark Peek 53263a93856SMark Peek queue->q_header = NULL; 53363a93856SMark Peek queue->saved_header = NULL; 53463a93856SMark Peek queue->kernel_if = (struct vmci_queue_kernel_if *)(queue + 1); 53563a93856SMark Peek queue->kernel_if->num_pages = num_pages; 53663a93856SMark Peek queue->kernel_if->dmas = (struct vmci_dma_alloc *)(queue->kernel_if + 53763a93856SMark Peek 1); 53863a93856SMark Peek for (i = 0; i < num_pages; i++) { 53963a93856SMark Peek vmci_dma_malloc(PAGE_SIZE, 1, &queue->kernel_if->dmas[i]); 54063a93856SMark Peek if (!queue->kernel_if->dmas[i].dma_vaddr) { 54163a93856SMark Peek /* Size excl. the header. */ 54263a93856SMark Peek vmci_free_queue(queue, i * PAGE_SIZE); 54363a93856SMark Peek return (NULL); 54463a93856SMark Peek } 54563a93856SMark Peek } 54663a93856SMark Peek 54763a93856SMark Peek /* Queue header is the first page. */ 54863a93856SMark Peek queue->q_header = (void *)queue->kernel_if->dmas[0].dma_vaddr; 54963a93856SMark Peek 55063a93856SMark Peek return ((void *)queue); 55163a93856SMark Peek } 55263a93856SMark Peek 55363a93856SMark Peek /* 55463a93856SMark Peek *------------------------------------------------------------------------------ 55563a93856SMark Peek * 55663a93856SMark Peek * vmci_free_queue -- 55763a93856SMark Peek * 55863a93856SMark Peek * Frees kernel VA space for a given queue and its queue header, and frees 55963a93856SMark Peek * physical data pages. 56063a93856SMark Peek * 56163a93856SMark Peek * Results: 56263a93856SMark Peek * None. 56363a93856SMark Peek * 56463a93856SMark Peek * Side effects: 56563a93856SMark Peek * Memory is freed. 56663a93856SMark Peek * 56763a93856SMark Peek *------------------------------------------------------------------------------ 56863a93856SMark Peek */ 56963a93856SMark Peek 57063a93856SMark Peek void 57163a93856SMark Peek vmci_free_queue(void *q, uint64_t size) 57263a93856SMark Peek { 57363a93856SMark Peek struct vmci_queue *queue = q; 57463a93856SMark Peek 57563a93856SMark Peek if (queue) { 57663a93856SMark Peek const size_t num_pages = CEILING(size, PAGE_SIZE) + 1; 57763a93856SMark Peek uint64_t i; 57863a93856SMark Peek 57963a93856SMark Peek /* Given size doesn't include header, so add in a page here. */ 58063a93856SMark Peek for (i = 0; i < num_pages; i++) 58163a93856SMark Peek vmci_dma_free(&queue->kernel_if->dmas[i]); 58263a93856SMark Peek free(queue, M_DEVBUF); 58363a93856SMark Peek } 58463a93856SMark Peek } 58563a93856SMark Peek 58663a93856SMark Peek /* 58763a93856SMark Peek *------------------------------------------------------------------------------ 58863a93856SMark Peek * 58963a93856SMark Peek * vmci_alloc_ppn_set -- 59063a93856SMark Peek * 59163a93856SMark Peek * Allocates two list of PPNs --- one for the pages in the produce queue, 59263a93856SMark Peek * and the other for the pages in the consume queue. Intializes the list of 59363a93856SMark Peek * PPNs with the page frame numbers of the KVA for the two queues (and the 59463a93856SMark Peek * queue headers). 59563a93856SMark Peek * 59663a93856SMark Peek * Results: 59763a93856SMark Peek * Success or failure. 59863a93856SMark Peek * 59963a93856SMark Peek * Side effects: 60063a93856SMark Peek * Memory may be allocated. 60163a93856SMark Peek * 60263a93856SMark Peek *----------------------------------------------------------------------------- 60363a93856SMark Peek */ 60463a93856SMark Peek 60563a93856SMark Peek int 60663a93856SMark Peek vmci_alloc_ppn_set(void *prod_q, uint64_t num_produce_pages, void *cons_q, 60763a93856SMark Peek uint64_t num_consume_pages, struct ppn_set *ppn_set) 60863a93856SMark Peek { 60963a93856SMark Peek struct vmci_queue *consume_q = cons_q; 61063a93856SMark Peek struct vmci_queue *produce_q = prod_q; 61163a93856SMark Peek vmci_ppn_list consume_ppns; 61263a93856SMark Peek vmci_ppn_list produce_ppns; 61363a93856SMark Peek uint64_t i; 61463a93856SMark Peek 61563a93856SMark Peek if (!produce_q || !num_produce_pages || !consume_q || 61663a93856SMark Peek !num_consume_pages || !ppn_set) 61763a93856SMark Peek return (VMCI_ERROR_INVALID_ARGS); 61863a93856SMark Peek 61963a93856SMark Peek if (ppn_set->initialized) 62063a93856SMark Peek return (VMCI_ERROR_ALREADY_EXISTS); 62163a93856SMark Peek 62263a93856SMark Peek produce_ppns = 62363a93856SMark Peek vmci_alloc_kernel_mem(num_produce_pages * sizeof(*produce_ppns), 62463a93856SMark Peek VMCI_MEMORY_NORMAL); 62563a93856SMark Peek if (!produce_ppns) 62663a93856SMark Peek return (VMCI_ERROR_NO_MEM); 62763a93856SMark Peek 62863a93856SMark Peek consume_ppns = 62963a93856SMark Peek vmci_alloc_kernel_mem(num_consume_pages * sizeof(*consume_ppns), 63063a93856SMark Peek VMCI_MEMORY_NORMAL); 63163a93856SMark Peek if (!consume_ppns) { 63263a93856SMark Peek vmci_free_kernel_mem(produce_ppns, 63363a93856SMark Peek num_produce_pages * sizeof(*produce_ppns)); 63463a93856SMark Peek return (VMCI_ERROR_NO_MEM); 63563a93856SMark Peek } 63663a93856SMark Peek 63763a93856SMark Peek for (i = 0; i < num_produce_pages; i++) { 63863a93856SMark Peek unsigned long pfn; 63963a93856SMark Peek 64063a93856SMark Peek produce_ppns[i] = 64163a93856SMark Peek pfn = produce_q->kernel_if->dmas[i].dma_paddr >> PAGE_SHIFT; 64263a93856SMark Peek 64363a93856SMark Peek /* 64463a93856SMark Peek * Fail allocation if PFN isn't supported by hypervisor. 64563a93856SMark Peek */ 64663a93856SMark Peek 64763a93856SMark Peek if (sizeof(pfn) > 64863a93856SMark Peek sizeof(*produce_ppns) && pfn != produce_ppns[i]) 64963a93856SMark Peek goto ppn_error; 65063a93856SMark Peek } 65163a93856SMark Peek for (i = 0; i < num_consume_pages; i++) { 65263a93856SMark Peek unsigned long pfn; 65363a93856SMark Peek 65463a93856SMark Peek consume_ppns[i] = 65563a93856SMark Peek pfn = consume_q->kernel_if->dmas[i].dma_paddr >> PAGE_SHIFT; 65663a93856SMark Peek 65763a93856SMark Peek /* 65863a93856SMark Peek * Fail allocation if PFN isn't supported by hypervisor. 65963a93856SMark Peek */ 66063a93856SMark Peek 66163a93856SMark Peek if (sizeof(pfn) > 66263a93856SMark Peek sizeof(*consume_ppns) && pfn != consume_ppns[i]) 66363a93856SMark Peek goto ppn_error; 66463a93856SMark Peek } 66563a93856SMark Peek 66663a93856SMark Peek ppn_set->num_produce_pages = num_produce_pages; 66763a93856SMark Peek ppn_set->num_consume_pages = num_consume_pages; 66863a93856SMark Peek ppn_set->produce_ppns = produce_ppns; 66963a93856SMark Peek ppn_set->consume_ppns = consume_ppns; 67063a93856SMark Peek ppn_set->initialized = true; 67163a93856SMark Peek return (VMCI_SUCCESS); 67263a93856SMark Peek 67363a93856SMark Peek ppn_error: 67463a93856SMark Peek vmci_free_kernel_mem(produce_ppns, num_produce_pages * 67563a93856SMark Peek sizeof(*produce_ppns)); 67663a93856SMark Peek vmci_free_kernel_mem(consume_ppns, num_consume_pages * 67763a93856SMark Peek sizeof(*consume_ppns)); 67863a93856SMark Peek return (VMCI_ERROR_INVALID_ARGS); 67963a93856SMark Peek } 68063a93856SMark Peek 68163a93856SMark Peek /* 68263a93856SMark Peek *------------------------------------------------------------------------------ 68363a93856SMark Peek * 68463a93856SMark Peek * vmci_free_ppn_set -- 68563a93856SMark Peek * 68663a93856SMark Peek * Frees the two list of PPNs for a queue pair. 68763a93856SMark Peek * 68863a93856SMark Peek * Results: 68963a93856SMark Peek * None. 69063a93856SMark Peek * 69163a93856SMark Peek * Side effects: 69263a93856SMark Peek * None. 69363a93856SMark Peek * 69463a93856SMark Peek *------------------------------------------------------------------------------ 69563a93856SMark Peek */ 69663a93856SMark Peek 69763a93856SMark Peek void 69863a93856SMark Peek vmci_free_ppn_set(struct ppn_set *ppn_set) 69963a93856SMark Peek { 70063a93856SMark Peek 70163a93856SMark Peek ASSERT(ppn_set); 70263a93856SMark Peek if (ppn_set->initialized) { 70363a93856SMark Peek /* Do not call these functions on NULL inputs. */ 70463a93856SMark Peek ASSERT(ppn_set->produce_ppns && ppn_set->consume_ppns); 70563a93856SMark Peek vmci_free_kernel_mem(ppn_set->produce_ppns, 70663a93856SMark Peek ppn_set->num_produce_pages * 70763a93856SMark Peek sizeof(*ppn_set->produce_ppns)); 70863a93856SMark Peek vmci_free_kernel_mem(ppn_set->consume_ppns, 70963a93856SMark Peek ppn_set->num_consume_pages * 71063a93856SMark Peek sizeof(*ppn_set->consume_ppns)); 71163a93856SMark Peek } 71263a93856SMark Peek memset(ppn_set, 0, sizeof(*ppn_set)); 71363a93856SMark Peek } 71463a93856SMark Peek 71563a93856SMark Peek /* 71663a93856SMark Peek *------------------------------------------------------------------------------ 71763a93856SMark Peek * 71863a93856SMark Peek * vmci_populate_ppn_list -- 71963a93856SMark Peek * 72063a93856SMark Peek * Populates the list of PPNs in the hypercall structure with the PPNS 72163a93856SMark Peek * of the produce queue and the consume queue. 72263a93856SMark Peek * 72363a93856SMark Peek * Results: 72463a93856SMark Peek * VMCI_SUCCESS. 72563a93856SMark Peek * 72663a93856SMark Peek * Side effects: 72763a93856SMark Peek * None. 72863a93856SMark Peek * 72963a93856SMark Peek *------------------------------------------------------------------------------ 73063a93856SMark Peek */ 73163a93856SMark Peek 73263a93856SMark Peek int 73363a93856SMark Peek vmci_populate_ppn_list(uint8_t *call_buf, const struct ppn_set *ppn_set) 73463a93856SMark Peek { 73563a93856SMark Peek 73663a93856SMark Peek ASSERT(call_buf && ppn_set && ppn_set->initialized); 73763a93856SMark Peek memcpy(call_buf, ppn_set->produce_ppns, 73863a93856SMark Peek ppn_set->num_produce_pages * sizeof(*ppn_set->produce_ppns)); 73963a93856SMark Peek memcpy(call_buf + ppn_set->num_produce_pages * 74063a93856SMark Peek sizeof(*ppn_set->produce_ppns), ppn_set->consume_ppns, 74163a93856SMark Peek ppn_set->num_consume_pages * sizeof(*ppn_set->consume_ppns)); 74263a93856SMark Peek 74363a93856SMark Peek return (VMCI_SUCCESS); 74463a93856SMark Peek } 74563a93856SMark Peek 74663a93856SMark Peek /* 74763a93856SMark Peek *------------------------------------------------------------------------------ 74863a93856SMark Peek * 74963a93856SMark Peek * vmci_memcpy_{to,from}iovec -- 75063a93856SMark Peek * 75163a93856SMark Peek * These helper routines will copy the specified bytes to/from memory that's 75263a93856SMark Peek * specified as a struct iovec. The routines can not verify the correctness 75363a93856SMark Peek * of the struct iovec's contents. 75463a93856SMark Peek * 75563a93856SMark Peek * Results: 75663a93856SMark Peek * None. 75763a93856SMark Peek * 75863a93856SMark Peek * Side effects: 75963a93856SMark Peek * None. 76063a93856SMark Peek * 76163a93856SMark Peek *------------------------------------------------------------------------------ 76263a93856SMark Peek */ 76363a93856SMark Peek 76463a93856SMark Peek static inline void 76563a93856SMark Peek vmci_memcpy_toiovec(struct iovec *iov, uint8_t *src, size_t len) 76663a93856SMark Peek { 76763a93856SMark Peek 76863a93856SMark Peek while (len > 0) { 76963a93856SMark Peek if (iov->iov_len) { 77063a93856SMark Peek size_t to_copy = MIN(iov->iov_len, len); 77163a93856SMark Peek memcpy(iov->iov_base, src, to_copy); 77263a93856SMark Peek src += to_copy; 77363a93856SMark Peek len -= to_copy; 77463a93856SMark Peek iov->iov_base = (void *)((uintptr_t) iov->iov_base + 77563a93856SMark Peek to_copy); 77663a93856SMark Peek iov->iov_len -= to_copy; 77763a93856SMark Peek } 77863a93856SMark Peek iov++; 77963a93856SMark Peek } 78063a93856SMark Peek } 78163a93856SMark Peek 78263a93856SMark Peek static inline void 78363a93856SMark Peek vmci_memcpy_fromiovec(uint8_t *dst, struct iovec *iov, size_t len) 78463a93856SMark Peek { 78563a93856SMark Peek 78663a93856SMark Peek while (len > 0) { 78763a93856SMark Peek if (iov->iov_len) { 78863a93856SMark Peek size_t to_copy = MIN(iov->iov_len, len); 78963a93856SMark Peek memcpy(dst, iov->iov_base, to_copy); 79063a93856SMark Peek dst += to_copy; 79163a93856SMark Peek len -= to_copy; 79263a93856SMark Peek iov->iov_base = (void *)((uintptr_t) iov->iov_base + 79363a93856SMark Peek to_copy); 79463a93856SMark Peek iov->iov_len -= to_copy; 79563a93856SMark Peek } 79663a93856SMark Peek iov++; 79763a93856SMark Peek } 79863a93856SMark Peek } 79963a93856SMark Peek 80063a93856SMark Peek /* 80163a93856SMark Peek *------------------------------------------------------------------------------ 80263a93856SMark Peek * 80363a93856SMark Peek * __vmci_memcpy_to_queue -- 80463a93856SMark Peek * 80563a93856SMark Peek * Copies from a given buffer or iovector to a VMCI Queue. Assumes that 80663a93856SMark Peek * offset + size does not wrap around in the queue. 80763a93856SMark Peek * 80863a93856SMark Peek * Results: 80963a93856SMark Peek * Zero on success, negative error code on failure. 81063a93856SMark Peek * 81163a93856SMark Peek * Side effects: 81263a93856SMark Peek * None. 81363a93856SMark Peek * 81463a93856SMark Peek *------------------------------------------------------------------------------ 81563a93856SMark Peek */ 81663a93856SMark Peek 81763a93856SMark Peek #pragma GCC diagnostic ignored "-Wcast-qual" 81863a93856SMark Peek static int 81963a93856SMark Peek __vmci_memcpy_to_queue(struct vmci_queue *queue, uint64_t queue_offset, 82063a93856SMark Peek const void *src, size_t size, bool is_iovec) 82163a93856SMark Peek { 82263a93856SMark Peek struct vmci_queue_kernel_if *kernel_if = queue->kernel_if; 82363a93856SMark Peek size_t bytes_copied = 0; 82463a93856SMark Peek 82563a93856SMark Peek while (bytes_copied < size) { 82663a93856SMark Peek const uint64_t page_index = 82763a93856SMark Peek (queue_offset + bytes_copied) / PAGE_SIZE; 82863a93856SMark Peek const size_t page_offset = 82963a93856SMark Peek (queue_offset + bytes_copied) & (PAGE_SIZE - 1); 83063a93856SMark Peek void *va; 83163a93856SMark Peek size_t to_copy; 83263a93856SMark Peek 83363a93856SMark Peek /* Skip header. */ 83463a93856SMark Peek va = (void *)kernel_if->dmas[page_index + 1].dma_vaddr; 83563a93856SMark Peek 83663a93856SMark Peek ASSERT(va); 83763a93856SMark Peek /* 83863a93856SMark Peek * Fill up the page if we have enough payload, or else 83963a93856SMark Peek * copy the remaining bytes. 84063a93856SMark Peek */ 84163a93856SMark Peek to_copy = MIN(PAGE_SIZE - page_offset, size - bytes_copied); 84263a93856SMark Peek 84363a93856SMark Peek if (is_iovec) { 84463a93856SMark Peek struct iovec *iov = (struct iovec *)src; 84563a93856SMark Peek 84663a93856SMark Peek /* The iovec will track bytes_copied internally. */ 84763a93856SMark Peek vmci_memcpy_fromiovec((uint8_t *)va + page_offset, 84863a93856SMark Peek iov, to_copy); 84963a93856SMark Peek } else 85063a93856SMark Peek memcpy((uint8_t *)va + page_offset, 85163a93856SMark Peek (uint8_t *)src + bytes_copied, to_copy); 85263a93856SMark Peek bytes_copied += to_copy; 85363a93856SMark Peek } 85463a93856SMark Peek 85563a93856SMark Peek return (VMCI_SUCCESS); 85663a93856SMark Peek } 85763a93856SMark Peek 85863a93856SMark Peek /* 85963a93856SMark Peek *------------------------------------------------------------------------------ 86063a93856SMark Peek * 86163a93856SMark Peek * __vmci_memcpy_from_queue -- 86263a93856SMark Peek * 86363a93856SMark Peek * Copies to a given buffer or iovector from a VMCI Queue. Assumes that 86463a93856SMark Peek * offset + size does not wrap around in the queue. 86563a93856SMark Peek * 86663a93856SMark Peek * Results: 86763a93856SMark Peek * Zero on success, negative error code on failure. 86863a93856SMark Peek * 86963a93856SMark Peek * Side effects: 87063a93856SMark Peek * None. 87163a93856SMark Peek * 87263a93856SMark Peek *------------------------------------------------------------------------------ 87363a93856SMark Peek */ 87463a93856SMark Peek 87563a93856SMark Peek static int 87663a93856SMark Peek __vmci_memcpy_from_queue(void *dest, const struct vmci_queue *queue, 87763a93856SMark Peek uint64_t queue_offset, size_t size, bool is_iovec) 87863a93856SMark Peek { 87963a93856SMark Peek struct vmci_queue_kernel_if *kernel_if = queue->kernel_if; 88063a93856SMark Peek size_t bytes_copied = 0; 88163a93856SMark Peek 88263a93856SMark Peek while (bytes_copied < size) { 88363a93856SMark Peek const uint64_t page_index = 88463a93856SMark Peek (queue_offset + bytes_copied) / PAGE_SIZE; 88563a93856SMark Peek const size_t page_offset = 88663a93856SMark Peek (queue_offset + bytes_copied) & (PAGE_SIZE - 1); 88763a93856SMark Peek void *va; 88863a93856SMark Peek size_t to_copy; 88963a93856SMark Peek 89063a93856SMark Peek /* Skip header. */ 89163a93856SMark Peek va = (void *)kernel_if->dmas[page_index + 1].dma_vaddr; 89263a93856SMark Peek 89363a93856SMark Peek ASSERT(va); 89463a93856SMark Peek /* 89563a93856SMark Peek * Fill up the page if we have enough payload, or else 89663a93856SMark Peek * copy the remaining bytes. 89763a93856SMark Peek */ 89863a93856SMark Peek to_copy = MIN(PAGE_SIZE - page_offset, size - bytes_copied); 89963a93856SMark Peek 90063a93856SMark Peek if (is_iovec) { 90163a93856SMark Peek struct iovec *iov = (struct iovec *)dest; 90263a93856SMark Peek 90363a93856SMark Peek /* The iovec will track bytesCopied internally. */ 90463a93856SMark Peek vmci_memcpy_toiovec(iov, (uint8_t *)va + 90563a93856SMark Peek page_offset, to_copy); 90663a93856SMark Peek } else 90763a93856SMark Peek memcpy((uint8_t *)dest + bytes_copied, 90863a93856SMark Peek (uint8_t *)va + page_offset, to_copy); 90963a93856SMark Peek 91063a93856SMark Peek bytes_copied += to_copy; 91163a93856SMark Peek } 91263a93856SMark Peek 91363a93856SMark Peek return (VMCI_SUCCESS); 91463a93856SMark Peek } 91563a93856SMark Peek 91663a93856SMark Peek /* 91763a93856SMark Peek *------------------------------------------------------------------------------ 91863a93856SMark Peek * 91963a93856SMark Peek * vmci_memcpy_to_queue -- 92063a93856SMark Peek * 92163a93856SMark Peek * Copies from a given buffer to a VMCI Queue. 92263a93856SMark Peek * 92363a93856SMark Peek * Results: 92463a93856SMark Peek * Zero on success, negative error code on failure. 92563a93856SMark Peek * 92663a93856SMark Peek * Side effects: 92763a93856SMark Peek * None. 92863a93856SMark Peek * 92963a93856SMark Peek *------------------------------------------------------------------------------ 93063a93856SMark Peek */ 93163a93856SMark Peek 93263a93856SMark Peek int 93363a93856SMark Peek vmci_memcpy_to_queue(struct vmci_queue *queue, uint64_t queue_offset, 93463a93856SMark Peek const void *src, size_t src_offset, size_t size, int buf_type, 93563a93856SMark Peek bool can_block) 93663a93856SMark Peek { 93763a93856SMark Peek 93863a93856SMark Peek ASSERT(can_block); 93963a93856SMark Peek 94063a93856SMark Peek return (__vmci_memcpy_to_queue(queue, queue_offset, 94163a93856SMark Peek (uint8_t *)src + src_offset, size, false)); 94263a93856SMark Peek } 94363a93856SMark Peek 94463a93856SMark Peek /* 94563a93856SMark Peek *------------------------------------------------------------------------------ 94663a93856SMark Peek * 94763a93856SMark Peek * vmci_memcpy_from_queue -- 94863a93856SMark Peek * 94963a93856SMark Peek * Copies to a given buffer from a VMCI Queue. 95063a93856SMark Peek * 95163a93856SMark Peek * Results: 95263a93856SMark Peek * Zero on success, negative error code on failure. 95363a93856SMark Peek * 95463a93856SMark Peek * Side effects: 95563a93856SMark Peek * None. 95663a93856SMark Peek * 95763a93856SMark Peek *------------------------------------------------------------------------------ 95863a93856SMark Peek */ 95963a93856SMark Peek 96063a93856SMark Peek int 96163a93856SMark Peek vmci_memcpy_from_queue(void *dest, size_t dest_offset, 96263a93856SMark Peek const struct vmci_queue *queue, uint64_t queue_offset, size_t size, 96363a93856SMark Peek int buf_type, bool can_block) 96463a93856SMark Peek { 96563a93856SMark Peek 96663a93856SMark Peek ASSERT(can_block); 96763a93856SMark Peek 96863a93856SMark Peek return (__vmci_memcpy_from_queue((uint8_t *)dest + dest_offset, 96963a93856SMark Peek queue, queue_offset, size, false)); 97063a93856SMark Peek } 97163a93856SMark Peek 97263a93856SMark Peek /* 97363a93856SMark Peek *------------------------------------------------------------------------------ 97463a93856SMark Peek * 97563a93856SMark Peek * vmci_memcpy_to_queue_local -- 97663a93856SMark Peek * 97763a93856SMark Peek * Copies from a given buffer to a local VMCI queue. This is the 97863a93856SMark Peek * same as a regular copy. 97963a93856SMark Peek * 98063a93856SMark Peek * Results: 98163a93856SMark Peek * Zero on success, negative error code on failure. 98263a93856SMark Peek * 98363a93856SMark Peek * Side effects: 98463a93856SMark Peek * None. 98563a93856SMark Peek * 98663a93856SMark Peek *------------------------------------------------------------------------------ 98763a93856SMark Peek */ 98863a93856SMark Peek 98963a93856SMark Peek int 99063a93856SMark Peek vmci_memcpy_to_queue_local(struct vmci_queue *queue, uint64_t queue_offset, 99163a93856SMark Peek const void *src, size_t src_offset, size_t size, int buf_type, 99263a93856SMark Peek bool can_block) 99363a93856SMark Peek { 99463a93856SMark Peek 99563a93856SMark Peek ASSERT(can_block); 99663a93856SMark Peek 99763a93856SMark Peek return (__vmci_memcpy_to_queue(queue, queue_offset, 99863a93856SMark Peek (uint8_t *)src + src_offset, size, false)); 99963a93856SMark Peek } 100063a93856SMark Peek 100163a93856SMark Peek /* 100263a93856SMark Peek *------------------------------------------------------------------------------ 100363a93856SMark Peek * 100463a93856SMark Peek * vmci_memcpy_from_queue_local -- 100563a93856SMark Peek * 100663a93856SMark Peek * Copies to a given buffer from a VMCI Queue. 100763a93856SMark Peek * 100863a93856SMark Peek * Results: 100963a93856SMark Peek * Zero on success, negative error code on failure. 101063a93856SMark Peek * 101163a93856SMark Peek * Side effects: 101263a93856SMark Peek * None. 101363a93856SMark Peek * 101463a93856SMark Peek *------------------------------------------------------------------------------ 101563a93856SMark Peek */ 101663a93856SMark Peek 101763a93856SMark Peek int 101863a93856SMark Peek vmci_memcpy_from_queue_local(void *dest, size_t dest_offset, 101963a93856SMark Peek const struct vmci_queue *queue, uint64_t queue_offset, size_t size, 102063a93856SMark Peek int buf_type, bool can_block) 102163a93856SMark Peek { 102263a93856SMark Peek 102363a93856SMark Peek ASSERT(can_block); 102463a93856SMark Peek 102563a93856SMark Peek return (__vmci_memcpy_from_queue((uint8_t *)dest + dest_offset, 102663a93856SMark Peek queue, queue_offset, size, false)); 102763a93856SMark Peek } 102863a93856SMark Peek 102963a93856SMark Peek /*------------------------------------------------------------------------------ 103063a93856SMark Peek * 103163a93856SMark Peek * vmci_memcpy_to_queue_v -- 103263a93856SMark Peek * 103363a93856SMark Peek * Copies from a given iovec from a VMCI Queue. 103463a93856SMark Peek * 103563a93856SMark Peek * Results: 103663a93856SMark Peek * Zero on success, negative error code on failure. 103763a93856SMark Peek * 103863a93856SMark Peek * Side effects: 103963a93856SMark Peek * None. 104063a93856SMark Peek * 104163a93856SMark Peek *------------------------------------------------------------------------------ 104263a93856SMark Peek */ 104363a93856SMark Peek 104463a93856SMark Peek int 104563a93856SMark Peek vmci_memcpy_to_queue_v(struct vmci_queue *queue, uint64_t queue_offset, 104663a93856SMark Peek const void *src, size_t src_offset, size_t size, int buf_type, 104763a93856SMark Peek bool can_block) 104863a93856SMark Peek { 104963a93856SMark Peek 105063a93856SMark Peek ASSERT(can_block); 105163a93856SMark Peek 105263a93856SMark Peek /* 105363a93856SMark Peek * We ignore src_offset because src is really a struct iovec * and will 105463a93856SMark Peek * maintain offset internally. 105563a93856SMark Peek */ 105663a93856SMark Peek return (__vmci_memcpy_to_queue(queue, queue_offset, src, size, 105763a93856SMark Peek true)); 105863a93856SMark Peek } 105963a93856SMark Peek 106063a93856SMark Peek /* 106163a93856SMark Peek *------------------------------------------------------------------------------ 106263a93856SMark Peek * 106363a93856SMark Peek * vmci_memcpy_from_queue_v -- 106463a93856SMark Peek * 106563a93856SMark Peek * Copies to a given iovec from a VMCI Queue. 106663a93856SMark Peek * 106763a93856SMark Peek * Results: 106863a93856SMark Peek * Zero on success, negative error code on failure. 106963a93856SMark Peek * 107063a93856SMark Peek * Side effects: 107163a93856SMark Peek * None. 107263a93856SMark Peek * 107363a93856SMark Peek *------------------------------------------------------------------------------ 107463a93856SMark Peek */ 107563a93856SMark Peek 107663a93856SMark Peek int 107763a93856SMark Peek vmci_memcpy_from_queue_v(void *dest, size_t dest_offset, 107863a93856SMark Peek const struct vmci_queue *queue, uint64_t queue_offset, size_t size, 107963a93856SMark Peek int buf_type, bool can_block) 108063a93856SMark Peek { 108163a93856SMark Peek 108263a93856SMark Peek ASSERT(can_block); 108363a93856SMark Peek 108463a93856SMark Peek /* 108563a93856SMark Peek * We ignore dest_offset because dest is really a struct iovec * and 108663a93856SMark Peek * will maintain offset internally. 108763a93856SMark Peek */ 108863a93856SMark Peek return (__vmci_memcpy_from_queue(dest, queue, queue_offset, size, 108963a93856SMark Peek true)); 109063a93856SMark Peek } 109163a93856SMark Peek 109263a93856SMark Peek /* 109363a93856SMark Peek *------------------------------------------------------------------------------ 109463a93856SMark Peek * 109563a93856SMark Peek * vmci_read_port_bytes -- 109663a93856SMark Peek * 109763a93856SMark Peek * Copy memory from an I/O port to kernel memory. 109863a93856SMark Peek * 109963a93856SMark Peek * Results: 110063a93856SMark Peek * No results. 110163a93856SMark Peek * 110263a93856SMark Peek * Side effects: 110363a93856SMark Peek * None. 110463a93856SMark Peek * 110563a93856SMark Peek *------------------------------------------------------------------------------ 110663a93856SMark Peek */ 110763a93856SMark Peek 110863a93856SMark Peek void 110963a93856SMark Peek vmci_read_port_bytes(vmci_io_handle handle, vmci_io_port port, uint8_t *buffer, 111063a93856SMark Peek size_t buffer_length) 111163a93856SMark Peek { 111263a93856SMark Peek 111363a93856SMark Peek insb(port, buffer, buffer_length); 111463a93856SMark Peek } 1115