Changeset 77243 in vbox for trunk/src/VBox/Devices/VMMDev
- Timestamp:
- Feb 10, 2019 10:44:00 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 128750
- Location:
- trunk/src/VBox/Devices/VMMDev
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VMMDev/VMMDev.cpp
r77056 r77243 2302 2302 | VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS 2303 2303 | VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST 2304 | VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST 2304 2305 | VMMDEV_HVF_FAST_IRQ_ACK; 2305 2306 return VINF_SUCCESS; … … 4736 4737 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatHgcmLargeCmdAllocs,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 4737 4738 "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"); 4738 4741 #endif 4739 4742 -
trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
r77126 r77243 84 84 uint32_t cbData; 85 85 86 /** @todo save 8 bytes here by putting offFirstPage, cPages, and f32Direction 87 * into a bitfields like in VBOXHGCMPARMPAGES. */ 86 88 /** Offset in the first physical page of the region. */ 87 89 uint32_t offFirstPage; … … 103 105 } VBOXHGCMPARMPTR; 104 106 107 108 /** 109 * Pages w/o bounce buffering. 110 */ 111 typedef 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 105 128 /** 106 129 * Information about a guest HGCM parameter. … … 115 138 VBOXHGCMPARMVAL val; 116 139 VBOXHGCMPARMPTR ptr; 140 VBOXHGCMPARMPAGES Pages; 117 141 } u; 118 142 … … 130 154 bool fCancelled; 131 155 132 /** Whether the command was restored from saved state. */133 bool fRestored;134 135 156 /** Set if allocated from the memory cache, clear if heap. */ 136 157 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; 137 164 138 165 /** Copy of VMMDevRequestHeader::fRequestor. … … 331 358 || pGuestParm->enmType == VMMDevHGCMParmType_PageList 332 359 || pGuestParm->enmType == VMMDevHGCMParmType_ContiguousPageList) 360 { 333 361 if (pGuestParm->u.ptr.paPages != &pGuestParm->u.ptr.GCPhysSinglePage) 334 362 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 } 335 375 } 336 376 } … … 663 703 } 664 704 705 case VMMDevHGCMParmType_PageList: 706 RT_FALL_THRU(); 665 707 case VMMDevHGCMParmType_LinAddr_In: 666 708 case VMMDevHGCMParmType_LinAddr_Out: 667 709 case VMMDevHGCMParmType_LinAddr: 668 case VMMDevHGCMParmType_PageList:669 710 case VMMDevHGCMParmType_Embedded: 670 711 case VMMDevHGCMParmType_ContiguousPageList: … … 716 757 } 717 758 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 718 769 default: 719 770 ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER); … … 912 963 case VMMDevHGCMParmType_PageList: 913 964 case VMMDevHGCMParmType_ContiguousPageList: 965 case VMMDevHGCMParmType_NoBouncePageList: 914 966 { 915 967 #ifdef VBOX_WITH_64_BITS_GUESTS … … 944 996 VERR_INVALID_PARAMETER); 945 997 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 954 1016 RT_UNTRUSTED_VALIDATED_FENCE(); 955 1017 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. 958 1021 */ 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 */ 960 1071 pGuestParm->u.ptr.cbData = cbData; 961 1072 pGuestParm->u.ptr.offFirstPage = pPageListInfo->offFirstPage; … … 1219 1330 * Go over parameter descriptions saved in pCmd. 1220 1331 */ 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 ) 1223 1348 { 1224 1349 VBOXHGCMGUESTPARM * const pGuestParm = &pCmd->u.call.paGuestParms[i]; … … 1234 1359 const void *pvSrc = enmType == VMMDevHGCMParmType_32bit ? (void *)&pHostParm->u.uint32 1235 1360 : (void *)&pHostParm->u.uint64; 1361 /** @todo optimize memcpy away here. */ 1236 1362 memcpy((uint8_t *)pHGCMCall + pVal->offValue, pvSrc, pVal->cbValue); 1237 1363 break; … … 1243 1369 case VMMDevHGCMParmType_PageList: 1244 1370 { 1245 /** @todo Update the return buffer size .*/1371 /** @todo Update the return buffer size? */ 1246 1372 const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr; 1247 1373 if ( pPtr->cbData > 0 … … 1259 1385 case VMMDevHGCMParmType_Embedded: 1260 1386 { 1261 /** @todo Update the return buffer size! */1262 1387 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. */ 1263 1396 if ( pPtr->cbData > 0 1264 1397 && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST)) … … 1274 1407 case VMMDevHGCMParmType_ContiguousPageList: 1275 1408 { 1276 /** @todo Update the return buffer size. */1277 1409 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. */ 1278 1418 if ( pPtr->cbData > 0 1279 1419 && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST)) … … 1286 1426 if (RT_FAILURE(rc)) 1287 1427 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; 1288 1446 } 1289 1447 break; … … 1681 1839 1682 1840 uint32_t iPage; 1683 for (iPage = 0; iPage < pPtr->cPages; ++iPage)1841 for (iPage = 0; RT_SUCCESS(rc) && iPage < pPtr->cPages; ++iPage) 1684 1842 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. */ 1685 1849 } 1686 1850 else … … 1834 1998 } 1835 1999 } 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 } 1836 2005 else 1837 2006 { … … 2261 2430 * Reconstruct legacy commands. 2262 2431 */ 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)) 2264 2434 { /* likely */ } 2265 2435 else -
trunk/src/VBox/Devices/VMMDev/VMMDevState.h
r76565 r77243 319 319 STAMPROFILE StatHgcmCmdTotal; 320 320 STAMCOUNTER StatHgcmLargeCmdAllocs; 321 STAMCOUNTER StatHgcmFailedPageListLocking; 321 322 #endif /* VBOX_WITH_HGCM */ 322 323 STAMCOUNTER StatReqBufAllocs;
Note:
See TracChangeset
for help on using the changeset viewer.