VirtualBox

Changeset 75548 in vbox


Ignore:
Timestamp:
Nov 18, 2018 4:52:14 AM (6 years ago)
Author:
vboxsync
Message:

VMMDev,VBoxGuestR0Lib: Added a new HGCM parameter type that allows embedding small buffers into the request (similar to the page list info structure). Currently only available to kernel code (i.e. shared folders). bugref:9172

Location:
trunk
Files:
3 edited

Legend:

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

    r72627 r75548  
    274274    VMMDevHGCMParmType_LinAddr_Locked_Out = 9,  /**< Locked Out (write; host->guest) */
    275275    VMMDevHGCMParmType_PageList           = 10, /**< Physical addresses of locked pages for a buffer. */
     276    VMMDevHGCMParmType_Embedded           = 11, /**< Small buffer embedded in request. */
    276277    VMMDevHGCMParmType_SizeHack           = 0x7fffffff
    277278} HGCMFunctionParameterType;
     
    304305        struct
    305306        {
    306             uint32_t size;   /**< Size of the buffer described by the page list. */
    307             uint32_t offset; /**< Relative to the request header, valid if size != 0. */
     307            uint32_t size;      /**< Size of the buffer described by the page list. */
     308            uint32_t offset;    /**< Relative to the request header of a HGCMPageListInfo structure, valid if size != 0. */
    308309        } PageList;
     310        struct
     311        {
     312            uint32_t fFlags : 8;        /**< VBOX_HGCM_F_PARM_*. */
     313            uint32_t offData : 24;      /**< Relative to the request header, valid if cb != 0. */
     314            uint32_t cbData;            /**< The buffer size. */
     315        } Embedded;
    309316    } u;
    310317#  ifdef __cplusplus
     
    380387            uint32_t offset; /**< Relative to the request header, valid if size != 0. */
    381388        } PageList;
     389        struct
     390        {
     391            uint32_t fFlags : 8;        /**< VBOX_HGCM_F_PARM_*. */
     392            uint32_t offData : 24;      /**< Relative to the request header, valid if cb != 0. */
     393            uint32_t cbData;            /**< The buffer size. */
     394        } Embedded;
    382395    } u;
    383396#  ifdef __cplusplus
     
    468481            uint32_t offset; /**< Relative to the request header, valid if size != 0. */
    469482        } PageList;
     483        struct
     484        {
     485            uint32_t fFlags : 8;        /**< VBOX_HGCM_F_PARM_*. */
     486            uint32_t offData : 24;      /**< Relative to the request header (must be a valid offset even if cbData is zero). */
     487            uint32_t cbData;            /**< The buffer size. */
     488        } Embedded;
    470489    } u;
    471490#  ifdef __cplusplus
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp

    r75126 r75548  
    5656/** The max parameter buffer size for a kernel request. */
    5757#define VBGLR0_MAX_HGCM_KERNEL_PARM     (16*_1M)
     58/** The max embedded buffer size. */
     59#define VBGLR0_MAX_HGCM_EMBEDDED_BUFFER _64K
     60
    5861#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN)
    5962/** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted
     
    258261                    Log4(("GstHGCMCall: parm=%u type=pglst: cb=0\n", iParm));
    259262                break;
     263
     264            case VMMDevHGCMParmType_Embedded:
     265                if (fIsUser) /// @todo relax this.
     266                    return VERR_INVALID_PARAMETER;
     267                cb = pSrcParm->u.Embedded.cbData;
     268                if (cb)
     269                {
     270                    uint32_t off = pSrcParm->u.Embedded.offData;
     271                    AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_EMBEDDED_BUFFER, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_EMBEDDED_BUFFER),
     272                                    VERR_INVALID_PARAMETER);
     273                    AssertMsgReturn(cb <= cbCallInfo - cParms * sizeof(HGCMFunctionParameter),
     274                                    ("cb=%#x cParms=%#x cbCallInfo=%3x\n", cb, cParms, cbCallInfo),
     275                                    VERR_INVALID_PARAMETER);
     276                    AssertMsgReturn(   off >= cParms * sizeof(HGCMFunctionParameter)
     277                                    && off <= cbCallInfo - cb,
     278                                    ("offData=%#x cParms=%#x cbCallInfo=%#x\n", off, cParms, cbCallInfo),
     279                                    VERR_INVALID_PARAMETER);
     280                    AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pSrcParm->u.Embedded.fFlags),
     281                                    ("%#x\n", pSrcParm->u.Embedded.fFlags), VERR_INVALID_PARAMETER);
     282
     283                    *pcbExtra += RT_ALIGN_32(cb, 8);
     284                }
     285                else
     286                    Log4(("GstHGCMCall: parm=%u type=embed: cb=0\n", iParm));
     287                break;
     288
    260289
    261290            case VMMDevHGCMParmType_LinAddr_Locked_In:
     
    543572                }
    544573                else
    545                     pDstParm->u.PageList.offset = 0;
    546                 break;
     574                    pDstParm->u.PageList.offset = 0; /** @todo will fail on the host side now */
     575                break;
     576
     577            case VMMDevHGCMParmType_Embedded:
     578            {
     579                uint32_t const cb = pSrcParm->u.Embedded.cbData;
     580                pDstParm->type = VMMDevHGCMParmType_Embedded;
     581                pDstParm->u.Embedded.cbData  = cb;
     582                pDstParm->u.Embedded.offData = offExtra;
     583                if (cb > 0)
     584                {
     585                    uint8_t *pbDst = (uint8_t *)pHGCMCall + offExtra;
     586                    if (pSrcParm->u.Embedded.fFlags & VBOX_HGCM_F_PARM_DIRECTION_TO_HOST)
     587                    {
     588                        memcpy(pbDst, (uint8_t const *)pCallInfo + pSrcParm->u.Embedded.offData, cb);
     589                        if (RT_ALIGN(cb, 8) != cb)
     590                            memset(pbDst + cb, 0, RT_ALIGN(cb, 8) - cb);
     591                    }
     592                    else
     593                        RT_BZERO(pbDst, RT_ALIGN(cb, 8));
     594                    offExtra += RT_ALIGN(cb, 8);
     595                }
     596                break;
     597            }
    547598
    548599            case VMMDevHGCMParmType_LinAddr_Locked_In:
     
    762813 * @returns rc, unless RTR0MemUserCopyTo fails.
    763814 * @param   pCallInfo           Call info structure to update.
     815 * @param   cbCallInfo          The size of the client request.
    764816 * @param   pHGCMCall           HGCM call request.
     817 * @param   cbHGCMCall          The size of the HGCM call request.
    765818 * @param   pParmInfo           Parameter locking/buffering info.
    766819 * @param   fIsUser             Is it a user (true) or kernel request.
     
    768821 *                              preserve informational status codes.
    769822 */
    770 static int vbglR0HGCMInternalCopyBackResult(PVBGLIOCHGCMCALL pCallInfo, VMMDevHGCMCall const *pHGCMCall,
     823static int vbglR0HGCMInternalCopyBackResult(PVBGLIOCHGCMCALL pCallInfo, uint32_t cbCallInfo,
     824                                            VMMDevHGCMCall const *pHGCMCall, uint32_t cbHGCMCall,
    771825                                            struct VbglR0ParmInfo *pParmInfo, bool fIsUser, int rc)
    772826{
     
    791845     * Copy back parameters.
    792846     */
     847    /** @todo This is assuming user data (pDstParm) is buffered.  Not true
     848     *        on OS/2, though I'm not sure we care... */
    793849    for (iParm = 0; iParm < cParms; iParm++, pSrcParm++, pDstParm++)
    794850    {
     
    803859                pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
    804860                break;
     861
     862            case VMMDevHGCMParmType_Embedded:
     863            {
     864                uint32_t cb;
     865                pDstParm->u.Embedded.cbData = cb = pSrcParm->u.Embedded.cbData;
     866                if (    cb > 0
     867                    && (pDstParm->u.Embedded.fFlags & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
     868                {
     869                    uint32_t const offDst = pDstParm->u.Embedded.offData;
     870                    uint32_t const offSrc = pDstParm->u.Embedded.offData;
     871                    AssertReturn(offDst < cbCallInfo, VERR_INTERNAL_ERROR_2);
     872                    AssertReturn(offDst >= sizeof(*pCallInfo) + cParms * sizeof(*pDstParm), VERR_INTERNAL_ERROR_2);
     873                    AssertReturn(cb <= cbCallInfo - offDst , VERR_INTERNAL_ERROR_2);
     874                    AssertReturn(offSrc < cbCallInfo, VERR_INTERNAL_ERROR_2);
     875                    AssertReturn(offSrc >= sizeof(*pHGCMCall) + cParms * sizeof(*pSrcParm), VERR_INTERNAL_ERROR_2);
     876                    AssertReturn(cb <= cbHGCMCall - offSrc, VERR_INTERNAL_ERROR_2);
     877
     878                    memcpy((uint8_t *)pCallInfo + offDst, (uint8_t const *)pHGCMCall + offSrc, cb);
     879                }
     880                break;
     881            }
    805882
    806883            case VMMDevHGCMParmType_LinAddr_Locked_In:
     
    902979         */
    903980        VMMDevHGCMCall *pHGCMCall;
    904         rc = VbglR0GRAlloc((VMMDevRequestHeader **)&pHGCMCall,
    905                            sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra,
    906                            VMMDevReq_HGCMCall);
     981        uint32_t const  cbHGCMCall = sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra;
     982        rc = VbglR0GRAlloc((VMMDevRequestHeader **)&pHGCMCall, cbHGCMCall, VMMDevReq_HGCMCall);
    907983        if (RT_SUCCESS(rc))
    908984        {
     
    919995                 * Copy back the result (parameters and buffers that changed).
    920996                 */
    921                 rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, pHGCMCall, &ParmInfo, fIsUser, rc);
     997                rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, cbCallInfo, pHGCMCall, cbHGCMCall, &ParmInfo, fIsUser, rc);
    922998            }
    923999            else
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r75538 r75548  
    621621 * @param   pThis           The VMMDev instance data.
    622622 * @param   pCmd            Command structure where host parameters needs initialization.
    623  */
    624 static int vmmdevHGCMInitHostParameters(PVMMDEV pThis, PVBOXHGCMCMD pCmd)
     623 * @param   pbReq           The request buffer.
     624 */
     625static int vmmdevHGCMInitHostParameters(PVMMDEV pThis, PVBOXHGCMCMD pCmd, uint8_t const *pbReq)
    625626{
    626627    AssertReturn(pCmd->enmCmdType == VBOXHGCMCMDTYPE_CALL, VERR_INTERNAL_ERROR);
     
    653654            case VMMDevHGCMParmType_LinAddr:
    654655            case VMMDevHGCMParmType_PageList:
     656            case VMMDevHGCMParmType_Embedded:
    655657            {
    656658                const uint32_t cbData = pGuestParm->u.ptr.cbData;
     
    668670                    if (pGuestParm->u.ptr.fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_TO_HOST)
    669671                    {
    670                         int rc = vmmdevHGCMGuestBufferRead(pThis->pDevIns, pv, cbData, &pGuestParm->u.ptr);
    671                         ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
    672                         RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     672                        if (pGuestParm->enmType != VMMDevHGCMParmType_Embedded)
     673                        {
     674                            int rc = vmmdevHGCMGuestBufferRead(pThis->pDevIns, pv, cbData, &pGuestParm->u.ptr);
     675                            ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
     676                            RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     677                        }
     678                        else
     679                        {
     680                            memcpy(pv, &pbReq[pGuestParm->u.ptr.offFirstPage], cbData);
     681                            RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     682                        }
    673683                    }
    674684                }
     
    889899                cbTotalData += cbData;
    890900
     901/** @todo respect zero byte page lists...    */
    891902                /* Check that the page list info is within the request. */
    892903                ASSERT_GUEST_RETURN(   offPageListInfo >= offExtra
     
    935946            }
    936947
     948            case VMMDevHGCMParmType_Embedded:
     949            {
     950#ifdef VBOX_WITH_64_BITS_GUESTS
     951                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.Embedded.cbData, HGCMFunctionParameter32, u.Embedded.cbData);
     952                uint32_t const cbData    = ((HGCMFunctionParameter64 *)pu8HGCMParm)->u.Embedded.cbData;
     953                uint32_t const offData   = ((HGCMFunctionParameter64 *)pu8HGCMParm)->u.Embedded.offData;
     954                uint32_t const fFlags    = ((HGCMFunctionParameter64 *)pu8HGCMParm)->u.Embedded.fFlags;
     955#else
     956                uint32_t const cbData    = ((HGCMFunctionParameter   *)pu8HGCMParm)->u.Embedded.cbData;
     957                uint32_t const offData   = ((HGCMFunctionParameter   *)pu8HGCMParm)->u.Embedded.offData;
     958                uint32_t const fFlags    = ((HGCMFunctionParameter   *)pu8HGCMParm)->u.Embedded.fFlags;
     959#endif
     960                LogFunc(("Embedded guest parameter cb %u, offset %u, flags %#x\n", cbData, offData, fFlags));
     961
     962                ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE - cbTotalData, VERR_INVALID_PARAMETER);
     963                cbTotalData += cbData;
     964
     965                /* Check flags and buffer range. */
     966                ASSERT_GUEST_MSG_RETURN(VBOX_HGCM_F_PARM_ARE_VALID(fFlags), ("%#x\n", fFlags), VERR_INVALID_FLAGS);
     967                ASSERT_GUEST_MSG_RETURN(   offData >= offExtra
     968                                        && offData <= cbHGCMCall
     969                                        && cbData  <= cbHGCMCall - offData,
     970                                        ("offData=%#x cbData=%#x cbHGCMCall=%#x offExtra=%#x\n", offData, cbData, cbHGCMCall, offExtra),
     971                                        VERR_INVALID_PARAMETER);
     972                RT_UNTRUSTED_VALIDATED_FENCE();
     973
     974                /* We use part of the ptr member. */
     975                pGuestParm->u.ptr.fu32Direction     = fFlags;
     976                pGuestParm->u.ptr.cbData            = cbData;
     977                pGuestParm->u.ptr.offFirstPage      = offData;
     978                pGuestParm->u.ptr.GCPhysSinglePage  = pCmd->GCPhys + offData;
     979                pGuestParm->u.ptr.cPages            = 1;
     980                pGuestParm->u.ptr.paPages           = &pGuestParm->u.ptr.GCPhysSinglePage;
     981                break;
     982            }
     983
    937984            default:
    938985                ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER);
     
    9951042        {
    9961043            /* Copy guest data to host parameters, so HGCM services can use the data. */
    997             rc = vmmdevHGCMInitHostParameters(pThis, pCmd);
     1044            rc = vmmdevHGCMInitHostParameters(pThis, pCmd, (uint8_t const *)pHGCMCall);
    9981045            if (RT_SUCCESS(rc))
    9991046            {
     
    10031050                vmmdevHGCMAddCommand(pThis, pCmd);
    10041051
     1052#if 1
     1053                if (    pCmd->u.call.u32Function == 9
     1054                    &&  pCmd->u.call.cParms      == 5)
     1055                {
     1056                    vmmdevHGCMRemoveCommand(pThis, pCmd);
     1057
     1058                    if (pCmd->pvReqLocked)
     1059                    {
     1060                        VMMDevHGCMRequestHeader volatile *pHeader = (VMMDevHGCMRequestHeader volatile *)pCmd->pvReqLocked;
     1061                        pHeader->header.rc = VINF_SUCCESS;
     1062                        pHeader->result    = VINF_SUCCESS;
     1063                        pHeader->fu32Flags |= VBOX_HGCM_REQ_DONE;
     1064                    }
     1065                    else
     1066                    {
     1067                        VMMDevHGCMRequestHeader *pHeader = (VMMDevHGCMRequestHeader *)pHGCMCall;
     1068                        pHeader->header.rc = VINF_SUCCESS;
     1069                        pHeader->result    = VINF_SUCCESS;
     1070                        pHeader->fu32Flags |= VBOX_HGCM_REQ_DONE;
     1071                        PDMDevHlpPhysWrite(pThis->pDevIns, GCPhys, pHeader,  sizeof(*pHeader));
     1072                    }
     1073                    vmmdevHGCMCmdFree(pThis, pCmd);
     1074                    return VINF_HGCM_ASYNC_EXECUTE; /* ignored, but avoids assertions. */
     1075                }
     1076#endif
     1077
    10051078                rc = pThis->pHGCMDrv->pfnCall(pThis->pHGCMDrv, pCmd,
    10061079                                              pCmd->u.call.u32ClientID, pCmd->u.call.u32Function,
    10071080                                              pCmd->u.call.cParms, pCmd->u.call.paHostParms, tsArrival);
    1008                 if (RT_SUCCESS(rc))
     1081
     1082                if (rc == VINF_HGCM_ASYNC_EXECUTE)
    10091083                {
    1010                     Assert(rc == VINF_HGCM_ASYNC_EXECUTE);
    1011 
    10121084                    /*
    10131085                     * Done.  Just update statistics and return.
     
    11391211                    uint32_t cbSrc = pHostParm->u.pointer.size;
    11401212                    rc = vmmdevHGCMGuestBufferWrite(pThis->pDevIns, pPtr, pvSrc, cbSrc);
     1213                }
     1214                break;
     1215            }
     1216
     1217            case VMMDevHGCMParmType_Embedded:
     1218            {
     1219                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     1220                if (   pPtr->cbData > 0
     1221                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
     1222                {
     1223                    const void *pvSrc = pHostParm->u.pointer.addr;
     1224                    uint32_t    cbSrc = pHostParm->u.pointer.size;
     1225                    if (pCmd->pvReqLocked)
     1226                        memcpy((uint8_t *)pCmd->pvReqLocked + pPtr->offFirstPage, pvSrc, cbSrc);
     1227                    else
     1228                        rc = PDMDevHlpPhysWrite(pThis->pDevIns, pGuestParm->u.ptr.GCPhysSinglePage, pvSrc, cbSrc);
    11411229                }
    11421230                break;
     
    14871575                             || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr_Out
    14881576                             || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
    1489                              || pGuestParm->enmType == VMMDevHGCMParmType_PageList)
     1577                             || pGuestParm->enmType == VMMDevHGCMParmType_PageList
     1578                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded)
    14901579                    {
    14911580                        const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     
    16191708                             || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr_Out
    16201709                             || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
    1621                              || pGuestParm->enmType == VMMDevHGCMParmType_PageList)
     1710                             || pGuestParm->enmType == VMMDevHGCMParmType_PageList
     1711                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded)
    16221712                    {
    16231713                        VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     
    16281718                        if (RT_SUCCESS(rc))
    16291719                        {
    1630                             pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
    1631                             AssertStmt(pPtr->paPages, rc = VERR_NO_MEMORY);
     1720                            if (pPtr->cPages == 1)
     1721                                pPtr->paPages = &pPtr->GCPhysSinglePage;
     1722                            else
     1723                            {
     1724                                AssertReturn(pGuestParm->enmType != VMMDevHGCMParmType_Embedded, VERR_INTERNAL_ERROR_3);
     1725                                pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
     1726                                AssertStmt(pPtr->paPages, rc = VERR_NO_MEMORY);
     1727                            }
    16321728
    16331729                            if (RT_SUCCESS(rc))
     
    20922188                    case VBOXHGCMCMDTYPE_CALL:
    20932189                    {
    2094                         rcCmd = vmmdevHGCMInitHostParameters(pThis, pCmd);
     2190                        rcCmd = vmmdevHGCMInitHostParameters(pThis, pCmd, (uint8_t const *)pReqHdr);
    20952191                        if (RT_SUCCESS(rcCmd))
    20962192                        {
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