vboxhgcm.c revision cb0578a5309e1fc264e5a4acc30543bea075be43
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * VBox HGCM connection
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 2008-2012 Oracle Corporation
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * This file is part of VirtualBox Open Source Edition (OSE), as
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * available from http://www.virtualbox.org. This file is free software;
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * you can redistribute it and/or modify it under the terms of the GNU
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * General Public License (GPL) as published by the Free Software
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Foundation, in version 2 as it comes in the "COPYING" file of the
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16a68807e13caea3183a41a5292f1b3f48b81a26Mark Andrews#if 1 /** @todo Try use the Vbgl interface instead of talking directly to the driver? */
31d3464c0c0a35236c7924f698c5a8a66a9ed534Mark Andrews#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
31d3464c0c0a35236c7924f698c5a8a66a9ed534Mark Andrews/*@todo move define somewhere else, and make sure it's less than VBGLR0_MAX_HGCM_KERNEL_PARM*/
a252c2771f59409d38b12d076513aeef89c3aeb1David Lawrence/*If we fail to pass data in one chunk, send it in chunks of this size instead*/
3b84ea68c0764dc9143ef37cdcf3f270ac225212Andreas Gustafsson# define MIN(a, b) ((a) < (b) ? (a) : (b))
846f974d5737710588eb676b64ba138da27c45ddMark Andrews//#define IN_GUEST
846f974d5737710588eb676b64ba138da27c45ddMark Andrews//#if defined(IN_GUEST)
846f974d5737710588eb676b64ba138da27c45ddMark Andrews//#define VBOX_WITH_CRHGSMIPROFILE
cdd5e378208eb7073cd3493326860df04b3ad036Andreas Gustafsson} VBOXCRHGSMIPROFILE, *PVBOXCRHGSMIPROFILE;
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_GET_TIME_NANO() RTTimeNanoTS()
3b84ea68c0764dc9143ef37cdcf3f270ac225212Andreas Gustafsson#define VBOXCRHGSMIPROFILE_GET_TIME_MILLI() RTTimeMilliTS()
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_LOG_STEP_TIME (10000000000.)
6526fd032fc418411da3af4201214e95c113d3e2Mark AndrewsDECLINLINE(void) vboxCrHgsmiProfileStart(PVBOXCRHGSMIPROFILE pProfile)
6526fd032fc418411da3af4201214e95c113d3e2Mark Andrews pProfile->cStartTime = VBOXCRHGSMIPROFILE_GET_TIME_NANO();
6526fd032fc418411da3af4201214e95c113d3e2Mark AndrewsDECLINLINE(void) vboxCrHgsmiProfileStep(PVBOXCRHGSMIPROFILE pProfile, uint64_t cStepTime)
6526fd032fc418411da3af4201214e95c113d3e2Mark Andrews// bool bDisable;
6526fd032fc418411da3af4201214e95c113d3e2Mark Andrews} VBOXCRHGSMIPROFILE_SCOPE, *PVBOXCRHGSMIPROFILE_SCOPE;
846f974d5737710588eb676b64ba138da27c45ddMark Andrewsstatic void vboxCrHgsmiLog(char * szString, ...)
6526fd032fc418411da3af4201214e95c113d3e2Mark Andrews _vsnprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList);
846f974d5737710588eb676b64ba138da27c45ddMark AndrewsDECLINLINE(void) vboxCrHgsmiProfileLog(PVBOXCRHGSMIPROFILE pProfile, uint64_t cTime)
846f974d5737710588eb676b64ba138da27c45ddMark Andrews uint64_t profileTime = cTime - pProfile->cStartTime;
846f974d5737710588eb676b64ba138da27c45ddMark Andrews double percent = ((double)100.0) * pProfile->cStepsTime / profileTime;
846f974d5737710588eb676b64ba138da27c45ddMark Andrews double cps = ((double)1000000000.) * pProfile->cSteps / profileTime;
846f974d5737710588eb676b64ba138da27c45ddMark Andrews vboxCrHgsmiLog("hgcm: cps: %.1f, host %.1f%%\n", cps, percent);
846f974d5737710588eb676b64ba138da27c45ddMark AndrewsDECLINLINE(void) vboxCrHgsmiProfileScopeEnter(PVBOXCRHGSMIPROFILE_SCOPE pScope)
6526fd032fc418411da3af4201214e95c113d3e2Mark Andrews// pScope->bDisable = false;
6526fd032fc418411da3af4201214e95c113d3e2Mark Andrews pScope->cStartTime = VBOXCRHGSMIPROFILE_GET_TIME_NANO();
5e2b6219d2a7e3dafc17e4979d081639996bbf9fMark AndrewsDECLINLINE(void) vboxCrHgsmiProfileScopeExit(PVBOXCRHGSMIPROFILE_SCOPE pScope)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson// if (!pScope->bDisable)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson uint64_t cTime = VBOXCRHGSMIPROFILE_GET_TIME_NANO();
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson vboxCrHgsmiProfileStep(&g_VBoxProfile, cTime - pScope->cStartTime);
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson if (VBOXCRHGSMIPROFILE_LOG_STEP_TIME < cTime - g_VBoxProfile.cStartTime)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson vboxCrHgsmiProfileLog(&g_VBoxProfile, cTime);
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson#define VBOXCRHGSMIPROFILE_INIT() vboxCrHgsmiProfileStart(&g_VBoxProfile)
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson#define VBOXCRHGSMIPROFILE_TERM() do {} while (0)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_FUNC_PROLOGUE() \
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson VBOXCRHGSMIPROFILE_SCOPE __vboxCrHgsmiProfileScope; \
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson vboxCrHgsmiProfileScopeEnter(&__vboxCrHgsmiProfileScope);
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_FUNC_EPILOGUE() \
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson vboxCrHgsmiProfileScopeExit(&__vboxCrHgsmiProfileScope); \
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_INIT() do {} while (0)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_TERM() do {} while (0)
595cc914dd4b0d4f0639aa3939bb9b602dc4c6f1Bob Halley#define VBOXCRHGSMIPROFILE_FUNC_PROLOGUE() do {} while (0)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define VBOXCRHGSMIPROFILE_FUNC_EPILOGUE() do {} while (0)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafssontypedef struct {
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafssonstatic CRVBOXHGCMDATA g_crvboxhgcm = {0,};
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
f80c797d42f213e026478a0e767a8dbbc2352e7fAndreas Gustafsson#define CR_VBOXHGCM_BUFFER_MAGIC 0xABCDE321
8ca42f6318be756354b70260050132545aa680d3Mark Andrews#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
#define TRUE true
#define FALSE false
int rc;
return VINF_SUCCESS;
return rc;
if (ppHgsmi)
return VINF_SUCCESS;
#ifdef VBOX_CRHGSMI_WITH_D3DDEV
if (pClient)
return NULL;
#ifdef VBOX_CRHGSMI_WITH_D3DDEV
return pClient;
if (pHgsmi)
return NULL;
int rc;
if (!buf)
cbSize);
return buf;
int rc;
return NULL;
return pBuf;
int rc;
return pHdr;
return NULL;
int rc;
return pHdr;
int rc;
return rc;
return rc;
return NULL;
int rc;
return NULL;
DECLINLINE(void) _crVBoxHGSMIFillCmd(VBOXUHGSMI_BUFFER_SUBMIT *pSubm, PCRVBOXHGSMI_CLIENT pClient, uint32_t cbData)
#ifndef IN_GUEST
return FALSE;
return TRUE;
crDebug("Host buffer too small %d out of requested %d bytes, reallocating", conn->cbHostBufferAllocated, len);
return FALSE;
return TRUE;
#ifdef IN_GUEST
# if defined(VBOX_WITH_CRHGSMI)
if (pClient)
# ifdef RT_OS_WINDOWS
NULL))
return VINF_SUCCESS;
/*On windows if we exceed max buffer len, we only get ERROR_GEN_FAILURE, and parms.hdr.result isn't changed.
return VERR_OUT_OF_RANGE;
return VERR_NOT_SUPPORTED;
int rc;
# ifdef RT_OS_LINUX
if (rc == 0)
if (rc >= 0)
return VINF_SUCCESS;
# ifdef RT_OS_LINUX
if (rc==0)
return VINF_SUCCESS;
return -rc;
return VERR_NOT_SUPPORTED;
return VERR_NOT_SUPPORTED;
#ifdef CHROMIUM_THREADSAFE
if (!buf)
if (!buf)
#ifdef CHROMIUM_THREADSAFE
void *pvBuff;
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
return pvBuff;
int rc;
#ifdef IN_GUEST
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
int rc;
crVBoxHGCMWriteReadExact(CRConnection *conn, const void *buf, unsigned int len, CRVBOXHGCMBUFFERKIND bufferKind)
int rc;
crDebug("SHCRGL_GUEST_FN_WRITE_BUFFER, offset=%u, size=%u", wbParms.ui32Offset.u.value32, wbParms.pBuffer.u.Pointer.size);
crError("SHCRGL_GUEST_FN_WRITE_BUFFER (%i) failed with %x %x\n", wbParms.pBuffer.u.Pointer.size, rc, wbParms.hdr.result);
crDebug("Reallocating host buffer from %d to %d bytes", conn->cbHostBufferAllocated, parms.cbWriteback.u.value32);
#ifdef CHROMIUM_THREADSAFE
#ifndef IN_GUEST
#ifdef CHROMIUM_THREADSAFE
#ifdef IN_GUEST
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
int rc;
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
case CR_VBOXHGCM_MEMORY:
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
case CR_VBOXHGCM_MEMORY_BIG:
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
#ifndef IN_GUEST
#ifndef IN_GUEST
/* CR_MESSAGE_OPCODES is freed in crserverlib/server_stream.c with crNetFree.
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
#ifdef IN_GUEST
int rc;
crWarning("Host doesn't accept our version %d.%d. Make sure you have appropriate additions installed!",
return FALSE;
return TRUE;
int rc;
return FALSE;
return TRUE;
#ifdef IN_GUEST
#ifdef RT_OS_WINDOWS
NULL,
NULL);
return FALSE;
return FALSE;
#ifdef RT_OS_WINDOWS
NULL))
int rc;
if (!rc)
return rc;
#ifdef RT_OS_WINDOWS
return rc;
return FALSE;
#ifdef RT_OS_WINDOWS
return FALSE;
return TRUE;
return FALSE;
#ifdef IN_GUEST
# ifdef RT_OS_WINDOWS
bool fHasActiveCons = false;
#ifdef CHROMIUM_THREADSAFE
#ifndef IN_GUEST
# ifdef RT_OS_WINDOWS
NULL) )
if (!fHasActiveCons)
# ifdef RT_OS_WINDOWS
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
bool _crVBoxHGSMIInit()
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
if (bHasHGSMI < 0)
int rc;
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
bHasHGSMI = 0;
return bHasHGSMI;
void _crVBoxHGSMITearDown()
int rc;
if (buf)
crWarning("_crVBoxHGSMIBufAlloc failed to allocate buffer of size (%d)", CRVBOXHGSMI_BUF_SIZE(cbSize));
void *pvBuf;
#ifdef CHROMIUM_THREADSAFE
if (pClient)
#ifdef CHROMIUM_THREADSAFE
return pvBuf;
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
int rc;
if (!pRecvBuffer)
if (!parms)
cbBuffer = 0;
if (cbBuffer)
if (pvData)
_crVBoxHGSMIWriteReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, void *buf, uint32_t offBuffer, unsigned int len, bool bIsBuffer)
CRVBOXHGSMIWRITEREAD *parms = (CRVBOXHGSMIWRITEREAD*)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
int rc;
if (!bIsBuffer)
void *pvBuf;
if (!pBuf)
offBuffer = 0;
if (!pRecvBuffer)
if (parms)
#ifdef DEBUG
if (cbWriteback)
if (pvData)
rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(cbWriteback), Flags, &pNewBuf);
crWarning("_crVBoxHGSMIWriteReadExact: pfnBufferCreate(%d) failed!", CRVBOXHGSMI_PAGE_ALIGN(cbWriteback));
if (!bIsBuffer)
static void _crVBoxHGSMIWriteExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI_BUFFER pBuf, uint32_t offStart, unsigned int len)
int rc;
#ifdef IN_GUEST
CRVBOXHGSMIINJECT *parms = (CRVBOXHGSMIINJECT *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
if (!parms)
CRVBOXHGSMIWRITE * parms = (CRVBOXHGSMIWRITE *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));;
#ifdef CHROMIUM_THREADSAFE
if (pClient)
#ifndef IN_GUEST
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
if (!pBuf)
#ifdef CHROMIUM_THREADSAFE
#ifdef IN_GUEST
_crVBoxHGSMIWriteExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len);
_crVBoxHGSMIWriteReadExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len, true);
#ifdef CHROMIUM_THREADSAFE
CRASSERT(0);
CRASSERT(0);
#ifdef CHROMIUM_THREADSAFE
CRASSERT(0);
#ifdef CHROMIUM_THREADSAFE
CRASSERT(0);
#ifdef IN_GUEST
#ifdef CHROMIUM_THREADSAFE
if (pClient)
#ifdef CHROMIUM_THREADSAFE
bool fHasActiveCons = false;
#ifdef CHROMIUM_THREADSAFE
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
#ifdef CHROMIUM_THREADSAFE
#ifdef CHROMIUM_THREADSAFE
CRASSERT(0);
#ifdef CHROMIUM_THREADSAFE
CRASSERT(0);
(void) mtu;
#ifdef RT_OS_WINDOWS
#ifdef CHROMIUM_THREADSAFE
case CR_VBOXHGCM_MEMORY:
case CR_VBOXHGCM_MEMORY_BIG:
void crVBoxHGCMTearDown(void)
#ifdef CHROMIUM_THREADSAFE
/* Connection count would be changed in calls to crNetDisconnect, so we have to store original value.
* Walking array backwards is not a good idea as it could cause some issues if we'd disconnect clients not in the
for (i=0; i<cCons; i++)
/* Note that [0] is intended, as the connections array would be shifted in each call to crNetDisconnect */
#ifdef CHROMIUM_THREADSAFE
#ifdef RT_OS_WINDOWS
int i, found = 0;
int n_bytes;
#ifdef CHROMIUM_THREADSAFE
if (found == 0) {
#ifdef CHROMIUM_THREADSAFE
#if defined(IN_GUEST)
int crVBoxHGCMRecv(
int32_t i;
#ifdef CHROMIUM_THREADSAFE
#ifdef IN_GUEST
if ( !conn )
if ( !conn )
#ifdef CHROMIUM_THREADSAFE