VirtualBox

Changeset 9662 in vbox for trunk


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
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuest.h

    r9435 r9662  
    169169    VMMDevReq_HGCMCall                   = 62,
    170170#endif /* VBOX_WITH_64_BITS_GUESTS */
     171    VMMDevReq_HGCMCancel                 = 64,
    171172#endif
    172173    VMMDevReq_VideoAccelEnable           = 70,
     
    791792
    792793#define VBOX_HGCM_MAX_PARMS 32
     794
     795/* The Cancel request is issued using the same physical memory address
     796 * as was used for the corresponding initial HGCMCall.
     797 */
     798typedef struct
     799{
     800    /* request header */
     801    VMMDevHGCMRequestHeader header;
     802} VMMDevHGCMCancel;
    793803
    794804#endif /* VBOX_HGCM */
     
    13721382            return sizeof(VMMDevHGCMCall);
    13731383#endif /* VBOX_WITH_64_BITS_GUESTS */
     1384        case VMMDevReq_HGCMCancel:
     1385            return sizeof(VMMDevHGCMCancel);
    13741386#endif /* VBOX_HGCM */
    13751387        case VMMDevReq_VideoAccelEnable:
  • trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp

    r9501 r9662  
    370370        if (rc != STATUS_WAIT_0)
    371371        {
    372             dprintf(("VBoxHGCMCallback: The external event was signalled or the wait timed out or terminated.\n"));
     372            dprintf(("VBoxHGCMCallback: The external event was signalled or the wait timed out or terminated rc = 0x%08X.\n", rc));
    373373            break;
    374374        }
  • trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp

    r8155 r9662  
    249249                     * that means the wait was interrrupted. That can happen
    250250                     * if system reboots or the VBoxService ended abnormally.
    251                      * In both cases it is OK to just leave the allocated memory
    252                      * in the physical heap. The memory leak does not affect normal
    253                      * operations.
    254                      * @todo VbglGRCancel (&pHGCMCall->header.header) need to be implemented.
    255                      *       The host will not write to the cancelled memory.
     251                     *
     252                     * Cancel the request, the host will not write to the
     253                     * memory related to the cancelled request.
    256254                     */
    257255                    pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     256
     257                    pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
     258                    VbglGRPerform (&pHGCMCall->header.header);
    258259                }
    259260            }
  • 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