Changeset 21489 in vbox for trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
- Timestamp:
- Jul 10, 2009 4:53:03 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
r21487 r21489 159 159 } 160 160 161 #if 0 /* new code using page list and whatnot. */162 161 163 162 /** … … 212 211 uint32_t u32; 213 212 214 AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), VERR_OUT_OF_RANGE); 213 AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), 214 VERR_OUT_OF_RANGE); 215 215 AssertMsgReturn( off >= pCallInfo->cParms * sizeof(HGCMFunctionParameter) 216 216 && off < cbCallInfo - sizeof(HGCMPageListInfo), … … 227 227 u32 = RT_ALIGN_32(pPgLst->offFirstPage + cb, PAGE_SIZE) >> PAGE_SHIFT; 228 228 AssertMsgReturn(cPages == u32, ("cPages=%#x u32=%#x\n", cPages, u32), VERR_INVALID_PARAMETER); 229 AssertMsgReturn(pPgLst->flags > VBOX_HGCM_F_PARM_DIRECTION_NONE && pPgLst->flags <= VBOX_HGCM_F_PARM_DIRECTION_BOTH, 230 ("%#x\n", pPgLst->flags), 231 VERR_INVALID_PARAMETER); 232 Log4(("GstHGCMCall: parm=%u type=pglst: cb=%#010x cPgs=%u offPg0=%#x flags=%#x\n", iParm, cb, cPages, pPgLst->offFirstPage, pPgLst->flags)); 229 AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pPgLst->flags), ("%#x\n", pPgLst->flags), VERR_INVALID_PARAMETER); 230 Log4(("GstHGCMCall: parm=%u type=pglst: cb=%#010x cPgs=%u offPg0=%#x flags=%#x\n", 231 iParm, cb, cPages, pPgLst->offFirstPage, pPgLst->flags)); 233 232 u32 = cPages; 234 233 while (u32-- > 0) … … 254 253 { 255 254 cb = pSrcParm->u.Pointer.size; 256 AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), VERR_OUT_OF_RANGE); 255 AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), 256 VERR_OUT_OF_RANGE); 257 257 if (cb != 0) 258 Log4(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr)); 258 Log4(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p\n", 259 iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr)); 259 260 else 260 261 Log4(("GstHGCMCall: parm=%u type=%#x: cb=0\n", iParm, pSrcParm->type)); … … 279 280 if (!fIsUser) 280 281 { 281 AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), VERR_OUT_OF_RANGE); 282 AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM), 283 VERR_OUT_OF_RANGE); 282 284 rc = RTR0MemObjLockKernel(&hObj, (void *)pSrcParm->u.Pointer.u.linearAddr, cb); 283 285 if (RT_FAILURE(rc)) … … 287 289 return rc; 288 290 } 289 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked kernel -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj)); 291 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked kernel -> %p\n", 292 iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj)); 290 293 } 291 294 else … … 294 297 { 295 298 Log(("GstHGCMCall: id=%#x fn=%u parm=%u pv=%p cb=%#x > %#x -> out of range\n", 296 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, VBGLR0_MAX_HGCM_USER_PARM)); 299 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, 300 cb, VBGLR0_MAX_HGCM_USER_PARM)); 297 301 return VERR_OUT_OF_RANGE; 298 302 } … … 306 310 return rc; 307 311 } 308 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked user -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj)); 312 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p locked user -> %p\n", 313 iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj)); 309 314 310 315 #else /* USE_BOUNCH_BUFFERS */ … … 333 338 RTMemTmpFree(pvSmallBuf); 334 339 Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n", 335 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc)); 340 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, 341 pSrcParm->u.Pointer.u.linearAddr, cb, rc)); 336 342 return rc; 337 343 } … … 341 347 { 342 348 RTMemTmpFree(pvSmallBuf); 343 Log(("GstHGCMCall: RTR0MemObjLockKernel failed for small buffer: rc=%Rrc pvSmallBuf=%p cb=%#x\n", rc, pvSmallBuf, cb)); 349 Log(("GstHGCMCall: RTR0MemObjLockKernel failed for small buffer: rc=%Rrc pvSmallBuf=%p cb=%#x\n", 350 rc, pvSmallBuf, cb)); 344 351 return rc; 345 352 } 346 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p small buffer %p -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, pvSmallBuf, hObj)); 353 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p small buffer %p -> %p\n", 354 iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, pvSmallBuf, hObj)); 347 355 } 348 356 else … … 360 368 RTR0MemObjFree(hObj, false /*fFreeMappings*/); 361 369 Log(("GstHGCMCall: id=%#x fn=%u parm=%u RTR0MemUserCopyFrom(,%p,%#x) -> %Rrc\n", 362 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, pSrcParm->u.Pointer.u.linearAddr, cb, rc)); 370 pCallInfo->u32ClientID, pCallInfo->u32Function, iParm, 371 pSrcParm->u.Pointer.u.linearAddr, cb, rc)); 363 372 return rc; 364 373 } 365 374 } 366 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p big buffer -> %p\n", iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj)); 375 Log3(("GstHGCMCall: parm=%u type=%#x: cb=%#010x pv=%p big buffer -> %p\n", 376 iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj)); 367 377 } 368 378 #endif /* USE_BOUNCH_BUFFERS */ … … 394 404 } 395 405 406 396 407 /** 397 408 * Translates locked linear address to the normal type. … … 416 427 } 417 428 429 418 430 /** 419 431 * Translates linear address types to page list direction flags. … … 453 465 * physical page lists. 454 466 */ 455 static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,456 bool fIsUser, struct VbglR0ParmInfo *pParmInfo)467 static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo, 468 uint32_t cbCallInfo, bool fIsUser, struct VbglR0ParmInfo *pParmInfo) 457 469 { 458 470 HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo); … … 598 610 * @param u32AsyncData Argument for the callback. 599 611 */ 600 static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) 612 static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback, 613 void *pvAsyncData, uint32_t u32AsyncData) 601 614 { 602 615 int rc; … … 752 765 } 753 766 767 754 768 DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 755 769 VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) … … 763 777 * Basic validation. 764 778 */ 765 AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 779 AssertMsgReturn( !pCallInfo 780 || !pfnAsyncCallback 781 || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS 782 || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 766 783 ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags), 767 784 VERR_INVALID_PARAMETER); … … 823 840 824 841 825 # 842 #if ARCH_BITS == 64 826 843 DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 827 844 VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) … … 837 854 * Input validation. 838 855 */ 839 AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 856 AssertMsgReturn( !pCallInfo 857 || !pfnAsyncCallback 858 || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS 859 || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 840 860 ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags), 841 861 VERR_INVALID_PARAMETER); … … 924 944 return rc; 925 945 } 926 # endif /* ARCH_BITS == 64 */ 927 928 # else /* old code: */ 929 930 /** @todo merge with the one below (use a header file). Too lazy now. */ 931 DECLR0VBGL(int) VbglR0HGCMInternalCall (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 932 VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) 933 { 934 VMMDevHGCMCall *pHGCMCall; 935 uint32_t cbParms; 936 HGCMFunctionParameter *pParm; 937 unsigned iParm; 938 int rc; 939 940 AssertMsgReturn(!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 941 ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pAsyncCallback, fFlags), 942 VERR_INVALID_PARAMETER); 943 944 Log (("GstHGCMCall: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d, fFlags=%#x\n", 945 pCallInfo->cParms, pCallInfo->u32Function, fFlags)); 946 947 pHGCMCall = NULL; 948 949 if (cbCallInfo == 0) 950 { 951 /* Caller did not specify the size (a valid value should be at least sizeof(VBoxGuestHGCMCallInfo)). 952 * Compute the size. 953 */ 954 cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter); 955 } 956 else if (cbCallInfo < sizeof (VBoxGuestHGCMCallInfo)) 957 { 958 return VERR_INVALID_PARAMETER; 959 } 960 else 961 { 962 cbParms = cbCallInfo - sizeof (VBoxGuestHGCMCallInfo); 963 } 964 965 /* Allocate request */ 966 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMCall, sizeof (VMMDevHGCMCall) + cbParms, VMMDevReq_HGCMCall); 967 968 Log (("GstHGCMCall: Allocated gr %p, rc = %Rrc, cbParms = %d\n", pHGCMCall, rc, cbParms)); 969 970 if (RT_SUCCESS(rc)) 971 { 972 void *apvCtx[VBOX_HGCM_MAX_PARMS]; 973 memset (apvCtx, 0, sizeof(void *) * pCallInfo->cParms); 974 975 /* Initialize request memory */ 976 pHGCMCall->header.fu32Flags = 0; 977 pHGCMCall->header.result = VINF_SUCCESS; 978 979 pHGCMCall->u32ClientID = pCallInfo->u32ClientID; 980 pHGCMCall->u32Function = pCallInfo->u32Function; 981 pHGCMCall->cParms = pCallInfo->cParms; 982 983 if (cbParms) 984 { 985 /* Lock user buffers. */ 986 pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo); 987 988 for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++) 989 { 990 switch (pParm->type) 991 { 992 case VMMDevHGCMParmType_32bit: 993 case VMMDevHGCMParmType_64bit: 994 break; 995 996 case VMMDevHGCMParmType_LinAddr_Locked_In: 997 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 998 rc = VERR_INVALID_PARAMETER; 999 else 1000 pParm->type = VMMDevHGCMParmType_LinAddr_In; 1001 break; 1002 case VMMDevHGCMParmType_LinAddr_Locked_Out: 1003 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1004 rc = VERR_INVALID_PARAMETER; 1005 else 1006 pParm->type = VMMDevHGCMParmType_LinAddr_Out; 1007 break; 1008 case VMMDevHGCMParmType_LinAddr_Locked: 1009 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1010 rc = VERR_INVALID_PARAMETER; 1011 else 1012 pParm->type = VMMDevHGCMParmType_LinAddr; 1013 break; 1014 1015 case VMMDevHGCMParmType_PageList: 1016 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1017 rc = VERR_INVALID_PARAMETER; 1018 break; 1019 1020 case VMMDevHGCMParmType_LinAddr_In: 1021 case VMMDevHGCMParmType_LinAddr_Out: 1022 case VMMDevHGCMParmType_LinAddr: 1023 /* PORTME: When porting this to Darwin and other systems where the entire kernel isn't mapped 1024 into every process, all linear address will have to be converted to physical SG lists at 1025 this point. Care must also be taken on these guests to not mix kernel and user addresses 1026 in HGCM calls, or we'll end up locking the wrong memory. If VMMDev/HGCM gets a linear address 1027 it will assume that it's in the current memory context (i.e. use CR3 to translate it). 1028 1029 These kind of problems actually applies to some patched linux kernels too, including older 1030 fedora releases. (The patch is the infamous 4G/4G patch, aka 4g4g, by Ingo Molnar.) */ 1031 rc = vbglLockLinear (&apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size, 1032 (pParm->type == VMMDevHGCMParmType_LinAddr_In) ? false : true /* write access */, 1033 fFlags); 1034 break; 1035 1036 default: 1037 rc = VERR_INVALID_PARAMETER; 1038 break; 1039 } 1040 if (RT_FAILURE (rc)) 1041 break; 1042 } 1043 memcpy (VMMDEV_HGCM_CALL_PARMS(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), cbParms); 1044 } 1045 1046 /* Check that the parameter locking was ok. */ 1047 if (RT_SUCCESS(rc)) 1048 { 1049 Log (("calling VbglGRPerform\n")); 1050 1051 /* Issue request */ 1052 rc = VbglGRPerform (&pHGCMCall->header.header); 1053 1054 Log (("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result)); 1055 1056 /** If the call failed, but as a result of the request itself, then pretend success 1057 * Upper layers will interpret the result code in the packet. 1058 */ 1059 if (RT_FAILURE(rc) && rc == pHGCMCall->header.result) 1060 { 1061 Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE); 1062 rc = VINF_SUCCESS; 1063 } 1064 1065 if (RT_SUCCESS(rc)) 1066 { 1067 /* Check if host decides to process the request asynchronously. */ 1068 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1069 { 1070 /* Wait for request completion interrupt notification from host */ 1071 Log (("Processing HGCM call asynchronously\n")); 1072 pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData); 1073 } 1074 1075 if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE) 1076 { 1077 if (cbParms) 1078 { 1079 memcpy (VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), VMMDEV_HGCM_CALL_PARMS(pHGCMCall), cbParms); 1080 } 1081 pCallInfo->result = pHGCMCall->header.result; 1082 } 1083 else 1084 { 1085 /* The callback returns without completing the request, 1086 * that means the wait was interrrupted. That can happen 1087 * if the request times out, the system reboots or the 1088 * VBoxService ended abnormally. 1089 * 1090 * Cancel the request, the host will not write to the 1091 * memory related to the cancelled request. 1092 */ 1093 Log (("Cancelling HGCM call\n")); 1094 pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED; 1095 1096 pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel; 1097 VbglGRPerform (&pHGCMCall->header.header); 1098 } 1099 } 1100 } 1101 1102 /* Unlock user buffers. */ 1103 pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo); 1104 1105 for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++) 1106 { 1107 if ( pParm->type == VMMDevHGCMParmType_LinAddr_In 1108 || pParm->type == VMMDevHGCMParmType_LinAddr_Out 1109 || pParm->type == VMMDevHGCMParmType_LinAddr) 1110 { 1111 if (apvCtx[iParm] != NULL) 1112 { 1113 vbglUnlockLinear (apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size); 1114 } 1115 } 1116 else 1117 Assert(!apvCtx[iParm]); 1118 } 1119 1120 if ((pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED) == 0) 1121 VbglGRFree (&pHGCMCall->header.header); 1122 else 1123 rc = VERR_INTERRUPTED; 1124 } 1125 1126 return rc; 1127 } 1128 1129 # if ARCH_BITS == 64 1130 /** @todo merge with the one above (use a header file). Too lazy now. */ 1131 DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 1132 VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) 1133 { 1134 VMMDevHGCMCall *pHGCMCall; 1135 uint32_t cbParms; 1136 HGCMFunctionParameter32 *pParm; 1137 unsigned iParm; 1138 int rc; 1139 1140 AssertMsgReturn(!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 1141 ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pAsyncCallback, fFlags), 1142 VERR_INVALID_PARAMETER); 1143 1144 Log (("GstHGCMCall32: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d, fFlags=%#x\n", 1145 pCallInfo->cParms, pCallInfo->u32Function, fFlags)); 1146 1147 pHGCMCall = NULL; 1148 1149 if (cbCallInfo == 0) 1150 { 1151 /* Caller did not specify the size (a valid value should be at least sizeof(VBoxGuestHGCMCallInfo)). 1152 * Compute the size. 1153 */ 1154 cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter32); 1155 } 1156 else if (cbCallInfo < sizeof (VBoxGuestHGCMCallInfo)) 1157 { 1158 return VERR_INVALID_PARAMETER; 1159 } 1160 else 1161 { 1162 cbParms = cbCallInfo - sizeof (VBoxGuestHGCMCallInfo); 1163 } 1164 1165 /* Allocate request */ 1166 rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMCall, sizeof (VMMDevHGCMCall) + cbParms, VMMDevReq_HGCMCall32); 1167 1168 Log (("GstHGCMCall32: Allocated gr %p, rc = %Rrc, cbParms = %d\n", pHGCMCall, rc, cbParms)); 1169 1170 if (RT_SUCCESS(rc)) 1171 { 1172 void *apvCtx[VBOX_HGCM_MAX_PARMS]; 1173 memset (apvCtx, 0, sizeof(void *) * pCallInfo->cParms); 1174 1175 /* Initialize request memory */ 1176 pHGCMCall->header.fu32Flags = 0; 1177 pHGCMCall->header.result = VINF_SUCCESS; 1178 1179 pHGCMCall->u32ClientID = pCallInfo->u32ClientID; 1180 pHGCMCall->u32Function = pCallInfo->u32Function; 1181 pHGCMCall->cParms = pCallInfo->cParms; 1182 1183 if (cbParms) 1184 { 1185 /* Lock user buffers. */ 1186 pParm = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo); 1187 1188 for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++) 1189 { 1190 switch (pParm->type) 1191 { 1192 case VMMDevHGCMParmType_32bit: 1193 case VMMDevHGCMParmType_64bit: 1194 break; 1195 1196 case VMMDevHGCMParmType_LinAddr_Locked_In: 1197 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1198 rc = VERR_INVALID_PARAMETER; 1199 else 1200 pParm->type = VMMDevHGCMParmType_LinAddr_In; 1201 break; 1202 case VMMDevHGCMParmType_LinAddr_Locked_Out: 1203 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1204 rc = VERR_INVALID_PARAMETER; 1205 else 1206 pParm->type = VMMDevHGCMParmType_LinAddr_Out; 1207 break; 1208 case VMMDevHGCMParmType_LinAddr_Locked: 1209 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1210 rc = VERR_INVALID_PARAMETER; 1211 else 1212 pParm->type = VMMDevHGCMParmType_LinAddr; 1213 break; 1214 1215 case VMMDevHGCMParmType_PageList: 1216 if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER) 1217 rc = VERR_INVALID_PARAMETER; 1218 break; 1219 1220 case VMMDevHGCMParmType_LinAddr_In: 1221 case VMMDevHGCMParmType_LinAddr_Out: 1222 case VMMDevHGCMParmType_LinAddr: 1223 /* PORTME: When porting this to Darwin and other systems where the entire kernel isn't mapped 1224 into every process, all linear address will have to be converted to physical SG lists at 1225 this point. Care must also be taken on these guests to not mix kernel and user addresses 1226 in HGCM calls, or we'll end up locking the wrong memory. If VMMDev/HGCM gets a linear address 1227 it will assume that it's in the current memory context (i.e. use CR3 to translate it). 1228 1229 These kind of problems actually applies to some patched linux kernels too, including older 1230 fedora releases. (The patch is the infamous 4G/4G patch, aka 4g4g, by Ingo Molnar.) */ 1231 rc = vbglLockLinear (&apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size, 1232 (pParm->type == VMMDevHGCMParmType_LinAddr_In) ? false : true /* write access */, 1233 fFlags); 1234 break; 1235 1236 default: 1237 rc = VERR_INVALID_PARAMETER; 1238 break; 1239 } 1240 if (RT_FAILURE (rc)) 1241 break; 1242 } 1243 memcpy (VMMDEV_HGCM_CALL_PARMS32(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo), cbParms); 1244 } 1245 1246 /* Check that the parameter locking was ok. */ 1247 if (RT_SUCCESS(rc)) 1248 { 1249 Log (("calling VbglGRPerform\n")); 1250 1251 /* Issue request */ 1252 rc = VbglGRPerform (&pHGCMCall->header.header); 1253 1254 Log (("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result)); 1255 1256 /** If the call failed, but as a result of the request itself, then pretend success 1257 * Upper layers will interpret the result code in the packet. 1258 */ 1259 if (RT_FAILURE(rc) && rc == pHGCMCall->header.result) 1260 { 1261 Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE); 1262 rc = VINF_SUCCESS; 1263 } 1264 1265 if (RT_SUCCESS(rc)) 1266 { 1267 /* Check if host decides to process the request asynchronously. */ 1268 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1269 { 1270 /* Wait for request completion interrupt notification from host */ 1271 Log (("Processing HGCM call asynchronously\n")); 1272 pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData); 1273 } 1274 1275 if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE) 1276 { 1277 if (cbParms) 1278 memcpy (VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo), VMMDEV_HGCM_CALL_PARMS32(pHGCMCall), cbParms); 1279 1280 pCallInfo->result = pHGCMCall->header.result; 1281 } 1282 else 1283 { 1284 /* The callback returns without completing the request, 1285 * that means the wait was interrrupted. That can happen 1286 * if the request times out, the system reboots or the 1287 * VBoxService ended abnormally. 1288 * 1289 * Cancel the request, the host will not write to the 1290 * memory related to the cancelled request. 1291 */ 1292 Log (("Cancelling HGCM call\n")); 1293 pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED; 1294 1295 pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel; 1296 VbglGRPerform (&pHGCMCall->header.header); 1297 } 1298 } 1299 } 1300 1301 /* Unlock user buffers. */ 1302 pParm = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo); 1303 1304 for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++) 1305 { 1306 if ( pParm->type == VMMDevHGCMParmType_LinAddr_In 1307 || pParm->type == VMMDevHGCMParmType_LinAddr_Out 1308 || pParm->type == VMMDevHGCMParmType_LinAddr) 1309 { 1310 if (apvCtx[iParm] != NULL) 1311 { 1312 vbglUnlockLinear (apvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size); 1313 } 1314 } 1315 else 1316 Assert(!apvCtx[iParm]); 1317 } 1318 1319 if ((pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED) == 0) 1320 VbglGRFree (&pHGCMCall->header.header); 1321 else 1322 rc = VERR_INTERRUPTED; 1323 } 1324 1325 return rc; 1326 } 1327 # endif /* ARCH_BITS == 64 */ 1328 1329 # endif /* old code */ 946 #endif /* ARCH_BITS == 64 */ 1330 947 1331 948 #endif /* VBGL_VBOXGUEST */
Note:
See TracChangeset
for help on using the changeset viewer.