VirtualBox

Changeset 20731 in vbox


Ignore:
Timestamp:
Jun 19, 2009 5:24:41 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
48847
Message:

Save more info about pending HGCM requests (xTracker #4032).

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

Legend:

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

    r19654 r20731  
    20242024
    20252025
    2026 #define VMMDEV_SSM_VERSION  8
     2026#define VMMDEV_SSM_VERSION  9
    20272027
    20282028/**
     
    21072107
    21082108#ifdef VBOX_WITH_HGCM
    2109     vmmdevHGCMLoadState (pThis, pSSMHandle);
     2109    vmmdevHGCMLoadState (pThis, pSSMHandle, u32Version);
    21102110#endif /* VBOX_WITH_HGCM */
    21112111
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r20024 r20731  
    3737typedef enum _VBOXHGCMCMDTYPE
    3838{
    39     VBOXHGCMCMDTYPE_LOADSTATE,
     39    VBOXHGCMCMDTYPE_LOADSTATE = 0,
    4040    VBOXHGCMCMDTYPE_CONNECT,
    4141    VBOXHGCMCMDTYPE_DISCONNECT,
     
    4848{
    4949    /* Index of the parameter. */
    50     int iParm;
     50    uint32_t iParm;
    5151
    5252    /* Offset in the first physical page of the region. */
     
    7070    struct VBOXHGCMCMD *pPrev;
    7171
     72    /* Size of memory buffer for this command structure, including trailing paHostParms.
     73     * This field simplifies loading of saved state.
     74     */
     75    uint32_t cbCmd;
     76
    7277    /* The type of the command. */
    7378    VBOXHGCMCMDTYPE enmCmdType;
     
    8287    uint32_t        cbSize;
    8388
    84     /* Pointer to converted host parameters in case of a Call request. */
     89    /* Pointer to converted host parameters in case of a Call request.
     90     * Parameters follow this structure in the same memory block.
     91     */
    8592    VBOXHGCMSVCPARM *paHostParms;
    8693
    8794    /* Linear pointer parameters information. */
    8895    int cLinPtrs;
     96
     97    /* How many pages for all linptrs of this command.
     98     * Only valid if cLinPtrs > 0. This field simplifies loading of saved state.
     99     */
     100    int cLinPtrPages;
    89101
    90102    /* Pointer to descriptions of linear pointers.  */
     
    126138        pVMMDevState->pHGCMCmdList = pCmd;
    127139
    128         pCmd->enmCmdType = enmCmdType;
     140        if (enmCmdType != VBOXHGCMCMDTYPE_LOADSTATE)
     141        {
     142            /* Loaded commands already have the right type. */
     143            pCmd->enmCmdType = enmCmdType;
     144        }
    129145        pCmd->GCPhys = GCPhys;
    130146        pCmd->cbSize = cbSize;
     
    322338}
    323339
     340static void logRelSavedCmdSizeMismatch (const char *pszFunction, uint32_t cbExpected, uint32_t cbCmdSize)
     341{
     342    LogRel(("Warning: VMMDev %s command length %d (expected %d)\n",
     343            pszFunction, cbCmdSize, cbExpected));
     344}
     345
    324346int vmmdevHGCMConnect (VMMDevState *pVMMDevState, VMMDevHGCMConnect *pHGCMConnect, RTGCPHYS GCPhys)
    325347{
    326348    int rc = VINF_SUCCESS;
    327349
    328     PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (sizeof (struct VBOXHGCMCMD) + pHGCMConnect->header.header.size);
     350    uint32_t cbCmdSize = sizeof (struct VBOXHGCMCMD) + pHGCMConnect->header.header.size;
     351
     352    PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (cbCmdSize);
    329353
    330354    if (pCmd)
     
    336360        memcpy(pHGCMConnectCopy, pHGCMConnect, pHGCMConnect->header.header.size);
    337361
     362        pCmd->cbCmd       = cbCmdSize;
    338363        pCmd->paHostParms = NULL;
    339364        pCmd->cLinPtrs = 0;
     
    354379}
    355380
     381static int vmmdevHGCMConnectSaved (VMMDevState *pVMMDevState, VMMDevHGCMConnect *pHGCMConnect, bool *pfHGCMCalled, VBOXHGCMCMD *pSavedCmd)
     382{
     383    int rc = VINF_SUCCESS;
     384
     385    uint32_t cbCmdSize = sizeof (struct VBOXHGCMCMD) + pHGCMConnect->header.header.size;
     386
     387    if (pSavedCmd->cbCmd < cbCmdSize)
     388    {
     389        logRelSavedCmdSizeMismatch ("HGCMConnect", pSavedCmd->cbCmd, cbCmdSize);
     390        return VERR_INVALID_PARAMETER;
     391    }
     392
     393    VMMDevHGCMConnect *pHGCMConnectCopy = (VMMDevHGCMConnect *)(pSavedCmd+1);
     394
     395    memcpy(pHGCMConnectCopy, pHGCMConnect, pHGCMConnect->header.header.size);
     396
     397    /* Only allow the guest to use existing services! */
     398    Assert(pHGCMConnect->loc.type == VMMDevHGCMLoc_LocalHost_Existing);
     399    pHGCMConnect->loc.type = VMMDevHGCMLoc_LocalHost_Existing;
     400
     401    rc = pVMMDevState->pHGCMDrv->pfnConnect (pVMMDevState->pHGCMDrv, pSavedCmd, &pHGCMConnectCopy->loc, &pHGCMConnectCopy->u32ClientID);
     402    if (RT_SUCCESS (rc))
     403    {
     404        *pfHGCMCalled = true;
     405    }
     406
     407    return rc;
     408}
     409
    356410int vmmdevHGCMDisconnect (VMMDevState *pVMMDevState, VMMDevHGCMDisconnect *pHGCMDisconnect, RTGCPHYS GCPhys)
    357411{
    358412    int rc = VINF_SUCCESS;
    359413
    360     PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (sizeof (struct VBOXHGCMCMD));
     414    uint32_t cbCmdSize = sizeof (struct VBOXHGCMCMD);
     415
     416    PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (cbCmdSize);
    361417
    362418    if (pCmd)
     
    364420        vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, pHGCMDisconnect->header.header.size, VBOXHGCMCMDTYPE_DISCONNECT);
    365421
     422        pCmd->cbCmd       = cbCmdSize;
    366423        pCmd->paHostParms = NULL;
    367424        pCmd->cLinPtrs = 0;
     
    373430    {
    374431        rc = VERR_NO_MEMORY;
     432    }
     433
     434    return rc;
     435}
     436
     437static int vmmdevHGCMDisconnectSaved (VMMDevState *pVMMDevState, VMMDevHGCMDisconnect *pHGCMDisconnect, bool *pfHGCMCalled, VBOXHGCMCMD *pSavedCmd)
     438{
     439    int rc = VINF_SUCCESS;
     440
     441    uint32_t cbCmdSize = sizeof (struct VBOXHGCMCMD);
     442
     443    if (pSavedCmd->cbCmd < cbCmdSize)
     444    {
     445        logRelSavedCmdSizeMismatch ("HGCMConnect", pSavedCmd->cbCmd, cbCmdSize);
     446        return VERR_INVALID_PARAMETER;
     447    }
     448
     449    rc = pVMMDevState->pHGCMDrv->pfnDisconnect (pVMMDevState->pHGCMDrv, pSavedCmd, pHGCMDisconnect->u32ClientID);
     450    if (RT_SUCCESS (rc))
     451    {
     452        *pfHGCMCalled = true;
    375453    }
    376454
     
    424502                case VMMDevHGCMParmType_LinAddr:     /* In & Out */
    425503                {
    426                     cbCmdSize += pGuestParm->u.Pointer.size;
    427 
    428                     if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     504                    if (pGuestParm->u.Pointer.size > 0)
    429505                    {
     506                        /* Only pointers with some actual data are counted. */
     507                        cbCmdSize += pGuestParm->u.Pointer.size;
     508
    430509                        cLinPtrs++;
    431510                        /* Take the offset into the current page also into account! */
     
    469548                case VMMDevHGCMParmType_LinAddr:     /* In & Out */
    470549                {
    471                     cbCmdSize += pGuestParm->u.Pointer.size;
    472 
    473                     if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     550                    if (pGuestParm->u.Pointer.size > 0)
    474551                    {
     552                        /* Only pointers with some actual data are counted. */
     553                        cbCmdSize += pGuestParm->u.Pointer.size;
     554
    475555                        cLinPtrs++;
    476556                        /* Take the offset into the current page also into account! */
     
    512592    memset (pCmd, 0, sizeof (*pCmd));
    513593
     594    pCmd->cbCmd       = cbCmdSize;
    514595    pCmd->paHostParms = NULL;
    515596    pCmd->cLinPtrs    = cLinPtrs;
     597    pCmd->cLinPtrPages = cLinPtrPages;
    516598
    517599    if (cLinPtrs > 0)
     
    632714                                 pcBuf += size;
    633715
    634                                  if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
    635                                  {
    636                                      /* Remember the guest physical pages that belong to the virtual address
    637                                       * region.
    638                                       */
    639                                      rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr++, pCmd->paLinPtrs, &pPages);
    640                                  }
     716                                 /* Remember the guest physical pages that belong to the virtual address region.
     717                                  * Do it for all linear pointers because load state will require In pointer info too.
     718                                  */
     719                                 rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr, pCmd->paLinPtrs, &pPages);
     720
     721                                 iLinPtr++;
    641722                             }
    642723                         }
     
    734815                                 pcBuf += size;
    735816
    736                                  if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
    737                                  {
    738                                      /* Remember the guest physical pages that belong to the virtual address
    739                                       * region.
    740                                       */
    741                                      rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr++, pCmd->paLinPtrs, &pPages);
    742                                  }
     817                                 /* Remember the guest physical pages that belong to the virtual address region.
     818                                  * Do it for all linear pointers because load state will require In pointer info too.
     819                                  */
     820                                 rc = vmmdevHGCMSaveLinPtr (pVMMDevState->pDevIns, i, linearAddr, size, iLinPtr, pCmd->paLinPtrs, &pPages);
     821
     822                                 iLinPtr++;
    743823                             }
    744824                         }
     
    771851
    772852        RTMemFree (pCmd);
     853    }
     854
     855    return rc;
     856}
     857
     858static void logRelLoadStatePointerIndexMismatch (uint32_t iParm, uint32_t iSavedParm, int iLinPtr, int cLinPtrs)
     859{
     860   LogRel(("Warning: VMMDev load state: a pointer parameter index mismatch %d (expected %d) (%d/%d)\n",
     861           (int)iParm, (int)iSavedParm, iLinPtr, cLinPtrs));
     862}
     863
     864static void logRelLoadStateBufferSizeMismatch (uint32_t size, uint32_t iPage, uint32_t cPages)
     865{
     866    LogRel(("Warning: VMMDev load state: buffer size mismatch: size %d, page %d/%d\n",
     867            (int)size, (int)iPage, (int)cPages));
     868}
     869
     870
     871static int vmmdevHGCMCallSaved (VMMDevState *pVMMDevState, VMMDevHGCMCall *pHGCMCall, bool f64Bits, bool *pfHGCMCalled, VBOXHGCMCMD *pSavedCmd)
     872{
     873    int rc = VINF_SUCCESS;
     874
     875    Log(("vmmdevHGCMCallSaved: client id = %d, function = %d, %s bit\n", pHGCMCall->u32ClientID, pHGCMCall->u32Function, f64Bits? "64": "32"));
     876
     877    /* Compute size and allocate memory block to hold:
     878     *    struct VBOXHGCMCMD
     879     *    VBOXHGCMSVCPARM[cParms]
     880     *    memory buffers for pointer parameters.
     881     */
     882
     883    uint32_t cParms = pHGCMCall->cParms;
     884
     885    Log(("vmmdevHGCMCall: cParms = %d\n", cParms));
     886
     887    /*
     888     * Compute size of required memory buffer.
     889     */
     890
     891    pSavedCmd->paHostParms = NULL;
     892
     893    /* Process parameters, changing them to host context pointers for easy
     894     * processing by connector. Guest must insure that the pointed data is actually
     895     * in the guest RAM and remains locked there for entire request processing.
     896     */
     897
     898    if (cParms != 0)
     899    {
     900        /* Compute addresses of host parms array and first memory buffer. */
     901        VBOXHGCMSVCPARM *pHostParm = (VBOXHGCMSVCPARM *)((uint8_t *)pSavedCmd + sizeof (struct VBOXHGCMCMD));
     902
     903        uint8_t *pu8Buf = (uint8_t *)pHostParm + cParms * sizeof (VBOXHGCMSVCPARM);
     904
     905        pSavedCmd->paHostParms = pHostParm;
     906
     907        uint32_t iParm;
     908        int iLinPtr = 0;
     909
     910        if (f64Bits)
     911        {
     912#ifdef VBOX_WITH_64_BITS_GUESTS
     913            HGCMFunctionParameter64 *pGuestParm = VMMDEV_HGCM_CALL_PARMS64(pHGCMCall);
     914#else
     915            HGCMFunctionParameter *pGuestParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
     916            AssertFailed (); /* This code should not be called in this case */
     917#endif /* VBOX_WITH_64_BITS_GUESTS */
     918
     919            for (iParm = 0; iParm < cParms && RT_SUCCESS(rc); iParm++, pGuestParm++, pHostParm++)
     920            {
     921                switch (pGuestParm->type)
     922                {
     923                     case VMMDevHGCMParmType_32bit:
     924                     {
     925                         uint32_t u32 = pGuestParm->u.value32;
     926
     927                         pHostParm->type = VBOX_HGCM_SVC_PARM_32BIT;
     928                         pHostParm->u.uint32 = u32;
     929
     930                         Log(("vmmdevHGCMCall: uint32 guest parameter %u\n", u32));
     931                         break;
     932                     }
     933
     934                     case VMMDevHGCMParmType_64bit:
     935                     {
     936                         uint64_t u64 = pGuestParm->u.value64;
     937
     938                         pHostParm->type = VBOX_HGCM_SVC_PARM_64BIT;
     939                         pHostParm->u.uint64 = u64;
     940
     941                         Log(("vmmdevHGCMCall: uint64 guest parameter %llu\n", u64));
     942                         break;
     943                     }
     944
     945                     case VMMDevHGCMParmType_PhysAddr:
     946                     {
     947                         uint32_t size = pGuestParm->u.Pointer.size;
     948#ifdef LOG_ENABLED
     949                         RTGCPHYS physAddr = pGuestParm->u.Pointer.u.physAddr;
     950#endif
     951
     952                         pHostParm->type = VBOX_HGCM_SVC_PARM_PTR;
     953                         pHostParm->u.pointer.size = size;
     954
     955                         AssertFailed();
     956                         /* rc = PDMDevHlpPhys2HCVirt (pVMMDevState->pDevIns, physAddr, size, &pHostParm->u.pointer.addr); */
     957
     958                         Log(("vmmdevHGCMCall: PhysAddr guest parameter %RGp\n", physAddr));
     959                         break;
     960                     }
     961
     962                     case VMMDevHGCMParmType_LinAddr_In:  /* In (read) */
     963                     case VMMDevHGCMParmType_LinAddr_Out: /* Out (write) */
     964                     case VMMDevHGCMParmType_LinAddr:     /* In & Out */
     965                     {
     966                         uint32_t size = pGuestParm->u.Pointer.size;
     967
     968                         pHostParm->type = VBOX_HGCM_SVC_PARM_PTR;
     969                         pHostParm->u.pointer.size = size;
     970
     971                         /* Copy guest data to an allocated buffer, so
     972                          * services can use the data.
     973                          */
     974
     975                         if (size == 0)
     976                         {
     977                             pHostParm->u.pointer.addr = NULL;
     978                         }
     979                         else
     980                         {
     981                             /* The saved command already have the page list in pCmd->paLinPtrs.
     982                              * Read data from guest pages.
     983                              */
     984                             /* Don't overdo it */
     985                             if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_Out)
     986                             {
     987                                 if (   iLinPtr >= pSavedCmd->cLinPtrs
     988                                     || pSavedCmd->paLinPtrs[iLinPtr].iParm != iParm)
     989                                 {
     990                                     logRelLoadStatePointerIndexMismatch (iParm, pSavedCmd->paLinPtrs[iLinPtr].iParm, iLinPtr, pSavedCmd->cLinPtrs);
     991                                     rc = VERR_INVALID_PARAMETER;
     992                                 }
     993                                 else
     994                                 {
     995                                     VBOXHGCMLINPTR *pLinPtr = &pSavedCmd->paLinPtrs[iLinPtr];
     996
     997                                     uint32_t iPage;
     998                                     uint32_t offPage = pLinPtr->offFirstPage;
     999                                     size_t cbRemaining = size;
     1000                                     uint8_t *pu8Dst = pu8Buf;
     1001                                     for (iPage = 0; iPage < pLinPtr->cPages; iPage++)
     1002                                     {
     1003                                         if (cbRemaining == 0)
     1004                                         {
     1005                                             logRelLoadStateBufferSizeMismatch (size, iPage, pLinPtr->cPages);
     1006                                             break;
     1007                                         }
     1008
     1009                                         size_t cbChunk = PAGE_SIZE - offPage;
     1010
     1011                                         if (cbChunk > cbRemaining)
     1012                                         {
     1013                                             cbChunk = cbRemaining;
     1014                                         }
     1015
     1016                                         rc = PDMDevHlpPhysRead(pVMMDevState->pDevIns,
     1017                                                                pLinPtr->paPages[iPage] + offPage,
     1018                                                                pu8Dst, cbChunk);
     1019
     1020                                         AssertRCBreak(rc);
     1021                                         
     1022                                         offPage = 0; /* A next page is read from 0 offset. */
     1023                                         cbRemaining -= cbChunk;
     1024                                         pu8Dst += cbChunk;
     1025                                     }
     1026                                 }
     1027                             }
     1028                             else
     1029                                 rc = VINF_SUCCESS;
     1030
     1031                             if (RT_SUCCESS(rc))
     1032                             {
     1033                                 pHostParm->u.pointer.addr = pu8Buf;
     1034                                 pu8Buf += size;
     1035
     1036                                 iLinPtr++;
     1037                             }
     1038                         }
     1039
     1040                         Log(("vmmdevHGCMCall: LinAddr guest parameter %RGv, rc = %Rrc\n",
     1041                              pGuestParm->u.Pointer.u.linearAddr, rc));
     1042                         break;
     1043                     }
     1044
     1045                    /* just to shut up gcc */
     1046                    default:
     1047                        break;
     1048                }
     1049            }
     1050        }
     1051        else
     1052        {
     1053#ifdef VBOX_WITH_64_BITS_GUESTS
     1054            HGCMFunctionParameter32 *pGuestParm = VMMDEV_HGCM_CALL_PARMS32(pHGCMCall);
     1055#else
     1056            HGCMFunctionParameter *pGuestParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
     1057#endif /* VBOX_WITH_64_BITS_GUESTS */
     1058
     1059            for (iParm = 0; iParm < cParms && RT_SUCCESS(rc); iParm++, pGuestParm++, pHostParm++)
     1060            {
     1061                switch (pGuestParm->type)
     1062                {
     1063                     case VMMDevHGCMParmType_32bit:
     1064                     {
     1065                         uint32_t u32 = pGuestParm->u.value32;
     1066
     1067                         pHostParm->type = VBOX_HGCM_SVC_PARM_32BIT;
     1068                         pHostParm->u.uint32 = u32;
     1069
     1070                         Log(("vmmdevHGCMCall: uint32 guest parameter %u\n", u32));
     1071                         break;
     1072                     }
     1073
     1074                     case VMMDevHGCMParmType_64bit:
     1075                     {
     1076                         uint64_t u64 = pGuestParm->u.value64;
     1077
     1078                         pHostParm->type = VBOX_HGCM_SVC_PARM_64BIT;
     1079                         pHostParm->u.uint64 = u64;
     1080
     1081                         Log(("vmmdevHGCMCall: uint64 guest parameter %llu\n", u64));
     1082                         break;
     1083                     }
     1084
     1085                     case VMMDevHGCMParmType_PhysAddr:
     1086                     {
     1087                         uint32_t size = pGuestParm->u.Pointer.size;
     1088#ifdef LOG_ENABLED
     1089                         RTGCPHYS physAddr = pGuestParm->u.Pointer.u.physAddr;
     1090#endif
     1091
     1092                         pHostParm->type = VBOX_HGCM_SVC_PARM_PTR;
     1093                         pHostParm->u.pointer.size = size;
     1094
     1095                         AssertFailed();
     1096                         /* rc = PDMDevHlpPhys2HCVirt (pVMMDevState->pDevIns, physAddr, size, &pHostParm->u.pointer.addr); */
     1097
     1098                         Log(("vmmdevHGCMCall: PhysAddr guest parameter %RGp\n", physAddr));
     1099                         break;
     1100                     }
     1101
     1102                     case VMMDevHGCMParmType_LinAddr_In:  /* In (read) */
     1103                     case VMMDevHGCMParmType_LinAddr_Out: /* Out (write) */
     1104                     case VMMDevHGCMParmType_LinAddr:     /* In & Out */
     1105                     {
     1106                         uint32_t size = pGuestParm->u.Pointer.size;
     1107
     1108                         pHostParm->type = VBOX_HGCM_SVC_PARM_PTR;
     1109                         pHostParm->u.pointer.size = size;
     1110
     1111                         /* Copy guest data to an allocated buffer, so
     1112                          * services can use the data.
     1113                          */
     1114
     1115                         if (size == 0)
     1116                         {
     1117                             pHostParm->u.pointer.addr = NULL;
     1118                         }
     1119                         else
     1120                         {
     1121                             /* The saved command already have the page list in pCmd->paLinPtrs.
     1122                              * Read data from guest pages.
     1123                              */
     1124                             /* Don't overdo it */
     1125                             if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_Out)
     1126                             {
     1127                                 if (   iLinPtr >= pSavedCmd->cLinPtrs
     1128                                     || pSavedCmd->paLinPtrs[iLinPtr].iParm != iParm)
     1129                                 {
     1130                                     logRelLoadStatePointerIndexMismatch (iParm, pSavedCmd->paLinPtrs[iLinPtr].iParm, iLinPtr, pSavedCmd->cLinPtrs);
     1131                                     rc = VERR_INVALID_PARAMETER;
     1132                                 }
     1133                                 else
     1134                                 {
     1135                                     VBOXHGCMLINPTR *pLinPtr = &pSavedCmd->paLinPtrs[iLinPtr];
     1136
     1137                                     uint32_t iPage;
     1138                                     uint32_t offPage = pLinPtr->offFirstPage;
     1139                                     size_t cbRemaining = size;
     1140                                     uint8_t *pu8Dst = pu8Buf;
     1141                                     for (iPage = 0; iPage < pLinPtr->cPages; iPage++)
     1142                                     {
     1143                                         if (cbRemaining == 0)
     1144                                         {
     1145                                             logRelLoadStateBufferSizeMismatch (size, iPage, pLinPtr->cPages);
     1146                                             break;
     1147                                         }
     1148
     1149                                         size_t cbChunk = PAGE_SIZE - offPage;
     1150
     1151                                         if (cbChunk > cbRemaining)
     1152                                         {
     1153                                             cbChunk = cbRemaining;
     1154                                         }
     1155
     1156                                         rc = PDMDevHlpPhysRead(pVMMDevState->pDevIns,
     1157                                                                pLinPtr->paPages[iPage] + offPage,
     1158                                                                pu8Dst, cbChunk);
     1159
     1160                                         AssertRCBreak(rc);
     1161                                         
     1162                                         offPage = 0; /* A next page is read from 0 offset. */
     1163                                         cbRemaining -= cbChunk;
     1164                                         pu8Dst += cbChunk;
     1165                                     }
     1166                                 }
     1167                             }
     1168                             else
     1169                                 rc = VINF_SUCCESS;
     1170
     1171                             if (RT_SUCCESS(rc))
     1172                             {
     1173                                 pHostParm->u.pointer.addr = pu8Buf;
     1174                                 pu8Buf += size;
     1175
     1176                                 iLinPtr++;
     1177                             }
     1178                         }
     1179
     1180                         Log(("vmmdevHGCMCall: LinAddr guest parameter %RGv, rc = %Rrc\n",
     1181                              pGuestParm->u.Pointer.u.linearAddr, rc));
     1182                         break;
     1183                     }
     1184
     1185                    /* just to shut up gcc */
     1186                    default:
     1187                        break;
     1188                }
     1189            }
     1190        }
     1191    }
     1192
     1193    if (RT_SUCCESS (rc))
     1194    {
     1195        /* Pass the function call to HGCM connector for actual processing */
     1196        rc = pVMMDevState->pHGCMDrv->pfnCall (pVMMDevState->pHGCMDrv, pSavedCmd, pHGCMCall->u32ClientID, pHGCMCall->u32Function, cParms, pSavedCmd->paHostParms);
     1197        if (RT_SUCCESS (rc))
     1198        {
     1199            *pfHGCMCalled = true;
     1200        }
    7731201    }
    7741202
     
    9501378                            uint32_t size = pGuestParm->u.Pointer.size;
    9511379
    952                             if (size > 0 && pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     1380                            if (size > 0)
    9531381                            {
    954                                 /* Use the saved page list. */
    955                                 rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr++, pCmd->paLinPtrs);
    956                                 AssertReleaseRC(rc);
     1382                                if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     1383                                {
     1384                                    /* Use the saved page list to write data back to the guest RAM. */
     1385                                    rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
     1386                                    AssertReleaseRC(rc);
     1387                                }
     1388
     1389                                /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
     1390                                iLinPtr++;
    9571391                            }
    9581392                        } break;
     
    10071441                            uint32_t size = pGuestParm->u.Pointer.size;
    10081442
    1009                             if (size > 0 && pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     1443                            if (size > 0)
    10101444                            {
    1011                                 /* Use the saved page list. */
    1012                                 rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr++, pCmd->paLinPtrs);
    1013                                 AssertReleaseRC(rc);
     1445                                if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     1446                                {
     1447                                    /* Use the saved page list to write data back to the guest RAM. */
     1448                                    rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
     1449                                    AssertReleaseRC(rc);
     1450                                }
     1451
     1452                                /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
     1453                                iLinPtr++;
    10141454                            }
    10151455                        } break;
     
    10641504                            uint32_t size = pGuestParm->u.Pointer.size;
    10651505
    1066                             if (size > 0 && pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     1506                            if (size > 0)
    10671507                            {
    1068                                 /* Use the saved page list. */
    1069                                 rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr++, pCmd->paLinPtrs);
    1070                                 AssertReleaseRC(rc);
     1508                                if (pGuestParm->type != VMMDevHGCMParmType_LinAddr_In)
     1509                                {
     1510                                    /* Use the saved page list to write data back to the guest RAM. */
     1511                                    rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
     1512                                    AssertReleaseRC(rc);
     1513                                }
     1514
     1515                                /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
     1516                                iLinPtr++;
    10711517                            }
    10721518                        } break;
     
    11791625            PVBOXHGCMCMD pNext = pIter->pNext;
    11801626
    1181             LogFlowFunc (("Saving %RGp\n", pIter->GCPhys));
     1627            LogFlowFunc (("Saving %RGp, size %d\n", pIter->GCPhys, pIter->cbSize));
     1628
     1629            /* GC physical address of the guest request. */
    11821630            rc = SSMR3PutGCPhys(pSSM, pIter->GCPhys);
    11831631            AssertRCReturn(rc, rc);
    11841632
     1633            /* Request packet size */
    11851634            rc = SSMR3PutU32(pSSM, pIter->cbSize);
    11861635            AssertRCReturn(rc, rc);
    11871636
     1637            /*
     1638             * Version 9+: save complete information about commands.
     1639             */
     1640
     1641            /* Size of entire command. */
     1642            rc = SSMR3PutU32(pSSM, pIter->cbCmd);
     1643            AssertRCReturn(rc, rc);
     1644
     1645            /* The type of the command. */
     1646            rc = SSMR3PutU32(pSSM, (uint32_t)pIter->enmCmdType);
     1647            AssertRCReturn(rc, rc);
     1648
     1649            /* Whether the command was cancelled by the guest. */
     1650            rc = SSMR3PutBool(pSSM, pIter->fCancelled);
     1651            AssertRCReturn(rc, rc);
     1652
     1653            /* Linear pointer parameters information. How many pointers. Always 0 if not a call command. */
     1654            rc = SSMR3PutU32(pSSM, (uint32_t)pIter->cLinPtrs);
     1655            AssertRCReturn(rc, rc);
     1656
     1657            if (pIter->cLinPtrs > 0)
     1658            {
     1659                /* How many pages for all linptrs in this command. */
     1660                rc = SSMR3PutU32(pSSM, (uint32_t)pIter->cLinPtrPages);
     1661                AssertRCReturn(rc, rc);
     1662            }
     1663
     1664            int i;
     1665            for (i = 0; i < pIter->cLinPtrs; i++)
     1666            {
     1667                /* Pointer to descriptions of linear pointers.  */
     1668                VBOXHGCMLINPTR *pLinPtr = &pIter->paLinPtrs[i];
     1669
     1670                /* Index of the parameter. */
     1671                rc = SSMR3PutU32(pSSM, (uint32_t)pLinPtr->iParm);
     1672                AssertRCReturn(rc, rc);
     1673
     1674                /* Offset in the first physical page of the region. */
     1675                rc = SSMR3PutU32(pSSM, pLinPtr->offFirstPage);
     1676                AssertRCReturn(rc, rc);
     1677
     1678                /* How many pages. */
     1679                rc = SSMR3PutU32(pSSM, pLinPtr->cPages);
     1680                AssertRCReturn(rc, rc);
     1681
     1682                uint32_t iPage;
     1683                for (iPage = 0; iPage < pLinPtr->cPages; iPage++)
     1684                {
     1685                    /* Array of the GC physical addresses for these pages.
     1686                     * It is assumed that the physical address of the locked resident
     1687                     * guest page does not change.
     1688                     */
     1689                    rc = SSMR3PutGCPhys(pSSM, pLinPtr->paPages[iPage]);
     1690                    AssertRCReturn(rc, rc);
     1691                }
     1692            }
     1693
     1694            /* A reserved field, will allow to extend saved data for a command. */
     1695            rc = SSMR3PutU32(pSSM, 0);
     1696            AssertRCReturn(rc, rc);
     1697
    11881698            vmmdevHGCMRemoveCommand (pVMMDevState, pIter);
    11891699
     
    11921702    }
    11931703
     1704    /* A reserved field, will allow to extend saved data for VMMDevHGCM. */
     1705    rc = SSMR3PutU32(pSSM, 0);
     1706    AssertRCReturn(rc, rc);
     1707
    11941708    return rc;
    11951709}
    11961710
    11971711/* @thread EMT */
    1198 int vmmdevHGCMLoadState(VMMDevState *pVMMDevState, PSSMHANDLE pSSM)
     1712int vmmdevHGCMLoadState(VMMDevState *pVMMDevState, PSSMHANDLE pSSM, uint32_t u32Version)
    11991713{
    12001714    int rc = VINF_SUCCESS;
     
    12091723    LogFlowFunc(("cCmds = %d\n", cCmds));
    12101724
    1211     while (cCmds--)
    1212     {
    1213         RTGCPHYS GCPhys;
    1214         uint32_t cbSize;
    1215 
    1216         rc = SSMR3GetGCPhys(pSSM, &GCPhys);
     1725    if (   SSM_VERSION_MAJOR(u32Version) ==  0
     1726        && SSM_VERSION_MINOR(u32Version) < 9)
     1727    {
     1728        /* Only the guest physical address is saved. */
     1729        while (cCmds--)
     1730        {
     1731            RTGCPHYS GCPhys;
     1732            uint32_t cbSize;
     1733
     1734            rc = SSMR3GetGCPhys(pSSM, &GCPhys);
     1735            AssertRCReturn(rc, rc);
     1736
     1737            rc = SSMR3GetU32(pSSM, &cbSize);
     1738            AssertRCReturn(rc, rc);
     1739
     1740            LogFlowFunc (("Restoring %RGp size %x bytes\n", GCPhys, cbSize));
     1741
     1742            PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (sizeof (struct VBOXHGCMCMD));
     1743            AssertReturn(pCmd, VERR_NO_MEMORY);
     1744
     1745            vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, cbSize, VBOXHGCMCMDTYPE_LOADSTATE);
     1746        }
     1747    }
     1748    else
     1749    {
     1750        /*
     1751         * Version 9+: Load complete information about commands.
     1752         */
     1753        uint32_t u32;
     1754        bool f;
     1755
     1756        while (cCmds--)
     1757        {
     1758            RTGCPHYS GCPhys;
     1759            uint32_t cbSize;
     1760
     1761            /* GC physical address of the guest request. */
     1762            rc = SSMR3GetGCPhys(pSSM, &GCPhys);
     1763            AssertRCReturn(rc, rc);
     1764
     1765            /* The request packet size */
     1766            rc = SSMR3GetU32(pSSM, &cbSize);
     1767            AssertRCReturn(rc, rc);
     1768
     1769            LogFlowFunc (("Restoring %RGp size %x bytes\n", GCPhys, cbSize));
     1770
     1771            /* Size of entire command. */
     1772            rc = SSMR3GetU32(pSSM, &u32);
     1773            AssertRCReturn(rc, rc);
     1774
     1775            PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (u32);
     1776            AssertReturn(pCmd, VERR_NO_MEMORY);
     1777            pCmd->cbCmd = u32;
     1778
     1779            /* The type of the command. */
     1780            rc = SSMR3GetU32(pSSM, &u32);
     1781            AssertRCReturn(rc, rc);
     1782            pCmd->enmCmdType = (VBOXHGCMCMDTYPE)u32;
     1783
     1784            /* Whether the command was cancelled by the guest. */
     1785            rc = SSMR3GetBool(pSSM, &f);
     1786            AssertRCReturn(rc, rc);
     1787            pCmd->fCancelled = f;
     1788
     1789            /* Linear pointer parameters information. How many pointers. Always 0 if not a call command. */
     1790            rc = SSMR3GetU32(pSSM, &u32);
     1791            AssertRCReturn(rc, rc);
     1792            pCmd->cLinPtrs = u32;
     1793
     1794            if (pCmd->cLinPtrs > 0)
     1795            {
     1796                /* How many pages for all linptrs in this command. */
     1797                rc = SSMR3GetU32(pSSM, &u32);
     1798                AssertRCReturn(rc, rc);
     1799                pCmd->cLinPtrPages = u32;
     1800
     1801                pCmd->paLinPtrs = (VBOXHGCMLINPTR *)RTMemAllocZ (  sizeof (VBOXHGCMLINPTR) * pCmd->cLinPtrs
     1802                                                                 + sizeof (RTGCPHYS) * pCmd->cLinPtrPages);
     1803                AssertReturn(pCmd->paLinPtrs, VERR_NO_MEMORY);
     1804
     1805                RTGCPHYS *pPages = (RTGCPHYS *)((uint8_t *)pCmd->paLinPtrs + sizeof (VBOXHGCMLINPTR) * pCmd->cLinPtrs);
     1806                int cPages = 0;
     1807
     1808                int i;
     1809                for (i = 0; i < pCmd->cLinPtrs; i++)
     1810                {
     1811                    /* Pointer to descriptions of linear pointers. */
     1812                    VBOXHGCMLINPTR *pLinPtr = &pCmd->paLinPtrs[i];
     1813
     1814                    pLinPtr->paPages = pPages;
     1815
     1816                    /* Index of the parameter. */
     1817                    rc = SSMR3GetU32(pSSM, &u32);
     1818                    AssertRCReturn(rc, rc);
     1819                    pLinPtr->iParm = u32;
     1820
     1821                    /* Offset in the first physical page of the region. */
     1822                    rc = SSMR3GetU32(pSSM, &u32);
     1823                    AssertRCReturn(rc, rc);
     1824                    pLinPtr->offFirstPage = u32;
     1825
     1826                    /* How many pages. */
     1827                    rc = SSMR3GetU32(pSSM, &u32);
     1828                    AssertRCReturn(rc, rc);
     1829                    pLinPtr->cPages = u32;
     1830
     1831                    uint32_t iPage;
     1832                    for (iPage = 0; iPage < pLinPtr->cPages; iPage++)
     1833                    {
     1834                        /* Array of the GC physical addresses for these pages.
     1835                         * It is assumed that the physical address of the locked resident
     1836                         * guest page does not change.
     1837                         */
     1838                        RTGCPHYS GCPhysPage;
     1839                        rc = SSMR3GetGCPhys(pSSM, &GCPhysPage);
     1840                        AssertRCReturn(rc, rc);
     1841
     1842                        /* Verify that the number of loaded pages is valid. */
     1843                        cPages++;
     1844                        if (cPages > pCmd->cLinPtrPages)
     1845                        {
     1846                            LogRel(("VMMDevHGCM load state failure: cPages %d, expected %d, ptr %d/%d\n",
     1847                                    cPages, pCmd->cLinPtrPages, i, pCmd->cLinPtrs));
     1848                            return VERR_SSM_UNEXPECTED_DATA;
     1849                        }
     1850
     1851                        *pPages++ = GCPhysPage;
     1852                    }
     1853                }
     1854            }
     1855
     1856            /* A reserved field, will allow to extend saved data for a command. */
     1857            rc = SSMR3GetU32(pSSM, &u32);
     1858            AssertRCReturn(rc, rc);
     1859           
     1860            vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, cbSize, VBOXHGCMCMDTYPE_LOADSTATE);
     1861        }
     1862
     1863        /* A reserved field, will allow to extend saved data for VMMDevHGCM. */
     1864        rc = SSMR3GetU32(pSSM, &u32);
    12171865        AssertRCReturn(rc, rc);
    1218 
    1219         rc = SSMR3GetU32(pSSM, &cbSize);
    1220         AssertRCReturn(rc, rc);
    1221 
    1222         LogFlowFunc (("Restoring %RGp size %x bytes\n", GCPhys, cbSize));
    1223 
    1224         PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)RTMemAllocZ (sizeof (struct VBOXHGCMCMD));
    1225         AssertReturn(pCmd, VERR_NO_MEMORY);
    1226 
    1227         vmmdevHGCMAddCommand (pVMMDevState, pCmd, GCPhys, cbSize, VBOXHGCMCMDTYPE_LOADSTATE);
    12281866    }
    12291867
     
    12431881    if (RT_SUCCESS (rc))
    12441882    {
     1883        /* Start from the current list head and commands loaded from saved state.
     1884         * New commands will be inserted at the list head, so they will not be seen by
     1885         * this loop.
     1886         */
    12451887        PVBOXHGCMCMD pIter = pVMMDevState->pHGCMCmdList;
    12461888
    12471889        while (pIter)
    12481890        {
     1891            /* This will remove the command from the list if resubmitting fails. */
     1892            bool fHGCMCalled = false;
     1893
    12491894            LogFlowFunc (("pIter %p\n", pIter));
    12501895
    12511896            PVBOXHGCMCMD pNext = pIter->pNext;
    12521897
    1253             VMMDevRequestHeader *requestHeader = (VMMDevRequestHeader *)RTMemAllocZ (pIter->cbSize);
     1898            VMMDevHGCMRequestHeader *requestHeader = (VMMDevHGCMRequestHeader *)RTMemAllocZ (pIter->cbSize);
    12541899            Assert(requestHeader);
    12551900            if (requestHeader == NULL)
    12561901                return VERR_NO_MEMORY;
    12571902
    1258             PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)pIter->GCPhys, requestHeader, pIter->cbSize);
     1903            PDMDevHlpPhysRead(pDevIns, pIter->GCPhys, requestHeader, pIter->cbSize);
    12591904
    12601905            /* the structure size must be greater or equal to the header size */
    1261             if (requestHeader->size < sizeof(VMMDevRequestHeader))
     1906            if (requestHeader->header.size < sizeof(VMMDevHGCMRequestHeader))
    12621907            {
    1263                 Log(("VMMDev request header size too small! size = %d\n", requestHeader->size));
     1908                Log(("VMMDev request header size too small! size = %d\n", requestHeader->header.size));
    12641909            }
    12651910            else
    12661911            {
    12671912                /* check the version of the header structure */
    1268                 if (requestHeader->version != VMMDEV_REQUEST_HEADER_VERSION)
     1913                if (requestHeader->header.version != VMMDEV_REQUEST_HEADER_VERSION)
    12691914                {
    1270                     Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->version, VMMDEV_REQUEST_HEADER_VERSION));
     1915                    Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->header.version, VMMDEV_REQUEST_HEADER_VERSION));
    12711916                }
    12721917                else
    12731918                {
    1274                     Log(("VMMDev request issued: %d\n", requestHeader->requestType));
    1275 
    1276                     switch (requestHeader->requestType)
     1919                    Log(("VMMDev request issued: %d, command type %d\n", requestHeader->header.requestType, pIter->enmCmdType));
     1920
     1921                    /* Use the saved command type. Even if the guest has changed the memory already,
     1922                     * HGCM should see the same command as it was before saving state.
     1923                     */
     1924                    switch (pIter->enmCmdType)
    12771925                    {
    1278                         case VMMDevReq_HGCMConnect:
     1926                        case VBOXHGCMCMDTYPE_CONNECT:
    12791927                        {
    1280                             if (requestHeader->size < sizeof(VMMDevHGCMConnect))
     1928                            if (requestHeader->header.size < sizeof(VMMDevHGCMConnect))
    12811929                            {
    12821930                                AssertMsgFailed(("VMMDevReq_HGCMConnect structure has invalid size!\n"));
    1283                                 requestHeader->rc = VERR_INVALID_PARAMETER;
     1931                                requestHeader->header.rc = VERR_INVALID_PARAMETER;
    12841932                            }
    12851933                            else if (!pVMMDevState->pHGCMDrv)
    12861934                            {
    12871935                                Log(("VMMDevReq_HGCMConnect HGCM Connector is NULL!\n"));
    1288                                 requestHeader->rc = VERR_NOT_SUPPORTED;
     1936                                requestHeader->header.rc = VERR_NOT_SUPPORTED;
    12891937                            }
    12901938                            else
     
    12941942                                Log(("VMMDevReq_HGCMConnect\n"));
    12951943
    1296                                 requestHeader->rc = vmmdevHGCMConnect (pVMMDevState, pHGCMConnect, pIter->GCPhys);
     1944                                requestHeader->header.rc = vmmdevHGCMConnectSaved (pVMMDevState, pHGCMConnect, &fHGCMCalled, pIter);
    12971945                            }
    12981946                            break;
    12991947                        }
    13001948
    1301                         case VMMDevReq_HGCMDisconnect:
     1949                        case VBOXHGCMCMDTYPE_DISCONNECT:
    13021950                        {
    1303                             if (requestHeader->size < sizeof(VMMDevHGCMDisconnect))
     1951                            if (requestHeader->header.size < sizeof(VMMDevHGCMDisconnect))
    13041952                            {
    13051953                                AssertMsgFailed(("VMMDevReq_HGCMDisconnect structure has invalid size!\n"));
    1306                                 requestHeader->rc = VERR_INVALID_PARAMETER;
     1954                                requestHeader->header.rc = VERR_INVALID_PARAMETER;
    13071955                            }
    13081956                            else if (!pVMMDevState->pHGCMDrv)
    13091957                            {
    13101958                                Log(("VMMDevReq_HGCMDisconnect HGCM Connector is NULL!\n"));
    1311                                 requestHeader->rc = VERR_NOT_SUPPORTED;
     1959                                requestHeader->header.rc = VERR_NOT_SUPPORTED;
    13121960                            }
    13131961                            else
     
    13161964
    13171965                                Log(("VMMDevReq_VMMDevHGCMDisconnect\n"));
    1318                                 requestHeader->rc = vmmdevHGCMDisconnect (pVMMDevState, pHGCMDisconnect, pIter->GCPhys);
     1966                                requestHeader->header.rc = vmmdevHGCMDisconnectSaved (pVMMDevState, pHGCMDisconnect, &fHGCMCalled, pIter);
    13191967                            }
    13201968                            break;
    13211969                        }
    13221970
    1323 #ifdef VBOX_WITH_64_BITS_GUESTS
    1324                         case VMMDevReq_HGCMCall64:
    1325                         case VMMDevReq_HGCMCall32:
    1326 #else
    1327                         case VMMDevReq_HGCMCall:
    1328 #endif /* VBOX_WITH_64_BITS_GUESTS */
     1971                        case VBOXHGCMCMDTYPE_CALL:
    13291972                        {
    1330                             if (requestHeader->size < sizeof(VMMDevHGCMCall))
     1973                            if (requestHeader->header.size < sizeof(VMMDevHGCMCall))
    13311974                            {
    13321975                                AssertMsgFailed(("VMMDevReq_HGCMCall structure has invalid size!\n"));
    1333                                 requestHeader->rc = VERR_INVALID_PARAMETER;
     1976                                requestHeader->header.rc = VERR_INVALID_PARAMETER;
    13341977                            }
    13351978                            else if (!pVMMDevState->pHGCMDrv)
    13361979                            {
    13371980                                Log(("VMMDevReq_HGCMCall HGCM Connector is NULL!\n"));
    1338                                 requestHeader->rc = VERR_NOT_SUPPORTED;
     1981                                requestHeader->header.rc = VERR_NOT_SUPPORTED;
    13391982                            }
    13401983                            else
     
    13441987                                Log(("VMMDevReq_HGCMCall: sizeof (VMMDevHGCMRequest) = %04X\n", sizeof (VMMDevHGCMCall)));
    13451988
    1346                                 Log(("%.*Rhxd\n", requestHeader->size, requestHeader));
     1989                                Log(("%.*Rhxd\n", requestHeader->header.size, requestHeader));
    13471990
    13481991#ifdef VBOX_WITH_64_BITS_GUESTS
    1349                                 bool f64Bits = (requestHeader->requestType == VMMDevReq_HGCMCall64);
     1992                                bool f64Bits = (requestHeader->header.requestType == VMMDevReq_HGCMCall64);
    13501993#else
    13511994                                bool f64Bits = false;
    13521995#endif /* VBOX_WITH_64_BITS_GUESTS */
    1353                                 requestHeader->rc = vmmdevHGCMCall (pVMMDevState, pHGCMCall, pIter->GCPhys, f64Bits);
     1996                                requestHeader->header.rc = vmmdevHGCMCallSaved (pVMMDevState, pHGCMCall, f64Bits, &fHGCMCalled, pIter);
    13541997                            }
    13551998                            break;
    13561999                        }
     2000                        case VBOXHGCMCMDTYPE_LOADSTATE:
     2001                        {
     2002                            /* Old saved state. */
     2003                            switch (requestHeader->header.requestType)
     2004                            {
     2005                                case VMMDevReq_HGCMConnect:
     2006                                {
     2007                                    if (requestHeader->header.size < sizeof(VMMDevHGCMConnect))
     2008                                    {
     2009                                        AssertMsgFailed(("VMMDevReq_HGCMConnect structure has invalid size!\n"));
     2010                                        requestHeader->header.rc = VERR_INVALID_PARAMETER;
     2011                                    }
     2012                                    else if (!pVMMDevState->pHGCMDrv)
     2013                                    {
     2014                                        Log(("VMMDevReq_HGCMConnect HGCM Connector is NULL!\n"));
     2015                                        requestHeader->header.rc = VERR_NOT_SUPPORTED;
     2016                                    }
     2017                                    else
     2018                                    {
     2019                                        VMMDevHGCMConnect *pHGCMConnect = (VMMDevHGCMConnect *)requestHeader;
     2020
     2021                                        Log(("VMMDevReq_HGCMConnect\n"));
     2022
     2023                                        requestHeader->header.rc = vmmdevHGCMConnect (pVMMDevState, pHGCMConnect, pIter->GCPhys);
     2024                                    }
     2025                                    break;
     2026                                }
     2027
     2028                                case VMMDevReq_HGCMDisconnect:
     2029                                {
     2030                                    if (requestHeader->header.size < sizeof(VMMDevHGCMDisconnect))
     2031                                    {
     2032                                        AssertMsgFailed(("VMMDevReq_HGCMDisconnect structure has invalid size!\n"));
     2033                                        requestHeader->header.rc = VERR_INVALID_PARAMETER;
     2034                                    }
     2035                                    else if (!pVMMDevState->pHGCMDrv)
     2036                                    {
     2037                                        Log(("VMMDevReq_HGCMDisconnect HGCM Connector is NULL!\n"));
     2038                                        requestHeader->header.rc = VERR_NOT_SUPPORTED;
     2039                                    }
     2040                                    else
     2041                                    {
     2042                                        VMMDevHGCMDisconnect *pHGCMDisconnect = (VMMDevHGCMDisconnect *)requestHeader;
     2043
     2044                                        Log(("VMMDevReq_VMMDevHGCMDisconnect\n"));
     2045                                        requestHeader->header.rc = vmmdevHGCMDisconnect (pVMMDevState, pHGCMDisconnect, pIter->GCPhys);
     2046                                    }
     2047                                    break;
     2048                                }
     2049
     2050#ifdef VBOX_WITH_64_BITS_GUESTS
     2051                                case VMMDevReq_HGCMCall64:
     2052                                case VMMDevReq_HGCMCall32:
     2053#else
     2054                                case VMMDevReq_HGCMCall:
     2055#endif /* VBOX_WITH_64_BITS_GUESTS */
     2056                                {
     2057                                    if (requestHeader->header.size < sizeof(VMMDevHGCMCall))
     2058                                    {
     2059                                        AssertMsgFailed(("VMMDevReq_HGCMCall structure has invalid size!\n"));
     2060                                        requestHeader->header.rc = VERR_INVALID_PARAMETER;
     2061                                    }
     2062                                    else if (!pVMMDevState->pHGCMDrv)
     2063                                    {
     2064                                        Log(("VMMDevReq_HGCMCall HGCM Connector is NULL!\n"));
     2065                                        requestHeader->header.rc = VERR_NOT_SUPPORTED;
     2066                                    }
     2067                                    else
     2068                                    {
     2069                                        VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)requestHeader;
     2070
     2071                                        Log(("VMMDevReq_HGCMCall: sizeof (VMMDevHGCMRequest) = %04X\n", sizeof (VMMDevHGCMCall)));
     2072
     2073                                        Log(("%.*Rhxd\n", requestHeader->header.size, requestHeader));
     2074
     2075#ifdef VBOX_WITH_64_BITS_GUESTS
     2076                                        bool f64Bits = (requestHeader->header.requestType == VMMDevReq_HGCMCall64);
     2077#else
     2078                                        bool f64Bits = false;
     2079#endif /* VBOX_WITH_64_BITS_GUESTS */
     2080                                        requestHeader->header.rc = vmmdevHGCMCall (pVMMDevState, pHGCMCall, pIter->GCPhys, f64Bits);
     2081                                    }
     2082                                    break;
     2083                                }
     2084                                default:
     2085                                    AssertMsgFailed(("Unknown request type %x during LoadState\n", requestHeader->header.requestType));
     2086                                    LogRel(("VMMDEV: Ignoring unknown request type %x during LoadState\n", requestHeader->header.requestType));
     2087                            }
     2088                        } break;
     2089
    13572090                        default:
    1358                             AssertMsgFailed(("Unknown request type %x during LoadState\n", requestHeader->requestType));
    1359                             LogRel(("VMMDEV: Ignoring unknown request type %x during LoadState\n", requestHeader->requestType));
     2091                            AssertMsgFailed(("Unknown request type %x during LoadState\n", requestHeader->header.requestType));
     2092                            LogRel(("VMMDEV: Ignoring unknown request type %x during LoadState\n", requestHeader->header.requestType));
    13602093                    }
    13612094                }
    13622095            }
    13632096
    1364             /* Write back the request */
    1365             PDMDevHlpPhysWrite(pDevIns, pIter->GCPhys, requestHeader, pIter->cbSize);
    1366             RTMemFree(requestHeader);
    1367 
    1368             vmmdevHGCMRemoveCommand (pVMMDevState, pIter);
    1369             RTMemFree(pIter);
     2097            if (pIter->enmCmdType == VBOXHGCMCMDTYPE_LOADSTATE)
     2098            {
     2099                /* Old saved state. Remove the LOADSTATE command. */
     2100
     2101                /* Write back the request */
     2102                PDMDevHlpPhysWrite(pDevIns, pIter->GCPhys, requestHeader, pIter->cbSize);
     2103                RTMemFree(requestHeader);
     2104                requestHeader = NULL;
     2105
     2106                vmmdevHGCMRemoveCommand (pVMMDevState, pIter);
     2107
     2108                if (pIter->paLinPtrs != NULL)
     2109                {
     2110                     RTMemFree(pIter->paLinPtrs);
     2111                }
     2112
     2113                RTMemFree(pIter);
     2114            }
     2115            else
     2116            {
     2117                if (!fHGCMCalled)
     2118                {
     2119                   /* HGCM was not called. Return the error to the guest. Guest may try to repeat the call. */
     2120                   requestHeader->header.rc = VERR_TRY_AGAIN;
     2121                   requestHeader->fu32Flags |= VBOX_HGCM_REQ_DONE;
     2122                }
     2123
     2124                /* Write back the request */
     2125                PDMDevHlpPhysWrite(pDevIns, pIter->GCPhys, requestHeader, pIter->cbSize);
     2126                RTMemFree(requestHeader);
     2127                requestHeader = NULL;
     2128
     2129                if (!fHGCMCalled)
     2130                {
     2131                   /* HGCM was not called. Deallocate the current command and then notify guest. */
     2132                   vmmdevHGCMRemoveCommand (pVMMDevState, pIter);
     2133
     2134                   if (pIter->paLinPtrs != NULL)
     2135                   {
     2136                        RTMemFree(pIter->paLinPtrs);
     2137                   }
     2138
     2139                   RTMemFree(pIter);
     2140               
     2141                   VMMDevNotifyGuest (pVMMDevState, VMMDEV_EVENT_HGCM);
     2142                }
     2143            }
     2144
    13702145            pIter = pNext;
    13712146        }
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.h

    r20374 r20731  
    3939
    4040int vmmdevHGCMSaveState(VMMDevState *pVMMDevState, PSSMHANDLE pSSM);
    41 int vmmdevHGCMLoadState(VMMDevState *pVMMDevState, PSSMHANDLE pSSM);
     41int vmmdevHGCMLoadState(VMMDevState *pVMMDevState, PSSMHANDLE pSSM, uint32_t u32Version);
    4242int vmmdevHGCMLoadStateDone(VMMDevState *pVMMDevState, PSSMHANDLE pSSM);
    4343RT_C_DECLS_END
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