Changeset 77243 in vbox for trunk/src/VBox
- Timestamp:
- Feb 10, 2019 10:44:00 PM (6 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 7 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; -
trunk/src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp
r76971 r77243 643 643 } 644 644 645 /* *Read object content. */645 /* Read object content. */ 646 646 case SHFL_FN_READ: 647 { 647 648 pStat = &g_StatRead; 648 649 pStatFail = &g_StatReadFail; … … 650 651 651 652 /* Verify parameter count and types. */ 652 if (cParms != SHFL_CPARMS_READ) 653 { 654 rc = VERR_INVALID_PARAMETER; 655 } 656 else 657 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ 658 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ 659 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */ 660 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */ 661 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ 662 ) 663 { 664 rc = VERR_INVALID_PARAMETER; 665 } 666 else 667 { 668 /* Fetch parameters. */ 669 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; 670 SHFLHANDLE Handle = paParms[1].u.uint64; 671 uint64_t offset = paParms[2].u.uint64; 672 uint32_t count = paParms[3].u.uint32; 673 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr; 674 675 /* Verify parameters values. */ 676 if ( Handle == SHFL_HANDLE_ROOT 677 || count > paParms[4].u.pointer.size 678 ) 679 { 680 rc = VERR_INVALID_PARAMETER; 681 } 682 else 683 if (Handle == SHFL_HANDLE_NIL) 684 { 685 AssertMsgFailed(("Invalid handle!\n")); 686 rc = VERR_INVALID_HANDLE; 687 } 688 else 689 { 690 /* Execute the function. */ 691 if (g_pStatusLed) 692 { 693 Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); 694 g_pStatusLed->Asserted.s.fReading = g_pStatusLed->Actual.s.fReading = 1; 695 } 696 697 rc = vbsfRead (pClient, root, Handle, offset, &count, pBuffer); 698 if (g_pStatusLed) 699 g_pStatusLed->Actual.s.fReading = 0; 700 701 if (RT_SUCCESS(rc)) 702 { 703 /* Update parameters.*/ 704 paParms[3].u.uint32 = count; 705 } 706 else 707 { 708 paParms[3].u.uint32 = 0; /* nothing read */ 709 } 710 } 711 } 712 break; 713 714 /** Write new object content. */ 653 ASSERT_GUEST_STMT_BREAK(cParms == SHFL_CPARMS_READ, rc = VERR_WRONG_PARAMETER_COUNT); 654 ASSERT_GUEST_STMT_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* root */ 655 ASSERT_GUEST_STMT_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* handle */ 656 ASSERT_GUEST_STMT_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* offset */ 657 ASSERT_GUEST_STMT_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* count */ 658 ASSERT_GUEST_STMT_BREAK( paParms[4].type == VBOX_HGCM_SVC_PARM_PTR 659 || paParms[4].type == VBOX_HGCM_SVC_PARM_PAGES, rc = VERR_WRONG_PARAMETER_TYPE); /* buffer */ 660 661 /* Fetch parameters. */ 662 SHFLROOT const idRoot = (SHFLROOT)paParms[0].u.uint32; 663 SHFLHANDLE const hFile = paParms[1].u.uint64; 664 uint64_t const offFile = paParms[2].u.uint64; 665 uint32_t cbRead = paParms[3].u.uint32; 666 667 /* Verify parameters values. */ 668 ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_ROOT, rc == VERR_INVALID_PARAMETER); 669 ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_NIL, rc == VERR_INVALID_HANDLE); 670 if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR) 671 ASSERT_GUEST_STMT_BREAK(cbRead <= paParms[4].u.pointer.size, rc == VERR_INVALID_HANDLE); 672 else 673 ASSERT_GUEST_STMT_BREAK(cbRead <= paParms[4].u.Pages.cb, rc == VERR_OUT_OF_RANGE); 674 675 /* Execute the function. */ 676 if (g_pStatusLed) 677 { 678 Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); 679 g_pStatusLed->Asserted.s.fReading = g_pStatusLed->Actual.s.fReading = 1; 680 } 681 682 if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR) 683 rc = vbsfRead(pClient, idRoot, hFile, offFile, &cbRead, (uint8_t *)paParms[4].u.pointer.addr); 684 else 685 rc = vbsfReadPages(pClient, idRoot, hFile, offFile, &cbRead, &paParms[4].u.Pages); 686 687 if (g_pStatusLed) 688 g_pStatusLed->Actual.s.fReading = 0; 689 690 /* Update parameters.*/ 691 paParms[3].u.uint32 = RT_SUCCESS(rc) ? cbRead : 0 /* nothing read */; 692 break; 693 } 694 695 /* Write new object content. */ 715 696 case SHFL_FN_WRITE: 697 { 716 698 pStat = &g_StatWrite; 717 699 pStatFail = &g_StatWriteFail; … … 719 701 720 702 /* Verify parameter count and types. */ 721 if (cParms != SHFL_CPARMS_WRITE) 722 { 723 rc = VERR_INVALID_PARAMETER; 724 } 725 else 726 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ 727 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ 728 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */ 729 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */ 730 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ 731 ) 732 { 733 rc = VERR_INVALID_PARAMETER; 734 } 735 else 736 { 737 /* Fetch parameters. */ 738 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; 739 SHFLHANDLE Handle = paParms[1].u.uint64; 740 uint64_t offset = paParms[2].u.uint64; 741 uint32_t count = paParms[3].u.uint32; 742 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr; 743 744 /* Verify parameters values. */ 745 if ( Handle == SHFL_HANDLE_ROOT 746 || count > paParms[4].u.pointer.size 747 ) 748 { 749 rc = VERR_INVALID_PARAMETER; 750 } 751 else 752 if (Handle == SHFL_HANDLE_NIL) 753 { 754 AssertMsgFailed(("Invalid handle!\n")); 755 rc = VERR_INVALID_HANDLE; 756 } 757 else 758 { 759 /* Execute the function. */ 760 if (g_pStatusLed) 761 { 762 Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); 763 g_pStatusLed->Asserted.s.fWriting = g_pStatusLed->Actual.s.fWriting = 1; 764 } 765 766 rc = vbsfWrite (pClient, root, Handle, offset, &count, pBuffer); 767 if (g_pStatusLed) 768 g_pStatusLed->Actual.s.fWriting = 0; 769 770 if (RT_SUCCESS(rc)) 771 { 772 /* Update parameters.*/ 773 paParms[3].u.uint32 = count; 774 } 775 else 776 { 777 paParms[3].u.uint32 = 0; /* nothing read */ 778 } 779 } 780 } 781 break; 782 783 /** Lock/unlock a range in the object. */ 703 ASSERT_GUEST_STMT_BREAK(cParms == SHFL_CPARMS_WRITE, rc = VERR_WRONG_PARAMETER_COUNT); 704 ASSERT_GUEST_STMT_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* root */ 705 ASSERT_GUEST_STMT_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* handle */ 706 ASSERT_GUEST_STMT_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* offset */ 707 ASSERT_GUEST_STMT_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* count */ 708 ASSERT_GUEST_STMT_BREAK( paParms[4].type == VBOX_HGCM_SVC_PARM_PTR 709 || paParms[4].type == VBOX_HGCM_SVC_PARM_PAGES, rc = VERR_WRONG_PARAMETER_TYPE); /* buffer */ 710 /* Fetch parameters. */ 711 SHFLROOT const idRoot = (SHFLROOT)paParms[0].u.uint32; 712 SHFLHANDLE const hFile = paParms[1].u.uint64; 713 uint64_t offFile = paParms[2].u.uint64; 714 uint32_t cbWrite = paParms[3].u.uint32; 715 716 /* Verify parameters values. */ 717 ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_ROOT, rc == VERR_INVALID_PARAMETER); 718 ASSERT_GUEST_STMT_BREAK(hFile != SHFL_HANDLE_NIL, rc == VERR_INVALID_HANDLE); 719 if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR) 720 ASSERT_GUEST_STMT_BREAK(cbWrite <= paParms[4].u.pointer.size, rc == VERR_INVALID_HANDLE); 721 else 722 ASSERT_GUEST_STMT_BREAK(cbWrite <= paParms[4].u.Pages.cb, rc == VERR_OUT_OF_RANGE); 723 724 /* Execute the function. */ 725 if (g_pStatusLed) 726 { 727 Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); 728 g_pStatusLed->Asserted.s.fWriting = g_pStatusLed->Actual.s.fWriting = 1; 729 } 730 731 if (paParms[4].type == VBOX_HGCM_SVC_PARM_PTR) 732 rc = vbsfWrite(pClient, idRoot, hFile, &offFile, &cbWrite, (uint8_t *)paParms[4].u.pointer.addr); 733 else 734 rc = vbsfWritePages(pClient, idRoot, hFile, &offFile, &cbWrite, &paParms[4].u.Pages); 735 736 if (g_pStatusLed) 737 g_pStatusLed->Actual.s.fWriting = 0; 738 739 /* Update parameters.*/ 740 if (RT_SUCCESS(rc)) 741 { 742 paParms[3].u.uint32 = cbWrite; 743 paParms[4].u.uint64 = offFile; 744 } 745 else 746 paParms[3].u.uint32 = 0; 747 break; 748 } 749 750 /* Lock/unlock a range in the object. */ 784 751 case SHFL_FN_LOCK: 785 752 pStat = &g_StatLock; … … 869 836 break; 870 837 871 /* *List object content. */838 /* List object content. */ 872 839 case SHFL_FN_LIST: 873 840 { … … 1152 1119 } 1153 1120 1154 /* *Query/set object information. */1121 /* Query/set object information. */ 1155 1122 case SHFL_FN_INFORMATION: 1156 1123 { … … 1235 1202 } 1236 1203 1237 /* *Remove or rename object */1204 /* Remove or rename object */ 1238 1205 case SHFL_FN_REMOVE: 1239 1206 { -
trunk/src/VBox/HostServices/SharedFolders/shflhandle.h
r76570 r77243 52 52 { 53 53 RTFILE Handle; 54 uint64_t fOpenFlags; /**< RTFILE_O_XXX. */ 54 55 } file; 55 56 struct … … 57 58 RTDIR Handle; 58 59 RTDIR SearchHandle; 59 PRTDIRENTRYEX pLastValidEntry; /*last found file in a directory search */60 PRTDIRENTRYEX pLastValidEntry; /**< last found file in a directory search */ 60 61 } dir; 61 62 }; -
trunk/src/VBox/HostServices/SharedFolders/vbsf.cpp
r76553 r77243 31 31 32 32 #include <VBox/AssertGuest.h> 33 #include <VBox/param.h> 33 34 #include <iprt/alloc.h> 34 35 #include <iprt/assert.h> … … 479 480 { 480 481 pHandle->root = root; 482 pHandle->file.fOpenFlags = fOpen; 481 483 rc = RTFileOpen(&pHandle->file.Handle, pszPath, fOpen); 482 484 } … … 1017 1019 } 1018 1020 1021 /** 1022 * Helper for vbsfReadPages and vbsfWritePages that creates a S/G buffer from a 1023 * pages parameter. 1024 */ 1025 static int vbsfPagesToSgBuf(VBOXHGCMSVCPARMPAGES const *pPages, uint32_t cbLeft, PRTSGBUF pSgBuf) 1026 { 1027 PRTSGSEG paSegs = (PRTSGSEG)RTMemTmpAlloc(sizeof(paSegs[0]) * pPages->cPages); 1028 if (paSegs) 1029 { 1030 /* 1031 * Convert the pages to segments. 1032 */ 1033 uint32_t iSeg = 0; 1034 uint32_t iPage = 0; 1035 for (;;) 1036 { 1037 Assert(iSeg < pPages->cPages); 1038 Assert(iPage < pPages->cPages); 1039 1040 /* Current page. */ 1041 void *pvSeg; 1042 paSegs[iSeg].pvSeg = pvSeg = pPages->papvPages[iPage]; 1043 size_t cbSeg = PAGE_SIZE - ((uintptr_t)pvSeg & PAGE_OFFSET_MASK); 1044 iPage++; 1045 1046 /* Adjacent to the next page? */ 1047 while ( iPage < pPages->cPages 1048 && (uintptr_t)pvSeg + cbSeg == (uintptr_t)pPages->papvPages[iPage]) 1049 { 1050 iPage++; 1051 cbSeg += PAGE_SIZE; 1052 } 1053 1054 /* Adjust for max size. */ 1055 if (cbLeft <= cbSeg) 1056 { 1057 paSegs[iSeg++].cbSeg = cbLeft; 1058 break; 1059 } 1060 paSegs[iSeg++].cbSeg = cbSeg; 1061 cbLeft -= cbSeg; 1062 } 1063 1064 /* 1065 * Initialize the s/g buffer and execute the read. 1066 */ 1067 RTSgBufInit(pSgBuf, paSegs, iSeg); 1068 return VINF_SUCCESS; 1069 } 1070 pSgBuf->paSegs = NULL; 1071 return VERR_NO_TMP_MEMORY; 1072 } 1073 1074 1019 1075 #ifdef UNITTEST 1020 1076 /** Unit test the SHFL_FN_READ API. Located here as a form of API … … 1045 1101 if (RT_LIKELY(*pcbBuffer != 0)) 1046 1102 { 1103 /** @todo use RTFileReadAt! */ 1047 1104 rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL); 1048 1105 if (RT_SUCCESS(rc)) … … 1063 1120 LogFunc(("%Rrc bytes read 0x%RX32\n", rc, *pcbBuffer)); 1064 1121 return rc; 1122 } 1123 1124 /** 1125 * SHFL_FN_READ w/o bounce buffering. 1126 */ 1127 int vbsfReadPages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t offFile, 1128 uint32_t *pcbRead, PVBOXHGCMSVCPARMPAGES pPages) 1129 { 1130 LogFunc(("pClient %p, idRoot %#RX32, hFile %#RX64, offFile %#RX64, cbRead %#RX32, cPages %#x\n", 1131 pClient, idRoot, hFile, offFile, *pcbRead, pPages->cPages)); 1132 1133 AssertPtrReturn(pClient, VERR_INVALID_PARAMETER); 1134 1135 size_t cbTotal = 0; 1136 SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, hFile); 1137 int rc = vbsfCheckHandleAccess(pClient, idRoot, pHandle, VBSF_CHECK_ACCESS_READ); 1138 if (RT_SUCCESS(rc)) 1139 { 1140 uint32_t const cbToRead = *pcbRead; 1141 if (cbToRead > 0) 1142 { 1143 ASSERT_GUEST_RETURN(pPages->cPages > 0, VERR_INTERNAL_ERROR_3); 1144 1145 /* 1146 * Convert to a scatter-gather buffer. 1147 * 1148 * We need not do any platform specific code here as the RTSGBUF 1149 * segment array maps directly onto the posix iovec structure. 1150 * Windows does currently benefit much from this conversion, but 1151 * so be it. 1152 */ 1153 RTSGBUF SgBuf; 1154 rc = vbsfPagesToSgBuf(pPages, cbToRead, &SgBuf); 1155 if (RT_SUCCESS(rc)) 1156 { 1157 rc = RTFileSgReadAt(pHandle->file.Handle, offFile, &SgBuf, cbToRead, &cbTotal); 1158 while (rc == VERR_INTERRUPTED) 1159 { 1160 RTSgBufReset(&SgBuf); 1161 rc = RTFileSgReadAt(pHandle->file.Handle, offFile, &SgBuf, cbToRead, &cbTotal); 1162 } 1163 1164 RTMemTmpFree((void *)SgBuf.paSegs); 1165 } 1166 else 1167 rc = VERR_NO_TMP_MEMORY; 1168 1169 *pcbRead = (uint32_t)cbTotal; 1170 } 1171 else 1172 { 1173 /* Reading zero bytes always succeeds. */ 1174 rc = VINF_SUCCESS; 1175 } 1176 } 1177 else 1178 *pcbRead = 0; 1179 1180 LogFunc(("%Rrc bytes read %#zx\n", rc, cbTotal)); 1181 return rc; 1182 } 1183 1184 /** 1185 * Helps with writes to RTFILE_O_APPEND files. 1186 */ 1187 static uint64_t vbsfWriteCalcPostAppendFilePosition(RTFILE hFile, uint64_t offGuessed) 1188 { 1189 RTFSOBJINFO ObjInfo; 1190 int rc2 = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING); 1191 if (RT_SUCCESS(rc2) && (uint64_t)ObjInfo.cbObject >= offGuessed) 1192 return ObjInfo.cbObject; 1193 return offGuessed; 1065 1194 } 1066 1195 … … 1077 1206 } 1078 1207 #endif 1079 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer) 1080 { 1081 LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64, offset 0x%RX64, bytes 0x%RX32\n", 1082 pClient, root, Handle, offset, pcbBuffer? *pcbBuffer: 0)); 1208 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t *poffFile, 1209 uint32_t *pcbBuffer, uint8_t *pBuffer) 1210 { 1211 uint64_t offFile = *poffFile; 1212 LogFunc(("pClient %p, root 0x%RX32, Handle 0x%RX64, offFile 0x%RX64, bytes 0x%RX32\n", 1213 pClient, idRoot, hFile, offFile, *pcbBuffer)); 1083 1214 1084 1215 AssertPtrReturn(pClient, VERR_INVALID_PARAMETER); 1085 1216 1086 SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, Handle);1087 int rc = vbsfCheckHandleAccess(pClient, root, pHandle, VBSF_CHECK_ACCESS_WRITE);1217 SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, hFile); 1218 int rc = vbsfCheckHandleAccess(pClient, idRoot, pHandle, VBSF_CHECK_ACCESS_WRITE); 1088 1219 if (RT_SUCCESS(rc)) 1089 { /* likely */ } 1220 { 1221 size_t const cbToWrite = *pcbBuffer; 1222 if (RT_LIKELY(cbToWrite != 0)) 1223 { 1224 /** @todo use RTFileWriteAt unless RTFILE_O_APPEND is in effect. */ 1225 rc = RTFileSeek(pHandle->file.Handle, offFile, RTFILE_SEEK_BEGIN, NULL); 1226 if (RT_SUCCESS(rc)) 1227 { 1228 size_t cbWritten = 0; 1229 rc = RTFileWrite(pHandle->file.Handle, pBuffer, cbToWrite, &cbWritten); 1230 *pcbBuffer = (uint32_t)cbWritten; 1231 1232 /* Update the file offset (mainly for RTFILE_O_APPEND), */ 1233 if (RT_SUCCESS(rc)) 1234 { 1235 offFile += cbWritten; 1236 if (!(pHandle->file.fOpenFlags & RTFILE_O_APPEND)) 1237 *poffFile = offFile; 1238 else 1239 *poffFile = vbsfWriteCalcPostAppendFilePosition(pHandle->file.Handle, offFile); 1240 } 1241 } 1242 else 1243 AssertRC(rc); 1244 } 1245 else 1246 { 1247 /** @todo What writing zero bytes should do? */ 1248 rc = VINF_SUCCESS; 1249 } 1250 } 1090 1251 else 1091 return rc; 1092 1093 if (RT_LIKELY(*pcbBuffer != 0)) 1094 { 1095 rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL); 1096 if (RT_SUCCESS(rc)) 1097 { 1098 size_t count = 0; 1099 rc = RTFileWrite(pHandle->file.Handle, pBuffer, *pcbBuffer, &count); 1100 *pcbBuffer = (uint32_t)count; 1252 *pcbBuffer = 0; 1253 LogFunc(("%Rrc bytes written 0x%RX32\n", rc, *pcbBuffer)); 1254 return rc; 1255 } 1256 1257 /** 1258 * SHFL_FN_WRITE w/o bounce buffering. 1259 */ 1260 int vbsfWritePages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t *poffFile, 1261 uint32_t *pcbWrite, PVBOXHGCMSVCPARMPAGES pPages) 1262 { 1263 uint64_t offFile = *poffFile; 1264 LogFunc(("pClient %p, idRoot %#RX32, hFile %#RX64, offFile %#RX64, cbWrite %#RX32, cPages %#x\n", 1265 pClient, idRoot, hFile, offFile, *pcbWrite, pPages->cPages)); 1266 1267 AssertPtrReturn(pClient, VERR_INVALID_PARAMETER); 1268 1269 size_t cbTotal = 0; 1270 SHFLFILEHANDLE *pHandle = vbsfQueryFileHandle(pClient, hFile); 1271 int rc = vbsfCheckHandleAccess(pClient, idRoot, pHandle, VBSF_CHECK_ACCESS_WRITE); 1272 if (RT_SUCCESS(rc)) 1273 { 1274 uint32_t const cbToWrite = *pcbWrite; 1275 if (cbToWrite > 0) 1276 { 1277 ASSERT_GUEST_RETURN(pPages->cPages > 0, VERR_INTERNAL_ERROR_3); 1278 1279 /* 1280 * Convert to a scatter-gather buffer. 1281 * 1282 * We need not do any platform specific code here as the RTSGBUF 1283 * segment array maps directly onto the posix iovec structure. 1284 * Windows does currently benefit much from this conversion, but 1285 * so be it. 1286 */ 1287 RTSGBUF SgBuf; 1288 rc = vbsfPagesToSgBuf(pPages, cbToWrite, &SgBuf); 1289 if (RT_SUCCESS(rc)) 1290 { 1291 //#ifndef RT_OS_LINUX 1292 /* Cannot use RTFileSgWriteAt or RTFileWriteAt when opened with 1293 RTFILE_O_APPEND, except for on linux where the offset is 1294 then ignored by the low level kernel API. */ 1295 if (pHandle->file.fOpenFlags & RTFILE_O_APPEND) 1296 { 1297 /* paranoia */ 1298 RTFileSeek(pHandle->file.Handle, 0, RTFILE_SEEK_END, NULL); 1299 1300 for (size_t iSeg = 0; iSeg < SgBuf.cSegs; iSeg++) 1301 { 1302 size_t cbWrittenNow = 0; 1303 do 1304 rc = RTFileWrite(pHandle->file.Handle, SgBuf.paSegs[iSeg].pvSeg, 1305 SgBuf.paSegs[iSeg].cbSeg, &cbWrittenNow); 1306 while (rc == VERR_INTERRUPTED); 1307 if (RT_SUCCESS(rc)) 1308 { 1309 cbTotal += cbWrittenNow; 1310 if (cbWrittenNow < SgBuf.paSegs[iSeg].cbSeg) 1311 break; 1312 } 1313 else 1314 { 1315 if (cbTotal > 0) 1316 rc = VINF_SUCCESS; 1317 break; 1318 } 1319 } 1320 } 1321 else 1322 //#endif 1323 { 1324 rc = RTFileSgWriteAt(pHandle->file.Handle, offFile, &SgBuf, cbToWrite, &cbTotal); 1325 while (rc == VERR_INTERRUPTED) 1326 { 1327 RTSgBufReset(&SgBuf); 1328 rc = RTFileSgWriteAt(pHandle->file.Handle, offFile, &SgBuf, cbToWrite, &cbTotal); 1329 } 1330 } 1331 1332 RTMemTmpFree((void *)SgBuf.paSegs); 1333 1334 /* Update the file offset (mainly for RTFILE_O_APPEND), */ 1335 if (RT_SUCCESS(rc)) 1336 { 1337 offFile += cbTotal; 1338 if (!(pHandle->file.fOpenFlags & RTFILE_O_APPEND)) 1339 *poffFile = offFile; 1340 else 1341 *poffFile = vbsfWriteCalcPostAppendFilePosition(pHandle->file.Handle, offFile); 1342 } 1343 } 1344 else 1345 rc = VERR_NO_TMP_MEMORY; 1346 1347 *pcbWrite = (uint32_t)cbTotal; 1101 1348 } 1102 1349 else 1103 AssertRC(rc); 1350 { 1351 /* Writing zero bytes always succeeds. */ 1352 rc = VINF_SUCCESS; 1353 } 1104 1354 } 1105 1355 else 1106 { 1107 /** @todo What writing zero bytes should do? */ 1108 rc = VINF_SUCCESS; 1109 } 1110 1111 LogFunc(("%Rrc bytes written 0x%RX32\n", rc, *pcbBuffer)); 1356 *pcbWrite = 0; 1357 1358 LogFunc(("%Rrc bytes written %#zx\n", rc, cbTotal)); 1112 1359 return rc; 1113 1360 } -
trunk/src/VBox/HostServices/SharedFolders/vbsf.h
r76570 r77243 30 30 31 31 int vbsfRead(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer); 32 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer); 32 int vbsfReadPages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t offFile, 33 uint32_t *pcbBuffer, PVBOXHGCMSVCPARMPAGES pPages); 34 int vbsfWrite(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t *poffFile, uint32_t *pcbBuffer, uint8_t *pBuffer); 35 int vbsfWritePages(SHFLCLIENTDATA *pClient, SHFLROOT idRoot, SHFLHANDLE hFile, uint64_t *poffFile, 36 uint32_t *pcbBuffer, PVBOXHGCMSVCPARMPAGES pPages); 37 33 38 int vbsfLock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags); 34 39 int vbsfUnlock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags);
Note:
See TracChangeset
for help on using the changeset viewer.