~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to modules/linux/vmci/linux/vmciKernelIf.c

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
68
68
 
69
69
struct VMCIQueueKernelIf {
70
70
   struct page **page;
 
71
   struct page **headerPage;
 
72
   void *va;
 
73
   VMCIMutex __mutex;
 
74
   VMCIMutex *mutex;
 
75
   Bool host;
 
76
   Bool isDataMapped;
 
77
   size_t numPages;
71
78
};
72
79
 
73
80
typedef struct VMCIDelayedWorkInfo {
706
713
 
707
714
void
708
715
VMCI_WaitOnEvent(VMCIEvent *event,              // IN:
709
 
                 VMCIEventReleaseCB releaseCB,  // IN:
710
 
                 void *clientData)              // IN:
 
716
                 VMCIEventReleaseCB releaseCB,  // IN:
 
717
                 void *clientData)              // IN:
711
718
{
712
719
   /*
713
720
    * XXX Should this be a TASK_UNINTERRUPTIBLE wait? I'm leaving it
779
786
 */
780
787
 
781
788
int
782
 
VMCIMutex_Init(VMCIMutex *mutex) // IN:
 
789
VMCIMutex_Init(VMCIMutex *mutex,  // IN
 
790
               char *name,        // IN: Unused
 
791
               VMCILockRank rank) // IN: Unused
783
792
{
784
793
   sema_init(mutex, 1);
785
794
   return VMCI_SUCCESS;
878
887
 */
879
888
 
880
889
void *
881
 
VMCI_AllocQueue(uint64 size) // IN: size of queue (not including header)
 
890
VMCI_AllocQueue(uint64 size,  // IN: size of queue (not including header)
 
891
                uint32 flags) // IN: queuepair flags
882
892
{
883
893
   uint64 i;
884
894
   VMCIQueue *queue;
895
905
    * unresponsive, because we allocate page-by-page, and we allow the
896
906
    * system to wait for pages rather than fail.
897
907
    */
 
908
 
898
909
   if (size > VMCI_MAX_GUEST_QP_MEMORY) {
899
910
      ASSERT(FALSE);
900
911
      return NULL;
901
912
   }
902
913
 
 
914
   /*
 
915
    * If pinning is requested then double-check the size of the queue.
 
916
    * VMCIQPair_Alloc() will do this for the total queuepair size.
 
917
    */
 
918
 
 
919
   if ((flags & VMCI_QPFLAG_PINNED) && size > VMCI_MAX_PINNED_QP_MEMORY) {
 
920
      return NULL;
 
921
   }
 
922
 
903
923
   qHeader = (VMCIQueueHeader *)vmalloc(queueSize);
904
924
   if (!qHeader) {
905
925
      return NULL;
907
927
 
908
928
   queue = (VMCIQueue *)((uint8 *)qHeader + PAGE_SIZE);
909
929
   queue->qHeader = qHeader;
 
930
   queue->savedHeader = NULL;
910
931
   queue->kernelIf = (VMCIQueueKernelIf *)((uint8 *)queue + sizeof *queue);
 
932
   queue->kernelIf->headerPage = NULL; // Unused in guest.
911
933
   queue->kernelIf->page = (struct page **)((uint8 *)queue->kernelIf +
912
934
                                            sizeof *(queue->kernelIf));
 
935
   queue->kernelIf->va = NULL;
 
936
   queue->kernelIf->host = FALSE;
 
937
   queue->kernelIf->isDataMapped = FALSE;
913
938
 
914
939
   for (i = 0; i < numDataPages; i++) {
915
940
      queue->kernelIf->page[i] = alloc_pages(GFP_KERNEL, 0);
916
941
      if (!queue->kernelIf->page[i]) {
917
 
         while (i) {
918
 
            __free_page(queue->kernelIf->page[--i]);
919
 
         }
920
 
         vfree(qHeader);
921
 
         return NULL;
922
 
      }
 
942
         VMCI_FreeQueue(queue, i * PAGE_SIZE);
 
943
         return NULL;
 
944
      }
 
945
   }
 
946
 
 
947
   /*
 
948
    * alloc_pages() returns pinned PAs, but we need a permanent mapping to VA
 
949
    * if the caller has requested pinned queuepairs.  Map all of them into
 
950
    * kernel VA now, for the lifetime of the queue.  The page VAs will be
 
951
    * contiguous.
 
952
    */
 
953
 
 
954
   if (flags & VMCI_QPFLAG_PINNED) {
 
955
      queue->kernelIf->va = vmap(queue->kernelIf->page, numDataPages, VM_MAP,
 
956
                                 PAGE_KERNEL);
 
957
      if (NULL == queue->kernelIf->va) {
 
958
         VMCI_FreeQueue(queue, numDataPages * PAGE_SIZE);
 
959
         return NULL;
 
960
      }
 
961
      queue->kernelIf->isDataMapped = TRUE;
923
962
   }
924
963
 
925
964
   return (void *)queue;
951
990
 
952
991
   if (queue) {
953
992
      uint64 i;
 
993
 
 
994
      if (queue->kernelIf->isDataMapped) {
 
995
         ASSERT(queue->kernelIf->va);
 
996
         vunmap(queue->kernelIf->va);
 
997
         queue->kernelIf->va = NULL;
 
998
      }
 
999
 
 
1000
      ASSERT(NULL == queue->kernelIf->va);
 
1001
 
954
1002
      for (i = 0; i < CEILING(size, PAGE_SIZE); i++) {
955
1003
         __free_page(queue->kernelIf->page[i]);
956
1004
      }
1159
1207
   while (bytesCopied < size) {
1160
1208
      uint64 pageIndex = (queueOffset + bytesCopied) / PAGE_SIZE;
1161
1209
      size_t pageOffset = (queueOffset + bytesCopied) & (PAGE_SIZE - 1);
1162
 
      void *va = kmap(kernelIf->page[pageIndex]);
 
1210
      void *va;
1163
1211
      size_t toCopy;
1164
1212
 
 
1213
      if (kernelIf->isDataMapped) {
 
1214
         va = (void *)((uint8 *)kernelIf->va + (pageIndex * PAGE_SIZE));
 
1215
      } else {
 
1216
         va = kmap(kernelIf->page[pageIndex]);
 
1217
      }
 
1218
 
1165
1219
      ASSERT(va);
1166
1220
      if (size - bytesCopied > PAGE_SIZE - pageOffset) {
1167
1221
         /* Enough payload to fill up from this page. */
1177
1231
         /* The iovec will track bytesCopied internally. */
1178
1232
         err = memcpy_fromiovec((uint8 *)va + pageOffset, iov, toCopy);
1179
1233
         if (err != 0) {
1180
 
            kunmap(kernelIf->page[pageIndex]);
 
1234
            if (!kernelIf->isDataMapped) {
 
1235
               kunmap(kernelIf->page[pageIndex]);
 
1236
            }
1181
1237
            return VMCI_ERROR_INVALID_ARGS;
1182
1238
         }
1183
1239
      } else {
1185
1241
      }
1186
1242
 
1187
1243
      bytesCopied += toCopy;
1188
 
      kunmap(kernelIf->page[pageIndex]);
 
1244
      if (!kernelIf->isDataMapped) {
 
1245
         kunmap(kernelIf->page[pageIndex]);
 
1246
      }
1189
1247
   }
1190
1248
 
1191
1249
   return VMCI_SUCCESS;
1224
1282
   while (bytesCopied < size) {
1225
1283
      uint64 pageIndex = (queueOffset + bytesCopied) / PAGE_SIZE;
1226
1284
      size_t pageOffset = (queueOffset + bytesCopied) & (PAGE_SIZE - 1);
1227
 
      void *va = kmap(kernelIf->page[pageIndex]);
 
1285
      void *va;
1228
1286
      size_t toCopy;
1229
1287
 
 
1288
      if (kernelIf->isDataMapped) {
 
1289
         va = (void *)((uint8 *)kernelIf->va + (pageIndex * PAGE_SIZE));
 
1290
      } else {
 
1291
         va = kmap(kernelIf->page[pageIndex]);
 
1292
      }
 
1293
 
1230
1294
      ASSERT(va);
1231
1295
      if (size - bytesCopied > PAGE_SIZE - pageOffset) {
1232
1296
         /* Enough payload to fill up this page. */
1242
1306
         /* The iovec will track bytesCopied internally. */
1243
1307
         err = memcpy_toiovec(iov, (uint8 *)va + pageOffset, toCopy);
1244
1308
         if (err != 0) {
1245
 
            kunmap(kernelIf->page[pageIndex]);
 
1309
            if (!kernelIf->isDataMapped) {
 
1310
               kunmap(kernelIf->page[pageIndex]);
 
1311
            }
1246
1312
            return VMCI_ERROR_INVALID_ARGS;
1247
1313
         }
1248
1314
      } else {
1250
1316
      }
1251
1317
 
1252
1318
      bytesCopied += toCopy;
1253
 
      kunmap(kernelIf->page[pageIndex]);
 
1319
      if (!kernelIf->isDataMapped) {
 
1320
         kunmap(kernelIf->page[pageIndex]);
 
1321
      }
1254
1322
   }
1255
1323
 
1256
1324
   return VMCI_SUCCESS;
1279
1347
                  const void *src,    // IN:
1280
1348
                  size_t srcOffset,   // IN:
1281
1349
                  size_t size,        // IN:
1282
 
                  int bufType)        // IN: Unused
 
1350
                  int bufType,        // IN: Unused
 
1351
                  Bool canBlock)      // IN: Unused
1283
1352
{
 
1353
   ASSERT(canBlock || !queue->kernelIf->host);
 
1354
 
1284
1355
   return __VMCIMemcpyToQueue(queue, queueOffset,
1285
1356
                              (uint8 *)src + srcOffset, size, FALSE);
1286
1357
}
1308
1379
                    const VMCIQueue *queue, // IN:
1309
1380
                    uint64 queueOffset,     // IN:
1310
1381
                    size_t size,            // IN:
1311
 
                    int bufType)            // IN: Unused
1312
 
{
 
1382
                    int bufType,            // IN: Unused
 
1383
                    Bool canBlock)          // IN: Unused
 
1384
{
 
1385
   ASSERT(canBlock || !queue->kernelIf->host);
 
1386
 
 
1387
   return __VMCIMemcpyFromQueue((uint8 *)dest + destOffset,
 
1388
                                queue, queueOffset, size, FALSE);
 
1389
}
 
1390
 
 
1391
 
 
1392
/*
 
1393
 *-----------------------------------------------------------------------------
 
1394
 *
 
1395
 * VMCIMemcpyToQueueLocal --
 
1396
 *
 
1397
 *      Copies from a given buffer to a local VMCI queue. On Linux, this is the
 
1398
 *      same as a regular copy.
 
1399
 *
 
1400
 * Results:
 
1401
 *      Zero on success, negative error code on failure.
 
1402
 *
 
1403
 * Side effects:
 
1404
 *      None.
 
1405
 *
 
1406
 *-----------------------------------------------------------------------------
 
1407
 */
 
1408
 
 
1409
int
 
1410
VMCIMemcpyToQueueLocal(VMCIQueue *queue,     // OUT
 
1411
                       uint64 queueOffset,   // IN
 
1412
                       const void *src,      // IN
 
1413
                       size_t srcOffset,     // IN
 
1414
                       size_t size,          // IN
 
1415
                       int bufType,          // IN: Unused
 
1416
                       Bool canBlock)        // IN: Unused
 
1417
{
 
1418
   ASSERT(canBlock || !queue->kernelIf->host);
 
1419
 
 
1420
   return __VMCIMemcpyToQueue(queue, queueOffset,
 
1421
                              (uint8 *)src + srcOffset, size, FALSE);;
 
1422
}
 
1423
 
 
1424
 
 
1425
/*
 
1426
 *-----------------------------------------------------------------------------
 
1427
 *
 
1428
 * VMCIMemcpyFromQueueLocal --
 
1429
 *
 
1430
 *      Copies to a given buffer from a VMCI Queue.
 
1431
 *
 
1432
 * Results:
 
1433
 *      Zero on success, negative error code on failure.
 
1434
 *
 
1435
 * Side effects:
 
1436
 *      None.
 
1437
 *
 
1438
 *-----------------------------------------------------------------------------
 
1439
 */
 
1440
 
 
1441
int
 
1442
VMCIMemcpyFromQueueLocal(void *dest,             // OUT:
 
1443
                         size_t destOffset,      // IN:
 
1444
                         const VMCIQueue *queue, // IN:
 
1445
                         uint64 queueOffset,     // IN:
 
1446
                         size_t size,            // IN:
 
1447
                         int bufType,            // IN: Unused
 
1448
                         Bool canBlock)          // IN: Unused
 
1449
{
 
1450
   ASSERT(canBlock || !queue->kernelIf->host);
 
1451
 
1313
1452
   return __VMCIMemcpyFromQueue((uint8 *)dest + destOffset,
1314
1453
                                queue, queueOffset, size, FALSE);
1315
1454
}
1337
1476
                   const void *src,       // IN: iovec
1338
1477
                   size_t srcOffset,      // IN: ignored
1339
1478
                   size_t size,           // IN:
1340
 
                   int bufType)           // IN: ignored
 
1479
                   int bufType,           // IN: Unused
 
1480
                   Bool canBlock)         // IN: Unused
1341
1481
{
 
1482
   ASSERT(canBlock || !queue->kernelIf->host);
1342
1483
 
1343
1484
   /*
1344
1485
    * We ignore srcOffset because src is really a struct iovec * and will
1370
1511
                     const VMCIQueue *queue,  // IN:
1371
1512
                     uint64 queueOffset,      // IN:
1372
1513
                     size_t size,             // IN:
1373
 
                     int bufType)             // IN: ignored
 
1514
                     int bufType,             // IN: Unused
 
1515
                     Bool canBlock)           // IN: Unused
1374
1516
{
 
1517
   ASSERT(canBlock || !queue->kernelIf->host);
 
1518
 
1375
1519
   /*
1376
1520
    * We ignore destOffset because dest is really a struct iovec * and will
1377
1521
    * maintain offset internally.
1438
1582
VMCIHost_AllocQueue(uint64 size) // IN:
1439
1583
{
1440
1584
   VMCIQueue *queue;
1441
 
   const uint queueSize = sizeof *queue + sizeof *(queue->kernelIf);
 
1585
   const size_t numPages = CEILING(size, PAGE_SIZE) + 1;
 
1586
   const size_t queueSize = sizeof *queue + sizeof *(queue->kernelIf);
 
1587
   const size_t queuePageSize = numPages * sizeof *queue->kernelIf->page;
1442
1588
 
1443
 
   queue = VMCI_AllocKernelMem(queueSize, VMCI_MEMORY_NORMAL);
 
1589
   queue = VMCI_AllocKernelMem(queueSize + queuePageSize, VMCI_MEMORY_NORMAL);
1444
1590
   if (queue) {
1445
1591
      queue->qHeader = NULL;
 
1592
      queue->savedHeader = NULL;
1446
1593
      queue->kernelIf = (VMCIQueueKernelIf *)((uint8 *)queue + sizeof *queue);
 
1594
      queue->kernelIf->host = TRUE;
 
1595
      queue->kernelIf->mutex = NULL;
 
1596
      queue->kernelIf->numPages = numPages;
 
1597
      queue->kernelIf->headerPage = (struct page **)((uint8*)queue + queueSize);
 
1598
      queue->kernelIf->page = &queue->kernelIf->headerPage[1];
 
1599
      memset(queue->kernelIf->headerPage, 0,
 
1600
             sizeof *queue->kernelIf->headerPage * queue->kernelIf->numPages);
 
1601
      queue->kernelIf->va = NULL;
 
1602
      queue->kernelIf->isDataMapped = FALSE;
1447
1603
   }
1448
1604
 
1449
1605
   return queue;
1481
1637
/*
1482
1638
 *-----------------------------------------------------------------------------
1483
1639
 *
 
1640
 * VMCI_InitQueueMutex()
 
1641
 *
 
1642
 *       Initialize the mutex for the pair of queues.  This mutex is used to
 
1643
 *       protect the qHeader and the buffer from changing out from under any
 
1644
 *       users of either queue.  Of course, it's only any good if the mutexes
 
1645
 *       are actually acquired.  Queue structure must lie on non-paged memory
 
1646
 *       or we cannot guarantee access to the mutex.
 
1647
 *
 
1648
 * Results:
 
1649
 *       None.
 
1650
 *
 
1651
 * Side Effects:
 
1652
 *       None.
 
1653
 *
 
1654
 *----------------------------------------------------------------------------
 
1655
 */
 
1656
 
 
1657
void
 
1658
VMCI_InitQueueMutex(VMCIQueue *produceQ, // IN/OUT
 
1659
                    VMCIQueue *consumeQ) // IN/OUT
 
1660
{
 
1661
   ASSERT(produceQ);
 
1662
   ASSERT(consumeQ);
 
1663
   ASSERT(produceQ->kernelIf);
 
1664
   ASSERT(consumeQ->kernelIf);
 
1665
 
 
1666
   /*
 
1667
    * Only the host queue has shared state - the guest queues do not
 
1668
    * need to synchronize access using a queue mutex.
 
1669
    */
 
1670
 
 
1671
   if (produceQ->kernelIf->host) {
 
1672
      produceQ->kernelIf->mutex = &produceQ->kernelIf->__mutex;
 
1673
      consumeQ->kernelIf->mutex = &produceQ->kernelIf->__mutex;
 
1674
      sema_init(produceQ->kernelIf->mutex, 1);
 
1675
   }
 
1676
}
 
1677
 
 
1678
 
 
1679
/*
 
1680
 *-----------------------------------------------------------------------------
 
1681
 *
 
1682
 * VMCI_CleanupQueueMutex()
 
1683
 *
 
1684
 *       Cleans up the mutex for the pair of queues.
 
1685
 *
 
1686
 * Results:
 
1687
 *       None.
 
1688
 *
 
1689
 * Side Effects:
 
1690
 *       None.
 
1691
 *
 
1692
 *----------------------------------------------------------------------------
 
1693
 */
 
1694
 
 
1695
void
 
1696
VMCI_CleanupQueueMutex(VMCIQueue *produceQ, // IN/OUT
 
1697
                       VMCIQueue *consumeQ) // IN/OUT
 
1698
{
 
1699
   ASSERT(produceQ);
 
1700
   ASSERT(consumeQ);
 
1701
   ASSERT(produceQ->kernelIf);
 
1702
   ASSERT(consumeQ->kernelIf);
 
1703
 
 
1704
   if (produceQ->kernelIf->host) {
 
1705
      produceQ->kernelIf->mutex = NULL;
 
1706
      consumeQ->kernelIf->mutex = NULL;
 
1707
   }
 
1708
}
 
1709
 
 
1710
 
 
1711
/*
 
1712
 *-----------------------------------------------------------------------------
 
1713
 *
 
1714
 * VMCI_AcquireQueueMutex()
 
1715
 *
 
1716
 *       Acquire the mutex for the queue.  Note that the produceQ and
 
1717
 *       the consumeQ share a mutex.  So, only one of the two need to
 
1718
 *       be passed in to this routine.  Either will work just fine.
 
1719
 *
 
1720
 * Results:
 
1721
 *       VMCI_SUCCESS always.
 
1722
 *
 
1723
 * Side Effects:
 
1724
 *       May block the caller.
 
1725
 *
 
1726
 *----------------------------------------------------------------------------
 
1727
 */
 
1728
 
 
1729
int
 
1730
VMCI_AcquireQueueMutex(VMCIQueue *queue, // IN
 
1731
                       Bool canBlock)    // IN: Unused
 
1732
{
 
1733
   ASSERT(queue);
 
1734
   ASSERT(queue->kernelIf);
 
1735
 
 
1736
   if (queue->kernelIf->host) {
 
1737
      ASSERT(canBlock);
 
1738
      ASSERT(queue->kernelIf->mutex);
 
1739
      down(queue->kernelIf->mutex);
 
1740
   }
 
1741
 
 
1742
   return VMCI_SUCCESS;
 
1743
}
 
1744
 
 
1745
 
 
1746
/*
 
1747
 *-----------------------------------------------------------------------------
 
1748
 *
 
1749
 * VMCI_ReleaseQueueMutex()
 
1750
 *
 
1751
 *       Release the mutex for the queue.  Note that the produceQ and
 
1752
 *       the consumeQ share a mutex.  So, only one of the two need to
 
1753
 *       be passed in to this routine.  Either will work just fine.
 
1754
 *
 
1755
 * Results:
 
1756
 *       None.
 
1757
 *
 
1758
 * Side Effects:
 
1759
 *       May block the caller.
 
1760
 *
 
1761
 *----------------------------------------------------------------------------
 
1762
 */
 
1763
 
 
1764
void
 
1765
VMCI_ReleaseQueueMutex(VMCIQueue *queue) // IN
 
1766
{
 
1767
   ASSERT(queue);
 
1768
   ASSERT(queue->kernelIf);
 
1769
 
 
1770
   if (queue->kernelIf->host) {
 
1771
      ASSERT(queue->kernelIf->mutex);
 
1772
      up(queue->kernelIf->mutex);
 
1773
   }
 
1774
}
 
1775
 
 
1776
 
 
1777
/*
 
1778
 *-----------------------------------------------------------------------------
 
1779
 *
 
1780
 * VMCI_LockQueueHeader()
 
1781
 *
 
1782
 *       Acquire a spinlock guarding the queue header.  Note that the produceQ
 
1783
 *       and the consumeQ share the lock mutex.  So, only one of the two need to
 
1784
 *       be passed in to this routine.  Either will work just fine.
 
1785
 *
 
1786
 * Results:
 
1787
 *       None.
 
1788
 *
 
1789
 * Side Effects:
 
1790
 *       None.
 
1791
 *
 
1792
 *----------------------------------------------------------------------------
 
1793
 */
 
1794
 
 
1795
void
 
1796
VMCI_LockQueueHeader(VMCIQueue *queue) // IN
 
1797
{
 
1798
   ASSERT(queue);
 
1799
   ASSERT(queue->kernelIf);
 
1800
   ASSERT(!queue->kernelIf->host);
 
1801
 
 
1802
   /*
 
1803
    * We don't support non-blocking on the host right now, so we won't get
 
1804
    * here for a host queue.  And there's no lock required on the guest.  So
 
1805
    * this is a NOP.
 
1806
    */
 
1807
}
 
1808
 
 
1809
 
 
1810
/*
 
1811
 *-----------------------------------------------------------------------------
 
1812
 *
 
1813
 * VMCI_UnlockQueueHeader()
 
1814
 *
 
1815
 *       Release the spinlock guarding the queue header.
 
1816
 *
 
1817
 * Results:
 
1818
 *       None.
 
1819
 *
 
1820
 * Side Effects:
 
1821
 *       None.
 
1822
 *
 
1823
 *----------------------------------------------------------------------------
 
1824
 */
 
1825
 
 
1826
void
 
1827
VMCI_UnlockQueueHeader(VMCIQueue *queue) // IN
 
1828
{
 
1829
   ASSERT(queue);
 
1830
   ASSERT(queue->kernelIf);
 
1831
   ASSERT(!queue->kernelIf->host);
 
1832
}
 
1833
 
 
1834
 
 
1835
/*
 
1836
 *-----------------------------------------------------------------------------
 
1837
 *
1484
1838
 * VMCIReleasePageStorePages --
1485
1839
 *
1486
1840
 *       Helper function to release pages in the PageStoreAttachInfo
1508
1862
         set_page_dirty(pages[i]);
1509
1863
      }
1510
1864
      page_cache_release(pages[i]);
1511
 
   }
 
1865
      pages[i] = NULL;
 
1866
   }
 
1867
}
 
1868
 
 
1869
 
 
1870
/*
 
1871
 *-----------------------------------------------------------------------------
 
1872
 *
 
1873
 * VMCIHost_RegisterUserMemory --
 
1874
 *
 
1875
 *       Registers the specification of the user pages used for backing a queue
 
1876
 *       pair. Enough information to map in pages is stored in the OS specific
 
1877
 *       part of the VMCIQueue structure.
 
1878
 *
 
1879
 * Results:
 
1880
 *       VMCI_SUCCESS on sucess, negative error code on failure.
 
1881
 *
 
1882
 * Side Effects:
 
1883
 *       None.
 
1884
 *
 
1885
 *-----------------------------------------------------------------------------
 
1886
 */
 
1887
 
 
1888
int
 
1889
VMCIHost_RegisterUserMemory(QueuePairPageStore *pageStore,  // IN
 
1890
                            VMCIQueue *produceQ,            // OUT
 
1891
                            VMCIQueue *consumeQ)            // OUT
 
1892
{
 
1893
   VA64 produceUVA;
 
1894
   VA64 consumeUVA;
 
1895
 
 
1896
   ASSERT(produceQ->kernelIf->headerPage && consumeQ->kernelIf->headerPage);
 
1897
 
 
1898
   /*
 
1899
    * The new style and the old style mapping only differs in that we either
 
1900
    * get a single or two UVAs, so we split the single UVA range at the
 
1901
    * appropriate spot.
 
1902
    */
 
1903
 
 
1904
   produceUVA = pageStore->pages;
 
1905
   consumeUVA = pageStore->pages + produceQ->kernelIf->numPages * PAGE_SIZE;
 
1906
   return VMCIHost_GetUserMemory(produceUVA, consumeUVA, produceQ, consumeQ);
 
1907
}
 
1908
 
 
1909
 
 
1910
/*
 
1911
 *-----------------------------------------------------------------------------
 
1912
 *
 
1913
 * VMCIHost_UnregisterUserMemory --
 
1914
 *
 
1915
 *       Releases and removes the references to user pages stored in the attach
 
1916
 *       struct.
 
1917
 *
 
1918
 * Results:
 
1919
 *       None
 
1920
 *
 
1921
 * Side Effects:
 
1922
 *       Pages are released from the page cache and may become
 
1923
 *       swappable again.
 
1924
 *
 
1925
 *-----------------------------------------------------------------------------
 
1926
 */
 
1927
 
 
1928
void
 
1929
VMCIHost_UnregisterUserMemory(VMCIQueue *produceQ,         // IN/OUT
 
1930
                              VMCIQueue *consumeQ)         // IN/OUT
 
1931
{
 
1932
   ASSERT(produceQ->kernelIf);
 
1933
   ASSERT(consumeQ->kernelIf);
 
1934
   ASSERT(!produceQ->qHeader && !consumeQ->qHeader);
 
1935
 
 
1936
   VMCIReleasePages(produceQ->kernelIf->headerPage, produceQ->kernelIf->numPages, TRUE);
 
1937
   memset(produceQ->kernelIf->headerPage, 0,
 
1938
          sizeof *produceQ->kernelIf->headerPage * produceQ->kernelIf->numPages);
 
1939
   VMCIReleasePages(consumeQ->kernelIf->headerPage, consumeQ->kernelIf->numPages, TRUE);
 
1940
   memset(consumeQ->kernelIf->headerPage, 0,
 
1941
          sizeof *consumeQ->kernelIf->headerPage * consumeQ->kernelIf->numPages);
 
1942
}
 
1943
 
 
1944
 
 
1945
/*
 
1946
 *-----------------------------------------------------------------------------
 
1947
 *
 
1948
 * VMCIHost_MapQueues --
 
1949
 *
 
1950
 *       Once VMCIHost_RegisterUserMemory has been performed on a
 
1951
 *       queue, the queue pair headers can be mapped into the
 
1952
 *       kernel. Once mapped, they must be unmapped with
 
1953
 *       VMCIHost_UnmapQueues prior to calling
 
1954
 *       VMCIHost_UnregisterUserMemory.
 
1955
 *
 
1956
 * Results:
 
1957
 *       VMCI_SUCCESS if pages are mapped, appropriate error code otherwise.
 
1958
 *
 
1959
 * Side Effects:
 
1960
 *       Pages are pinned.
 
1961
 *
 
1962
 *-----------------------------------------------------------------------------
 
1963
 */
 
1964
 
 
1965
int
 
1966
VMCIHost_MapQueues(VMCIQueue *produceQ,  // IN/OUT
 
1967
                   VMCIQueue *consumeQ,  // IN/OUT
 
1968
                   uint32 flags)         // UNUSED
 
1969
{
 
1970
   int result;
 
1971
 
 
1972
   if (!produceQ->qHeader || !consumeQ->qHeader) {
 
1973
      struct page *headers[2];
 
1974
 
 
1975
      if (produceQ->qHeader != consumeQ->qHeader) {
 
1976
         return VMCI_ERROR_QUEUEPAIR_MISMATCH;
 
1977
      }
 
1978
 
 
1979
      if (produceQ->kernelIf->headerPage == NULL ||
 
1980
          *produceQ->kernelIf->headerPage == NULL) {
 
1981
         return VMCI_ERROR_UNAVAILABLE;
 
1982
      }
 
1983
 
 
1984
      ASSERT(*produceQ->kernelIf->headerPage && *consumeQ->kernelIf->headerPage);
 
1985
 
 
1986
      headers[0] = *produceQ->kernelIf->headerPage;
 
1987
      headers[1] = *consumeQ->kernelIf->headerPage;
 
1988
 
 
1989
      produceQ->qHeader = vmap(headers, 2, VM_MAP, PAGE_KERNEL);
 
1990
      if (produceQ->qHeader != NULL) {
 
1991
         consumeQ->qHeader =
 
1992
            (VMCIQueueHeader *)((uint8 *)produceQ->qHeader + PAGE_SIZE);
 
1993
         result = VMCI_SUCCESS;
 
1994
      } else {
 
1995
         Log("vmap failed\n");
 
1996
         result = VMCI_ERROR_NO_MEM;
 
1997
     }
 
1998
   } else {
 
1999
      result = VMCI_SUCCESS;
 
2000
   }
 
2001
 
 
2002
   return result;
 
2003
}
 
2004
 
 
2005
 
 
2006
/*
 
2007
 *-----------------------------------------------------------------------------
 
2008
 *
 
2009
 * VMCIHost_UnmapQueues --
 
2010
 *
 
2011
 *       Unmaps previously mapped queue pair headers from the kernel.
 
2012
 *
 
2013
 * Results:
 
2014
 *       VMCI_SUCCESS always.
 
2015
 *
 
2016
 * Side Effects:
 
2017
 *       Pages are unpinned.
 
2018
 *
 
2019
 *-----------------------------------------------------------------------------
 
2020
 */
 
2021
 
 
2022
int
 
2023
VMCIHost_UnmapQueues(VMCIGuestMemID gid,   // IN
 
2024
                     VMCIQueue *produceQ,  // IN/OUT
 
2025
                     VMCIQueue *consumeQ)  // IN/OUT
 
2026
{
 
2027
   if (produceQ->qHeader) {
 
2028
      ASSERT(consumeQ->qHeader);
 
2029
 
 
2030
      if (produceQ->qHeader < consumeQ->qHeader) {
 
2031
         vunmap(produceQ->qHeader);
 
2032
      } else {
 
2033
         vunmap(consumeQ->qHeader);
 
2034
      }
 
2035
      produceQ->qHeader = NULL;
 
2036
      consumeQ->qHeader = NULL;
 
2037
   }
 
2038
 
 
2039
   return VMCI_SUCCESS;
1512
2040
}
1513
2041
 
1514
2042
 
1516
2044
 *-----------------------------------------------------------------------------
1517
2045
 *
1518
2046
 * VMCIHost_GetUserMemory --
 
2047
 *
 
2048
 *
1519
2049
 *       Lock the user pages referenced by the {produce,consume}Buffer
1520
2050
 *       struct into memory and populate the {produce,consume}Pages
1521
2051
 *       arrays in the attach structure with them.
1530
2060
 */
1531
2061
 
1532
2062
int
1533
 
VMCIHost_GetUserMemory(PageStoreAttachInfo *attach,      // IN/OUT
1534
 
                       VMCIQueue *produceQ,              // OUT
1535
 
                       VMCIQueue *consumeQ)              // OUT
 
2063
VMCIHost_GetUserMemory(VA64 produceUVA,       // IN
 
2064
                       VA64 consumeUVA,       // IN
 
2065
                       VMCIQueue *produceQ,   // OUT
 
2066
                       VMCIQueue *consumeQ)   // OUT
1536
2067
{
1537
2068
   int retval;
1538
2069
   int err = VMCI_SUCCESS;
1539
2070
 
1540
 
 
1541
 
   attach->producePages =
1542
 
      VMCI_AllocKernelMem(attach->numProducePages * sizeof attach->producePages[0],
1543
 
                          VMCI_MEMORY_NORMAL);
1544
 
   if (attach->producePages == NULL) {
1545
 
      return VMCI_ERROR_NO_MEM;
1546
 
   }
1547
 
   attach->consumePages =
1548
 
      VMCI_AllocKernelMem(attach->numConsumePages * sizeof attach->consumePages[0],
1549
 
                          VMCI_MEMORY_NORMAL);
1550
 
   if (attach->consumePages == NULL) {
1551
 
      err = VMCI_ERROR_NO_MEM;
1552
 
      goto errorDealloc;
1553
 
   }
1554
 
 
1555
2071
   down_write(&current->mm->mmap_sem);
1556
2072
   retval = get_user_pages(current,
1557
2073
                           current->mm,
1558
 
                           (VA)attach->produceBuffer,
1559
 
                           attach->numProducePages,
 
2074
                           (VA)produceUVA,
 
2075
                           produceQ->kernelIf->numPages,
1560
2076
                           1, 0,
1561
 
                           attach->producePages,
 
2077
                           produceQ->kernelIf->headerPage,
1562
2078
                           NULL);
1563
 
   if (retval < attach->numProducePages) {
1564
 
      Log("get_user_pages(produce) failed: %d\n", retval);
1565
 
      VMCIReleasePages(attach->producePages, retval, FALSE);
 
2079
   if (retval < produceQ->kernelIf->numPages) {
 
2080
      Log("get_user_pages(produce) failed (retval=%d)\n", retval);
 
2081
      VMCIReleasePages(produceQ->kernelIf->headerPage, retval, FALSE);
1566
2082
      err = VMCI_ERROR_NO_MEM;
1567
2083
      goto out;
1568
2084
   }
1569
2085
 
1570
2086
   retval = get_user_pages(current,
1571
2087
                           current->mm,
1572
 
                           (VA)attach->consumeBuffer,
1573
 
                           attach->numConsumePages,
 
2088
                           (VA)consumeUVA,
 
2089
                           consumeQ->kernelIf->numPages,
1574
2090
                           1, 0,
1575
 
                           attach->consumePages,
 
2091
                           consumeQ->kernelIf->headerPage,
1576
2092
                           NULL);
1577
 
   if (retval < attach->numConsumePages) {
1578
 
      Log("get_user_pages(consume) failed: %d\n", retval);
1579
 
      VMCIReleasePages(attach->consumePages, retval, FALSE);
1580
 
      VMCIReleasePages(attach->producePages, attach->numProducePages, FALSE);
 
2093
   if (retval < consumeQ->kernelIf->numPages) {
 
2094
      Log("get_user_pages(consume) failed (retval=%d)\n", retval);
 
2095
      VMCIReleasePages(consumeQ->kernelIf->headerPage, retval, FALSE);
 
2096
      VMCIReleasePages(produceQ->kernelIf->headerPage,
 
2097
                       produceQ->kernelIf->numPages, FALSE);
1581
2098
      err = VMCI_ERROR_NO_MEM;
1582
2099
   }
1583
2100
 
1584
2101
out:
1585
2102
   up_write(&current->mm->mmap_sem);
1586
2103
 
1587
 
   if (err == VMCI_SUCCESS) {
1588
 
      struct page *headers[2];
1589
 
 
1590
 
      headers[0] = attach->producePages[0];
1591
 
      headers[1] = attach->consumePages[0];
1592
 
 
1593
 
      produceQ->qHeader = vmap(headers, 2, VM_MAP, PAGE_KERNEL);
1594
 
      if (produceQ->qHeader != NULL) {
1595
 
         consumeQ->qHeader =
1596
 
            (VMCIQueueHeader *)((uint8 *)produceQ->qHeader + PAGE_SIZE);
1597
 
         produceQ->kernelIf->page = &attach->producePages[1];
1598
 
         consumeQ->kernelIf->page = &attach->consumePages[1];
1599
 
      } else {
1600
 
         Log("vmap failed\n");
1601
 
         VMCIReleasePages(attach->producePages, attach->numProducePages, FALSE);
1602
 
         VMCIReleasePages(attach->consumePages, attach->numConsumePages, FALSE);
1603
 
         err = VMCI_ERROR_NO_MEM;
1604
 
     }
1605
 
   }
1606
 
 
1607
 
errorDealloc:
1608
 
   if (err < VMCI_SUCCESS) {
1609
 
      if (attach->producePages != NULL) {
1610
 
         VMCI_FreeKernelMem(attach->producePages,
1611
 
                            attach->numProducePages *
1612
 
                            sizeof attach->producePages[0]);
1613
 
      }
1614
 
      if (attach->consumePages != NULL) {
1615
 
         VMCI_FreeKernelMem(attach->consumePages,
1616
 
                            attach->numConsumePages *
1617
 
                            sizeof attach->consumePages[0]);
1618
 
      }
1619
 
   }
1620
 
 
1621
2104
   return err;
1622
2105
}
1623
2106
 
1640
2123
 */
1641
2124
 
1642
2125
void
1643
 
VMCIHost_ReleaseUserMemory(PageStoreAttachInfo *attach,      // IN/OUT
1644
 
                           VMCIQueue *produceQ,              // OUT
1645
 
                           VMCIQueue *consumeQ)              // OUT
 
2126
VMCIHost_ReleaseUserMemory(VMCIQueue *produceQ,  // IN/OUT
 
2127
                           VMCIQueue *consumeQ)  // IN/OUT
1646
2128
{
1647
 
   ASSERT(attach->producePages);
1648
 
   ASSERT(attach->consumePages);
1649
 
   ASSERT(produceQ->qHeader);
1650
 
 
1651
 
   vunmap(produceQ->qHeader);
1652
 
 
1653
 
   VMCIReleasePages(attach->producePages, attach->numProducePages, TRUE);
1654
 
   VMCIReleasePages(attach->consumePages, attach->numConsumePages, TRUE);
1655
 
 
1656
 
   VMCI_FreeKernelMem(attach->producePages,
1657
 
                      attach->numProducePages *
1658
 
                      sizeof attach->producePages[0]);
1659
 
   VMCI_FreeKernelMem(attach->consumePages,
1660
 
                      attach->numConsumePages *
1661
 
                      sizeof attach->consumePages[0]);
 
2129
   ASSERT(produceQ->kernelIf->headerPage);
 
2130
 
 
2131
   VMCIHost_UnregisterUserMemory(produceQ, consumeQ);
1662
2132
}
1663
2133
 
1664
2134
 
1680
2150
 
1681
2151
void
1682
2152
VMCI_ReadPortBytes(VMCIIoHandle handle,  // IN: Unused
1683
 
                   VMCIIoPort port,      // IN
1684
 
                   uint8 *buffer,        // OUT
1685
 
                   size_t bufferLength)  // IN
 
2153
                   VMCIIoPort port,      // IN
 
2154
                   uint8 *buffer,        // OUT
 
2155
                   size_t bufferLength)  // IN
1686
2156
{
1687
2157
   insb(port, buffer, bufferLength);
1688
2158
}