1/*-
2 * Copyright (c) 2018 VMware, Inc.
3 *
4 * SPDX-License-Identifier: (BSD-2-Clause OR GPL-2.0)
5 *
6 * $FreeBSD$
7 */
8
9#ifndef _VMCI_DEFS_H_
10#define _VMCI_DEFS_H_
11
12#include <sys/types.h>
13#include <machine/atomic.h>
14
15#include "vmci_kernel_defs.h"
16
17#pragma GCC diagnostic ignored "-Wcast-qual"
18
19/* Register offsets. */
20#define VMCI_STATUS_ADDR		0x00
21#define VMCI_CONTROL_ADDR		0x04
22#define VMCI_ICR_ADDR			0x08
23#define VMCI_IMR_ADDR			0x0c
24#define VMCI_DATA_OUT_ADDR		0x10
25#define VMCI_DATA_IN_ADDR		0x14
26#define VMCI_CAPS_ADDR			0x18
27#define VMCI_RESULT_LOW_ADDR		0x1c
28#define VMCI_RESULT_HIGH_ADDR		0x20
29
30/* Status register bits. */
31#define VMCI_STATUS_INT_ON		0x1
32
33/* Control register bits. */
34#define VMCI_CONTROL_RESET		0x1
35#define VMCI_CONTROL_INT_ENABLE		0x2
36#define VMCI_CONTROL_INT_DISABLE	0x4
37
38/* Capabilities register bits. */
39#define VMCI_CAPS_HYPERCALL		0x1
40#define VMCI_CAPS_GUESTCALL		0x2
41#define VMCI_CAPS_DATAGRAM		0x4
42#define VMCI_CAPS_NOTIFICATIONS		0x8
43
44/* Interrupt Cause register bits. */
45#define VMCI_ICR_DATAGRAM		0x1
46#define VMCI_ICR_NOTIFICATION		0x2
47
48/* Interrupt Mask register bits. */
49#define VMCI_IMR_DATAGRAM		0x1
50#define VMCI_IMR_NOTIFICATION		0x2
51
52/* Interrupt type. */
53typedef enum vmci_intr_type {
54	VMCI_INTR_TYPE_INTX =	0,
55	VMCI_INTR_TYPE_MSI =	1,
56	VMCI_INTR_TYPE_MSIX =	2
57} vmci_intr_type;
58
59/*
60 * Maximum MSI/MSI-X interrupt vectors in the device.
61 */
62#define VMCI_MAX_INTRS			2
63
64/*
65 * Supported interrupt vectors. There is one for each ICR value above,
66 * but here they indicate the position in the vector array/message ID.
67 */
68#define VMCI_INTR_DATAGRAM		0
69#define VMCI_INTR_NOTIFICATION		1
70
71/*
72 * A single VMCI device has an upper limit of 128 MiB on the amount of
73 * memory that can be used for queue pairs.
74 */
75#define VMCI_MAX_GUEST_QP_MEMORY	(128 * 1024 * 1024)
76
77/*
78 * We have a fixed set of resource IDs available in the VMX.
79 * This allows us to have a very simple implementation since we statically
80 * know how many will create datagram handles. If a new caller arrives and
81 * we have run out of slots we can manually increment the maximum size of
82 * available resource IDs.
83 */
84
85typedef uint32_t vmci_resource;
86
87/* VMCI reserved hypervisor datagram resource IDs. */
88#define VMCI_RESOURCES_QUERY		0
89#define VMCI_GET_CONTEXT_ID		1
90#define VMCI_SET_NOTIFY_BITMAP		2
91#define VMCI_DOORBELL_LINK		3
92#define VMCI_DOORBELL_UNLINK		4
93#define VMCI_DOORBELL_NOTIFY		5
94/*
95 * VMCI_DATAGRAM_REQUEST_MAP and VMCI_DATAGRAM_REMOVE_MAP are
96 * obsoleted by the removal of VM to VM communication.
97 */
98#define VMCI_DATAGRAM_REQUEST_MAP	6
99#define VMCI_DATAGRAM_REMOVE_MAP	7
100#define VMCI_EVENT_SUBSCRIBE		8
101#define VMCI_EVENT_UNSUBSCRIBE		9
102#define VMCI_QUEUEPAIR_ALLOC		10
103#define VMCI_QUEUEPAIR_DETACH		11
104/*
105 * VMCI_VSOCK_VMX_LOOKUP was assigned to 12 for Fusion 3.0/3.1,
106 * WS 7.0/7.1 and ESX 4.1
107 */
108#define VMCI_HGFS_TRANSPORT		13
109#define VMCI_UNITY_PBRPC_REGISTER	14
110/*
111 * This resource is used for VMCI socket control packets sent to the
112 * hypervisor (CID 0) because RID 1 is already reserved.
113 */
114#define VSOCK_PACKET_HYPERVISOR_RID	15
115#define VMCI_RESOURCE_MAX		16
116/*
117 * The core VMCI device functionality only requires the resource IDs of
118 * VMCI_QUEUEPAIR_DETACH and below.
119 */
120#define VMCI_CORE_DEVICE_RESOURCE_MAX	VMCI_QUEUEPAIR_DETACH
121
122/*
123 * VMCI reserved host datagram resource IDs.
124 * vsock control channel has resource id 1.
125 */
126#define VMCI_DVFILTER_DATA_PATH_DATAGRAM	2
127
128/* VMCI Ids. */
129typedef uint32_t vmci_id;
130
131struct vmci_id_range {
132	int8_t	action;	/* VMCI_FA_X, for use in filters. */
133	vmci_id	begin;	/* Beginning of range. */
134	vmci_id	end;	/* End of range. */
135};
136
137struct vmci_handle {
138	vmci_id	context;
139	vmci_id	resource;
140};
141
142static inline struct vmci_handle
143VMCI_MAKE_HANDLE(vmci_id cid, vmci_id rid)
144{
145	struct vmci_handle h;
146
147	h.context = cid;
148	h.resource = rid;
149	return (h);
150}
151
152#define VMCI_HANDLE_TO_CONTEXT_ID(_handle)				\
153	((_handle).context)
154#define VMCI_HANDLE_TO_RESOURCE_ID(_handle)				\
155	((_handle).resource)
156#define VMCI_HANDLE_EQUAL(_h1, _h2)					\
157	((_h1).context == (_h2).context && (_h1).resource == (_h2).resource)
158
159#define VMCI_INVALID_ID			0xFFFFFFFF
160static const struct vmci_handle VMCI_INVALID_HANDLE = {VMCI_INVALID_ID,
161	    VMCI_INVALID_ID};
162
163#define VMCI_HANDLE_INVALID(_handle)					\
164	VMCI_HANDLE_EQUAL((_handle), VMCI_INVALID_HANDLE)
165
166/*
167 * The below defines can be used to send anonymous requests.
168 * This also indicates that no response is expected.
169 */
170#define VMCI_ANON_SRC_CONTEXT_ID					\
171	VMCI_INVALID_ID
172#define VMCI_ANON_SRC_RESOURCE_ID					\
173	VMCI_INVALID_ID
174#define VMCI_ANON_SRC_HANDLE						\
175	VMCI_MAKE_HANDLE(VMCI_ANON_SRC_CONTEXT_ID,			\
176	VMCI_ANON_SRC_RESOURCE_ID)
177
178/* The lowest 16 context ids are reserved for internal use. */
179#define VMCI_RESERVED_CID_LIMIT		16
180
181/*
182 * Hypervisor context id, used for calling into hypervisor
183 * supplied services from the VM.
184 */
185#define VMCI_HYPERVISOR_CONTEXT_ID	0
186
187/*
188 * Well-known context id, a logical context that contains a set of
189 * well-known services. This context ID is now obsolete.
190 */
191#define VMCI_WELL_KNOWN_CONTEXT_ID	1
192
193/*
194 * Context ID used by host endpoints.
195 */
196#define VMCI_HOST_CONTEXT_ID		2
197#define VMCI_HOST_CONTEXT_INVALID_EVENT	((uintptr_t)~0)
198
199#define VMCI_CONTEXT_IS_VM(_cid)					\
200	(VMCI_INVALID_ID != _cid && _cid > VMCI_HOST_CONTEXT_ID)
201
202/*
203 * The VMCI_CONTEXT_RESOURCE_ID is used together with VMCI_MAKE_HANDLE to make
204 * handles that refer to a specific context.
205 */
206#define VMCI_CONTEXT_RESOURCE_ID	0
207
208/*
209 *------------------------------------------------------------------------------
210 *
211 * VMCI error codes.
212 *
213 *------------------------------------------------------------------------------
214 */
215
216#define VMCI_SUCCESS_QUEUEPAIR_ATTACH		5
217#define VMCI_SUCCESS_QUEUEPAIR_CREATE		4
218#define VMCI_SUCCESS_LAST_DETACH		3
219#define VMCI_SUCCESS_ACCESS_GRANTED		2
220#define VMCI_SUCCESS_ENTRY_DEAD			1
221#define VMCI_SUCCESS				0LL
222#define VMCI_ERROR_INVALID_RESOURCE		(-1)
223#define VMCI_ERROR_INVALID_ARGS			(-2)
224#define VMCI_ERROR_NO_MEM			(-3)
225#define VMCI_ERROR_DATAGRAM_FAILED		(-4)
226#define VMCI_ERROR_MORE_DATA			(-5)
227#define VMCI_ERROR_NO_MORE_DATAGRAMS		(-6)
228#define VMCI_ERROR_NO_ACCESS			(-7)
229#define VMCI_ERROR_NO_HANDLE			(-8)
230#define VMCI_ERROR_DUPLICATE_ENTRY		(-9)
231#define VMCI_ERROR_DST_UNREACHABLE		(-10)
232#define VMCI_ERROR_PAYLOAD_TOO_LARGE		(-11)
233#define VMCI_ERROR_INVALID_PRIV			(-12)
234#define VMCI_ERROR_GENERIC			(-13)
235#define VMCI_ERROR_PAGE_ALREADY_SHARED		(-14)
236#define VMCI_ERROR_CANNOT_SHARE_PAGE		(-15)
237#define VMCI_ERROR_CANNOT_UNSHARE_PAGE		(-16)
238#define VMCI_ERROR_NO_PROCESS			(-17)
239#define VMCI_ERROR_NO_DATAGRAM			(-18)
240#define VMCI_ERROR_NO_RESOURCES			(-19)
241#define VMCI_ERROR_UNAVAILABLE			(-20)
242#define VMCI_ERROR_NOT_FOUND			(-21)
243#define VMCI_ERROR_ALREADY_EXISTS		(-22)
244#define VMCI_ERROR_NOT_PAGE_ALIGNED		(-23)
245#define VMCI_ERROR_INVALID_SIZE			(-24)
246#define VMCI_ERROR_REGION_ALREADY_SHARED	(-25)
247#define VMCI_ERROR_TIMEOUT			(-26)
248#define VMCI_ERROR_DATAGRAM_INCOMPLETE		(-27)
249#define VMCI_ERROR_INCORRECT_IRQL		(-28)
250#define VMCI_ERROR_EVENT_UNKNOWN		(-29)
251#define VMCI_ERROR_OBSOLETE			(-30)
252#define VMCI_ERROR_QUEUEPAIR_MISMATCH		(-31)
253#define VMCI_ERROR_QUEUEPAIR_NOTSET		(-32)
254#define VMCI_ERROR_QUEUEPAIR_NOTOWNER		(-33)
255#define VMCI_ERROR_QUEUEPAIR_NOTATTACHED	(-34)
256#define VMCI_ERROR_QUEUEPAIR_NOSPACE		(-35)
257#define VMCI_ERROR_QUEUEPAIR_NODATA		(-36)
258#define VMCI_ERROR_BUSMEM_INVALIDATION		(-37)
259#define VMCI_ERROR_MODULE_NOT_LOADED		(-38)
260#define VMCI_ERROR_DEVICE_NOT_FOUND		(-39)
261#define VMCI_ERROR_QUEUEPAIR_NOT_READY		(-40)
262#define VMCI_ERROR_WOULD_BLOCK			(-41)
263
264/* VMCI clients should return error code withing this range */
265#define VMCI_ERROR_CLIENT_MIN			(-500)
266#define VMCI_ERROR_CLIENT_MAX			(-550)
267
268/* Internal error codes. */
269#define VMCI_SHAREDMEM_ERROR_BAD_CONTEXT	(-1000)
270
271#define VMCI_PATH_MAX				256
272
273/* VMCI reserved events. */
274typedef uint32_t vmci_event_type;
275
276#define VMCI_EVENT_CTX_ID_UPDATE	0	// Only applicable to guest
277						// endpoints
278#define VMCI_EVENT_CTX_REMOVED		1	// Applicable to guest and host
279#define VMCI_EVENT_QP_RESUMED		2	// Only applicable to guest
280						// endpoints
281#define VMCI_EVENT_QP_PEER_ATTACH	3	// Applicable to guest, host
282						// and VMX
283#define VMCI_EVENT_QP_PEER_DETACH	4	// Applicable to guest, host
284						// and VMX
285#define VMCI_EVENT_MEM_ACCESS_ON	5	// Applicable to VMX and vmk. On
286						// vmk, this event has the
287						// Context payload type
288#define VMCI_EVENT_MEM_ACCESS_OFF	6	// Applicable to VMX and vmk.
289						// Same as above for the payload
290						// type
291#define VMCI_EVENT_GUEST_PAUSED		7	// Applicable to vmk. This
292						// event has the Context
293						// payload type
294#define VMCI_EVENT_GUEST_UNPAUSED	8	// Applicable to vmk. Same as
295						// above for the payload type.
296#define VMCI_EVENT_MAX			9
297
298/*
299 * Of the above events, a few are reserved for use in the VMX, and other
300 * endpoints (guest and host kernel) should not use them. For the rest of the
301 * events, we allow both host and guest endpoints to subscribe to them, to
302 * maintain the same API for host and guest endpoints.
303 */
304
305#define VMCI_EVENT_VALID_VMX(_event)					\
306	(_event == VMCI_EVENT_QP_PEER_ATTACH ||				\
307	_event == VMCI_EVENT_QP_PEER_DETACH ||				\
308	_event == VMCI_EVENT_MEM_ACCESS_ON ||				\
309	_event == VMCI_EVENT_MEM_ACCESS_OFF)
310
311#define VMCI_EVENT_VALID(_event)					\
312	(_event < VMCI_EVENT_MAX &&					\
313	_event != VMCI_EVENT_MEM_ACCESS_ON &&				\
314	_event != VMCI_EVENT_MEM_ACCESS_OFF &&				\
315	_event != VMCI_EVENT_GUEST_PAUSED &&				\
316	_event != VMCI_EVENT_GUEST_UNPAUSED)
317
318/* Reserved guest datagram resource ids. */
319#define VMCI_EVENT_HANDLER		0
320
321/*
322 * VMCI coarse-grained privileges (per context or host process/endpoint. An
323 * entity with the restricted flag is only allowed to interact with the
324 * hypervisor and trusted entities.
325 */
326typedef uint32_t vmci_privilege_flags;
327
328#define VMCI_PRIVILEGE_FLAG_RESTRICTED		0x01
329#define VMCI_PRIVILEGE_FLAG_TRUSTED		0x02
330#define VMCI_PRIVILEGE_ALL_FLAGS					\
331	(VMCI_PRIVILEGE_FLAG_RESTRICTED | VMCI_PRIVILEGE_FLAG_TRUSTED)
332#define VMCI_NO_PRIVILEGE_FLAGS			0x00
333#define VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS	VMCI_NO_PRIVILEGE_FLAGS
334#define VMCI_LEAST_PRIVILEGE_FLAGS		VMCI_PRIVILEGE_FLAG_RESTRICTED
335#define VMCI_MAX_PRIVILEGE_FLAGS		VMCI_PRIVILEGE_FLAG_TRUSTED
336
337/* 0 through VMCI_RESERVED_RESOURCE_ID_MAX are reserved. */
338#define VMCI_RESERVED_RESOURCE_ID_MAX		1023
339
340#define VMCI_DOMAIN_NAME_MAXLEN			32
341
342#define VMCI_LGPFX				"vmci: "
343
344/*
345 * struct vmci_queue_header
346 *
347 * A Queue cannot stand by itself as designed. Each Queue's header contains a
348 * pointer into itself (the producer_tail) and into its peer (consumer_head).
349 * The reason for the separation is one of accessibility: Each end-point can
350 * modify two things: where the next location to enqueue is within its produce_q
351 * (producer_tail); and where the next dequeue location is in its consume_q
352 * (consumer_head).
353 *
354 * An end-point cannot modify the pointers of its peer (guest to guest; NOTE
355 * that in the host both queue headers are mapped r/w). But, each end-point
356 * needs read access to both Queue header structures in order to determine how
357 * much space is used (or left) in the Queue. This is because for an end-point
358 * to know how full its produce_q is, it needs to use the consumer_head that
359 * points into the produce_q but -that- consumer_head is in the Queue header
360 * for that end-points consume_q.
361 *
362 * Thoroughly confused?  Sorry.
363 *
364 * producer_tail: the point to enqueue new entrants.  When you approach a line
365 * in a store, for example, you walk up to the tail.
366 *
367 * consumer_head: the point in the queue from which the next element is
368 * dequeued. In other words, who is next in line is he who is at the head of
369 * the line.
370 *
371 * Also, producer_tail points to an empty byte in the Queue, whereas
372 * consumer_head points to a valid byte of data (unless producer_tail ==
373 * consumer_head in which case consumerHead does not point to a valid byte of
374 * data).
375 *
376 * For a queue of buffer 'size' bytes, the tail and head pointers will be in
377 * the range [0, size-1].
378 *
379 * If produce_q_header->producer_tail == consume_q_header->consumer_head then
380 * the produce_q is empty.
381 */
382struct vmci_queue_header {
383	/* All fields are 64bit and aligned. */
384	struct vmci_handle	handle;		/* Identifier. */
385	volatile uint64_t	producer_tail;	/* Offset in this queue. */
386	volatile uint64_t	consumer_head;	/* Offset in peer queue. */
387};
388
389/*
390 * If one client of a QueuePair is a 32bit entity, we restrict the QueuePair
391 * size to be less than 4GB, and use 32bit atomic operations on the head and
392 * tail pointers. 64bit atomic read on a 32bit entity involves cmpxchg8b which
393 * is an atomic read-modify-write. This will cause traces to fire when a 32bit
394 * consumer tries to read the producer's tail pointer, for example, because the
395 * consumer has read-only access to the producer's tail pointer.
396 *
397 * We provide the following macros to invoke 32bit or 64bit atomic operations
398 * based on the architecture the code is being compiled on.
399 */
400
401#ifdef __x86_64__
402#define QP_MAX_QUEUE_SIZE_ARCH		CONST64U(0xffffffffffffffff)
403#define qp_atomic_read_offset(x)	atomic_load_64(x)
404#define qp_atomic_write_offset(x, y)	atomic_store_64(x, y)
405#else /* __x86_64__ */
406	/*
407	 * Wrappers below are being used because atomic_store_<type> operates
408	 * on a specific <type>. Likewise for atomic_load_<type>
409	 */
410
411	static inline uint32_t
412	type_safe_atomic_read_32(void *var)
413	{
414		return (atomic_load_32((volatile uint32_t *)(var)));
415	}
416
417	static inline void
418	type_safe_atomic_write_32(void *var, uint32_t val)
419	{
420		atomic_store_32((volatile uint32_t *)(var), (uint32_t)(val));
421	}
422
423#define QP_MAX_QUEUE_SIZE_ARCH		CONST64U(0xffffffff)
424#define qp_atomic_read_offset(x)	type_safe_atomic_read_32((void *)(x))
425#define qp_atomic_write_offset(x, y)					\
426	type_safe_atomic_write_32((void *)(x), (uint32_t)(y))
427#endif /* __x86_64__ */
428
429/*
430 *------------------------------------------------------------------------------
431 *
432 * qp_add_pointer --
433 *
434 *     Helper to add a given offset to a head or tail pointer. Wraps the value
435 *     of the pointer around the max size of the queue.
436 *
437 * Results:
438 *     None.
439 *
440 * Side effects:
441 *     None.
442 *
443 *------------------------------------------------------------------------------
444 */
445
446static inline void
447qp_add_pointer(volatile uint64_t *var, size_t add, uint64_t size)
448{
449	uint64_t new_val = qp_atomic_read_offset(var);
450
451	if (new_val >= size - add)
452		new_val -= size;
453
454	new_val += add;
455	qp_atomic_write_offset(var, new_val);
456}
457
458/*
459 *------------------------------------------------------------------------------
460 *
461 * vmci_queue_header_producer_tail --
462 *
463 *     Helper routine to get the Producer Tail from the supplied queue.
464 *
465 * Results:
466 *     The contents of the queue's producer tail.
467 *
468 * Side effects:
469 *     None.
470 *
471 *------------------------------------------------------------------------------
472 */
473
474static inline uint64_t
475vmci_queue_header_producer_tail(const struct vmci_queue_header *q_header)
476{
477	struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
478	return (qp_atomic_read_offset(&qh->producer_tail));
479}
480
481/*
482 *------------------------------------------------------------------------------
483 *
484 * vmci_queue_header_consumer_head --
485 *
486 *     Helper routine to get the Consumer Head from the supplied queue.
487 *
488 * Results:
489 *     The contents of the queue's consumer tail.
490 *
491 * Side effects:
492 *     None.
493 *
494 *------------------------------------------------------------------------------
495 */
496
497static inline uint64_t
498vmci_queue_header_consumer_head(const struct vmci_queue_header *q_header)
499{
500	struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
501	return (qp_atomic_read_offset(&qh->consumer_head));
502}
503
504/*
505 *------------------------------------------------------------------------------
506 *
507 * vmci_queue_header_add_producer_tail --
508 *
509 *     Helper routine to increment the Producer Tail. Fundamentally,
510 *     qp_add_pointer() is used to manipulate the tail itself.
511 *
512 * Results:
513 *     None.
514 *
515 * Side effects:
516 *     None.
517 *
518 *------------------------------------------------------------------------------
519 */
520
521static inline void
522vmci_queue_header_add_producer_tail(struct vmci_queue_header *q_header,
523    size_t add, uint64_t queue_size)
524{
525
526	qp_add_pointer(&q_header->producer_tail, add, queue_size);
527}
528
529/*
530 *------------------------------------------------------------------------------
531 *
532 * vmci_queue_header_add_consumer_head --
533 *
534 *     Helper routine to increment the Consumer Head. Fundamentally,
535 *     qp_add_pointer() is used to manipulate the head itself.
536 *
537 * Results:
538 *     None.
539 *
540 * Side effects:
541 *     None.
542 *
543 *------------------------------------------------------------------------------
544 */
545
546static inline void
547vmci_queue_header_add_consumer_head(struct vmci_queue_header *q_header,
548    size_t add, uint64_t queue_size)
549{
550
551	qp_add_pointer(&q_header->consumer_head, add, queue_size);
552}
553
554/*
555 *------------------------------------------------------------------------------
556 *
557 * vmci_queue_header_get_pointers --
558 *
559 *     Helper routine for getting the head and the tail pointer for a queue.
560 *     Both the VMCIQueues are needed to get both the pointers for one queue.
561 *
562 * Results:
563 *     None.
564 *
565 * Side effects:
566 *     None.
567 *
568 *------------------------------------------------------------------------------
569 */
570
571static inline void
572vmci_queue_header_get_pointers(const struct vmci_queue_header *produce_q_header,
573    const struct vmci_queue_header *consume_q_header, uint64_t *producer_tail,
574    uint64_t *consumer_head)
575{
576
577	if (producer_tail)
578		*producer_tail =
579		    vmci_queue_header_producer_tail(produce_q_header);
580
581	if (consumer_head)
582		*consumer_head =
583		    vmci_queue_header_consumer_head(consume_q_header);
584}
585
586/*
587 *------------------------------------------------------------------------------
588 *
589 * vmci_queue_header_reset_pointers --
590 *
591 *     Reset the tail pointer (of "this" queue) and the head pointer (of "peer"
592 *     queue).
593 *
594 * Results:
595 *     None.
596 *
597 * Side effects:
598 *     None.
599 *
600 *------------------------------------------------------------------------------
601 */
602
603static inline void
604vmci_queue_header_reset_pointers(struct vmci_queue_header *q_header)
605{
606
607	qp_atomic_write_offset(&q_header->producer_tail, CONST64U(0));
608	qp_atomic_write_offset(&q_header->consumer_head, CONST64U(0));
609}
610
611/*
612 *------------------------------------------------------------------------------
613 *
614 * vmci_queue_header_init --
615 *
616 *     Initializes a queue's state (head & tail pointers).
617 *
618 * Results:
619 *     None.
620 *
621 * Side effects:
622 *     None.
623 *
624 *------------------------------------------------------------------------------
625 */
626
627static inline void
628vmci_queue_header_init(struct vmci_queue_header *q_header,
629    const struct vmci_handle handle)
630{
631
632	q_header->handle = handle;
633	vmci_queue_header_reset_pointers(q_header);
634}
635
636/*
637 *------------------------------------------------------------------------------
638 *
639 * vmci_queue_header_free_space --
640 *
641 *     Finds available free space in a produce queue to enqueue more data or
642 *     reports an error if queue pair corruption is detected.
643 *
644 * Results:
645 *     Free space size in bytes or an error code.
646 *
647 * Side effects:
648 *     None.
649 *
650 *------------------------------------------------------------------------------
651 */
652
653static inline int64_t
654vmci_queue_header_free_space(const struct vmci_queue_header *produce_q_header,
655    const struct vmci_queue_header *consume_q_header,
656    const uint64_t produce_q_size)
657{
658	uint64_t free_space;
659	uint64_t head;
660	uint64_t tail;
661
662	tail = vmci_queue_header_producer_tail(produce_q_header);
663	head = vmci_queue_header_consumer_head(consume_q_header);
664
665	if (tail >= produce_q_size || head >= produce_q_size)
666		return (VMCI_ERROR_INVALID_SIZE);
667
668	/*
669	 * Deduct 1 to avoid tail becoming equal to head which causes ambiguity.
670	 * If head and tail are equal it means that the queue is empty.
671	 */
672
673	if (tail >= head)
674		free_space = produce_q_size - (tail - head) - 1;
675	else
676		free_space = head - tail - 1;
677
678	return (free_space);
679}
680
681/*
682 *------------------------------------------------------------------------------
683 *
684 * vmci_queue_header_buf_ready --
685 *
686 *     vmci_queue_header_free_space() does all the heavy lifting of determing
687 *     the number of free bytes in a Queue. This routine, then subtracts that
688 *     size from the full size of the Queue so the caller knows how many bytes
689 *     are ready to be dequeued.
690 *
691 * Results:
692 *     On success, available data size in bytes (up to MAX_INT64).
693 *     On failure, appropriate error code.
694 *
695 * Side effects:
696 *     None.
697 *
698 *------------------------------------------------------------------------------
699 */
700
701static inline int64_t
702vmci_queue_header_buf_ready(const struct vmci_queue_header *consume_q_header,
703    const struct vmci_queue_header *produce_q_header,
704    const uint64_t consume_q_size)
705{
706	int64_t free_space;
707
708	free_space = vmci_queue_header_free_space(consume_q_header,
709	    produce_q_header, consume_q_size);
710	if (free_space < VMCI_SUCCESS)
711		return (free_space);
712	else
713		return (consume_q_size - free_space - 1);
714}
715
716#endif /* !_VMCI_DEFS_H_ */
717