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;
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]) {
918
__free_page(queue->kernelIf->page[--i]);
942
VMCI_FreeQueue(queue, i * PAGE_SIZE);
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
954
if (flags & VMCI_QPFLAG_PINNED) {
955
queue->kernelIf->va = vmap(queue->kernelIf->page, numDataPages, VM_MAP,
957
if (NULL == queue->kernelIf->va) {
958
VMCI_FreeQueue(queue, numDataPages * PAGE_SIZE);
961
queue->kernelIf->isDataMapped = TRUE;
925
964
return (void *)queue;
1308
1379
const VMCIQueue *queue, // IN:
1309
1380
uint64 queueOffset, // IN:
1310
1381
size_t size, // IN:
1311
int bufType) // IN: Unused
1382
int bufType, // IN: Unused
1383
Bool canBlock) // IN: Unused
1385
ASSERT(canBlock || !queue->kernelIf->host);
1387
return __VMCIMemcpyFromQueue((uint8 *)dest + destOffset,
1388
queue, queueOffset, size, FALSE);
1393
*-----------------------------------------------------------------------------
1395
* VMCIMemcpyToQueueLocal --
1397
* Copies from a given buffer to a local VMCI queue. On Linux, this is the
1398
* same as a regular copy.
1401
* Zero on success, negative error code on failure.
1406
*-----------------------------------------------------------------------------
1410
VMCIMemcpyToQueueLocal(VMCIQueue *queue, // OUT
1411
uint64 queueOffset, // IN
1412
const void *src, // IN
1413
size_t srcOffset, // IN
1415
int bufType, // IN: Unused
1416
Bool canBlock) // IN: Unused
1418
ASSERT(canBlock || !queue->kernelIf->host);
1420
return __VMCIMemcpyToQueue(queue, queueOffset,
1421
(uint8 *)src + srcOffset, size, FALSE);;
1426
*-----------------------------------------------------------------------------
1428
* VMCIMemcpyFromQueueLocal --
1430
* Copies to a given buffer from a VMCI Queue.
1433
* Zero on success, negative error code on failure.
1438
*-----------------------------------------------------------------------------
1442
VMCIMemcpyFromQueueLocal(void *dest, // OUT:
1443
size_t destOffset, // IN:
1444
const VMCIQueue *queue, // IN:
1445
uint64 queueOffset, // IN:
1447
int bufType, // IN: Unused
1448
Bool canBlock) // IN: Unused
1450
ASSERT(canBlock || !queue->kernelIf->host);
1313
1452
return __VMCIMemcpyFromQueue((uint8 *)dest + destOffset,
1314
1453
queue, queueOffset, size, FALSE);
1438
1582
VMCIHost_AllocQueue(uint64 size) // IN:
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;
1443
queue = VMCI_AllocKernelMem(queueSize, VMCI_MEMORY_NORMAL);
1589
queue = VMCI_AllocKernelMem(queueSize + queuePageSize, VMCI_MEMORY_NORMAL);
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;
1482
1638
*-----------------------------------------------------------------------------
1640
* VMCI_InitQueueMutex()
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.
1654
*----------------------------------------------------------------------------
1658
VMCI_InitQueueMutex(VMCIQueue *produceQ, // IN/OUT
1659
VMCIQueue *consumeQ) // IN/OUT
1663
ASSERT(produceQ->kernelIf);
1664
ASSERT(consumeQ->kernelIf);
1667
* Only the host queue has shared state - the guest queues do not
1668
* need to synchronize access using a queue mutex.
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);
1680
*-----------------------------------------------------------------------------
1682
* VMCI_CleanupQueueMutex()
1684
* Cleans up the mutex for the pair of queues.
1692
*----------------------------------------------------------------------------
1696
VMCI_CleanupQueueMutex(VMCIQueue *produceQ, // IN/OUT
1697
VMCIQueue *consumeQ) // IN/OUT
1701
ASSERT(produceQ->kernelIf);
1702
ASSERT(consumeQ->kernelIf);
1704
if (produceQ->kernelIf->host) {
1705
produceQ->kernelIf->mutex = NULL;
1706
consumeQ->kernelIf->mutex = NULL;
1712
*-----------------------------------------------------------------------------
1714
* VMCI_AcquireQueueMutex()
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.
1721
* VMCI_SUCCESS always.
1724
* May block the caller.
1726
*----------------------------------------------------------------------------
1730
VMCI_AcquireQueueMutex(VMCIQueue *queue, // IN
1731
Bool canBlock) // IN: Unused
1734
ASSERT(queue->kernelIf);
1736
if (queue->kernelIf->host) {
1738
ASSERT(queue->kernelIf->mutex);
1739
down(queue->kernelIf->mutex);
1742
return VMCI_SUCCESS;
1747
*-----------------------------------------------------------------------------
1749
* VMCI_ReleaseQueueMutex()
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.
1759
* May block the caller.
1761
*----------------------------------------------------------------------------
1765
VMCI_ReleaseQueueMutex(VMCIQueue *queue) // IN
1768
ASSERT(queue->kernelIf);
1770
if (queue->kernelIf->host) {
1771
ASSERT(queue->kernelIf->mutex);
1772
up(queue->kernelIf->mutex);
1778
*-----------------------------------------------------------------------------
1780
* VMCI_LockQueueHeader()
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.
1792
*----------------------------------------------------------------------------
1796
VMCI_LockQueueHeader(VMCIQueue *queue) // IN
1799
ASSERT(queue->kernelIf);
1800
ASSERT(!queue->kernelIf->host);
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
1811
*-----------------------------------------------------------------------------
1813
* VMCI_UnlockQueueHeader()
1815
* Release the spinlock guarding the queue header.
1823
*----------------------------------------------------------------------------
1827
VMCI_UnlockQueueHeader(VMCIQueue *queue) // IN
1830
ASSERT(queue->kernelIf);
1831
ASSERT(!queue->kernelIf->host);
1836
*-----------------------------------------------------------------------------
1484
1838
* VMCIReleasePageStorePages --
1486
1840
* Helper function to release pages in the PageStoreAttachInfo
1508
1862
set_page_dirty(pages[i]);
1510
1864
page_cache_release(pages[i]);
1871
*-----------------------------------------------------------------------------
1873
* VMCIHost_RegisterUserMemory --
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.
1880
* VMCI_SUCCESS on sucess, negative error code on failure.
1885
*-----------------------------------------------------------------------------
1889
VMCIHost_RegisterUserMemory(QueuePairPageStore *pageStore, // IN
1890
VMCIQueue *produceQ, // OUT
1891
VMCIQueue *consumeQ) // OUT
1896
ASSERT(produceQ->kernelIf->headerPage && consumeQ->kernelIf->headerPage);
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
1904
produceUVA = pageStore->pages;
1905
consumeUVA = pageStore->pages + produceQ->kernelIf->numPages * PAGE_SIZE;
1906
return VMCIHost_GetUserMemory(produceUVA, consumeUVA, produceQ, consumeQ);
1911
*-----------------------------------------------------------------------------
1913
* VMCIHost_UnregisterUserMemory --
1915
* Releases and removes the references to user pages stored in the attach
1922
* Pages are released from the page cache and may become
1925
*-----------------------------------------------------------------------------
1929
VMCIHost_UnregisterUserMemory(VMCIQueue *produceQ, // IN/OUT
1930
VMCIQueue *consumeQ) // IN/OUT
1932
ASSERT(produceQ->kernelIf);
1933
ASSERT(consumeQ->kernelIf);
1934
ASSERT(!produceQ->qHeader && !consumeQ->qHeader);
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);
1946
*-----------------------------------------------------------------------------
1948
* VMCIHost_MapQueues --
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.
1957
* VMCI_SUCCESS if pages are mapped, appropriate error code otherwise.
1962
*-----------------------------------------------------------------------------
1966
VMCIHost_MapQueues(VMCIQueue *produceQ, // IN/OUT
1967
VMCIQueue *consumeQ, // IN/OUT
1968
uint32 flags) // UNUSED
1972
if (!produceQ->qHeader || !consumeQ->qHeader) {
1973
struct page *headers[2];
1975
if (produceQ->qHeader != consumeQ->qHeader) {
1976
return VMCI_ERROR_QUEUEPAIR_MISMATCH;
1979
if (produceQ->kernelIf->headerPage == NULL ||
1980
*produceQ->kernelIf->headerPage == NULL) {
1981
return VMCI_ERROR_UNAVAILABLE;
1984
ASSERT(*produceQ->kernelIf->headerPage && *consumeQ->kernelIf->headerPage);
1986
headers[0] = *produceQ->kernelIf->headerPage;
1987
headers[1] = *consumeQ->kernelIf->headerPage;
1989
produceQ->qHeader = vmap(headers, 2, VM_MAP, PAGE_KERNEL);
1990
if (produceQ->qHeader != NULL) {
1992
(VMCIQueueHeader *)((uint8 *)produceQ->qHeader + PAGE_SIZE);
1993
result = VMCI_SUCCESS;
1995
Log("vmap failed\n");
1996
result = VMCI_ERROR_NO_MEM;
1999
result = VMCI_SUCCESS;
2007
*-----------------------------------------------------------------------------
2009
* VMCIHost_UnmapQueues --
2011
* Unmaps previously mapped queue pair headers from the kernel.
2014
* VMCI_SUCCESS always.
2017
* Pages are unpinned.
2019
*-----------------------------------------------------------------------------
2023
VMCIHost_UnmapQueues(VMCIGuestMemID gid, // IN
2024
VMCIQueue *produceQ, // IN/OUT
2025
VMCIQueue *consumeQ) // IN/OUT
2027
if (produceQ->qHeader) {
2028
ASSERT(consumeQ->qHeader);
2030
if (produceQ->qHeader < consumeQ->qHeader) {
2031
vunmap(produceQ->qHeader);
2033
vunmap(consumeQ->qHeader);
2035
produceQ->qHeader = NULL;
2036
consumeQ->qHeader = NULL;
2039
return VMCI_SUCCESS;
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
1538
2069
int err = VMCI_SUCCESS;
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;
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;
1555
2071
down_write(¤t->mm->mmap_sem);
1556
2072
retval = get_user_pages(current,
1558
(VA)attach->produceBuffer,
1559
attach->numProducePages,
2075
produceQ->kernelIf->numPages,
1561
attach->producePages,
2077
produceQ->kernelIf->headerPage,
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;
1570
2086
retval = get_user_pages(current,
1572
(VA)attach->consumeBuffer,
1573
attach->numConsumePages,
2089
consumeQ->kernelIf->numPages,
1575
attach->consumePages,
2091
consumeQ->kernelIf->headerPage,
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;
1585
2102
up_write(¤t->mm->mmap_sem);
1587
if (err == VMCI_SUCCESS) {
1588
struct page *headers[2];
1590
headers[0] = attach->producePages[0];
1591
headers[1] = attach->consumePages[0];
1593
produceQ->qHeader = vmap(headers, 2, VM_MAP, PAGE_KERNEL);
1594
if (produceQ->qHeader != NULL) {
1596
(VMCIQueueHeader *)((uint8 *)produceQ->qHeader + PAGE_SIZE);
1597
produceQ->kernelIf->page = &attach->producePages[1];
1598
consumeQ->kernelIf->page = &attach->consumePages[1];
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;
1608
if (err < VMCI_SUCCESS) {
1609
if (attach->producePages != NULL) {
1610
VMCI_FreeKernelMem(attach->producePages,
1611
attach->numProducePages *
1612
sizeof attach->producePages[0]);
1614
if (attach->consumePages != NULL) {
1615
VMCI_FreeKernelMem(attach->consumePages,
1616
attach->numConsumePages *
1617
sizeof attach->consumePages[0]);
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
1647
ASSERT(attach->producePages);
1648
ASSERT(attach->consumePages);
1649
ASSERT(produceQ->qHeader);
1651
vunmap(produceQ->qHeader);
1653
VMCIReleasePages(attach->producePages, attach->numProducePages, TRUE);
1654
VMCIReleasePages(attach->consumePages, attach->numConsumePages, TRUE);
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);
2131
VMCIHost_UnregisterUserMemory(produceQ, consumeQ);