VirtualBox

Changeset 77243 in vbox for trunk/src/VBox/Devices/VMMDev


Ignore:
Timestamp:
Feb 10, 2019 10:44:00 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128750
Message:

HGCM,SharedFolders: Added new variation on the HGCM page list type that does not use a bounce buffer. bugref:9172

  • Added VMMDevHGCMParmType_NoBouncePageList.
  • Made VMMDevHGCMParmType_Embedded
Location:
trunk/src/VBox/Devices/VMMDev
Files:
3 edited

Legend:

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

    r77056 r77243  
    23022302                    | VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
    23032303                    | VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST
     2304                    | VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
    23042305                    | VMMDEV_HVF_FAST_IRQ_ACK;
    23052306    return VINF_SUCCESS;
     
    47364737    PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatHgcmLargeCmdAllocs,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
    47374738                           "Times the allocation cache could not be used.", "/HGCM/LargeCmdAllocs");
     4739    PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatHgcmFailedPageListLocking,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
     4740                           "Times no-bounce page list locking failed.", "/HGCM/FailedPageListLocking");
    47384741#endif
    47394742
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r77126 r77243  
    8484    uint32_t cbData;
    8585
     86/** @todo save 8 bytes here by putting offFirstPage, cPages, and f32Direction
     87 *        into a bitfields like in VBOXHGCMPARMPAGES. */
    8688    /** Offset in the first physical page of the region. */
    8789    uint32_t offFirstPage;
     
    103105} VBOXHGCMPARMPTR;
    104106
     107
     108/**
     109 * Pages w/o bounce buffering.
     110 */
     111typedef struct VBOXHGCMPARMPAGES
     112{
     113    /** The buffer size. */
     114    uint32_t        cbData;
     115    /** Start of buffer offset into the first page. */
     116    uint32_t        offFirstPage : 12;
     117    /** VBOX_HGCM_F_PARM_XXX flags. */
     118    uint32_t        fFlags : 3;
     119    /** Set if we've locked all the pages. */
     120    uint32_t        fLocked : 1;
     121    /** Number of pages. */
     122    uint32_t        cPages : 16;
     123    /**< Array of page locks followed by array of page pointers, the first page
     124     * pointer is adjusted by offFirstPage. */
     125    PPGMPAGEMAPLOCK paPgLocks;
     126} VBOXHGCMPARMPAGES;
     127
    105128/**
    106129 * Information about a guest HGCM parameter.
     
    115138        VBOXHGCMPARMVAL       val;
    116139        VBOXHGCMPARMPTR       ptr;
     140        VBOXHGCMPARMPAGES     Pages;
    117141    } u;
    118142
     
    130154    bool                fCancelled;
    131155
    132     /** Whether the command was restored from saved state. */
    133     bool                fRestored;
    134 
    135156    /** Set if allocated from the memory cache, clear if heap. */
    136157    bool                fMemCache;
     158
     159    /** Whether the command was restored from saved state. */
     160    bool                fRestored : 1;
     161    /** Whether this command has a no-bounce page list and needs to be restored
     162     *  from guest memory the old fashioned way. */
     163    bool                fRestoreFromGuestMem : 1;
    137164
    138165    /** Copy of VMMDevRequestHeader::fRequestor.
     
    331358                    || pGuestParm->enmType == VMMDevHGCMParmType_PageList
    332359                    || pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList)
     360                {
    333361                    if (pGuestParm->u.ptr.paPages != &pGuestParm->u.ptr.GCPhysSinglePage)
    334362                        RTMemFree(pGuestParm->u.ptr.paPages);
     363                }
     364                else if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     365                {
     366                    if (pGuestParm->u.Pages.paPgLocks)
     367                    {
     368                        if (pGuestParm->u.Pages.fLocked)
     369                            PDMDevHlpPhysBulkReleasePageMappingLocks(pThis->pDevInsR3, pGuestParm->u.Pages.cPages,
     370                                                                     pGuestParm->u.Pages.paPgLocks);
     371                        RTMemFree(pGuestParm->u.Pages.paPgLocks);
     372                        pGuestParm->u.Pages.paPgLocks = NULL;
     373                    }
     374                }
    335375            }
    336376        }
     
    663703            }
    664704
     705            case VMMDevHGCMParmType_PageList:
     706                RT_FALL_THRU();
    665707            case VMMDevHGCMParmType_LinAddr_In:
    666708            case VMMDevHGCMParmType_LinAddr_Out:
    667709            case VMMDevHGCMParmType_LinAddr:
    668             case VMMDevHGCMParmType_PageList:
    669710            case VMMDevHGCMParmType_Embedded:
    670711            case VMMDevHGCMParmType_ContiguousPageList:
     
    716757            }
    717758
     759            case VMMDevHGCMParmType_NoBouncePageList:
     760            {
     761                pHostParm->type = VBOX_HGCM_SVC_PARM_PAGES;
     762                pHostParm->u.Pages.cb        = pGuestParm->u.Pages.cbData;
     763                pHostParm->u.Pages.cPages    = pGuestParm->u.Pages.cPages;
     764                pHostParm->u.Pages.papvPages = (void **)&pGuestParm->u.Pages.paPgLocks[pGuestParm->u.Pages.cPages];
     765
     766                break;
     767            }
     768
    718769            default:
    719770                ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER);
     
    912963            case VMMDevHGCMParmType_PageList:
    913964            case VMMDevHGCMParmType_ContiguousPageList:
     965            case VMMDevHGCMParmType_NoBouncePageList:
    914966            {
    915967#ifdef VBOX_WITH_64_BITS_GUESTS
     
    944996                                    VERR_INVALID_PARAMETER);
    945997
    946                 /* Contiguous page lists only ever have a single page. */
    947                 ASSERT_GUEST_RETURN(   pPageListInfo->cPages == 1
    948                                     || pGuestParm->enmType == VMMDevHGCMParmType_PageList, VERR_INVALID_PARAMETER);
    949 
    950                 /* Other fields of PageListInfo. */
    951                 ASSERT_GUEST_RETURN(   (pPageListInfo->flags & ~VBOX_HGCM_F_PARM_DIRECTION_BOTH) == 0
    952                                     && pPageListInfo->offFirstPage < PAGE_SIZE,
    953                                     VERR_INVALID_PARAMETER);
     998                /* Flags. */
     999                ASSERT_GUEST_MSG_RETURN(VBOX_HGCM_F_PARM_ARE_VALID(pPageListInfo->flags),
     1000                                        ("%#x\n", pPageListInfo->flags), VERR_INVALID_FLAGS);
     1001                /* First page offset. */
     1002                ASSERT_GUEST_MSG_RETURN(pPageListInfo->offFirstPage < PAGE_SIZE,
     1003                                        ("%#x\n", pPageListInfo->offFirstPage), VERR_INVALID_PARAMETER);
     1004
     1005                /* Contiguous page lists only ever have a single page and
     1006                   no-bounce page list requires cPages to match the size exactly.
     1007                   Plain page list does not impose any restrictions on cPages currently. */
     1008                ASSERT_GUEST_MSG_RETURN(      pPageListInfo->cPages
     1009                                           == (pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList ? 1
     1010                                               : RT_ALIGN_32(pPageListInfo->offFirstPage + cbData, PAGE_SIZE) >> PAGE_SHIFT)
     1011                                        || pGuestParm->enmType == VMMDevHGCMParmType_PageList,
     1012                                        ("offFirstPage=%#x cbData=%#x cPages=%#x enmType=%d\n",
     1013                                         pPageListInfo->offFirstPage, cbData, pPageListInfo->cPages, pGuestParm->enmType),
     1014                                        VERR_INVALID_PARAMETER);
     1015
    9541016                RT_UNTRUSTED_VALIDATED_FENCE();
    9551017
    956                 /* cbData is not checked to fit into the pages, because the host code does not access
    957                  * more than the provided number of pages.
     1018                /*
     1019                 * Deal with no-bounce buffers first, as
     1020                 * VMMDevHGCMParmType_PageList is the fallback.
    9581021                 */
    959 
     1022                if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     1023                {
     1024                    /* Validate page offsets */
     1025                    ASSERT_GUEST_MSG_RETURN(   !(pPageListInfo->aPages[0] & PAGE_OFFSET_MASK)
     1026                                            || (pPageListInfo->aPages[0] & PAGE_OFFSET_MASK) == pPageListInfo->offFirstPage,
     1027                                            ("%#RX64 offFirstPage=%#x\n", pPageListInfo->aPages[0], pPageListInfo->offFirstPage),
     1028                                            VERR_INVALID_POINTER);
     1029                    uint32_t const cPages = pPageListInfo->cPages;
     1030                    for (uint32_t iPage = 1; iPage < cPages; iPage++)
     1031                        ASSERT_GUEST_MSG_RETURN(!(pPageListInfo->aPages[iPage] & PAGE_OFFSET_MASK),
     1032                                                ("[%#zx]=%#RX64\n", iPage, pPageListInfo->aPages[iPage]), VERR_INVALID_POINTER);
     1033                    RT_UNTRUSTED_VALIDATED_FENCE();
     1034
     1035                    pGuestParm->u.Pages.cbData       = cbData;
     1036                    pGuestParm->u.Pages.offFirstPage = pPageListInfo->offFirstPage;
     1037                    pGuestParm->u.Pages.fFlags       = pPageListInfo->flags;
     1038                    pGuestParm->u.Pages.cPages       = (uint16_t)cPages;
     1039                    pGuestParm->u.Pages.fLocked      = false;
     1040                    pGuestParm->u.Pages.paPgLocks    = (PPGMPAGEMAPLOCK)RTMemAllocZ(  (sizeof(PGMPAGEMAPLOCK) + sizeof(void *))
     1041                                                                                    * cPages);
     1042                    AssertReturn(pGuestParm->u.Pages.paPgLocks, VERR_NO_MEMORY);
     1043
     1044                    /* Make sure the page offsets are sensible. */
     1045                    int rc = VINF_SUCCESS;
     1046                    void **papvPages = (void **)&pGuestParm->u.Pages.paPgLocks[cPages];
     1047                    if (pPageListInfo->flags & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST)
     1048                        rc = PDMDevHlpPhysBulkGCPhys2CCPtr(pThis->pDevInsR3, cPages, pPageListInfo->aPages, 0 /*fFlags*/,
     1049                                                           papvPages, pGuestParm->u.Pages.paPgLocks);
     1050                    else
     1051                        rc = PDMDevHlpPhysBulkGCPhys2CCPtrReadOnly(pThis->pDevInsR3, cPages, pPageListInfo->aPages, 0 /*fFlags*/,
     1052                                                                   (void const **)papvPages, pGuestParm->u.Pages.paPgLocks);
     1053                    if (RT_SUCCESS(rc))
     1054                    {
     1055                        papvPages[0] = (void *)((uintptr_t)papvPages[0] | pPageListInfo->offFirstPage);
     1056                        pGuestParm->u.Pages.fLocked = true;
     1057                        break;
     1058                    }
     1059
     1060                    /* Locking failed, bail out.  In case of MMIO we fall back on regular page list handling. */
     1061                    RTMemFree(pGuestParm->u.Pages.paPgLocks);
     1062                    pGuestParm->u.Pages.paPgLocks = NULL;
     1063                    STAM_REL_COUNTER_INC(&pThis->StatHgcmFailedPageListLocking);
     1064                    ASSERT_GUEST_MSG_RETURN(rc == VERR_PGM_PHYS_PAGE_RESERVED, ("cPages=%u %Rrc\n", cPages, rc), rc);
     1065                    pGuestParm->enmType = VMMDevHGCMParmType_PageList;
     1066                }
     1067
     1068                /*
     1069                 * Regular page list or contiguous page list.
     1070                 */
    9601071                pGuestParm->u.ptr.cbData        = cbData;
    9611072                pGuestParm->u.ptr.offFirstPage  = pPageListInfo->offFirstPage;
     
    12191330     * Go over parameter descriptions saved in pCmd.
    12201331     */
    1221     uint32_t i;
    1222     for (i = 0; i < pCmd->u.call.cParms; ++i)
     1332#ifdef VBOX_WITH_64_BITS_GUESTS
     1333    HGCMFunctionParameter64 *pReqParm         = (HGCMFunctionParameter64 *)(pbReq + sizeof(VMMDevHGCMCall));
     1334    size_t const             cbHGCMParmStruct = pCmd->enmRequestType == VMMDevReq_HGCMCall64
     1335                                              ? sizeof(HGCMFunctionParameter64) : sizeof(HGCMFunctionParameter32);
     1336#else
     1337    HGCMFunctionParameter   *pReqParm         = (HGCMFunctionParameter   *)(pbReq + sizeof(VMMDevHGCMCall));
     1338    size_t const             cbHGCMParmStruct = sizeof(HGCMFunctionParameter);
     1339#endif
     1340    for (uint32_t i = 0;
     1341         i < pCmd->u.call.cParms;
     1342#ifdef VBOX_WITH_64_BITS_GUESTS
     1343         ++i, pReqParm = (HGCMFunctionParameter64 *)((uint8_t *)pReqParm + cbHGCMParmStruct)
     1344#else
     1345         ++i, pReqParm = (HGCMFunctionParameter   *)((uint8_t *)pReqParm + cbHGCMParmStruct)
     1346#endif
     1347        )
    12231348    {
    12241349        VBOXHGCMGUESTPARM * const pGuestParm = &pCmd->u.call.paGuestParms[i];
     
    12341359                const void *pvSrc = enmType == VMMDevHGCMParmType_32bit ? (void *)&pHostParm->u.uint32
    12351360                                                                        : (void *)&pHostParm->u.uint64;
     1361/** @todo optimize memcpy away here. */
    12361362                memcpy((uint8_t *)pHGCMCall + pVal->offValue, pvSrc, pVal->cbValue);
    12371363                break;
     
    12431369            case VMMDevHGCMParmType_PageList:
    12441370            {
    1245 /** @todo Update the return buffer size. */
     1371/** @todo Update the return buffer size? */
    12461372                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
    12471373                if (   pPtr->cbData > 0
     
    12591385            case VMMDevHGCMParmType_Embedded:
    12601386            {
    1261 /** @todo Update the return buffer size!  */
    12621387                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     1388
     1389                /* Update size. */
     1390#ifdef VBOX_WITH_64_BITS_GUESTS
     1391                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.Embedded.cbData, HGCMFunctionParameter32, u.Embedded.cbData);
     1392#endif
     1393                pReqParm->u.Embedded.cbData = pHostParm->u.pointer.size;
     1394
     1395                /* Copy out data. */
    12631396                if (   pPtr->cbData > 0
    12641397                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
     
    12741407            case VMMDevHGCMParmType_ContiguousPageList:
    12751408            {
    1276 /** @todo Update the return buffer size.  */
    12771409                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
     1410
     1411                /* Update size. */
     1412#ifdef VBOX_WITH_64_BITS_GUESTS
     1413                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.PageList.size, HGCMFunctionParameter32, u.PageList.size);
     1414#endif
     1415                pReqParm->u.PageList.size = pHostParm->u.pointer.size;
     1416
     1417                /* Copy out data. */
    12781418                if (   pPtr->cbData > 0
    12791419                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
     
    12861426                    if (RT_FAILURE(rc))
    12871427                        break;
     1428                }
     1429                break;
     1430            }
     1431
     1432            case VMMDevHGCMParmType_NoBouncePageList:
     1433            {
     1434                /* Update size. */
     1435#ifdef VBOX_WITH_64_BITS_GUESTS
     1436                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.PageList.size, HGCMFunctionParameter32, u.PageList.size);
     1437#endif
     1438                pReqParm->u.PageList.size = pHostParm->u.Pages.cb;
     1439
     1440                /* unlock early. */
     1441                if (pGuestParm->u.Pages.fLocked)
     1442                {
     1443                    PDMDevHlpPhysBulkReleasePageMappingLocks(pThis->pDevInsR3, pGuestParm->u.Pages.cPages,
     1444                                                             pGuestParm->u.Pages.paPgLocks);
     1445                    pGuestParm->u.Pages.fLocked = false;
    12881446                }
    12891447                break;
     
    16811839
    16821840                        uint32_t iPage;
    1683                         for (iPage = 0; iPage < pPtr->cPages; ++iPage)
     1841                        for (iPage = 0; RT_SUCCESS(rc) && iPage < pPtr->cPages; ++iPage)
    16841842                            rc = SSMR3PutGCPhys(pSSM, pPtr->paPages[iPage]);
     1843                    }
     1844                    else if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     1845                    {
     1846                        /* We don't have the page addresses here, so it will need to be
     1847                           restored from guest memory.  This isn't an issue as it is only
     1848                           use with services which won't survive a save/restore anyway. */
    16851849                    }
    16861850                    else
     
    18341998                        }
    18351999                    }
     2000                    else if (pGuestParm->enmType == VMMDevHGCMParmType_NoBouncePageList)
     2001                    {
     2002                        /* This request type can only be stored from guest memory for now. */
     2003                        pCmd->fRestoreFromGuestMem = true;
     2004                    }
    18362005                    else
    18372006                    {
     
    22612430             * Reconstruct legacy commands.
    22622431             */
    2263             if (RT_LIKELY(pThis->u32SSMVersion >= VMMDEV_SAVED_STATE_VERSION_HGCM_PARAMS))
     2432            if (RT_LIKELY(   pThis->u32SSMVersion >= VMMDEV_SAVED_STATE_VERSION_HGCM_PARAMS
     2433                          && !pCmd->fRestoreFromGuestMem))
    22642434            { /* likely */ }
    22652435            else
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r76565 r77243  
    319319    STAMPROFILE StatHgcmCmdTotal;
    320320    STAMCOUNTER StatHgcmLargeCmdAllocs;
     321    STAMCOUNTER StatHgcmFailedPageListLocking;
    321322#endif /* VBOX_WITH_HGCM */
    322323    STAMCOUNTER StatReqBufAllocs;
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