1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifndef _VMW_VMCI_DEF_H_
17#define _VMW_VMCI_DEF_H_
18
19#include <linux/atomic.h>
20
21
22#define VMCI_STATUS_ADDR 0x00
23#define VMCI_CONTROL_ADDR 0x04
24#define VMCI_ICR_ADDR 0x08
25#define VMCI_IMR_ADDR 0x0c
26#define VMCI_DATA_OUT_ADDR 0x10
27#define VMCI_DATA_IN_ADDR 0x14
28#define VMCI_CAPS_ADDR 0x18
29#define VMCI_RESULT_LOW_ADDR 0x1c
30#define VMCI_RESULT_HIGH_ADDR 0x20
31
32
33#define VMCI_MAX_DEVICES 1
34
35
36#define VMCI_STATUS_INT_ON 0x1
37
38
39#define VMCI_CONTROL_RESET 0x1
40#define VMCI_CONTROL_INT_ENABLE 0x2
41#define VMCI_CONTROL_INT_DISABLE 0x4
42
43
44#define VMCI_CAPS_HYPERCALL 0x1
45#define VMCI_CAPS_GUESTCALL 0x2
46#define VMCI_CAPS_DATAGRAM 0x4
47#define VMCI_CAPS_NOTIFICATIONS 0x8
48
49
50#define VMCI_ICR_DATAGRAM 0x1
51#define VMCI_ICR_NOTIFICATION 0x2
52
53
54#define VMCI_IMR_DATAGRAM 0x1
55#define VMCI_IMR_NOTIFICATION 0x2
56
57
58enum {
59 VMCI_INTR_TYPE_INTX = 0,
60 VMCI_INTR_TYPE_MSI = 1,
61 VMCI_INTR_TYPE_MSIX = 2,
62};
63
64
65#define VMCI_MAX_INTRS 2
66
67
68
69
70
71enum {
72 VMCI_INTR_DATAGRAM = 0,
73 VMCI_INTR_NOTIFICATION = 1,
74};
75
76
77
78
79
80#define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024)
81
82
83
84
85
86
87#define VMCI_MAX_PINNED_QP_MEMORY (32 * 1024)
88
89
90
91
92
93
94
95
96
97
98enum {
99 VMCI_RESOURCES_QUERY = 0,
100 VMCI_GET_CONTEXT_ID = 1,
101 VMCI_SET_NOTIFY_BITMAP = 2,
102 VMCI_DOORBELL_LINK = 3,
103 VMCI_DOORBELL_UNLINK = 4,
104 VMCI_DOORBELL_NOTIFY = 5,
105
106
107
108
109 VMCI_DATAGRAM_REQUEST_MAP = 6,
110 VMCI_DATAGRAM_REMOVE_MAP = 7,
111 VMCI_EVENT_SUBSCRIBE = 8,
112 VMCI_EVENT_UNSUBSCRIBE = 9,
113 VMCI_QUEUEPAIR_ALLOC = 10,
114 VMCI_QUEUEPAIR_DETACH = 11,
115
116
117
118
119
120 VMCI_HGFS_TRANSPORT = 13,
121 VMCI_UNITY_PBRPC_REGISTER = 14,
122 VMCI_RPC_PRIVILEGED = 15,
123 VMCI_RPC_UNPRIVILEGED = 16,
124 VMCI_RESOURCE_MAX = 17,
125};
126
127
128
129
130
131
132
133
134
135struct vmci_handle {
136 u32 context;
137 u32 resource;
138};
139
140#define vmci_make_handle(_cid, _rid) \
141 (struct vmci_handle){ .context = _cid, .resource = _rid }
142
143static inline bool vmci_handle_is_equal(struct vmci_handle h1,
144 struct vmci_handle h2)
145{
146 return h1.context == h2.context && h1.resource == h2.resource;
147}
148
149#define VMCI_INVALID_ID ~0
150static const struct vmci_handle VMCI_INVALID_HANDLE = {
151 .context = VMCI_INVALID_ID,
152 .resource = VMCI_INVALID_ID
153};
154
155static inline bool vmci_handle_is_invalid(struct vmci_handle h)
156{
157 return vmci_handle_is_equal(h, VMCI_INVALID_HANDLE);
158}
159
160
161
162
163
164#define VMCI_ANON_SRC_CONTEXT_ID VMCI_INVALID_ID
165#define VMCI_ANON_SRC_RESOURCE_ID VMCI_INVALID_ID
166static const struct vmci_handle VMCI_ANON_SRC_HANDLE = {
167 .context = VMCI_ANON_SRC_CONTEXT_ID,
168 .resource = VMCI_ANON_SRC_RESOURCE_ID
169};
170
171
172#define VMCI_RESERVED_CID_LIMIT ((u32) 16)
173
174
175
176
177
178#define VMCI_HYPERVISOR_CONTEXT_ID 0
179
180
181
182
183
184#define VMCI_WELL_KNOWN_CONTEXT_ID 1
185
186
187
188
189#define VMCI_HOST_CONTEXT_ID 2
190
191#define VMCI_CONTEXT_IS_VM(_cid) (VMCI_INVALID_ID != (_cid) && \
192 (_cid) > VMCI_HOST_CONTEXT_ID)
193
194
195
196
197
198#define VMCI_CONTEXT_RESOURCE_ID 0
199
200
201
202
203enum {
204 VMCI_SUCCESS_QUEUEPAIR_ATTACH = 5,
205 VMCI_SUCCESS_QUEUEPAIR_CREATE = 4,
206 VMCI_SUCCESS_LAST_DETACH = 3,
207 VMCI_SUCCESS_ACCESS_GRANTED = 2,
208 VMCI_SUCCESS_ENTRY_DEAD = 1,
209 VMCI_SUCCESS = 0,
210 VMCI_ERROR_INVALID_RESOURCE = (-1),
211 VMCI_ERROR_INVALID_ARGS = (-2),
212 VMCI_ERROR_NO_MEM = (-3),
213 VMCI_ERROR_DATAGRAM_FAILED = (-4),
214 VMCI_ERROR_MORE_DATA = (-5),
215 VMCI_ERROR_NO_MORE_DATAGRAMS = (-6),
216 VMCI_ERROR_NO_ACCESS = (-7),
217 VMCI_ERROR_NO_HANDLE = (-8),
218 VMCI_ERROR_DUPLICATE_ENTRY = (-9),
219 VMCI_ERROR_DST_UNREACHABLE = (-10),
220 VMCI_ERROR_PAYLOAD_TOO_LARGE = (-11),
221 VMCI_ERROR_INVALID_PRIV = (-12),
222 VMCI_ERROR_GENERIC = (-13),
223 VMCI_ERROR_PAGE_ALREADY_SHARED = (-14),
224 VMCI_ERROR_CANNOT_SHARE_PAGE = (-15),
225 VMCI_ERROR_CANNOT_UNSHARE_PAGE = (-16),
226 VMCI_ERROR_NO_PROCESS = (-17),
227 VMCI_ERROR_NO_DATAGRAM = (-18),
228 VMCI_ERROR_NO_RESOURCES = (-19),
229 VMCI_ERROR_UNAVAILABLE = (-20),
230 VMCI_ERROR_NOT_FOUND = (-21),
231 VMCI_ERROR_ALREADY_EXISTS = (-22),
232 VMCI_ERROR_NOT_PAGE_ALIGNED = (-23),
233 VMCI_ERROR_INVALID_SIZE = (-24),
234 VMCI_ERROR_REGION_ALREADY_SHARED = (-25),
235 VMCI_ERROR_TIMEOUT = (-26),
236 VMCI_ERROR_DATAGRAM_INCOMPLETE = (-27),
237 VMCI_ERROR_INCORRECT_IRQL = (-28),
238 VMCI_ERROR_EVENT_UNKNOWN = (-29),
239 VMCI_ERROR_OBSOLETE = (-30),
240 VMCI_ERROR_QUEUEPAIR_MISMATCH = (-31),
241 VMCI_ERROR_QUEUEPAIR_NOTSET = (-32),
242 VMCI_ERROR_QUEUEPAIR_NOTOWNER = (-33),
243 VMCI_ERROR_QUEUEPAIR_NOTATTACHED = (-34),
244 VMCI_ERROR_QUEUEPAIR_NOSPACE = (-35),
245 VMCI_ERROR_QUEUEPAIR_NODATA = (-36),
246 VMCI_ERROR_BUSMEM_INVALIDATION = (-37),
247 VMCI_ERROR_MODULE_NOT_LOADED = (-38),
248 VMCI_ERROR_DEVICE_NOT_FOUND = (-39),
249 VMCI_ERROR_QUEUEPAIR_NOT_READY = (-40),
250 VMCI_ERROR_WOULD_BLOCK = (-41),
251
252
253 VMCI_ERROR_CLIENT_MIN = (-500),
254 VMCI_ERROR_CLIENT_MAX = (-550),
255
256
257 VMCI_SHAREDMEM_ERROR_BAD_CONTEXT = (-1000),
258};
259
260
261enum {
262
263 VMCI_EVENT_CTX_ID_UPDATE = 0,
264
265
266 VMCI_EVENT_CTX_REMOVED = 1,
267
268
269 VMCI_EVENT_QP_RESUMED = 2,
270
271
272 VMCI_EVENT_QP_PEER_ATTACH = 3,
273
274
275 VMCI_EVENT_QP_PEER_DETACH = 4,
276
277
278
279
280
281 VMCI_EVENT_MEM_ACCESS_ON = 5,
282
283
284
285
286
287 VMCI_EVENT_MEM_ACCESS_OFF = 6,
288 VMCI_EVENT_MAX = 7,
289};
290
291
292
293
294
295
296
297
298#define VMCI_EVENT_VALID_VMX(_event) ((_event) == VMCI_EVENT_MEM_ACCESS_ON || \
299 (_event) == VMCI_EVENT_MEM_ACCESS_OFF)
300
301#define VMCI_EVENT_VALID(_event) ((_event) < VMCI_EVENT_MAX && \
302 !VMCI_EVENT_VALID_VMX(_event))
303
304
305#define VMCI_EVENT_HANDLER 0
306
307
308
309
310
311
312enum {
313 VMCI_NO_PRIVILEGE_FLAGS = 0,
314 VMCI_PRIVILEGE_FLAG_RESTRICTED = 1,
315 VMCI_PRIVILEGE_FLAG_TRUSTED = 2,
316 VMCI_PRIVILEGE_ALL_FLAGS = (VMCI_PRIVILEGE_FLAG_RESTRICTED |
317 VMCI_PRIVILEGE_FLAG_TRUSTED),
318 VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS = VMCI_NO_PRIVILEGE_FLAGS,
319 VMCI_LEAST_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_RESTRICTED,
320 VMCI_MAX_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_TRUSTED,
321};
322
323
324#define VMCI_RESERVED_RESOURCE_ID_MAX 1023
325
326
327
328
329
330
331
332
333
334
335#define VMCI_VERSION_SHIFT_WIDTH 16
336#define VMCI_MAKE_VERSION(_major, _minor) \
337 ((_major) << VMCI_VERSION_SHIFT_WIDTH | (u16) (_minor))
338
339#define VMCI_VERSION_MAJOR(v) ((u32) (v) >> VMCI_VERSION_SHIFT_WIDTH)
340#define VMCI_VERSION_MINOR(v) ((u16) (v))
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365#define VMCI_VERSION VMCI_VERSION_NOVMVM
366#define VMCI_VERSION_NOVMVM VMCI_MAKE_VERSION(11, 0)
367#define VMCI_VERSION_NOTIFY VMCI_MAKE_VERSION(10, 0)
368#define VMCI_VERSION_HOSTQP VMCI_MAKE_VERSION(9, 0)
369#define VMCI_VERSION_PREHOSTQP VMCI_MAKE_VERSION(8, 0)
370#define VMCI_VERSION_PREVERS2 VMCI_MAKE_VERSION(1, 0)
371
372#define VMCI_SOCKETS_MAKE_VERSION(_p) \
373 ((((_p)[0] & 0xFF) << 24) | (((_p)[1] & 0xFF) << 16) | ((_p)[2]))
374
375
376
377
378
379
380
381
382#define IOCTL_VMCI_VERSION _IO(7, 0x9f)
383#define IOCTL_VMCI_INIT_CONTEXT _IO(7, 0xa0)
384#define IOCTL_VMCI_QUEUEPAIR_SETVA _IO(7, 0xa4)
385#define IOCTL_VMCI_NOTIFY_RESOURCE _IO(7, 0xa5)
386#define IOCTL_VMCI_NOTIFICATIONS_RECEIVE _IO(7, 0xa6)
387#define IOCTL_VMCI_VERSION2 _IO(7, 0xa7)
388#define IOCTL_VMCI_QUEUEPAIR_ALLOC _IO(7, 0xa8)
389#define IOCTL_VMCI_QUEUEPAIR_SETPAGEFILE _IO(7, 0xa9)
390#define IOCTL_VMCI_QUEUEPAIR_DETACH _IO(7, 0xaa)
391#define IOCTL_VMCI_DATAGRAM_SEND _IO(7, 0xab)
392#define IOCTL_VMCI_DATAGRAM_RECEIVE _IO(7, 0xac)
393#define IOCTL_VMCI_CTX_ADD_NOTIFICATION _IO(7, 0xaf)
394#define IOCTL_VMCI_CTX_REMOVE_NOTIFICATION _IO(7, 0xb0)
395#define IOCTL_VMCI_CTX_GET_CPT_STATE _IO(7, 0xb1)
396#define IOCTL_VMCI_CTX_SET_CPT_STATE _IO(7, 0xb2)
397#define IOCTL_VMCI_GET_CONTEXT_ID _IO(7, 0xb3)
398#define IOCTL_VMCI_SOCKETS_VERSION _IO(7, 0xb4)
399#define IOCTL_VMCI_SOCKETS_GET_AF_VALUE _IO(7, 0xb8)
400#define IOCTL_VMCI_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
401#define IOCTL_VMCI_SET_NOTIFY _IO(7, 0xcb)
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443struct vmci_queue_header {
444
445 struct vmci_handle handle;
446 atomic64_t producer_tail;
447 atomic64_t consumer_head;
448};
449
450
451
452
453
454
455
456
457
458
459
460struct vmci_datagram {
461 struct vmci_handle dst;
462 struct vmci_handle src;
463 u64 payload_size;
464};
465
466
467
468
469
470
471#define VMCI_FLAG_DG_NONE 0
472#define VMCI_FLAG_WELLKNOWN_DG_HND 0x1
473#define VMCI_FLAG_ANYCID_DG_HND 0x2
474#define VMCI_FLAG_DG_DELAYED_CB 0x4
475
476
477
478
479
480#define VMCI_MAX_DG_SIZE (17 * 4096)
481#define VMCI_MAX_DG_PAYLOAD_SIZE (VMCI_MAX_DG_SIZE - \
482 sizeof(struct vmci_datagram))
483#define VMCI_DG_PAYLOAD(_dg) (void *)((char *)(_dg) + \
484 sizeof(struct vmci_datagram))
485#define VMCI_DG_HEADERSIZE sizeof(struct vmci_datagram)
486#define VMCI_DG_SIZE(_dg) (VMCI_DG_HEADERSIZE + (size_t)(_dg)->payload_size)
487#define VMCI_DG_SIZE_ALIGNED(_dg) ((VMCI_DG_SIZE(_dg) + 7) & (~((size_t) 0x7)))
488#define VMCI_MAX_DATAGRAM_QUEUE_SIZE (VMCI_MAX_DG_SIZE * 2)
489
490struct vmci_event_payload_qp {
491 struct vmci_handle handle;
492 u32 peer_id;
493 u32 _pad;
494};
495
496
497enum {
498
499 VMCI_QPFLAG_ATTACH_ONLY = 1 << 0,
500
501
502 VMCI_QPFLAG_LOCAL = 1 << 1,
503
504
505 VMCI_QPFLAG_NONBLOCK = 1 << 2,
506
507
508 VMCI_QPFLAG_PINNED = 1 << 3,
509
510
511 VMCI_QP_ALL_FLAGS = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QPFLAG_LOCAL |
512 VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED),
513
514
515 VMCI_QP_ASYMM = (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED),
516 VMCI_QP_ASYMM_PEER = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QP_ASYMM),
517};
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534#define VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE \
535 (VMCI_MAX_DATAGRAM_QUEUE_SIZE + \
536 1024 * (sizeof(struct vmci_datagram) + \
537 sizeof(struct vmci_event_data_max)))
538
539
540
541
542
543
544struct vmci_resource_query_hdr {
545 struct vmci_datagram hdr;
546 u32 num_resources;
547 u32 _padding;
548};
549
550
551
552
553
554struct vmci_resource_query_msg {
555 u32 num_resources;
556 u32 _padding;
557 u32 resources[1];
558};
559
560
561
562
563
564
565
566#define VMCI_RESOURCE_QUERY_MAX_NUM 31
567
568
569#define VMCI_RESOURCE_QUERY_MAX_SIZE \
570 (sizeof(struct vmci_resource_query_hdr) + \
571 sizeof(u32) * VMCI_RESOURCE_QUERY_MAX_NUM)
572
573
574
575
576
577struct vmci_notify_bm_set_msg {
578 struct vmci_datagram hdr;
579 u32 bitmap_ppn;
580 u32 _pad;
581};
582
583
584
585
586
587
588struct vmci_doorbell_link_msg {
589 struct vmci_datagram hdr;
590 struct vmci_handle handle;
591 u64 notify_idx;
592};
593
594
595
596
597
598
599struct vmci_doorbell_unlink_msg {
600 struct vmci_datagram hdr;
601 struct vmci_handle handle;
602};
603
604
605
606
607
608struct vmci_doorbell_notify_msg {
609 struct vmci_datagram hdr;
610 struct vmci_handle handle;
611};
612
613
614
615
616
617struct vmci_event_data {
618 u32 event;
619 u32 _pad;
620
621};
622
623
624
625
626
627
628struct vmci_event_payld_ctx {
629 u32 context_id;
630 u32 _pad;
631};
632
633struct vmci_event_payld_qp {
634 struct vmci_handle handle;
635 u32 peer_id;
636 u32 _pad;
637};
638
639
640
641
642
643
644
645struct vmci_event_data_max {
646 struct vmci_event_data event_data;
647 union {
648 struct vmci_event_payld_ctx context_payload;
649 struct vmci_event_payld_qp qp_payload;
650 } ev_data_payload;
651};
652
653
654
655
656
657
658struct vmci_event_msg {
659 struct vmci_datagram hdr;
660
661
662 struct vmci_event_data event_data;
663
664
665};
666
667
668struct vmci_event_ctx {
669 struct vmci_event_msg msg;
670 struct vmci_event_payld_ctx payload;
671};
672
673
674struct vmci_event_qp {
675 struct vmci_event_msg msg;
676 struct vmci_event_payld_qp payload;
677};
678
679
680
681
682
683struct vmci_qp_alloc_msg {
684 struct vmci_datagram hdr;
685 struct vmci_handle handle;
686 u32 peer;
687 u32 flags;
688 u64 produce_size;
689 u64 consume_size;
690 u64 num_ppns;
691
692
693};
694
695struct vmci_qp_detach_msg {
696 struct vmci_datagram hdr;
697 struct vmci_handle handle;
698};
699
700
701#define VMCI_FLAG_DELAYED_CB 0x01
702
703typedef void (*vmci_callback) (void *client_data);
704
705
706
707
708
709
710
711struct vmci_qp;
712
713
714typedef int (*vmci_datagram_recv_cb) (void *client_data,
715 struct vmci_datagram *msg);
716
717
718typedef void (*vmci_event_cb) (u32 sub_id, const struct vmci_event_data *ed,
719 void *client_data);
720
721
722
723
724
725static inline const void *
726vmci_event_data_const_payload(const struct vmci_event_data *ev_data)
727{
728 return (const char *)ev_data + sizeof(*ev_data);
729}
730
731static inline void *vmci_event_data_payload(struct vmci_event_data *ev_data)
732{
733 return (void *)vmci_event_data_const_payload(ev_data);
734}
735
736
737
738
739
740
741
742
743
744
745
746static inline u64 vmci_q_read_pointer(atomic64_t *var)
747{
748#if defined(CONFIG_X86_32)
749 return atomic_read((atomic_t *)var);
750#else
751 return atomic64_read(var);
752#endif
753}
754
755
756
757
758
759
760
761static inline void vmci_q_set_pointer(atomic64_t *var,
762 u64 new_val)
763{
764#if defined(CONFIG_X86_32)
765 return atomic_set((atomic_t *)var, (u32)new_val);
766#else
767 return atomic64_set(var, new_val);
768#endif
769}
770
771
772
773
774
775static inline void vmci_qp_add_pointer(atomic64_t *var,
776 size_t add,
777 u64 size)
778{
779 u64 new_val = vmci_q_read_pointer(var);
780
781 if (new_val >= size - add)
782 new_val -= size;
783
784 new_val += add;
785
786 vmci_q_set_pointer(var, new_val);
787}
788
789
790
791
792static inline u64
793vmci_q_header_producer_tail(const struct vmci_queue_header *q_header)
794{
795 struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
796 return vmci_q_read_pointer(&qh->producer_tail);
797}
798
799
800
801
802static inline u64
803vmci_q_header_consumer_head(const struct vmci_queue_header *q_header)
804{
805 struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
806 return vmci_q_read_pointer(&qh->consumer_head);
807}
808
809
810
811
812
813static inline void
814vmci_q_header_add_producer_tail(struct vmci_queue_header *q_header,
815 size_t add,
816 u64 queue_size)
817{
818 vmci_qp_add_pointer(&q_header->producer_tail, add, queue_size);
819}
820
821
822
823
824
825static inline void
826vmci_q_header_add_consumer_head(struct vmci_queue_header *q_header,
827 size_t add,
828 u64 queue_size)
829{
830 vmci_qp_add_pointer(&q_header->consumer_head, add, queue_size);
831}
832
833
834
835
836
837static inline void
838vmci_q_header_get_pointers(const struct vmci_queue_header *produce_q_header,
839 const struct vmci_queue_header *consume_q_header,
840 u64 *producer_tail,
841 u64 *consumer_head)
842{
843 if (producer_tail)
844 *producer_tail = vmci_q_header_producer_tail(produce_q_header);
845
846 if (consumer_head)
847 *consumer_head = vmci_q_header_consumer_head(consume_q_header);
848}
849
850static inline void vmci_q_header_init(struct vmci_queue_header *q_header,
851 const struct vmci_handle handle)
852{
853 q_header->handle = handle;
854 atomic64_set(&q_header->producer_tail, 0);
855 atomic64_set(&q_header->consumer_head, 0);
856}
857
858
859
860
861
862static s64
863vmci_q_header_free_space(const struct vmci_queue_header *produce_q_header,
864 const struct vmci_queue_header *consume_q_header,
865 const u64 produce_q_size)
866{
867 u64 tail;
868 u64 head;
869 u64 free_space;
870
871 tail = vmci_q_header_producer_tail(produce_q_header);
872 head = vmci_q_header_consumer_head(consume_q_header);
873
874 if (tail >= produce_q_size || head >= produce_q_size)
875 return VMCI_ERROR_INVALID_SIZE;
876
877
878
879
880
881
882 if (tail >= head)
883 free_space = produce_q_size - (tail - head) - 1;
884 else
885 free_space = head - tail - 1;
886
887 return free_space;
888}
889
890
891
892
893
894
895
896
897
898
899static inline s64
900vmci_q_header_buf_ready(const struct vmci_queue_header *consume_q_header,
901 const struct vmci_queue_header *produce_q_header,
902 const u64 consume_q_size)
903{
904 s64 free_space;
905
906 free_space = vmci_q_header_free_space(consume_q_header,
907 produce_q_header, consume_q_size);
908 if (free_space < VMCI_SUCCESS)
909 return free_space;
910
911 return consume_q_size - free_space - 1;
912}
913
914
915#endif
916