VirtualBox

Changeset 9662 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 12, 2008 2:48:02 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
31993
Message:

Implemented cancelling of HGCM requests from the guest.

Location:
trunk/src/VBox/Devices/VMMDev
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VMMDev/VBoxDev.cpp

    r9435 r9662  
    11001100        }
    11011101#endif /* VBOX_HGCM */
     1102
     1103        case VMMDevReq_HGCMCancel:
     1104        {
     1105            if (pRequestHeader->size < sizeof(VMMDevHGCMCancel))
     1106            {
     1107                AssertMsgFailed(("VMMDevReq_HGCMCancel structure has invalid size!\n"));
     1108                pRequestHeader->rc = VERR_INVALID_PARAMETER;
     1109            }
     1110            else if (!pData->pHGCMDrv)
     1111            {
     1112                Log(("VMMDevReq_HGCMCancel HGCM Connector is NULL!\n"));
     1113                pRequestHeader->rc = VERR_NOT_SUPPORTED;
     1114            }
     1115            else
     1116            {
     1117                VMMDevHGCMCancel *pHGCMCancel = (VMMDevHGCMCancel *)pRequestHeader;
     1118
     1119                Log(("VMMDevReq_VMMDevHGCMCancel\n"));
     1120                pRequestHeader->rc = vmmdevHGCMCancel (pData, pHGCMCancel, (RTGCPHYS)u32);
     1121            }
     1122            break;
     1123        }
    11021124
    11031125        case VMMDevReq_VideoAccelEnable:
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r9435 r9662  
    7474    VBOXHGCMCMDTYPE enmCmdType;
    7575
     76    /* Whether the command was cancelled by the guest. */
     77    bool fCancelled;
     78
    7679    /* GC physical address of the guest request. */
    7780    RTGCPHYS        GCPhys;
     
    179182    return rc;
    180183}
     184
     185
     186static PVBOXHGCMCMD vmmdevHGCMFindCommand (VMMDevState *pVMMDevState, RTGCPHYS GCPhys)
     187{
     188    PVBOXHGCMCMD pCmd = NULL;
     189
     190    int rc = vmmdevHGCMCmdListLock (pVMMDevState);
     191   
     192    if (VBOX_SUCCESS (rc))
     193    {
     194        pCmd = pVMMDevState->pHGCMCmdList;
     195
     196        while (pCmd)
     197        {
     198            if (pCmd->GCPhys == GCPhys)
     199            {
     200                break;
     201            }
     202            pCmd = pCmd->pNext;
     203        }
     204
     205        vmmdevHGCMCmdListUnlock (pVMMDevState);
     206    }
     207   
     208    LogFlowFunc(("%p\n", pCmd));
     209    return pCmd;
     210}
     211
    181212
    182213static int vmmdevHGCMSaveLinPtr (PPDMDEVINS pDevIns,
     
    746777}
    747778
     779/* @thread EMT */
     780int vmmdevHGCMCancel (VMMDevState *pVMMDevState, VMMDevHGCMCancel *pHGCMCancel, RTGCPHYS GCPhys)
     781{
     782    int rc = VINF_SUCCESS;
     783
     784    NOREF(pHGCMCancel);
     785
     786    Log(("vmmdevHGCMCancel\n"));
     787
     788    /* Find the command in the list. */
     789    PVBOXHGCMCMD pCmd = vmmdevHGCMFindCommand (pVMMDevState, GCPhys);
     790
     791    if (pCmd)
     792    {
     793        pCmd->fCancelled = true;
     794    }
     795    else
     796    {
     797        rc = VERR_INVALID_PARAMETER;
     798    }
     799
     800    return rc;
     801}
     802
    748803static int vmmdevHGCMCmdVerify (PVBOXHGCMCMD pCmd, VMMDevHGCMRequestHeader *pHeader)
    749804{
     
    751806    {
    752807        case VBOXHGCMCMDTYPE_CONNECT:
    753             if (pHeader->header.requestType == VMMDevReq_HGCMConnect) return VINF_SUCCESS;
     808            if (   pHeader->header.requestType == VMMDevReq_HGCMConnect
     809                || pHeader->header.requestType == VMMDevReq_HGCMCancel) return VINF_SUCCESS;
    754810            break;
    755811
    756812        case VBOXHGCMCMDTYPE_DISCONNECT:
    757             if (pHeader->header.requestType == VMMDevReq_HGCMDisconnect) return VINF_SUCCESS;
     813            if (   pHeader->header.requestType == VMMDevReq_HGCMDisconnect
     814                || pHeader->header.requestType == VMMDevReq_HGCMCancel) return VINF_SUCCESS;
    758815            break;
    759816
     
    761818#ifdef VBOX_WITH_64_BITS_GUESTS
    762819            if (   pHeader->header.requestType == VMMDevReq_HGCMCall32
    763                 || pHeader->header.requestType == VMMDevReq_HGCMCall64) return VINF_SUCCESS;
     820                || pHeader->header.requestType == VMMDevReq_HGCMCall64
     821                || pHeader->header.requestType == VMMDevReq_HGCMCancel) return VINF_SUCCESS;
    764822#else
    765             if (   pHeader->header.requestType == VMMDevReq_HGCMCall) return VINF_SUCCESS;
     823            if (   pHeader->header.requestType == VMMDevReq_HGCMCall
     824                || pHeader->header.requestType == VMMDevReq_HGCMCancel) return VINF_SUCCESS;
    766825#endif /* VBOX_WITH_64_BITS_GUESTS */
    767826
     
    781840DECLCALLBACK(void) hgcmCompletedWorker (PPDMIHGCMPORT pInterface, int32_t result, PVBOXHGCMCMD pCmd)
    782841{
    783     VMMDevState             *pVMMDevState = PDMIHGCMPORT_2_VMMDEVSTATE(pInterface);
    784     VMMDevHGCMRequestHeader *pHeader;
    785     int                      rc = VINF_SUCCESS;
    786 
    787     pHeader = (VMMDevHGCMRequestHeader *)RTMemAllocZ (pCmd->cbSize);
    788     Assert(pHeader);
    789     if (pHeader == NULL)
     842    VMMDevState *pVMMDevState = PDMIHGCMPORT_2_VMMDEVSTATE(pInterface);
     843
     844    int rc = VINF_SUCCESS;
     845
     846    if (result == VINF_HGCM_SAVE_STATE)
     847    {
     848        /* If the completion routine was called because HGCM saves its state,
     849         * then currently nothing to be done here. The pCmd stays in the list
     850         * and will be saved later when the VMMDev state will be saved.
     851         *
     852         * It it assumed that VMMDev saves state after the HGCM services,
     853         * and, therefore, VBOXHGCMCMD structures are not removed by
     854         * vmmdevHGCMSaveState from the list, while HGCM uses them.
     855         */
     856        LogFlowFunc(("VINF_HGCM_SAVE_STATE for command %p\n", pCmd));
    790857        return;
    791 
    792     PDMDevHlpPhysRead(pVMMDevState->pDevIns, (RTGCPHYS)pCmd->GCPhys, pHeader, pCmd->cbSize);
    793 
    794     if (result != VINF_HGCM_SAVE_STATE)
    795     {
     858    }
     859
     860    /* Check whether the command has been already cancelled by the guest.
     861     * If it was cancelled, then the data must not be written back to the
     862     * guest RAM.
     863     */
     864    if (pCmd->fCancelled)
     865    {
     866        /* Just remove the command from the internal list, so the memory can be freed. */
     867        LogFlowFunc(("A cancelled command %p\n", pCmd));
     868        vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
     869    }
     870    else
     871    {
     872        /* Preallocated block for requests which have up to 8 parameters (most of requests). */
     873#ifdef VBOX_WITH_64_BITS_GUESTS
     874        uint8_t au8Prealloc[sizeof (VMMDevHGCMCall) + 8 * sizeof (HGCMFunctionParameter64)];
     875#else
     876        uint8_t au8Prealloc[sizeof (VMMDevHGCMCall) + 8 * sizeof (HGCMFunctionParameter)];
     877#endif /* VBOX_WITH_64_BITS_GUESTS */
     878
     879        VMMDevHGCMRequestHeader *pHeader;
     880
     881        if (pCmd->cbSize <= sizeof (au8Prealloc))
     882        {
     883            pHeader = (VMMDevHGCMRequestHeader *)&au8Prealloc[0];
     884        }
     885        else
     886        {
     887            pHeader = (VMMDevHGCMRequestHeader *)RTMemAlloc (pCmd->cbSize);
     888            Assert(pHeader);
     889            if (pHeader == NULL)
     890            {
     891                LogRel(("VMMDev: Failed to allocate %d bytes for HGCM request completion!!!\n", pCmd->cbSize));
     892
     893                /* Do some cleanup. The command have to be excluded from list of active commands anyway. */
     894                vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
     895                return;
     896            }
     897        }
     898
     899        PDMDevHlpPhysRead(pVMMDevState->pDevIns, pCmd->GCPhys, pHeader, pCmd->cbSize);
     900
    796901        /* Setup return codes. */
    797902        pHeader->result = result;
     
    9951100        else
    9961101        {
    997             /* Return error to the guest. */
     1102            /* Command type is wrong. Return error to the guest. */
    9981103            pHeader->header.rc = rc;
    9991104        }
    10001105
    1001         /* Mark request as processed*/
     1106        /* Mark request as processed. */
    10021107        pHeader->fu32Flags |= VBOX_HGCM_REQ_DONE;
    10031108
     
    10051110        PDMDevHlpPhysWrite(pVMMDevState->pDevIns, pCmd->GCPhys, pHeader, pCmd->cbSize);
    10061111
    1007         /* It it assumed that VMMDev saves state after the HGCM services. */
     1112        /* The command has been completely processed and can be removed from the list. */
    10081113        vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
    10091114
     
    10111116        VMMDevNotifyGuest (pVMMDevState, VMMDEV_EVENT_HGCM);
    10121117
    1013         if (pCmd->paLinPtrs)
    1014         {
    1015             RTMemFree (pCmd->paLinPtrs);
    1016         }
    1017        
    1018         RTMemFree (pCmd);
    1019     }
    1020     RTMemFree(pHeader);
     1118        if ((uint8_t *)pHeader != &au8Prealloc[0])
     1119        {
     1120            /* Only if it was allocated from heap. */
     1121            RTMemFree (pHeader);
     1122        }
     1123    }
     1124
     1125    /* Deallocate the command memory. */
     1126    if (pCmd->paLinPtrs)
     1127    {
     1128        RTMemFree (pCmd->paLinPtrs);
     1129    }
     1130       
     1131    RTMemFree (pCmd);
    10211132
    10221133    return;
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.h

    r9435 r9662  
    3535DECLCALLBACK(int) vmmdevHGCMDisconnect (VMMDevState *pVMMDevState, VMMDevHGCMDisconnect *pHGCMDisconnect, RTGCPHYS GCPtr);
    3636DECLCALLBACK(int) vmmdevHGCMCall (VMMDevState *pVMMDevState, VMMDevHGCMCall *pHGCMCall, RTGCPHYS GCPtr, bool f64Bits);
     37DECLCALLBACK(int) vmmdevHGCMCancel (VMMDevState *pVMMDevState, VMMDevHGCMCancel *pHGCMCancel, RTGCPHYS GCPtr);
    3738
    3839DECLCALLBACK(void) hgcmCompleted (PPDMIHGCMPORT pInterface, int32_t result, PVBOXHGCMCMD pCmdPtr);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette