VirtualBox

Ignore:
Timestamp:
Jul 10, 2009 4:53:03 PM (15 years ago)
Author:
vboxsync
Message:

VbglR0HGCMInternal.cpp: Enable the physical page list code everywhere.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp

    r21487 r21489  
    159159}
    160160
    161 #if 0 /* new code using page list and whatnot. */
    162161
    163162/**
     
    212211                    uint32_t            u32;
    213212
    214                     AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), VERR_OUT_OF_RANGE);
     213                    AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
     214                                    VERR_OUT_OF_RANGE);
    215215                    AssertMsgReturn(   off >= pCallInfo->cParms * sizeof(HGCMFunctionParameter)
    216216                                    && off < cbCallInfo - sizeof(HGCMPageListInfo),
     
    227227                    u32 = RT_ALIGN_32(pPgLst->offFirstPage + cb, PAGE_SIZE) >> PAGE_SHIFT;
    228228                    AssertMsgReturn(cPages == u32, ("cPages=%#x u32=%#x\n", cPages, u32), VERR_INVALID_PARAMETER);
    229                     AssertMsgReturn(pPgLst->flags > VBOX_HGCM_F_PARM_DIRECTION_NONE && pPgLst->flags <= VBOX_HGCM_F_PARM_DIRECTION_BOTH,
    230                                     ("%#x\n", pPgLst->flags),
    231                                     VERR_INVALID_PARAMETER);
    232                     Log4(("GstHGCMCall: parm=%u type=pglst: cb=%#010x cPgs=%u offPg0=%#x flags=%#x\n", iParm, cb, cPages, pPgLst->offFirstPage, pPgLst->flags));
     229                    AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pPgLst->flags), ("%#x\n", pPgLst->flags), VERR_INVALID_PARAMETER);
     230                    Log4(("GstHGCMCall: parm=%u type=pglst: cb=%#010x cPgs=%u offPg0=%#x flags=%#x\n",
     231                          iParm, cb, cPages, pPgLst->offFirstPage, pPgLst->flags));
    233232                    u32 = cPages;
    234233                    while (u32-- > 0)
     
    254253                {
    255254                    cb = pSrcParm->u.Pointer.size;
    256                     AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), VERR_OUT_OF_RANGE);
     255                    AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
     256                                    VERR_OUT_OF_RANGE);
    257257                    if (cb != 0)
    258                         Log4(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr));
     258                        Log4(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p\n",
     259                              iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr));
    259260                    else
    260261                        Log4(("GstHGCMCall: parm=%u type=%#x: cb=0\n", iParm, pSrcParm->type));
     
    279280                    if (!fIsUser)
    280281                    {
    281                         AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), VERR_OUT_OF_RANGE);
     282                        AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
     283                                        VERR_OUT_OF_RANGE);
    282284                        rc = RTR0MemObjLockKernel(&hObj, (void *)pSrcParm->u.Pointer.u.linearAddr, cb);
    283285                        if (RT_FAILURE(rc))
     
    287289                            return rc;
    288290                        }
    289                         Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked kernel -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
     291                        Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked kernel -> %p\n",
     292                              iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
    290293                    }
    291294                    else
     
    294297                        {
    295298                            Log(("GstHGCMCall: id=%#x fn=%u parm=%u pv=%p cb=%#x > %#x -> out of range\n",
    296                                  pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, VBGLR0_MAX_HGCM_USER_PARM));
     299                                 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr,
     300                                 cb, VBGLR0_MAX_HGCM_USER_PARM));
    297301                            return VERR_OUT_OF_RANGE;
    298302                        }
     
    306310                            return rc;
    307311                        }
    308                         Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked user -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
     312                        Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked user -> %p\n",
     313                              iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
    309314
    310315#else  /* USE_BOUNCH_BUFFERS */
     
    333338                                    RTMemTmpFree(pvSmallBuf);
    334339                                    Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n",
    335                                          pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc));
     340                                         pCallInfo->u32ClientID, pCallInfo->u32Function, iParm,
     341                                         pSrcParm->u.Pointer.u.linearAddr, cb, rc));
    336342                                    return rc;
    337343                                }
     
    341347                            {
    342348                                RTMemTmpFree(pvSmallBuf);
    343                                 Log(("GstHGCMCall: RTR0MemObjLockKernel failed for small buffer: rc=%Rrc pvSmallBuf=%p cb=%#x\n", rc, pvSmallBuf, cb));
     349                                Log(("GstHGCMCall: RTR0MemObjLockKernel failed for small buffer: rc=%Rrc pvSmallBuf=%p cb=%#x\n",
     350                                     rc, pvSmallBuf, cb));
    344351                                return rc;
    345352                            }
    346                             Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p small buffer %p -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, pvSmallBuf, hObj));
     353                            Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p small buffer %p -> %p\n",
     354                                  iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, pvSmallBuf, hObj));
    347355                        }
    348356                        else
     
    360368                                    RTR0MemObjFree(hObj, false /*fFreeMappings*/);
    361369                                    Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n",
    362                                          pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc));
     370                                         pCallInfo->u32ClientID, pCallInfo->u32Function, iParm,
     371                                         pSrcParm->u.Pointer.u.linearAddr, cb, rc));
    363372                                    return rc;
    364373                                }
    365374                            }
    366                             Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p big buffer -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
     375                            Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p big buffer -> %p\n",
     376                                  iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
    367377                        }
    368378#endif /* USE_BOUNCH_BUFFERS */
     
    394404}
    395405
     406
    396407/**
    397408 * Translates locked linear address to the normal type.
     
    416427}
    417428
     429
    418430/**
    419431 * Translates linear address types to page list direction flags.
     
    453465 *                          physical page lists.
    454466 */
    455 static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,
    456                                        bool fIsUser, struct VbglR0ParmInfo *pParmInfo)
     467static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo,
     468                                       uint32_t cbCallInfo, bool fIsUser, struct VbglR0ParmInfo *pParmInfo)
    457469{
    458470    HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     
    598610 * @param   u32AsyncData        Argument for the callback.
    599611 */
    600 static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     612static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback,
     613                                    void *pvAsyncData, uint32_t u32AsyncData)
    601614{
    602615    int rc;
     
    752765}
    753766
     767
    754768DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    755769                                       VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     
    763777     * Basic validation.
    764778     */
    765     AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
     779    AssertMsgReturn(   !pCallInfo
     780                    || !pfnAsyncCallback
     781                    || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
     782                    || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
    766783                    ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
    767784                    VERR_INVALID_PARAMETER);
     
    823840
    824841
    825 #  if ARCH_BITS == 64
     842#if ARCH_BITS == 64
    826843DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    827844                                         VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     
    837854     * Input validation.
    838855     */
    839     AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
     856    AssertMsgReturn(    !pCallInfo
     857                    ||  !pfnAsyncCallback
     858                    ||  pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
     859                    || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
    840860                    ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
    841861                    VERR_INVALID_PARAMETER);
     
    924944    return rc;
    925945}
    926 #  endif /* ARCH_BITS == 64 */
    927 
    928 # else /* old code: */
    929 
    930 /** @todo merge with the one below (use a header file). Too lazy now. */
    931 DECLR0VBGL(int) VbglR0HGCMInternalCall (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    932                                         VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
    933 {
    934     VMMDevHGCMCall *pHGCMCall;
    935     uint32_t cbParms;
    936     HGCMFunctionParameter *pParm;
    937     unsigned iParm;
    938     int rc;
    939 
    940     AssertMsgReturn(!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
    941                     ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pAsyncCallback, fFlags),
    942                     VERR_INVALID_PARAMETER);
    943 
    944     Log (("GstHGCMCall: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d, fFlags=%#x\n",
    945           pCallInfo->cParms, pCallInfo->u32Function, fFlags));
    946 
    947     pHGCMCall = NULL;
    948 
    949     if (cbCallInfo == 0)
    950     {
    951         /* Caller did not specify the size (a valid value should be at least sizeof(VBoxGuestHGCMCallInfo)).
    952          * Compute the size.
    953          */
    954         cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter);
    955     }
    956     else if (cbCallInfo < sizeof (VBoxGuestHGCMCallInfo))
    957     {
    958         return VERR_INVALID_PARAMETER;
    959     }
    960     else
    961     {
    962         cbParms = cbCallInfo - sizeof (VBoxGuestHGCMCallInfo);
    963     }
    964 
    965     /* Allocate request */
    966     rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMCall, sizeof (VMMDevHGCMCall) + cbParms, VMMDevReq_HGCMCall);
    967 
    968     Log (("GstHGCMCall: Allocated gr %p, rc = %Rrc, cbParms = %d\n", pHGCMCall, rc, cbParms));
    969 
    970     if (RT_SUCCESS(rc))
    971     {
    972         void *apvCtx[VBOX_HGCM_MAX_PARMS];
    973         memset (apvCtx, 0, sizeof(void *) * pCallInfo->cParms);
    974 
    975         /* Initialize request memory */
    976         pHGCMCall->header.fu32Flags = 0;
    977         pHGCMCall->header.result    = VINF_SUCCESS;
    978 
    979         pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
    980         pHGCMCall->u32Function = pCallInfo->u32Function;
    981         pHGCMCall->cParms      = pCallInfo->cParms;
    982 
    983         if (cbParms)
    984         {
    985             /* Lock user buffers. */
    986             pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
    987 
    988             for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
    989             {
    990                 switch (pParm->type)
    991                 {
    992                 case VMMDevHGCMParmType_32bit:
    993                 case VMMDevHGCMParmType_64bit:
    994                     break;
    995 
    996                 case VMMDevHGCMParmType_LinAddr_Locked_In:
    997                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    998                         rc = VERR_INVALID_PARAMETER;
    999                     else
    1000                         pParm->type = VMMDevHGCMParmType_LinAddr_In;
    1001                     break;
    1002                 case VMMDevHGCMParmType_LinAddr_Locked_Out:
    1003                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1004                         rc = VERR_INVALID_PARAMETER;
    1005                     else
    1006                         pParm->type = VMMDevHGCMParmType_LinAddr_Out;
    1007                     break;
    1008                 case VMMDevHGCMParmType_LinAddr_Locked:
    1009                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1010                         rc = VERR_INVALID_PARAMETER;
    1011                     else
    1012                         pParm->type = VMMDevHGCMParmType_LinAddr;
    1013                     break;
    1014 
    1015                 case VMMDevHGCMParmType_PageList:
    1016                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1017                         rc = VERR_INVALID_PARAMETER;
    1018                     break;
    1019 
    1020                 case VMMDevHGCMParmType_LinAddr_In:
    1021                 case VMMDevHGCMParmType_LinAddr_Out:
    1022                 case VMMDevHGCMParmType_LinAddr:
    1023                     /* PORTME: When porting this to Darwin and other systems where the entire kernel isn't mapped
    1024                        into every process, all linear address will have to be converted to physical SG lists at
    1025                        this point. Care must also be taken on these guests to not mix kernel and user addresses
    1026                        in HGCM calls, or we'll end up locking the wrong memory. If VMMDev/HGCM gets a linear address
    1027                        it will assume that it's in the current memory context (i.e. use CR3 to translate it).
    1028 
    1029                        These kind of problems actually applies to some patched linux kernels too, including older
    1030                        fedora releases. (The patch is the infamous 4G/4G patch, aka 4g4g, by Ingo Molnar.) */
    1031                     rc = vbglLockLinear (&apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size,
    1032                                          (pParm->type == VMMDevHGCMParmType_LinAddr_In) ? false : true /* write access */,
    1033                                          fFlags);
    1034                     break;
    1035 
    1036                 default:
    1037                     rc = VERR_INVALID_PARAMETER;
    1038                     break;
    1039                 }
    1040                 if (RT_FAILURE (rc))
    1041                     break;
    1042             }
    1043             memcpy (VMMDEV_HGCM_CALL_PARMS(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), cbParms);
    1044         }
    1045 
    1046         /* Check that the parameter locking was ok. */
    1047         if (RT_SUCCESS(rc))
    1048         {
    1049             Log (("calling VbglGRPerform\n"));
    1050 
    1051             /* Issue request */
    1052             rc = VbglGRPerform (&pHGCMCall->header.header);
    1053 
    1054             Log (("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result));
    1055 
    1056             /** If the call failed, but as a result of the request itself, then pretend success
    1057              *  Upper layers will interpret the result code in the packet.
    1058              */
    1059             if (RT_FAILURE(rc) && rc == pHGCMCall->header.result)
    1060             {
    1061                 Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
    1062                 rc = VINF_SUCCESS;
    1063             }
    1064 
    1065             if (RT_SUCCESS(rc))
    1066             {
    1067                 /* Check if host decides to process the request asynchronously. */
    1068                 if (rc == VINF_HGCM_ASYNC_EXECUTE)
    1069                 {
    1070                     /* Wait for request completion interrupt notification from host */
    1071                     Log (("Processing HGCM call asynchronously\n"));
    1072                     pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData);
    1073                 }
    1074 
    1075                 if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
    1076                 {
    1077                     if (cbParms)
    1078                     {
    1079                         memcpy (VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), VMMDEV_HGCM_CALL_PARMS(pHGCMCall), cbParms);
    1080                     }
    1081                     pCallInfo->result = pHGCMCall->header.result;
    1082                 }
    1083                 else
    1084                 {
    1085                     /* The callback returns without completing the request,
    1086                      * that means the wait was interrrupted. That can happen
    1087                      * if the request times out, the system reboots or the
    1088                      * VBoxService ended abnormally.
    1089                      *
    1090                      * Cancel the request, the host will not write to the
    1091                      * memory related to the cancelled request.
    1092                      */
    1093                     Log (("Cancelling HGCM call\n"));
    1094                     pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
    1095 
    1096                     pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
    1097                     VbglGRPerform (&pHGCMCall->header.header);
    1098                 }
    1099             }
    1100         }
    1101 
    1102         /* Unlock user buffers. */
    1103         pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
    1104 
    1105         for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
    1106         {
    1107             if (   pParm->type == VMMDevHGCMParmType_LinAddr_In
    1108                 || pParm->type == VMMDevHGCMParmType_LinAddr_Out
    1109                 || pParm->type == VMMDevHGCMParmType_LinAddr)
    1110             {
    1111                 if (apvCtx[iParm] != NULL)
    1112                 {
    1113                     vbglUnlockLinear (apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
    1114                 }
    1115             }
    1116             else
    1117                 Assert(!apvCtx[iParm]);
    1118         }
    1119 
    1120         if ((pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED) == 0)
    1121             VbglGRFree (&pHGCMCall->header.header);
    1122         else
    1123             rc = VERR_INTERRUPTED;
    1124     }
    1125 
    1126     return rc;
    1127 }
    1128 
    1129 #  if ARCH_BITS == 64
    1130 /** @todo merge with the one above (use a header file). Too lazy now. */
    1131 DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    1132                                           VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
    1133 {
    1134     VMMDevHGCMCall *pHGCMCall;
    1135     uint32_t cbParms;
    1136     HGCMFunctionParameter32 *pParm;
    1137     unsigned iParm;
    1138     int rc;
    1139 
    1140     AssertMsgReturn(!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
    1141                     ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pAsyncCallback, fFlags),
    1142                     VERR_INVALID_PARAMETER);
    1143 
    1144     Log (("GstHGCMCall32: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d, fFlags=%#x\n",
    1145           pCallInfo->cParms, pCallInfo->u32Function, fFlags));
    1146 
    1147     pHGCMCall = NULL;
    1148 
    1149     if (cbCallInfo == 0)
    1150     {
    1151         /* Caller did not specify the size (a valid value should be at least sizeof(VBoxGuestHGCMCallInfo)).
    1152          * Compute the size.
    1153          */
    1154         cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter32);
    1155     }
    1156     else if (cbCallInfo < sizeof (VBoxGuestHGCMCallInfo))
    1157     {
    1158         return VERR_INVALID_PARAMETER;
    1159     }
    1160     else
    1161     {
    1162         cbParms = cbCallInfo - sizeof (VBoxGuestHGCMCallInfo);
    1163     }
    1164 
    1165     /* Allocate request */
    1166     rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMCall, sizeof (VMMDevHGCMCall) + cbParms, VMMDevReq_HGCMCall32);
    1167 
    1168     Log (("GstHGCMCall32: Allocated gr %p, rc = %Rrc, cbParms = %d\n", pHGCMCall, rc, cbParms));
    1169 
    1170     if (RT_SUCCESS(rc))
    1171     {
    1172         void *apvCtx[VBOX_HGCM_MAX_PARMS];
    1173         memset (apvCtx, 0, sizeof(void *) * pCallInfo->cParms);
    1174 
    1175         /* Initialize request memory */
    1176         pHGCMCall->header.fu32Flags = 0;
    1177         pHGCMCall->header.result    = VINF_SUCCESS;
    1178 
    1179         pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
    1180         pHGCMCall->u32Function = pCallInfo->u32Function;
    1181         pHGCMCall->cParms      = pCallInfo->cParms;
    1182 
    1183         if (cbParms)
    1184         {
    1185             /* Lock user buffers. */
    1186             pParm = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
    1187 
    1188             for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
    1189             {
    1190                 switch (pParm->type)
    1191                 {
    1192                 case VMMDevHGCMParmType_32bit:
    1193                 case VMMDevHGCMParmType_64bit:
    1194                     break;
    1195 
    1196                 case VMMDevHGCMParmType_LinAddr_Locked_In:
    1197                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1198                         rc = VERR_INVALID_PARAMETER;
    1199                     else
    1200                         pParm->type = VMMDevHGCMParmType_LinAddr_In;
    1201                     break;
    1202                 case VMMDevHGCMParmType_LinAddr_Locked_Out:
    1203                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1204                         rc = VERR_INVALID_PARAMETER;
    1205                     else
    1206                         pParm->type = VMMDevHGCMParmType_LinAddr_Out;
    1207                     break;
    1208                 case VMMDevHGCMParmType_LinAddr_Locked:
    1209                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1210                         rc = VERR_INVALID_PARAMETER;
    1211                     else
    1212                         pParm->type = VMMDevHGCMParmType_LinAddr;
    1213                     break;
    1214 
    1215                 case VMMDevHGCMParmType_PageList:
    1216                     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
    1217                         rc = VERR_INVALID_PARAMETER;
    1218                     break;
    1219 
    1220                 case VMMDevHGCMParmType_LinAddr_In:
    1221                 case VMMDevHGCMParmType_LinAddr_Out:
    1222                 case VMMDevHGCMParmType_LinAddr:
    1223                     /* PORTME: When porting this to Darwin and other systems where the entire kernel isn't mapped
    1224                        into every process, all linear address will have to be converted to physical SG lists at
    1225                        this point. Care must also be taken on these guests to not mix kernel and user addresses
    1226                        in HGCM calls, or we'll end up locking the wrong memory. If VMMDev/HGCM gets a linear address
    1227                        it will assume that it's in the current memory context (i.e. use CR3 to translate it).
    1228 
    1229                        These kind of problems actually applies to some patched linux kernels too, including older
    1230                        fedora releases. (The patch is the infamous 4G/4G patch, aka 4g4g, by Ingo Molnar.) */
    1231                     rc = vbglLockLinear (&apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size,
    1232                                          (pParm->type == VMMDevHGCMParmType_LinAddr_In) ? false : true /* write access */,
    1233                                          fFlags);
    1234                     break;
    1235 
    1236                 default:
    1237                     rc = VERR_INVALID_PARAMETER;
    1238                     break;
    1239                 }
    1240                 if (RT_FAILURE (rc))
    1241                     break;
    1242             }
    1243             memcpy (VMMDEV_HGCM_CALL_PARMS32(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo), cbParms);
    1244         }
    1245 
    1246         /* Check that the parameter locking was ok. */
    1247         if (RT_SUCCESS(rc))
    1248         {
    1249             Log (("calling VbglGRPerform\n"));
    1250 
    1251             /* Issue request */
    1252             rc = VbglGRPerform (&pHGCMCall->header.header);
    1253 
    1254             Log (("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result));
    1255 
    1256             /** If the call failed, but as a result of the request itself, then pretend success
    1257              *  Upper layers will interpret the result code in the packet.
    1258              */
    1259             if (RT_FAILURE(rc) && rc == pHGCMCall->header.result)
    1260             {
    1261                 Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
    1262                 rc = VINF_SUCCESS;
    1263             }
    1264 
    1265             if (RT_SUCCESS(rc))
    1266             {
    1267                 /* Check if host decides to process the request asynchronously. */
    1268                 if (rc == VINF_HGCM_ASYNC_EXECUTE)
    1269                 {
    1270                     /* Wait for request completion interrupt notification from host */
    1271                     Log (("Processing HGCM call asynchronously\n"));
    1272                     pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData);
    1273                 }
    1274 
    1275                 if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
    1276                 {
    1277                     if (cbParms)
    1278                         memcpy (VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo), VMMDEV_HGCM_CALL_PARMS32(pHGCMCall), cbParms);
    1279 
    1280                     pCallInfo->result = pHGCMCall->header.result;
    1281                 }
    1282                 else
    1283                 {
    1284                     /* The callback returns without completing the request,
    1285                      * that means the wait was interrrupted. That can happen
    1286                      * if the request times out, the system reboots or the
    1287                      * VBoxService ended abnormally.
    1288                      *
    1289                      * Cancel the request, the host will not write to the
    1290                      * memory related to the cancelled request.
    1291                      */
    1292                     Log (("Cancelling HGCM call\n"));
    1293                     pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
    1294 
    1295                     pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
    1296                     VbglGRPerform (&pHGCMCall->header.header);
    1297                 }
    1298             }
    1299         }
    1300 
    1301         /* Unlock user buffers. */
    1302         pParm = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
    1303 
    1304         for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
    1305         {
    1306             if (   pParm->type == VMMDevHGCMParmType_LinAddr_In
    1307                 || pParm->type == VMMDevHGCMParmType_LinAddr_Out
    1308                 || pParm->type == VMMDevHGCMParmType_LinAddr)
    1309             {
    1310                 if (apvCtx[iParm] != NULL)
    1311                 {
    1312                     vbglUnlockLinear (apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
    1313                 }
    1314             }
    1315             else
    1316                 Assert(!apvCtx[iParm]);
    1317         }
    1318 
    1319         if ((pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED) == 0)
    1320             VbglGRFree (&pHGCMCall->header.header);
    1321         else
    1322             rc = VERR_INTERRUPTED;
    1323     }
    1324 
    1325     return rc;
    1326 }
    1327 #  endif /* ARCH_BITS == 64 */
    1328 
    1329 # endif /* old code */
     946#endif /* ARCH_BITS == 64 */
    1330947
    1331948#endif /* VBGL_VBOXGUEST */
Note: See TracChangeset for help on using the changeset viewer.

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