~n-muench/ubuntu/oneiric/open-vm-tools/open-vm-tools.fix-836277

« back to all changes in this revision

Viewing changes to modules/linux/shared/vmci_queue_pair.h

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-07-30 12:56:49 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730125649-97sfj5li8axiseoo
Tags: 2009.07.22-179896-2
* Temporarily building without dumbnet, the recently uploaded
  new dumbnet upstream version broke down (Closes: #539006).
* Using more common name to store local debian additions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
#endif
50
50
 
51
51
#if defined __APPLE__
52
 
#include <string.h>
 
52
#  include <string.h>
 
53
#  ifdef __cplusplus
 
54
class IOMemoryDescriptor;
 
55
class IOMemoryMap;
 
56
#  else
 
57
typedef struct IOMemoryDescriptor IOMemoryDescriptor;
 
58
typedef struct IOMemoryMap IOMemoryMap;
 
59
#  endif
53
60
#endif // __APPLE__
54
61
 
55
62
#if defined(__linux__) && defined(__KERNEL__)
58
65
 
59
66
 
60
67
/*
 
68
 * VMCIQueueHeader
 
69
 *
 
70
 * A Queue cannot stand by itself as designed.  Each Queue's header
 
71
 * contains a pointer into itself (the producerTail) and into its peer
 
72
 * (consumerHead).  The reason for the separation is one of
 
73
 * accessibility: Each end-point can modify two things: where the next
 
74
 * location to enqueue is within its produceQ (producerTail); and
 
75
 * where the next location in its consumeQ (i.e., its peer's produceQ)
 
76
 * it can dequeue (consumerHead).  The end-point cannot modify the
 
77
 * pointers of its peer (guest to guest; NOTE that in the host both
 
78
 * queue headers are mapped r/w).  But, each end-point needs access to
 
79
 * both Queue header structures in order to determine how much space
 
80
 * is used (or left) in the Queue.  This is because for an end-point
 
81
 * to know how full its produceQ is, it needs to use the consumerHead
 
82
 * that points into the produceQ but -that- consumerHead is in the
 
83
 * Queue header for that end-points consumeQ.
 
84
 *
 
85
 * Thoroughly confused?  Sorry.
 
86
 *
 
87
 * producerTail: the point to enqueue new entrants.  When you approach
 
88
 * a line in a store, for example, you walk up to the tail.
 
89
 *
 
90
 * consumerHead: the point in the queue from which the next element is
 
91
 * dequeued.  In other words, who is next in line is he who is at the
 
92
 * head of the line.
 
93
 *
 
94
 * Also, producerTail points to an empty byte in the Queue, whereas
 
95
 * consumerHead points to a valid byte of data (unless producerTail ==
 
96
 * consumerHead in which case consumerHead does not point to a valid
 
97
 * byte of data).
 
98
 *
61
99
 * For a queue of buffer 'size' bytes, the tail and head pointers will be in
62
100
 * the range [0, size-1].
 
101
 *
 
102
 * If produceQ->producerTail == consumeQ->consumerHead then the
 
103
 * produceQ is empty.
63
104
 */
64
105
 
65
106
typedef struct VMCIQueueHeader {
237
278
         struct page **page;
238
279
      } VMCIQueue;
239
280
#     define VMCIQueuePair_QueueIsMapped(q)     ((q)->page != NULL)
240
 
#  elif defined(__APPLE__)
 
281
#  elif defined __APPLE__
241
282
      /*
242
 
       * Mac OS X Host
 
283
       * Mac OS Host
 
284
       *
243
285
       * The VMCIQueueHeader has been created elsewhere and this
244
286
       * structure (VMCIQueue) needs a pointer to that
245
287
       * VMCIQueueHeader.
246
288
       *
247
289
       * Also, the queue contents are managed dynamically by
248
290
       * mapping/unmapping the pages.  All we need is the VA64
249
 
       * base address of the buffer and the vm_map_t of the VMX
 
291
       * base address of the buffer and the task_t of the VMX
250
292
       * process hosting the queue file (i.e. buffer).
251
293
       *
252
294
       * Note, too, that the buffer contains one page of queue
253
295
       * header information (head and tail pointers).  But, that
254
 
       * for the life of the VMCIQueue structure's life the
 
296
       * for the life of the VMCIQueue structure the
255
297
       * buffer value contains the address past the header info.
256
298
       * This modification happens during FinishAttach and is
257
299
       * never reversed.
258
300
       */
259
301
      typedef struct VMCIQueue {
260
 
         VMCIQueueHeader *queueHeaderPtr;
261
 
         ipc_port_t headerPort, contentPort;
262
 
         Bool attached;
 
302
         VMCIQueueHeader *queueHeaderPtr;
 
303
         IOMemoryDescriptor *pages;
 
304
         IOMemoryMap *header;
263
305
      } VMCIQueue;
264
 
#     define VMCIQueuePair_QueueIsMapped(q)     ((q)->attached != FALSE)
 
306
#    define VMCIQueuePair_QueueIsMapped(q) ((q)->pages)
265
307
#  else
266
308
      /*
267
309
       * Windows Host
273
315
       * Also, the queue contents are managed by an array of bytes
274
316
       * which are managed elsewhere.  So, this structure simply
275
317
       * contains the address of that array of bytes.
 
318
       *
 
319
       * We have a mutex to protect the queue from accesses within the
 
320
       * kernel module.  NOTE: the guest may be enqueuing or dequeuing
 
321
       * while the host has the mutex locked.  However, multiple
 
322
       * kernel processes will not access the Queue simultaneously.
 
323
       *
 
324
       * What the mutex is trying to protect is the moment where the
 
325
       * guest detaches from a queue.  In that moment, we will
 
326
       * allocate memory to hold the guest's produceQ and we will
 
327
       * change the queueHeaderPtr to point to a newly allocated (in
 
328
       * kernel memory) structure.  And, the buffer pointer will be
 
329
       * changed to point to an in-kernel queue content (even if there
 
330
       * isn't any data in the queue for the host to consume).
 
331
       *
 
332
       * Note that a VMCIQueue allocated by the host passes through
 
333
       * three states before it's torn down.  First, the queue is
 
334
       * created by the host but doesn't point to any memory and
 
335
       * therefore can't absorb any enqueue requests.  (NOTE: On
 
336
       * Windows this could be solved because of the mutexes, as
 
337
       * explained above [only in reverse, if you will].  But unless
 
338
       * we added the same mutexes [or other rules about accessing the
 
339
       * queues] we can't can't solve this generally on other
 
340
       * operating systems.)
 
341
       *
 
342
       * When the guest calls SetPageStore(), then the queue is backed
 
343
       * by valid memory and the host can enqueue.
 
344
       *
 
345
       * When the guest detaches, enqueues are absorbed by /dev/null,
 
346
       * as it were.
276
347
       */
277
348
      typedef struct VMCIQueue {
278
349
         VMCIQueueHeader *queueHeaderPtr;
279
350
         uint8 *buffer;
 
351
         Bool enqueueToDevNull;
 
352
         FAST_MUTEX *mutex;    /* Access the mutex through this */
 
353
         FAST_MUTEX __mutex;   /* Don't touch except to init */
280
354
      } VMCIQueue;
 
355
#define VMCIQueuePair_EnqueueToDevNull(q)       ((q)->enqueueToDevNull)
281
356
#define VMCIQueuePair_QueueIsMapped(q)          ((q)->buffer != NULL)
282
357
#  endif
283
358
#endif
284
359
 
 
360
#ifndef VMCIQueuePair_EnqueueToDevNull
 
361
#define VMCIQueuePair_EnqueueToDevNull(q)       (FALSE)
 
362
#endif /* default VMCIQueuePair_EnqueueToDevNull() definition */
 
363
 
 
364
/*
 
365
 *-----------------------------------------------------------------------------
 
366
 *
 
367
 * VMCIMemcpy{To,From}QueueFunc() prototypes.  Functions of these
 
368
 * types are passed around to enqueue and dequeue routines.  Note that
 
369
 * often the functions passed are simply wrappers around memcpy
 
370
 * itself.
 
371
 *
 
372
 *-----------------------------------------------------------------------------
 
373
 */
 
374
typedef int VMCIMemcpyToQueueFunc(VMCIQueue *queue, uint64 queueOffset,
 
375
                                  const void *src, size_t srcOffset,
 
376
                                  size_t size);
 
377
typedef int VMCIMemcpyFromQueueFunc(void *dest, size_t destOffset,
 
378
                                    const VMCIQueue *queue, uint64 queueOffset,
 
379
                                    size_t size);
 
380
 
 
381
/*
 
382
 * NOTE: On Windows host we have special code to access the queue
 
383
 * contents (and QueuePair header) so that we can protect accesses
 
384
 * during tear down of the guest that owns the mappings of the
 
385
 * QueuePair queue contents.  See
 
386
 * bora/modules/vmcrosstalk/windows/vmciHostQueuePair.c
 
387
 */
 
388
 
 
389
#if !defined _WIN32 || defined VMX86_TOOLS || defined VMX86_VMX
285
390
 
286
391
/*
287
392
 *-----------------------------------------------------------------------------
425
530
/*
426
531
 *-----------------------------------------------------------------------------
427
532
 *
428
 
 * VMCIMemcpy{To,From}QueueFunc() prototypes.  Functions of these
429
 
 * types are passed around to enqueue and dequeue routines.  Note that
430
 
 * often the functions passed are simply wrappers around memcpy
431
 
 * itself.
432
 
 *
433
 
 *-----------------------------------------------------------------------------
434
 
 */
435
 
typedef int VMCIMemcpyToQueueFunc(VMCIQueue *queue, uint64 queueOffset,
436
 
                                  const void *src, size_t srcOffset,
437
 
                                  size_t size);
438
 
typedef int VMCIMemcpyFromQueueFunc(void *dest, size_t destOffset,
439
 
                                    const VMCIQueue *queue, uint64 queueOffset,
440
 
                                    size_t size);
441
 
 
442
 
/*
443
 
 *-----------------------------------------------------------------------------
444
 
 *
445
533
 * VMCIMemcpy{To,From}Queue[v]() prototypes (and, in some cases, an
446
534
 * inline version).
447
535
 *
817
905
   uint64 tail;
818
906
   size_t written;
819
907
 
 
908
   if (UNLIKELY(VMCIQueuePair_EnqueueToDevNull(produceQueue))) {
 
909
      return bufSize;
 
910
   }
 
911
 
820
912
   if (UNLIKELY(!VMCIQueuePair_QueueIsMapped(produceQueue) &&
821
913
                !VMCIQueuePair_QueueIsMapped(consumeQueue))) {
822
914
      return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
823
915
   }
824
916
 
825
 
   freeSpace = VMCIQueue_FreeSpace(produceQueue, consumeQueue,
826
 
                                   produceQSize);   if (!freeSpace) {
 
917
   freeSpace = VMCIQueue_FreeSpace(produceQueue, consumeQueue, produceQSize);
 
918
   if (!freeSpace) {
827
919
      return VMCI_ERROR_QUEUEPAIR_NOSPACE;
828
920
   }
829
 
 
830
921
   if (freeSpace < 0) {
831
922
      return (ssize_t)freeSpace;
832
923
   }
833
924
 
834
 
   written = (size_t)(freeSpace > bufSize ? bufSize : freeSpace);
 
925
   written = MIN((size_t)freeSpace, bufSize);
835
926
   tail = VMCIQueue_ProducerTail(produceQueue);
836
927
   if (LIKELY(tail + written < produceQSize)) {
837
928
      memcpyToQueue(produceQueue, tail, buf, 0, written);
913
1004
   return __VMCIQueue_Enqueue(produceQueue, consumeQueue, produceQSize,
914
1005
                              (void *)iov, iovSize, VMCIMemcpyToQueueV);
915
1006
}
916
 
#endif
 
1007
#endif /* Systems that support struct iovec */
917
1008
 
918
1009
 
919
1010
/*
954
1045
      return VMCI_ERROR_QUEUEPAIR_NODATA;
955
1046
   }
956
1047
 
957
 
   bufReady = VMCIQueue_BufReady(consumeQueue, produceQueue,
958
 
                                 consumeQSize);
 
1048
   bufReady = VMCIQueue_BufReady(consumeQueue, produceQueue, consumeQSize);
959
1049
   if (!bufReady) {
960
1050
      return VMCI_ERROR_QUEUEPAIR_NODATA;
961
1051
   }
963
1053
      return (ssize_t)bufReady;
964
1054
   }
965
1055
 
966
 
   written = (size_t)(bufReady > bufSize ? bufSize : bufReady);
 
1056
   written = MIN((size_t)bufReady, bufSize);
967
1057
   head = VMCIQueue_ConsumerHead(produceQueue);
968
1058
   if (LIKELY(head + written < consumeQSize)) {
969
1059
      memcpyFromQueue(buf, 0, consumeQueue, head, written);
1049
1139
   return __VMCIQueue_Dequeue(produceQueue, consumeQueue, consumeQSize,
1050
1140
                              (void *)iov, iovSize, VMCIMemcpyFromQueueV, TRUE);
1051
1141
}
1052
 
#endif
 
1142
#endif /* Systems that support struct iovec */
1053
1143
 
1054
1144
 
1055
1145
/*
1118
1208
   return __VMCIQueue_Dequeue(produceQueue, consumeQueue, consumeQSize,
1119
1209
                              (void *)iov, iovSize, VMCIMemcpyFromQueueV, FALSE);
1120
1210
}
1121
 
#endif
 
1211
#endif /* Systems that support struct iovec */
 
1212
 
 
1213
#else /* Windows 32 Host defined below */
 
1214
 
 
1215
int VMCIMemcpyToQueue(VMCIQueue *queue, uint64 queueOffset, const void *src,
 
1216
                      size_t srcOffset, size_t size);
 
1217
int VMCIMemcpyFromQueue(void *dest, size_t destOffset, const VMCIQueue *queue,
 
1218
                        uint64 queueOffset, size_t size);
 
1219
 
 
1220
void VMCIQueue_Init(const VMCIHandle handle, VMCIQueue *queue);
 
1221
void VMCIQueue_GetPointers(const VMCIQueue *produceQ,
 
1222
                           const VMCIQueue *consumeQ,
 
1223
                           uint64 *producerTail,
 
1224
                           uint64 *consumerHead);
 
1225
int64 VMCIQueue_FreeSpace(const VMCIQueue *produceQueue,
 
1226
                          const VMCIQueue *consumeQueue,
 
1227
                          const uint64 produceQSize);
 
1228
int64 VMCIQueue_BufReady(const VMCIQueue *consumeQueue,
 
1229
                         const VMCIQueue *produceQueue,
 
1230
                         const uint64 consumeQSize);
 
1231
ssize_t VMCIQueue_Enqueue(VMCIQueue *produceQueue,
 
1232
                          const VMCIQueue *consumeQueue,
 
1233
                          const uint64 produceQSize,
 
1234
                          const void *buf,
 
1235
                          size_t bufSize);
 
1236
ssize_t VMCIQueue_Dequeue(VMCIQueue *produceQueue,
 
1237
                          const VMCIQueue *consumeQueue,
 
1238
                          const uint64 consumeQSize,
 
1239
                          void *buf,
 
1240
                          size_t bufSize);
 
1241
ssize_t VMCIQueue_Peek(VMCIQueue *produceQueue,
 
1242
                       const VMCIQueue *consumeQueue,
 
1243
                       const uint64 consumeQSize,
 
1244
                       void *buf,
 
1245
                       size_t bufSize);
 
1246
 
 
1247
#endif /* defined _WIN32 && !defined VMX86_TOOLS */
1122
1248
 
1123
1249
#endif /* !_PUBLIC_VMCI_QUEUE_PAIR_H_ */