86
88
VMCIPrivilegeFlags privFlags;
87
89
Bool guestEndpoint;
90
#define VMCI_QPAIR_NO_QUEUE(_qp) (!(_qp)->produceQ->qHeader || \
91
!(_qp)->consumeQ->qHeader)
94
static int VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, VMCIQueue *consumeQ,
96
static int VMCIQPairGetQueueHeaders(const VMCIQPair *qpair,
97
VMCIQueueHeader **produceQHeader,
98
VMCIQueueHeader **consumeQHeader);
99
static int VMCIQPairWakeupCB(void *clientData);
100
static int VMCIQPairReleaseMutexCB(void *clientData);
101
static Bool VMCIQPairWaitForReadyQueue(VMCIQPair *qpair);
105
*-----------------------------------------------------------------------------
109
* Helper routine that will lock the QPair before subsequent operations.
112
* VMCI_SUCCESS if lock acquired. VMCI_ERROR_WOULD_BLOCK if queue mutex
113
* couldn't be acquired and qpair isn't allowed to block.
118
*-----------------------------------------------------------------------------
122
VMCIQPairLock(const VMCIQPair *qpair) // IN
124
#if !defined VMX86_VMX
125
if (qpair->flags & VMCI_QPFLAG_PINNED) {
126
VMCI_LockQueueHeader(qpair->produceQ);
129
return VMCI_AcquireQueueMutex(qpair->produceQ,
130
!(qpair->flags & VMCI_QPFLAG_NONBLOCK));
138
*-----------------------------------------------------------------------------
142
* Helper routine that will unlock the QPair after various operations.
150
*-----------------------------------------------------------------------------
154
VMCIQPairUnlock(const VMCIQPair *qpair) // IN
156
#if !defined VMX86_VMX
157
if (qpair->flags & VMCI_QPFLAG_PINNED) {
158
VMCI_UnlockQueueHeader(qpair->produceQ);
160
VMCI_ReleaseQueueMutex(qpair->produceQ);
167
*-----------------------------------------------------------------------------
169
* VMCIQPairHeaderLock --
171
* Helper routine that will lock the queue pair header before subsequent
172
* operations. If the queue pair is non blocking, a spinlock will be used.
173
* Otherwise, a regular mutex locking the complete queue pair will be used.
181
*-----------------------------------------------------------------------------
185
VMCIQPairLockHeader(const VMCIQPair *qpair) // IN
187
#if !defined VMX86_VMX
188
if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
189
VMCI_LockQueueHeader(qpair->produceQ);
191
(void)VMCI_AcquireQueueMutex(qpair->produceQ,
192
!(qpair->flags & VMCI_QPFLAG_NONBLOCK));
199
*-----------------------------------------------------------------------------
201
* VMCIQPairUnlockHeader --
203
* Helper routine that unlocks the queue pair header after calling
204
* VMCIQPairHeaderLock.
212
*-----------------------------------------------------------------------------
216
VMCIQPairUnlockHeader(const VMCIQPair *qpair) // IN
218
#if !defined VMX86_VMX
219
if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
220
VMCI_UnlockQueueHeader(qpair->produceQ);
222
VMCI_ReleaseQueueMutex(qpair->produceQ);
229
*-----------------------------------------------------------------------------
231
* VMCIQPairGetQueueHeaders --
233
* Helper routine that will retrieve the produce and consume
234
* headers of a given queue pair. If the guest memory of the
235
* queue pair is currently not available, the saved queue headers
236
* will be returned, if these are available.
239
* VMCI_SUCCESS if either current or saved queue headers are found.
240
* Appropriate error code otherwise.
245
*-----------------------------------------------------------------------------
249
VMCIQPairGetQueueHeaders(const VMCIQPair *qpair, // IN
250
VMCIQueueHeader **produceQHeader, // OUT
251
VMCIQueueHeader **consumeQHeader) // OUT
255
result = VMCIQPairMapQueueHeaders(qpair->produceQ, qpair->consumeQ,
256
!(qpair->flags & VMCI_QPFLAG_NONBLOCK));
257
if (result == VMCI_SUCCESS) {
258
*produceQHeader = qpair->produceQ->qHeader;
259
*consumeQHeader = qpair->consumeQ->qHeader;
260
} else if (qpair->produceQ->savedHeader && qpair->consumeQ->savedHeader) {
261
ASSERT(!qpair->guestEndpoint);
262
*produceQHeader = qpair->produceQ->savedHeader;
263
*consumeQHeader = qpair->consumeQ->savedHeader;
264
result = VMCI_SUCCESS;
272
*-----------------------------------------------------------------------------
274
* VMCIQPairMapQueueHeaders --
276
* The queue headers may not be mapped at all times. If a queue is
277
* currently not mapped, it will be attempted to do so.
280
* VMCI_SUCCESS if queues were validated, appropriate error code otherwise.
283
* May attempt to map in guest memory.
285
*-----------------------------------------------------------------------------
289
VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, // IN
290
VMCIQueue *consumeQ, // IN
295
if (NULL == produceQ->qHeader || NULL == consumeQ->qHeader) {
297
result = VMCIHost_MapQueues(produceQ, consumeQ, 0);
299
result = VMCI_ERROR_QUEUEPAIR_NOT_READY;
301
if (result < VMCI_SUCCESS) {
302
if (produceQ->savedHeader && consumeQ->savedHeader) {
303
return VMCI_ERROR_QUEUEPAIR_NOT_READY;
305
return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
315
*-----------------------------------------------------------------------------
317
* VMCIQPairWakeupCB --
319
* Callback from VMCI queue pair broker indicating that a queue
320
* pair that was previously not ready, now either is ready or
324
* VMCI_SUCCESS always.
329
*-----------------------------------------------------------------------------
333
VMCIQPairWakeupCB(void *clientData)
335
VMCIQPair *qpair = (VMCIQPair *)clientData;
338
VMCIQPairLock(qpair);
339
while (qpair->blocked > 0) {
341
VMCI_SignalEvent(&qpair->event);
343
VMCIQPairUnlock(qpair);
350
*-----------------------------------------------------------------------------
352
* VMCIQPairReleaseMutexCB --
354
* Callback from VMCI_WaitOnEvent releasing the queue pair mutex
355
* protecting the queue pair header state.
363
*-----------------------------------------------------------------------------
367
VMCIQPairReleaseMutexCB(void *clientData)
369
VMCIQPair *qpair = (VMCIQPair *)clientData;
371
VMCIQPairUnlock(qpair);
377
*-----------------------------------------------------------------------------
379
* VMCIQPairWaitForReadyQueue --
381
* Makes the calling thread wait for the queue pair to become
382
* ready for host side access.
385
* TRUE when thread is woken up after queue pair state change.
391
*-----------------------------------------------------------------------------
395
VMCIQPairWaitForReadyQueue(VMCIQPair *qpair)
397
if (UNLIKELY(qpair->guestEndpoint)) {
401
if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
405
VMCI_WaitOnEvent(&qpair->event, VMCIQPairReleaseMutexCB, qpair);
406
VMCIQPairLock(qpair);
149
468
return VMCI_ERROR_NO_RESOURCES;
471
retval = VMCI_Route(&src, &dst, FALSE, &route);
472
if (retval < VMCI_SUCCESS) {
473
if (VMCI_GuestPersonalityActive()) {
474
route = VMCI_ROUTE_AS_GUEST;
476
route = VMCI_ROUTE_AS_HOST;
480
if ((flags & (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED)) && !vmkernel) {
482
if (VMCI_ROUTE_AS_GUEST != route)
485
return VMCI_ERROR_INVALID_ARGS;
489
if (flags & VMCI_QPFLAG_PINNED) {
491
* Pinned pages implies non-blocking mode. Technically it doesn't
492
* have to, but there doesn't seem much point in pinning the pages if you
493
* can block since the queues will be small, so there's no performance
497
if (!(flags & VMCI_QPFLAG_NONBLOCK)) {
498
return VMCI_ERROR_INVALID_ARGS;
501
/* Limit the amount of memory that can be pinned. */
503
if (produceQSize + consumeQSize > VMCI_MAX_PINNED_QP_MEMORY) {
504
return VMCI_ERROR_NO_RESOURCES;
152
508
myQPair = VMCI_AllocKernelMem(sizeof *myQPair, VMCI_MEMORY_NONPAGED);
154
510
return VMCI_ERROR_NO_MEM;
252
* "Windows blocking call."
254
* Note that on the Windows platform, kernel module clients may
255
* block when calling into any these rouintes. The reason is
256
* that a mutex has to be acquired in order to view/modify the
257
* VMCIQueue structure fields: pointers, handle, and buffer data.
258
* However, other platforms don't require the acquisition of a
259
* mutex and thus don't block.
264
*-----------------------------------------------------------------------------
268
* Helper routine that will lock the QPair before subsequent operations.
274
* Windows blocking call.
276
*-----------------------------------------------------------------------------
280
VMCIQPairLock(const VMCIQPair *qpair) // IN
282
#if !defined VMX86_VMX
283
VMCI_AcquireQueueMutex(qpair->produceQ);
289
*-----------------------------------------------------------------------------
291
* VMCIQPair_Unlock --
293
* Helper routine that will unlock the QPair after various operations.
301
*-----------------------------------------------------------------------------
305
VMCIQPairUnlock(const VMCIQPair *qpair) // IN
307
#if !defined VMX86_VMX
308
VMCI_ReleaseQueueMutex(qpair->produceQ);
314
614
*-----------------------------------------------------------------------------
316
616
* VMCIQPair_GetProduceIndexes --
668
962
written = (size_t)(freeSpace > bufSize ? bufSize : freeSpace);
669
963
tail = VMCIQueueHeader_ProducerTail(produceQ->qHeader);
670
964
if (LIKELY(tail + written < produceQSize)) {
671
result = memcpyToQueue(produceQ, tail, buf, 0, written, bufType);
965
result = memcpyToQueue(produceQ, tail, buf, 0, written, bufType,
673
968
/* Tail pointer wraps around. */
675
970
const size_t tmp = (size_t)(produceQSize - tail);
677
result = memcpyToQueue(produceQ, tail, buf, 0, tmp, bufType);
972
result = memcpyToQueue(produceQ, tail, buf, 0, tmp, bufType, canBlock);
678
973
if (result >= VMCI_SUCCESS) {
679
result = memcpyToQueue(produceQ, 0, buf, tmp, written - tmp, bufType);
974
result = memcpyToQueue(produceQ, 0, buf, tmp, written - tmp, bufType,
747
1044
read = (size_t)(bufReady > bufSize ? bufSize : bufReady);
748
1045
head = VMCIQueueHeader_ConsumerHead(produceQ->qHeader);
749
1046
if (LIKELY(head + read < consumeQSize)) {
750
result = memcpyFromQueue(buf, 0, consumeQ, head, read, bufType);
1047
result = memcpyFromQueue(buf, 0, consumeQ, head, read, bufType, canBlock);
752
1049
/* Head pointer wraps around. */
754
1051
const size_t tmp = (size_t)(consumeQSize - head);
756
result = memcpyFromQueue(buf, 0, consumeQ, head, tmp, bufType);
1053
result = memcpyFromQueue(buf, 0, consumeQ, head, tmp, bufType, canBlock);
757
1054
if (result >= VMCI_SUCCESS) {
758
result = memcpyFromQueue(buf, tmp, consumeQ, 0, read - tmp, bufType);
1055
result = memcpyFromQueue(buf, tmp, consumeQ, 0, read - tmp, bufType,