VMMDevHGCM.cpp revision b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * VBox Guest/VMM/host communication:
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * HGCM - Host-Guest Communication Manager device
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * This file is part of VirtualBox Open Source Edition (OSE), as
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * available from http://www.virtualbox.org. This file is free software;
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * you can redistribute it and/or modify it under the terms of the GNU
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * General Public License (GPL) as published by the Free Software
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * Foundation, in version 2 as it comes in the "COPYING" file of the
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * Clara, CA 95054 USA or visit http://www.sun.com if you need
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * additional information or have any questions.
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering/* Information about a linear ptr parameter. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Index of the parameter. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Offset in the first physical page of the region. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* How many pages. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Pointer to array of the GC physical addresses for these pages.
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * It is assumed that the physical address of the locked resident
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering * guest page does not change.
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Active commands, list is protected by critsectHGCMCmdList. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* The type of the command. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Whether the command was cancelled by the guest. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* GC physical address of the guest request. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Request packet size */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Pointer to converted host parameters in case of a Call request. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Linear pointer parameters information. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Pointer to descriptions of linear pointers. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poetteringstatic int vmmdevHGCMCmdListLock (VMMDevState *pVMMDevState)
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering int rc = RTCritSectEnter (&pVMMDevState->critsectHGCMCmdList);
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poetteringstatic void vmmdevHGCMCmdListUnlock (VMMDevState *pVMMDevState)
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering int rc = RTCritSectLeave (&pVMMDevState->critsectHGCMCmdList);
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poetteringstatic int vmmdevHGCMAddCommand (VMMDevState *pVMMDevState, PVBOXHGCMCMD pCmd, RTGCPHYS GCPhys, uint32_t cbSize, VBOXHGCMCMDTYPE enmCmdType)
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* PPDMDEVINS pDevIns = pVMMDevState->pDevIns; */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering int rc = vmmdevHGCMCmdListLock (pVMMDevState);
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering LogFlowFunc(("%p type %d\n", pCmd, enmCmdType));
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Insert at the head of the list. The vmmdevHGCMLoadStateDone depends on this. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering pCmd->pNext = pVMMDevState->pHGCMCmdList;
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering pVMMDevState->pHGCMCmdList->pPrev = pCmd;
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Automatically enable HGCM events, if there are HGCM commands. */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering if ( enmCmdType == VBOXHGCMCMDTYPE_CONNECT
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering || enmCmdType == VBOXHGCMCMDTYPE_DISCONNECT
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering Log(("vmmdevHGCMAddCommand: u32HGCMEnabled = %d\n", pVMMDevState->u32HGCMEnabled));
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering if (ASMAtomicCmpXchgU32(&pVMMDevState->u32HGCMEnabled, 1, 0))
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering VMMDevCtlSetGuestFilterMask (pVMMDevState, VMMDEV_EVENT_HGCM, 0);
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poetteringstatic int vmmdevHGCMRemoveCommand (VMMDevState *pVMMDevState, PVBOXHGCMCMD pCmd)
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* PPDMDEVINS pDevIns = pVMMDevState->pDevIns; */
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering int rc = vmmdevHGCMCmdListLock (pVMMDevState);
7732f92bad5f24a4bd03bb357af46da56b0ac94dLennart Poettering /* Tail, do nothing. */
return rc;
while (pCmd)
return pCmd;
return rc;
void *pvHost,
Log(("vmmdevHGCMWriteLinPtr: page %d: dst %VGp, src %p, cbWrite %d\n", iPage, GCPhysDst, pu8Src, cbWrite));
iPage++;
u32Size = 0;
return rc;
PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (sizeof (struct VBOXHGCMCMD) + pHGCMConnect->header.header.size);
if (pCmd)
vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMConnect->header.header.size, VBOXHGCMCMDTYPE_CONNECT);
rc = pVMMDevState->pHGCMDrv->pfnConnect (pVMMDevState->pHGCMDrv, pCmd, &pHGCMConnectCopy->loc, &pHGCMConnectCopy->u32ClientID);
return rc;
int vmmdevHGCMDisconnect (VMMDevState *pVMMDevState, VMMDevHGCMDisconnect *pHGCMDisconnect, RTGCPHYS GCPhys)
if (pCmd)
vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMDisconnect->header.header.size, VBOXHGCMCMDTYPE_DISCONNECT);
rc = pVMMDevState->pHGCMDrv->pfnDisconnect (pVMMDevState->pHGCMDrv, pCmd, pHGCMDisconnect->u32ClientID);
return rc;
int vmmdevHGCMCall (VMMDevState *pVMMDevState, VMMDevHGCMCall *pHGCMCall, RTGCPHYS GCPhys, bool f64Bits)
Log(("vmmdevHGCMCall: client id = %d, function = %d, %s bit\n", pHGCMCall->u32ClientID, pHGCMCall->u32Function, f64Bits? "64": "32"));
uint32_t i;
if (f64Bits)
#ifdef VBOX_WITH_64_BITS_GUESTS
cLinPtrs++;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
#ifdef VBOX_WITH_64_BITS_GUESTS
cLinPtrs++;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
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:
#ifdef LOG_ENABLED
AssertFailed();
/* rc = PDMDevHlpPhys2HCVirt (pVMMDevState->pDevIns, physAddr, size, &pHostParm->u.pointer.addr); */
if (size == 0)
rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr++, pCmd->paLinPtrs, &pPages);
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
#ifdef LOG_ENABLED
AssertFailed();
/* rc = PDMDevHlpPhys2HCVirt (pVMMDevState->pDevIns, physAddr, size, &pHostParm->u.pointer.addr); */
if (size == 0)
rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr++, pCmd->paLinPtrs, &pPages);
vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMCall->header.header.size, VBOXHGCMCMDTYPE_CALL);
rc = pVMMDevState->pHGCMDrv->pfnCall (pVMMDevState->pHGCMDrv, pCmd, pHGCMCall->u32ClientID, pHGCMCall->u32Function, cParms, pCmd->paHostParms);
return rc;
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_64_BITS_GUESTS
#ifdef VBOX_WITH_64_BITS_GUESTS
case VMMDevReq_HGCMCall64:
uint32_t i;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr++, pCmd->paLinPtrs);
case VMMDevReq_HGCMCall32:
uint32_t i;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr++, pCmd->paLinPtrs);
case VMMDevReq_HGCMCall:
uint32_t i;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr++, pCmd->paLinPtrs);
case VMMDevReq_HGCMConnect:
int rc = VMR3ReqCallEx(PDMDevHlpGetVM(pVMMDevState->pDevIns), NULL, 0, VMREQFLAGS_NO_WAIT | VMREQFLAGS_VOID,
while (pIter)
cCmds++;
if (cCmds > 0)
while (pIter)
return rc;
while (cCmds--)
return rc;
while (pIter)
return VERR_NO_MEMORY;
Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->version, VMMDEV_REQUEST_HEADER_VERSION));
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;
LogRel(("VMMDEV: Ignoring unknown request type %x during LoadState\n", requestHeader->requestType));
return rc;