VMMDevHGCM.cpp revision 8021e7f4e7fa0ca88dcd007624b3e07abe14a033
0N/A * available from http://www.virtualbox.org. This file is free software;
2362N/A * Clara, CA 95054 USA or visit http://www.sun.com if you need
0N/A#include "VMMDevHGCM.h"
0N/A#ifdef VBOX_WITH_DTRACE
0N/A# include "VBoxDD-dtrace.h"
0N/A# define VBOXDD_HGCMCALL_ENTER(a,b,c,d) do { } while (0)
0N/A# define VBOXDD_HGCMCALL_COMPLETED_REQ(a,b) do { } while (0)
0N/A# define VBOXDD_HGCMCALL_COMPLETED_EMT(a,b) do { } while (0)
0N/A# define VBOXDD_HGCMCALL_COMPLETED_DONE(a,b,c,d) do { } while (0)
0N/Atypedef enum _VBOXHGCMCMDTYPE
1178N/Atypedef struct _VBOXHGCMLINPTR
1178N/Astruct VBOXHGCMCMD
0N/A bool fCancelled;
0N/A int cLinPtrPages;
0N/Astatic int vmmdevHGCMAddCommand (VMMDevState *pVMMDevState, PVBOXHGCMCMD pCmd, RTGCPHYS GCPhys, uint32_t cbSize, VBOXHGCMCMDTYPE enmCmdType)
1178N/A Log(("vmmdevHGCMSaveLinPtr: parm %d: %RGv %d = %d pages\n", iParm, GCPtr, u32Size, cPages));
1178N/A Log(("vmmdevHGCMWriteLinPtr: parm %d: size %d, cPages = %d\n", iParm, u32Size, pLinPtr->cPages));
1178N/A Log(("vmmdevHGCMWriteLinPtr: page %d: dst %RGp, src %p, cbWrite %d\n", iPage, GCPhysDst, pu8Src, cbWrite));
0N/Astatic int vmmdevHGCMPageListRead(PPDMDEVINSR3 pDevIns, void *pvDst, uint32_t cbDst, const HGCMPageListInfo *pPageListInfo)
1178N/A return PDMDevHlpPhysRead(pDevIns, pPageListInfo->aPages[0] | pPageListInfo->offFirstPage, pvDst, cbDst);
0N/A if (cbRemaining == 0)
0N/Astatic int vmmdevHGCMPageListWrite(PPDMDEVINSR3 pDevIns, const HGCMPageListInfo *pPageListInfo, const void *pvSrc, uint32_t cbSrc)
0N/A if (cbRemaining == 0)
0N/Astatic void logRelSavedCmdSizeMismatch (const char *pszFunction, uint32_t cbExpected, uint32_t cbCmdSize)
0N/Aint vmmdevHGCMConnect (VMMDevState *pVMMDevState, VMMDevHGCMConnect *pHGCMConnect, RTGCPHYS GCPhys)
0N/A vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMConnect->header.header.size, VBOXHGCMCMDTYPE_CONNECT);
0N/A rc = pVMMDevState->pHGCMDrv->pfnConnect (pVMMDevState->pHGCMDrv, pCmd, &pHGCMConnectCopy->loc, &pHGCMConnectCopy->u32ClientID);
0N/Astatic int vmmdevHGCMConnectSaved (VMMDevState *pVMMDevState, VMMDevHGCMConnect *pHGCMConnect, bool *pfHGCMCalled, VBOXHGCMCMD *pSavedCmd)
0N/A return VERR_INVALID_PARAMETER;
1178N/A rc = pVMMDevState->pHGCMDrv->pfnConnect (pVMMDevState->pHGCMDrv, pSavedCmd, &pHGCMConnectCopy->loc, &pHGCMConnectCopy->u32ClientID);
1178N/A *pfHGCMCalled = true;
1178N/Aint vmmdevHGCMDisconnect (VMMDevState *pVMMDevState, VMMDevHGCMDisconnect *pHGCMDisconnect, RTGCPHYS GCPhys)
0N/A vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMDisconnect->header.header.size, VBOXHGCMCMDTYPE_DISCONNECT);
0N/A rc = pVMMDevState->pHGCMDrv->pfnDisconnect (pVMMDevState->pHGCMDrv, pCmd, pHGCMDisconnect->u32ClientID);
0N/Astatic int vmmdevHGCMDisconnectSaved (VMMDevState *pVMMDevState, VMMDevHGCMDisconnect *pHGCMDisconnect, bool *pfHGCMCalled, VBOXHGCMCMD *pSavedCmd)
0N/A return VERR_INVALID_PARAMETER;
0N/A rc = pVMMDevState->pHGCMDrv->pfnDisconnect (pVMMDevState->pHGCMDrv, pSavedCmd, pHGCMDisconnect->u32ClientID);
0N/A *pfHGCMCalled = true;
0N/Aint vmmdevHGCMCall (VMMDevState *pVMMDevState, VMMDevHGCMCall *pHGCMCall, uint32_t cbHGCMCall, RTGCPHYS GCPhys, bool f64Bits)
0N/A Log(("vmmdevHGCMCall: client id = %d, function = %d, %s bit\n", pHGCMCall->u32ClientID, pHGCMCall->u32Function, f64Bits? "64": "32"));
0N/A#ifdef VBOX_WITH_64_BITS_GUESTS
0N/A case VMMDevHGCMParmType_32bit:
0N/A case VMMDevHGCMParmType_64bit:
0N/A#ifdef VBOX_WITH_64_BITS_GUESTS
0N/A case VMMDevHGCMParmType_32bit:
return rc;
return VERR_NO_MEMORY;
if (cLinPtrs > 0)
return VERR_NO_MEMORY;
if (cParms != 0)
if (f64Bits)
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size == 0)
rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr, pCmd->paLinPtrs, &pPages);
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size == 0)
AssertFailed();
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size == 0)
rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr, pCmd->paLinPtrs, &pPages);
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size == 0)
AssertFailed();
vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMCall->header.header.size, VBOXHGCMCMDTYPE_CALL);
return rc;
static void logRelLoadStatePointerIndexMismatch (uint32_t iParm, uint32_t iSavedParm, int iLinPtr, int cLinPtrs)
LogRel(("Warning: VMMDev load state: a pointer parameter index mismatch %d (expected %d) (%d/%d)\n",
static int vmmdevHGCMCallSaved (VMMDevState *pVMMDevState, VMMDevHGCMCall *pHGCMCall, uint32_t cbHGCMCall, bool f64Bits, bool *pfHGCMCalled, VBOXHGCMCMD *pSavedCmd)
Log(("vmmdevHGCMCallSaved: client id = %d, function = %d, %s bit\n", pHGCMCall->u32ClientID, pHGCMCall->u32Function, f64Bits? "64": "32"));
if (cParms != 0)
VBOXHGCMSVCPARM *pHostParm = (VBOXHGCMSVCPARM *)((uint8_t *)pSavedCmd + sizeof (struct VBOXHGCMCMD));
int iLinPtr = 0;
if (f64Bits)
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size == 0)
logRelLoadStatePointerIndexMismatch (iParm, pSavedCmd->paLinPtrs[iLinPtr].iParm, iLinPtr, pSavedCmd->cLinPtrs);
if (cbRemaining == 0)
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size == 0)
AssertFailed();
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size == 0)
logRelLoadStatePointerIndexMismatch (iParm, pSavedCmd->paLinPtrs[iLinPtr].iParm, iLinPtr, pSavedCmd->cLinPtrs);
if (cbRemaining == 0)
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size == 0)
AssertFailed();
rc = pVMMDevState->pHGCMDrv->pfnCall (pVMMDevState->pHGCMDrv, pSavedCmd, pHGCMCall->u32ClientID, pHGCMCall->u32Function, cParms, pSavedCmd->paHostParms);
*pfHGCMCalled = true;
return rc;
if ( GCPhys == 0
return VERR_INVALID_PARAMETER;
if (pCmd)
return rc;
case VBOXHGCMCMDTYPE_CONNECT:
case VBOXHGCMCMDTYPE_CALL:
#ifdef VBOX_WITH_64_BITS_GUESTS
AssertFailed ();
LogRel(("VMMDEV: Invalid HGCM command: pCmd->enmCmdType = 0x%08X, pHeader->header.requestType = 0x%08X\n",
return VERR_INVALID_PARAMETER;
#define PDMIHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState *) ((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, HGCMPort)) )
DECLCALLBACK(void) hgcmCompletedWorker (PPDMIHGCMPORT pInterface, int32_t result, PVBOXHGCMCMD pCmd)
#ifdef VBOX_WITH_DTRACE
#ifdef VBOX_WITH_64_BITS_GUESTS
/** @todo s/pVMMDevState/pThis/g */
* didn't have to mess around with PDMDevHlpPhysRead/Write. We're
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevReq_HGCMCall64:
uint32_t i;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size > 0)
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size > 0)
/* Copy pHostParm->u.pointer.addr[pHostParm->u.pointer.size] to pages. */
rc = vmmdevHGCMPageListWrite(pVMMDevState->pDevIns, pPageListInfo, pHostParm->u.pointer.addr, size);
# ifdef VBOX_WITH_DTRACE
case VMMDevReq_HGCMCall32:
uint32_t i;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size > 0)
rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size > 0)
/* Copy pHostParm->u.pointer.addr[pHostParm->u.pointer.size] to pages. */
rc = vmmdevHGCMPageListWrite(pVMMDevState->pDevIns, pPageListInfo, pHostParm->u.pointer.addr, size);
# ifdef VBOX_WITH_DTRACE
case VMMDevReq_HGCMCall:
uint32_t i;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (size > 0)
rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
iLinPtr++;
HGCMPageListInfo *pPageListInfo = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + pGuestParm->u.PageList.offset);
uint32_t cbPageListInfo = sizeof (HGCMPageListInfo) + (pPageListInfo->cPages - 1) * sizeof (pPageListInfo->aPages[0]);
if (size > 0)
/* Copy pHostParm->u.pointer.addr[pHostParm->u.pointer.size] to pages. */
rc = vmmdevHGCMPageListWrite(pVMMDevState->pDevIns, pPageListInfo, pHostParm->u.pointer.addr, size);
# ifdef VBOX_WITH_DTRACE
case VMMDevReq_HGCMConnect:
while (pIter)
cCmds++;
if (cCmds > 0)
while (pIter)
return rc;
while (cCmds--)
while (cCmds--)
RTGCPHYS *pPages = (RTGCPHYS *)((uint8_t *)pCmd->paLinPtrs + sizeof (VBOXHGCMLINPTR) * pCmd->cLinPtrs);
int cPages = 0;
cPages++;
return VERR_SSM_UNEXPECTED_DATA;
return rc;
while (pIter)
bool fHGCMCalled = false;
return VERR_NO_MEMORY;
Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->header.version, VMMDEV_REQUEST_HEADER_VERSION));
Log(("VMMDev request issued: %d, command type %d\n", requestHeader->header.requestType, pIter->enmCmdType));
case VBOXHGCMCMDTYPE_CONNECT:
requestHeader->header.rc = vmmdevHGCMConnectSaved (pVMMDevState, pHGCMConnect, &fHGCMCalled, pIter);
requestHeader->header.rc = vmmdevHGCMDisconnectSaved (pVMMDevState, pHGCMDisconnect, &fHGCMCalled, pIter);
case VBOXHGCMCMDTYPE_CALL:
#ifdef VBOX_WITH_64_BITS_GUESTS
bool f64Bits = false;
requestHeader->header.rc = vmmdevHGCMCallSaved (pVMMDevState, pHGCMCall, requestHeader->header.size, f64Bits, &fHGCMCalled, pIter);
case VMMDevReq_HGCMConnect:
case VMMDevReq_HGCMDisconnect:
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevReq_HGCMCall64:
case VMMDevReq_HGCMCall32:
case VMMDevReq_HGCMCall:
#ifdef VBOX_WITH_64_BITS_GUESTS
bool f64Bits = false;
requestHeader->header.rc = vmmdevHGCMCall (pVMMDevState, pHGCMCall, requestHeader->header.size, pIter->GCPhys, f64Bits);
LogRel(("VMMDEV: Ignoring unknown request type %x during LoadState\n", requestHeader->header.requestType));
LogRel(("VMMDEV: Ignoring unknown request type %x during LoadState\n", requestHeader->header.requestType));
if (!fHGCMCalled)
if (!fHGCMCalled)
return rc;