Changeset 72300 in vbox for trunk/src/VBox/VMM/VMMR0
- Timestamp:
- May 23, 2018 3:13:06 PM (7 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR0
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp
r72291 r72300 90 90 */ 91 91 #include "../VMMAll/NEMAllNativeTemplate-win.cpp.h" 92 93 /** 94 * Worker for NEMR0InitVM that allocates a hypercall page. 95 * 96 * @returns VBox status code. 97 * @param pHypercallData The hypercall data page to initialize. 98 */ 99 static int nemR0InitHypercallData(PNEMR0HYPERCALLDATA pHypercallData) 100 { 101 int rc = RTR0MemObjAllocPage(&pHypercallData->hMemObj, PAGE_SIZE, false /*fExecutable*/); 102 if (RT_SUCCESS(rc)) 103 { 104 pHypercallData->HCPhysPage = RTR0MemObjGetPagePhysAddr(pHypercallData->hMemObj, 0 /*iPage*/); 105 AssertStmt(pHypercallData->HCPhysPage != NIL_RTHCPHYS, rc = VERR_INTERNAL_ERROR_3); 106 pHypercallData->pbPage = (uint8_t *)RTR0MemObjAddress(pHypercallData->hMemObj); 107 AssertStmt(pHypercallData->pbPage, rc = VERR_INTERNAL_ERROR_3); 108 if (RT_SUCCESS(rc)) 109 return VINF_SUCCESS; 110 111 /* bail out */ 112 RTR0MemObjFree(pHypercallData->hMemObj, true /*fFreeMappings*/); 113 } 114 pHypercallData->hMemObj = NIL_RTR0MEMOBJ; 115 pHypercallData->HCPhysPage = NIL_RTHCPHYS; 116 pHypercallData->pbPage = NULL; 117 return rc; 118 } 119 120 /** 121 * Worker for NEMR0CleanupVM and NEMR0InitVM that cleans up a hypercall page. 122 * 123 * @param pHypercallData The hypercall data page to uninitialize. 124 */ 125 static void nemR0DeleteHypercallData(PNEMR0HYPERCALLDATA pHypercallData) 126 { 127 /* Check pbPage here since it's NULL, whereas the hMemObj can be either 128 NIL_RTR0MEMOBJ or 0 (they aren't necessarily the same). */ 129 if (pHypercallData->pbPage != NULL) 130 { 131 RTR0MemObjFree(pHypercallData->hMemObj, true /*fFreeMappings*/); 132 pHypercallData->pbPage = NULL; 133 } 134 pHypercallData->hMemObj = NIL_RTR0MEMOBJ; 135 pHypercallData->HCPhysPage = NIL_RTHCPHYS; 136 } 92 137 93 138 … … 127 172 { 128 173 /* 129 * Allocate a page for each VCPU to place hypercall data on. 174 * Allocate a page for non-EMT threads to use for hypercalls (update 175 * statistics and such) and a critical section protecting it. 130 176 */ 131 for (VMCPUID i = 0; i < pGVM->cCpus; i++) 177 rc = RTCritSectInit(&pGVM->nem.s.HypercallDataCritSect); 178 if (RT_SUCCESS(rc)) 132 179 { 133 PGVMCPU pGVCpu = &pGVM->aCpus[i]; 134 rc = RTR0MemObjAllocPage(&pGVCpu->nem.s.hHypercallDataMemObj, PAGE_SIZE, false /*fExecutable*/); 180 rc = nemR0InitHypercallData(&pGVM->nem.s.HypercallData); 135 181 if (RT_SUCCESS(rc)) 136 182 { 137 pGVCpu->nem.s.HCPhysHypercallData = RTR0MemObjGetPagePhysAddr(pGVCpu->nem.s.hHypercallDataMemObj, 0 /*iPage*/); 138 pGVCpu->nem.s.pbHypercallData = (uint8_t *)RTR0MemObjAddress(pGVCpu->nem.s.hHypercallDataMemObj); 139 AssertStmt(pGVCpu->nem.s.HCPhysHypercallData != NIL_RTHCPHYS, rc = VERR_INTERNAL_ERROR_3); 140 AssertStmt(pGVCpu->nem.s.pbHypercallData, rc = VERR_INTERNAL_ERROR_3); 183 /* 184 * Allocate a page for each VCPU to place hypercall data on. 185 */ 186 for (VMCPUID i = 0; i < pGVM->cCpus; i++) 187 { 188 rc = nemR0InitHypercallData(&pGVM->aCpus[i].nem.s.HypercallData); 189 if (RT_FAILURE(rc)) 190 { 191 while (i-- > 0) 192 nemR0DeleteHypercallData(&pGVM->aCpus[i].nem.s.HypercallData); 193 break; 194 } 195 } 196 if (RT_SUCCESS(rc)) 197 { 198 /* 199 * So far, so good. 200 */ 201 return rc; 202 } 203 204 /* 205 * Bail out. 206 */ 207 nemR0DeleteHypercallData(&pGVM->nem.s.HypercallData); 141 208 } 142 else 143 pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ; 144 if (RT_FAILURE(rc)) 145 { 146 /* bail. */ 147 do 148 { 149 RTR0MemObjFree(pGVCpu->nem.s.hHypercallDataMemObj, true /*fFreeMappings*/); 150 pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ; 151 pGVCpu->nem.s.HCPhysHypercallData = NIL_RTHCPHYS; 152 pGVCpu->nem.s.pbHypercallData = NULL; 153 } while (i-- > 0); 154 return rc; 155 } 209 RTCritSectDelete(&pGVM->nem.s.HypercallDataCritSect); 156 210 } 157 /* 158 * So far, so good. 159 */ 160 return rc; 161 } 162 163 rc = VERR_NEM_MISSING_KERNEL_API; 164 } 165 166 RT_NOREF(pGVM, pVM); 211 } 212 else 213 rc = VERR_NEM_MISSING_KERNEL_API; 214 } 215 216 RT_NOREF(pVM); 167 217 return rc; 168 218 } … … 309 359 VMCPUID i = pGVM->cCpus; 310 360 while (i-- > 0) 311 { 312 PGVMCPU pGVCpu = &pGVM->aCpus[i]; 313 if (pGVCpu->nem.s.pbHypercallData) 314 { 315 pGVCpu->nem.s.pbHypercallData = NULL; 316 int rc = RTR0MemObjFree(pGVCpu->nem.s.hHypercallDataMemObj, true /*fFreeMappings*/); 317 AssertRC(rc); 318 } 319 pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ; 320 pGVCpu->nem.s.HCPhysHypercallData = NIL_RTHCPHYS; 321 } 361 nemR0DeleteHypercallData(&pGVM->aCpus[i].nem.s.HypercallData); 362 363 /* The non-EMT one too. */ 364 if (RTCritSectIsInitialized(&pGVM->nem.s.HypercallDataCritSect)) 365 RTCritSectDelete(&pGVM->nem.s.HypercallDataCritSect); 366 nemR0DeleteHypercallData(&pGVM->nem.s.HypercallData); 322 367 } 323 368 … … 372 417 * Ring-3 is not allowed to fill in the host physical addresses of the call. 373 418 */ 374 HV_INPUT_MAP_GPA_PAGES *pMapPages = (HV_INPUT_MAP_GPA_PAGES *)pGVCpu->nem.s. pbHypercallData;419 HV_INPUT_MAP_GPA_PAGES *pMapPages = (HV_INPUT_MAP_GPA_PAGES *)pGVCpu->nem.s.HypercallData.pbPage; 375 420 AssertPtrReturn(pMapPages, VERR_INTERNAL_ERROR_3); 376 421 pMapPages->TargetPartitionId = pGVM->nem.s.idHvPartition; … … 387 432 388 433 uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallMapGpaPages | ((uint64_t)cPages << 32), 389 pGVCpu->nem.s.H CPhysHypercallData, 0);434 pGVCpu->nem.s.HypercallData.HCPhysPage, 0); 390 435 Log6(("NEMR0MapPages: %RGp/%RGp L %u prot %#x -> %#RX64\n", 391 436 GCPhysDst, GCPhysSrc - cPages * X86_PAGE_SIZE, cPages, fFlags, uResult)); … … 454 499 * Compose and make the hypercall. 455 500 */ 456 HV_INPUT_UNMAP_GPA_PAGES *pUnmapPages = (HV_INPUT_UNMAP_GPA_PAGES *)pGVCpu->nem.s. pbHypercallData;501 HV_INPUT_UNMAP_GPA_PAGES *pUnmapPages = (HV_INPUT_UNMAP_GPA_PAGES *)pGVCpu->nem.s.HypercallData.pbPage; 457 502 AssertPtrReturn(pUnmapPages, VERR_INTERNAL_ERROR_3); 458 503 pUnmapPages->TargetPartitionId = pGVM->nem.s.idHvPartition; … … 461 506 462 507 uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallUnmapGpaPages | ((uint64_t)cPages << 32), 463 pGVCpu->nem.s.H CPhysHypercallData, 0);508 pGVCpu->nem.s.HypercallData.HCPhysPage, 0); 464 509 Log6(("NEMR0UnmapPages: %RGp L %u -> %#RX64\n", GCPhys, cPages, uResult)); 465 510 if (uResult == ((uint64_t)cPages << 32)) … … 467 512 #if 1 /* Do we need to do this? Hopefully not... */ 468 513 uint64_t volatile uR = g_pfnHvlInvokeHypercall(HvCallUncommitGpaPages | ((uint64_t)cPages << 32), 469 pGVCpu->nem.s.H CPhysHypercallData, 0);514 pGVCpu->nem.s.HypercallData.HCPhysPage, 0); 470 515 AssertMsg(uR == ((uint64_t)cPages << 32), ("uR=%#RX64\n", uR)); NOREF(uR); 471 516 #endif … … 527 572 { 528 573 PVMCPU pVCpu = &pGVM->pVM->aCpus[pGVCpu->idCpu]; 529 HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s. pbHypercallData;574 HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage; 530 575 AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3); 531 576 … … 1096 1141 * Set the registers. 1097 1142 */ 1098 Assert((uintptr_t)&pInput->Elements[iReg] - (uintptr_t)pGVCpu->nem.s. pbHypercallData< PAGE_SIZE); /* max is 127 */1143 Assert((uintptr_t)&pInput->Elements[iReg] - (uintptr_t)pGVCpu->nem.s.HypercallData.pbPage < PAGE_SIZE); /* max is 127 */ 1099 1144 1100 1145 /* … … 1102 1147 */ 1103 1148 uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallSetVpRegisters, iReg), 1104 pGVCpu->nem.s.H CPhysHypercallData, 0 /*GCPhysOutput*/);1149 pGVCpu->nem.s.HypercallData.HCPhysPage, 0 /*GCPhysOutput*/); 1105 1150 AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(iReg), 1106 1151 ("uResult=%RX64 iRegs=%#x\n", uResult, iReg), … … 1156 1201 NEM_TMPL_STATIC int nemR0WinImportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat) 1157 1202 { 1158 HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s. pbHypercallData;1203 HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage; 1159 1204 AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3); 1160 1205 … … 1339 1384 1340 1385 HV_REGISTER_VALUE *paValues = (HV_REGISTER_VALUE *)((uint8_t *)pInput + cbInput); 1341 Assert((uintptr_t)&paValues[cRegs] - (uintptr_t)pGVCpu->nem.s. pbHypercallData< PAGE_SIZE); /* (max is around 168 registers) */1386 Assert((uintptr_t)&paValues[cRegs] - (uintptr_t)pGVCpu->nem.s.HypercallData.pbPage < PAGE_SIZE); /* (max is around 168 registers) */ 1342 1387 RT_BZERO(paValues, cRegs * sizeof(paValues[0])); 1343 1388 … … 1346 1391 */ 1347 1392 uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallGetVpRegisters, cRegs), 1348 pGVCpu->nem.s.H CPhysHypercallData,1349 pGVCpu->nem.s.H CPhysHypercallData+ cbInput);1393 pGVCpu->nem.s.HypercallData.HCPhysPage, 1394 pGVCpu->nem.s.HypercallData.HCPhysPage + cbInput); 1350 1395 AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(cRegs), 1351 1396 ("uResult=%RX64 cRegs=%#x\n", uResult, cRegs), … … 1893 1938 } 1894 1939 1940 1941 /** 1942 * Updates statistics in the VM structure. 1943 * 1944 * @returns VBox status code. 1945 * @param pGVM The ring-0 VM handle. 1946 * @param pVM The cross context VM handle. 1947 * @param idCpu The calling EMT, or NIL. Necessary for getting the hypercall 1948 * page and arguments. 1949 */ 1950 VMMR0_INT_DECL(int) NEMR0UpdateStatistics(PGVM pGVM, PVM pVM, VMCPUID idCpu) 1951 { 1952 /* 1953 * Validate the call. 1954 */ 1955 int rc; 1956 if (idCpu == NIL_VMCPUID) 1957 rc = GVMMR0ValidateGVMandVM(pGVM, pVM); 1958 else 1959 rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu); 1960 if (RT_SUCCESS(rc)) 1961 { 1962 AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API); 1963 1964 PNEMR0HYPERCALLDATA pHypercallData = idCpu != NIL_VMCPUID 1965 ? &pGVM->aCpus[idCpu].nem.s.HypercallData 1966 : &pGVM->nem.s.HypercallData; 1967 if ( RT_VALID_PTR(pHypercallData->pbPage) 1968 && pHypercallData->HCPhysPage != NIL_RTHCPHYS) 1969 { 1970 if (idCpu == NIL_VMCPUID) 1971 rc = RTCritSectEnter(&pGVM->nem.s.HypercallDataCritSect); 1972 if (RT_SUCCESS(rc)) 1973 { 1974 /* 1975 * Query the memory statistics for the partition. 1976 */ 1977 HV_INPUT_GET_MEMORY_BALANCE *pInput = (HV_INPUT_GET_MEMORY_BALANCE *)pHypercallData->pbPage; 1978 pInput->TargetPartitionId = pGVM->nem.s.idHvPartition; 1979 pInput->ProximityDomainInfo.Flags.ProximityPreferred = 0; 1980 pInput->ProximityDomainInfo.Flags.ProxyimityInfoValid = 0; 1981 pInput->ProximityDomainInfo.Flags.Reserved = 0; 1982 pInput->ProximityDomainInfo.Id = 0; 1983 1984 HV_OUTPUT_GET_MEMORY_BALANCE *pOutput = (HV_OUTPUT_GET_MEMORY_BALANCE *)(pInput + 1); 1985 RT_ZERO(*pOutput); 1986 1987 uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallGetMemoryBalance, 1988 pHypercallData->HCPhysPage, 1989 pHypercallData->HCPhysPage + sizeof(*pInput)); 1990 if (uResult == HV_STATUS_SUCCESS) 1991 { 1992 pVM->nem.s.R0Stats.cPagesAvailable = pOutput->PagesAvailable; 1993 pVM->nem.s.R0Stats.cPagesInUse = pOutput->PagesInUse; 1994 rc = VINF_SUCCESS; 1995 } 1996 else 1997 { 1998 LogRel(("HvCallGetMemoryBalance -> %#RX64 (%#RX64 %#RX64)!!\n", 1999 uResult, pOutput->PagesAvailable, pOutput->PagesInUse)); 2000 rc = VINF_NEM_IPE_0; 2001 } 2002 2003 if (idCpu == NIL_VMCPUID) 2004 RTCritSectLeave(&pGVM->nem.s.HypercallDataCritSect); 2005 } 2006 } 2007 else 2008 rc = VERR_WRONG_ORDER; 2009 } 2010 return rc; 2011 } 2012 -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r71223 r72300 2062 2062 VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING); 2063 2063 break; 2064 2065 case VMMR0_DO_NEM_UPDATE_STATISTICS: 2066 if (u64Arg || pReqHdr) 2067 return VERR_INVALID_PARAMETER; 2068 rc = NEMR0UpdateStatistics(pGVM, pVM, idCpu); 2069 VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING); 2070 break; 2064 2071 # endif 2065 2072 #endif
Note:
See TracChangeset
for help on using the changeset viewer.