xref: /freebsd/sys/dev/vmware/vmci/vmci_kernel_if.c (revision 0f14bcbe)
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