VirtualBox

Ignore:
Timestamp:
Jul 10, 2009 2:08:15 AM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
49882
Message:

VbglR0HGCMInternal.cpp: Wrote and tested the physical page list code. Implemented bounch buffering for Linux. (both disabled)

File:
1 edited

Legend:

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

    r21459 r21464  
    2323#ifdef VBGL_VBOXGUEST
    2424
     25/*******************************************************************************
     26*   Header Files                                                               *
     27*******************************************************************************/
    2528#include "VBGLInternal.h"
     29#include <iprt/alloca.h>
     30#include <iprt/assert.h>
     31#include <iprt/mem.h>
     32#include <iprt/memobj.h>
    2633#include <iprt/string.h>
    27 #include <iprt/assert.h>
    28 #include <iprt/alloca.h>
     34
     35/*******************************************************************************
     36*   Defined Constants And Macros                                               *
     37*******************************************************************************/
     38/** The max parameter buffer size for a user request. */
     39#define VBGLR0_MAX_HGCM_USER_PARM       _1M
     40/** The max parameter buffer size for a kernel request. */
     41#define VBGLR0_MAX_HGCM_KERNEL_PARM     (16*_1M)
     42#ifdef RT_OS_LINUX
     43/** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted
     44 *  side effects. */
     45# define USE_BOUNCH_BUFFERS
     46#endif
     47
     48
    2949
    3050/* These functions can be only used by VBoxGuest. */
     
    120140}
    121141
     142#if 0 /* new code using page list and whatnot. */
     143
     144/**
     145 * Lock info structure used by VbglR0HGCMInternalCall and its helpers.
     146 */
     147struct VbglR0ParmInfo
     148{
     149    uint32_t cLockBufs;
     150    struct
     151    {
     152        uint32_t    iParm;
     153        RTR0MEMOBJ  hObj;
     154    } aLockBufs[10];
     155};
     156
     157/**
     158 * Preprocesses the HGCM call, validating and locking/buffering parameters.
     159 *
     160 * @returns VBox status code.
     161 *
     162 * @param   pCallInfo       The call info.
     163 * @param   cbCallInfo      The size of the call info structure.
     164 * @param   fIsUser         Is it a user request or kernel request.
     165 * @param   pcbExtra        Where to return the extra request space needed for
     166 *                          physical page lists.
     167 */
     168static int vbglR0HGCMInternalPreprocessCall(VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,
     169                                            bool fIsUser, struct VbglR0ParmInfo *pParmInfo,  size_t *pcbExtra)
     170{
     171    HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     172    uint32_t    cParms = pCallInfo->cParms;
     173    uint32_t    iParm;
     174
     175    /*
     176     * Lock down the any linear buffers so we can get their addresses
     177     * and figure out how much extra storage we need for page lists.
     178     */
     179    *pcbExtra = 0;
     180    pParmInfo->cLockBufs = 0;
     181    for (iParm = 0; iParm < cParms; iParm++, pSrcParm++)
     182    {
     183        switch (pSrcParm->type)
     184        {
     185            case VMMDevHGCMParmType_32bit:
     186            case VMMDevHGCMParmType_64bit:
     187                break;
     188
     189            case VMMDevHGCMParmType_PageList:
     190                if (fIsUser)
     191                    return VERR_INVALID_PARAMETER;
     192                if (pSrcParm->u.PageList.size)
     193                {
     194                    HGCMPageListInfo *pPgLst;
     195
     196                    if (pSrcParm->u.Pointer.size > VBGLR0_MAX_HGCM_KERNEL_PARM)
     197                        return VERR_OUT_OF_RANGE;
     198                    AssertReturn(   pSrcParm->u.PageList.offset >= pCallInfo->cParms * sizeof(HGCMFunctionParameter)
     199                                 && pSrcParm->u.PageList.offset < cbCallInfo - sizeof(HGCMPageListInfo), VERR_INVALID_PARAMETER);
     200                    pPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset);
     201                    AssertReturn(RT_OFFSETOF(HGCMPageListInfo, aPages[pPgLst->cPages]) + pSrcParm->u.PageList.offset <= cbCallInfo, VERR_INVALID_PARAMETER);
     202                    AssertReturn(pPgLst->offFirstPage < PAGE_SIZE, VERR_INVALID_PARAMETER);
     203                    AssertReturn(pPgLst->flags > VBOX_HGCM_F_PARM_DIRECTION_NONE && pPgLst->flags <= VBOX_HGCM_F_PARM_DIRECTION_BOTH, VERR_INVALID_PARAMETER);
     204
     205                    *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[pPgLst->cPages]);
     206                }
     207                break;
     208
     209            case VMMDevHGCMParmType_LinAddr_Locked_In:
     210            case VMMDevHGCMParmType_LinAddr_Locked_Out:
     211            case VMMDevHGCMParmType_LinAddr_Locked:
     212                if (fIsUser)
     213                    return VERR_INVALID_PARAMETER;
     214                if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
     215                {
     216                    if (pSrcParm->u.Pointer.size > VBGLR0_MAX_HGCM_KERNEL_PARM)
     217                        return VERR_OUT_OF_RANGE;
     218                    break;
     219                }
     220                /* fall thru */
     221
     222            case VMMDevHGCMParmType_LinAddr_In:
     223            case VMMDevHGCMParmType_LinAddr_Out:
     224            case VMMDevHGCMParmType_LinAddr:
     225                if (pSrcParm->u.Pointer.size > (fIsUser ? VBGLR0_MAX_HGCM_USER_PARM : VBGLR0_MAX_HGCM_KERNEL_PARM))
     226                    return VERR_OUT_OF_RANGE;
     227                if (pSrcParm->u.Pointer.size != 0)
     228                {
     229                    RTR0MEMOBJ hObj;
     230                    int rc;
     231
     232                    AssertReturn(pParmInfo->cLockBufs < RT_ELEMENTS(pParmInfo->aLockBufs), VERR_INVALID_PARAMETER);
     233                    if (!fIsUser)
     234                        rc = RTR0MemObjLockKernel(&hObj,
     235                                                  (void *)pSrcParm->u.Pointer.u.linearAddr,
     236                                                  pSrcParm->u.Pointer.size);
     237                    else
     238                    {
     239#ifdef USE_BOUNCH_BUFFERS
     240                        rc = RTR0MemObjAllocPage(&hObj,
     241                                                 pSrcParm->u.Pointer.size,
     242                                                 false /*fExecutable*/);
     243                        if (    RT_SUCCESS(rc)
     244                            &&  pSrcParm->type != VMMDevHGCMParmType_LinAddr_Out
     245                            &&  pSrcParm->type != VMMDevHGCMParmType_LinAddr_Locked_Out)
     246                        {
     247                            rc = RTR0MemUserCopyFrom(RTR0MemObjAddress(hObj),
     248                                                     pSrcParm->u.Pointer.u.linearAddr,
     249                                                     pSrcParm->u.Pointer.size + 2);
     250                            if (RT_FAILURE(rc))
     251                                RTR0MemObjFree(hObj, false /*fFreeMappings*/);
     252                        }
     253#else
     254                        rc = RTR0MemObjLockUser(&hObj,
     255                                                (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr,
     256                                                pSrcParm->u.Pointer.size,
     257                                                NIL_RTR0PROCESS);
     258#endif
     259                    }
     260                    if (RT_FAILURE(rc))
     261                        return rc;
     262
     263                    pParmInfo->aLockBufs[pParmInfo->cLockBufs].iParm = iParm;
     264                    pParmInfo->aLockBufs[pParmInfo->cLockBufs].hObj  = hObj;
     265                    pParmInfo->cLockBufs++;
     266
     267                    if (VBGLR0_CAN_USE_PHYS_PAGE_LIST())
     268                    {
     269                        size_t cPages = RTR0MemObjSize(hObj);
     270                        *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
     271                    }
     272                }
     273                break;
     274
     275            default:
     276                return VERR_INVALID_PARAMETER;
     277        }
     278    }
     279
     280    return VINF_SUCCESS;
     281}
     282
     283/**
     284 * Translates locked linear address to the normal type.
     285 * The locked types are only for the guest side and not handled by the host.
     286 *
     287 * @returns normal linear address type.
     288 * @param   enmType     The type.
     289 */
     290static HGCMFunctionParameterType vbglR0HGCMInternalConvertLinAddrType(HGCMFunctionParameterType enmType)
     291{
     292    switch (enmType)
     293    {
     294        case VMMDevHGCMParmType_LinAddr_Locked_In:
     295            return VMMDevHGCMParmType_LinAddr_In;
     296        case VMMDevHGCMParmType_LinAddr_Locked_Out:
     297            return VMMDevHGCMParmType_LinAddr_Out;
     298        case VMMDevHGCMParmType_LinAddr_Locked:
     299            return VMMDevHGCMParmType_LinAddr;
     300        default:
     301            return enmType;
     302    }
     303}
     304
     305/**
     306 * Translates linear address types to page list direction flags.
     307 *
     308 * @returns page list flags.
     309 * @param   enmType     The type.
     310 */
     311static uint32_t vbglR0HGCMInternalLinAddrTypeToPageListFlags(HGCMFunctionParameterType enmType)
     312{
     313    switch (enmType)
     314    {
     315        case VMMDevHGCMParmType_LinAddr_In:
     316        case VMMDevHGCMParmType_LinAddr_Locked_In:
     317            return VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     318
     319        case VMMDevHGCMParmType_LinAddr_Out:
     320        case VMMDevHGCMParmType_LinAddr_Locked_Out:
     321            return VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
     322
     323        default: AssertFailed();
     324        case VMMDevHGCMParmType_LinAddr:
     325        case VMMDevHGCMParmType_LinAddr_Locked:
     326            return VBOX_HGCM_F_PARM_DIRECTION_BOTH;
     327    }
     328}
     329
     330
     331/**
     332 * Initializes the call request that we're sending to the host.
     333 *
     334 * @returns VBox status code.
     335 *
     336 * @param   pCallInfo       The call info.
     337 * @param   cbCallInfo      The size of the call info structure.
     338 * @param   fIsUser         Is it a user request or kernel request.
     339 * @param   pcbExtra        Where to return the extra request space needed for
     340 *                          physical page lists.
     341 */
     342static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,
     343                                       bool fIsUser, struct VbglR0ParmInfo *pParmInfo)
     344{
     345    HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     346    HGCMFunctionParameter       *pDstParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
     347    uint32_t    cParms   = pCallInfo->cParms;
     348    uint32_t    offExtra = (uintptr_t)(pDstParm + cParms) - (uintptr_t)pHGCMCall;
     349    uint32_t    iLockBuf = 0;
     350    uint32_t    iParm;
     351
     352
     353    /*
     354     * The call request headers.
     355     */
     356    pHGCMCall->header.fu32Flags = 0;
     357    pHGCMCall->header.result    = VINF_SUCCESS;
     358
     359    pHGCMCall->u32ClientID = pCallInfo->u32ClientID;
     360    pHGCMCall->u32Function = pCallInfo->u32Function;
     361    pHGCMCall->cParms      = cParms;
     362
     363    /*
     364     * The parameters.
     365     */
     366    for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++)
     367    {
     368        switch (pSrcParm->type)
     369        {
     370            case VMMDevHGCMParmType_32bit:
     371            case VMMDevHGCMParmType_64bit:
     372                *pDstParm = *pSrcParm;
     373                break;
     374
     375            case VMMDevHGCMParmType_PageList:
     376                pDstParm->type = VMMDevHGCMParmType_PageList;
     377                pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
     378                if (pSrcParm->u.PageList.size)
     379                {
     380                    HGCMPageListInfo const *pSrcPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset);
     381                    HGCMPageListInfo       *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra);
     382                    uint32_t const          cPages    = pSrcPgLst->cPages;
     383                    uint32_t                iPage;
     384
     385                    pDstParm->u.PageList.offset = offExtra;
     386                    pDstPgLst->flags            = pSrcPgLst->flags;
     387                    pDstPgLst->offFirstPage     = pSrcPgLst->offFirstPage;
     388                    pDstPgLst->cPages           = cPages;
     389                    for (iPage = 0; iPage < cPages; iPage++)
     390                        pDstPgLst->aPages[iPage] = pSrcPgLst->aPages[iPage];
     391
     392                    offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
     393                }
     394                else
     395                    pDstParm->u.PageList.offset = 0;
     396                break;
     397
     398            case VMMDevHGCMParmType_LinAddr_Locked_In:
     399            case VMMDevHGCMParmType_LinAddr_Locked_Out:
     400            case VMMDevHGCMParmType_LinAddr_Locked:
     401                if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
     402                {
     403                    *pDstParm = *pSrcParm;
     404                    break;
     405                }
     406                /* fall thru */
     407
     408            case VMMDevHGCMParmType_LinAddr_In:
     409            case VMMDevHGCMParmType_LinAddr_Out:
     410            case VMMDevHGCMParmType_LinAddr:
     411                if (pSrcParm->u.Pointer.size != 0)
     412                {
     413                    RTR0MEMOBJ hObj = pParmInfo->aLockBufs[iLockBuf].hObj;
     414                    Assert(iParm == pParmInfo->aLockBufs[iLockBuf].iParm);
     415
     416                    if (VBGLR0_CAN_USE_PHYS_PAGE_LIST())
     417                    {
     418                        HGCMPageListInfo   *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra);
     419                        size_t const        cPages    = RTR0MemObjSize(hObj) >> PAGE_SHIFT;
     420                        size_t              iPage;
     421
     422                        pDstParm->type = VMMDevHGCMParmType_PageList;
     423                        pDstParm->u.PageList.size   = pSrcParm->u.Pointer.size;
     424                        pDstParm->u.PageList.offset = offExtra;
     425                        pDstPgLst->flags            = vbglR0HGCMInternalLinAddrTypeToPageListFlags(pSrcParm->type);
     426#ifdef USE_BOUNCH_BUFFERS
     427                        if (fIsUser)
     428                            pDstPgLst->offFirstPage = 0;
     429                        else
     430#endif
     431                            pDstPgLst->offFirstPage = pSrcParm->u.Pointer.u.linearAddr & PAGE_OFFSET_MASK;
     432                        pDstPgLst->cPages           = cPages; Assert(pDstPgLst->cPages == cPages);
     433                        for (iPage = 0; iPage < cPages; iPage++)
     434                        {
     435                            pDstPgLst->aPages[iPage] = RTR0MemObjGetPagePhysAddr(hObj, iPage);
     436                            Assert(pDstPgLst->aPages[iPage] != NIL_RTHCPHYS);
     437                        }
     438
     439                        offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]);
     440                    }
     441                    else
     442                    {
     443                        pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
     444                        pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
     445#ifdef USE_BOUNCH_BUFFERS
     446                        if (fIsUser)
     447                            pDstParm->u.Pointer.u.linearAddr = (uintptr_t)RTR0MemObjAddress(hObj);
     448                        else
     449#endif
     450                            pDstParm->u.Pointer.u.linearAddr = pSrcParm->u.Pointer.u.linearAddr;
     451                    }
     452                    iLockBuf++;
     453                }
     454                else
     455                {
     456                    pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
     457                    pDstParm->u.Pointer.size = 0;
     458                    pDstParm->u.Pointer.u.linearAddr = 0;
     459                }
     460                break;
     461
     462            default:
     463                AssertFailed();
     464                pDstParm->type = VMMDevHGCMParmType_Invalid;
     465                break;
     466        }
     467    }
     468}
     469
     470
     471/**
     472 * Performs the call and completion wait.
     473 *
     474 * @returns VBox status code of this operation, not necessarily the call.
     475 *
     476 * @param   pHGCMCall           The HGCM call info.
     477 * @param   pfnAsyncCallback    The async callback that will wait for the call
     478 *                              to complete.
     479 * @param   pvAsyncData         Argument for the callback.
     480 * @param   u32AsyncData        Argument for the callback.
     481 */
     482static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     483{
     484    int rc;
     485
     486    Log(("calling VbglGRPerform\n"));
     487    rc = VbglGRPerform(&pHGCMCall->header.header);
     488    Log(("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result));
     489
     490    /*
     491     * If the call failed, but as a result of the request itself, then pretend
     492     * success. Upper layers will interpret the result code in the packet.
     493     */
     494    if (    RT_FAILURE(rc)
     495        &&  rc == pHGCMCall->header.result)
     496    {
     497        Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
     498        rc = VINF_SUCCESS;
     499    }
     500
     501    /*
     502     * Check if host decides to process the request asynchronously,
     503     * if so, we wait for it to complete using the caller supplied callback.
     504     */
     505    if (    RT_SUCCESS(rc)
     506        &&  rc == VINF_HGCM_ASYNC_EXECUTE)
     507    {
     508        Log(("Processing HGCM call asynchronously\n"));
     509        /** @todo timeout vs. interrupted. */
     510        pfnAsyncCallback(&pHGCMCall->header, pvAsyncData, u32AsyncData);
     511
     512        /*
     513         * If the request isn't completed by the time the callback returns
     514         * we will have to try cancel it.
     515         */
     516        if (!(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE))
     517        {
     518            /** @todo use a new request for this! See @bugref{4052}. */
     519            pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     520            pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
     521            VbglGRPerform(&pHGCMCall->header.header);
     522            rc = VERR_INTERRUPTED;
     523        }
     524    }
     525    return rc;
     526}
     527
     528
     529/**
     530 * Copies the result of the call back to the caller info structure and user
     531 * buffers (if using bounce buffers).
     532 *
     533 * @returns rc, unless RTR0MemUserCopyTo fails.
     534 * @param   pCallInfo           Call info structure to update.
     535 * @param   pHGCMCall           HGCM call request.
     536 * @param   pParmInfo           Paramter locking/buffering info.
     537 * @param   fIsUser             Is it a user (true) or kernel request.
     538 * @param   rc                  The current result code. Passed along to
     539 *                              preserve informational status codes.
     540 */
     541static int vbglR0HGCMInternalCopyBackResult(VBoxGuestHGCMCallInfo *pCallInfo, VMMDevHGCMCall const *pHGCMCall,
     542                                            struct VbglR0ParmInfo *pParmInfo, bool fIsUser, int rc)
     543{
     544    HGCMFunctionParameter const *pSrcParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
     545    HGCMFunctionParameter       *pDstParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     546    uint32_t    cParms   = pCallInfo->cParms;
     547#ifdef USE_BOUNCH_BUFFERS
     548    uint32_t    iLockBuf = 0;
     549#endif
     550    uint32_t    iParm;
     551
     552    /*
     553     * The call result.
     554     */
     555    pCallInfo->result = pHGCMCall->header.result;
     556
     557    /*
     558     * Copy back parameters.
     559     */
     560    for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++)
     561    {
     562        switch (pDstParm->type)
     563        {
     564            case VMMDevHGCMParmType_32bit:
     565            case VMMDevHGCMParmType_64bit:
     566                *pDstParm = *pSrcParm;
     567                break;
     568
     569            case VMMDevHGCMParmType_PageList:
     570                pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
     571                break;
     572
     573            case VMMDevHGCMParmType_LinAddr_Locked_In:
     574            case VMMDevHGCMParmType_LinAddr_In:
     575#ifdef USE_BOUNCH_BUFFERS
     576                if (    fIsUser
     577                    &&  iLockBuf < pParmInfo->cLockBufs
     578                    &&  iParm   == pParmInfo->aLockBufs[iLockBuf].iParm)
     579                    iLockBuf++;
     580#endif
     581                pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
     582                break;
     583
     584            case VMMDevHGCMParmType_LinAddr_Locked_Out:
     585            case VMMDevHGCMParmType_LinAddr_Locked:
     586                if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
     587                {
     588                    pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
     589                    break;
     590                }
     591                /* fall thru */
     592
     593            case VMMDevHGCMParmType_LinAddr_Out:
     594            case VMMDevHGCMParmType_LinAddr:
     595            {
     596#ifdef USE_BOUNCH_BUFFERS
     597                if (fIsUser)
     598                {
     599                    if (    pSrcParm->u.Pointer.size != 0
     600                        &&  pDstParm->u.Pointer.size != 0)
     601                    {
     602                        Assert(pParmInfo->aLockBufs[iLockBuf].iParm == iParm);
     603                        int rc2 = RTR0MemUserCopyTo((RTR3PTR)pDstParm->u.Pointer.u.linearAddr,
     604                                                    RTR0MemObjAddress(pParmInfo->aLockBufs[iLockBuf].hObj),
     605                                                    RT_MIN(pSrcParm->u.Pointer.size, pDstParm->u.Pointer.size));
     606                        if (RT_FAILURE(rc2))
     607                            return rc2;
     608                        iLockBuf++;
     609                    }
     610                    else if (   iLockBuf < pParmInfo->cLockBufs
     611                             && iParm   == pParmInfo->aLockBufs[iLockBuf].iParm)
     612                        iLockBuf++;
     613                }
     614#endif
     615                pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
     616                break;
     617            }
     618
     619            default:
     620                AssertFailed();
     621                rc = VERR_INTERNAL_ERROR_4;
     622                break;
     623        }
     624    }
     625
     626#ifdef USE_BOUNCH_BUFFERS
     627    Assert(!fIsUser || pParmInfo->cLockBufs == iLockBuf);
     628#endif
     629    return rc;
     630}
     631
     632DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
     633                                       VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     634{
     635    bool                    fIsUser = (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER;
     636    struct VbglR0ParmInfo   ParmInfo;
     637    size_t                  cbExtra;
     638    int                     rc;
     639
     640    /*
     641     * Basic validation.
     642     */
     643    AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
     644                    ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
     645                    VERR_INVALID_PARAMETER);
     646    AssertReturn(   cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
     647                 || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter),
     648                 VERR_INVALID_PARAMETER);
     649
     650    Log (("VbglR0HGCMInternalCall: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d, fFlags=%#x\n",
     651          pCallInfo->cParms, pCallInfo->u32Function, fFlags));
     652
     653    /*
     654     * Preprocess the parameters, locking/buffering stuff.
     655     */
     656    rc = vbglR0HGCMInternalPreprocessCall(pCallInfo, cbCallInfo, fIsUser, &ParmInfo, &cbExtra);
     657    if (RT_SUCCESS(rc))
     658    {
     659        /*
     660         * Allocate the request buffer and recreate the call request.
     661         */
     662        VMMDevHGCMCall *pHGCMCall;
     663        rc = VbglGRAlloc((VMMDevRequestHeader **)&pHGCMCall,
     664                         sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra,
     665                         VMMDevReq_HGCMCall);
     666        if (RT_SUCCESS(rc))
     667        {
     668            vbglR0HGCMInternalInitCall(pHGCMCall, pCallInfo, cbCallInfo, fIsUser, &ParmInfo);
     669
     670            /*
     671             * Perform the call.
     672             */
     673            rc = vbglR0HGCMInternalDoCall(pHGCMCall, pfnAsyncCallback, pvAsyncData, u32AsyncData);
     674            if (RT_SUCCESS(rc))
     675            {
     676                /*
     677                 * Copy back the result (parameters and buffers that changed).
     678                 */
     679                rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, pHGCMCall, &ParmInfo, fIsUser, rc);
     680            }
     681
     682            VbglGRFree(&pHGCMCall->header.header);
     683        }
     684    }
     685
     686    /*
     687     * Copy back buffered data and release buffers & locks.
     688     */
     689    if (ParmInfo.cLockBufs)
     690        while (ParmInfo.cLockBufs-- > 0)
     691            RTR0MemObjFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].hObj, false /*fFreeMappings*/);
     692
     693    return rc;
     694}
     695
     696
     697#  if ARCH_BITS == 64
     698DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
     699                                         VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     700{
     701    VBoxGuestHGCMCallInfo   *pCallInfo64;
     702    HGCMFunctionParameter   *pParm64;
     703    HGCMFunctionParameter32 *pParm32;
     704    uint32_t                 cParms;
     705    uint32_t                 iParm;
     706    int rc;
     707
     708    /*
     709     * Input validation.
     710     */
     711    AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
     712                    ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
     713                    VERR_INVALID_PARAMETER);
     714    AssertReturn(   cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
     715                 || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter32),
     716                 VERR_INVALID_PARAMETER);
     717    AssertReturn((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_KERNEL, VERR_INVALID_PARAMETER);
     718
     719    cParms = pCallInfo->cParms;
     720    Log(("VbglR0HGCMInternalCall32: cParms=%d, u32Function=%d, fFlags=%#x\n", cParms, pCallInfo->u32Function, fFlags));
     721
     722    /*
     723     * The simple approach, allocate a temporary request and convert the parameters.
     724     */
     725    pCallInfo64 = (VBoxGuestHGCMCallInfo *)RTMemTmpAllocZ(sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter));
     726    if (!pCallInfo64)
     727        return VERR_NO_TMP_MEMORY;
     728
     729    *pCallInfo64 = *pCallInfo;
     730    pParm32 = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo);
     731    pParm64 = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo64);
     732    for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++)
     733    {
     734        switch (pParm32->type)
     735        {
     736            case VMMDevHGCMParmType_32bit:
     737                pParm64->type      = VMMDevHGCMParmType_32bit;
     738                pParm64->u.value32 = pParm32->u.value32;
     739                break;
     740
     741            case VMMDevHGCMParmType_64bit:
     742                pParm64->type      = VMMDevHGCMParmType_64bit;
     743                pParm64->u.value64 = pParm32->u.value64;
     744                break;
     745
     746            case VMMDevHGCMParmType_LinAddr_Out:
     747            case VMMDevHGCMParmType_LinAddr:
     748            case VMMDevHGCMParmType_LinAddr_In:
     749                pParm64->type                   = pParm32->type;
     750                pParm64->u.Pointer.size         = pParm32->u.Pointer.size;
     751                pParm64->u.Pointer.u.linearAddr = pParm32->u.Pointer.u.linearAddr;
     752                break;
     753
     754            default:
     755                rc = VERR_INVALID_PARAMETER;
     756                break;
     757        }
     758        if (RT_FAILURE(rc))
     759            break;
     760    }
     761    if (RT_SUCCESS(rc))
     762    {
     763        rc = VbglR0HGCMInternalCall(pCallInfo64, sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter), fFlags,
     764                                    pfnAsyncCallback, pvAsyncData, u32AsyncData);
     765
     766        /*
     767         * Copy back.
     768         */
     769        for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++)
     770        {
     771            switch (pParm32->type)
     772            {
     773                case VMMDevHGCMParmType_32bit:
     774                    pParm32->u.value32 = pParm32->u.value32;
     775                    break;
     776
     777                case VMMDevHGCMParmType_64bit:
     778                    pParm32->u.value64 = pParm64->u.value64;
     779                    break;
     780
     781                case VMMDevHGCMParmType_LinAddr_Out:
     782                case VMMDevHGCMParmType_LinAddr:
     783                case VMMDevHGCMParmType_LinAddr_In:
     784                    pParm32->u.Pointer.size = pParm64->u.Pointer.size;
     785                    break;
     786
     787                default:
     788                    rc = VERR_INTERNAL_ERROR_3;
     789                    break;
     790            }
     791        }
     792        *pCallInfo = *pCallInfo64;
     793    }
     794
     795    RTMemTmpFree(pCallInfo64);
     796    return rc;
     797}
     798#  endif /* ARCH_BITS == 64 */
     799
     800# else /* old code: */
    122801
    123802/** @todo merge with the one below (use a header file). Too lazy now. */
     
    319998    return rc;
    320999}
    321 # if ARCH_BITS == 64
     1000
     1001#  if ARCH_BITS == 64
    3221002/** @todo merge with the one above (use a header file). Too lazy now. */
    3231003DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
     
    5171197    return rc;
    5181198}
    519 # endif /* ARCH_BITS == 64 */
     1199#  endif /* ARCH_BITS == 64 */
     1200
     1201# endif /* old code */
    5201202
    5211203#endif /* VBGL_VBOXGUEST */
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