Changeset 67987 in vbox
- Timestamp:
- Jul 17, 2017 11:24:30 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 116996
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r66535 r67987 91 91 /** This VirtualBox build does not support raw-mode. */ 92 92 #define VERR_RAW_MODE_NOT_SUPPORTED (-1023) 93 /** Essential fields in the shared VM structure doesn't match the global one. */ 94 #define VERR_INCONSISTENT_VM_HANDLE (-1024) 93 95 /** @} */ 94 96 … … 2349 2351 /** Internal processing error \#2 in the GVMM code. */ 2350 2352 #define VERR_GVMM_IPE_2 (-5204) 2353 /** Cannot destroy VM because not all other EMTs have deregistered. */ 2354 #define VERR_GVMM_NOT_ALL_EMTS_DEREGISTERED (-5205) 2351 2355 /** @} */ 2352 2356 -
trunk/include/VBox/vmm/gvmm.h
r67955 r67987 165 165 GVMMR0DECL(int) GVMMR0DestroyVM(PGVM pGVM, PVM pVM); 166 166 GVMMR0DECL(int) GVMMR0RegisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu); 167 GVMMR0DECL(int) GVMMR0DeregisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu); 167 168 GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM); 168 169 GVMMR0DECL(int) GVMMR0ByVM(PVM pVM, PGVM *ppGVM); -
trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
r67956 r67987 362 362 static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM); 363 363 static int gvmmR0ByGVMandVM(PGVM pGVM, PVM pVM, PGVMM *ppGVMM, bool fTakeUsedLock); 364 static int gvmmR0ByGVMandVMandEMT(PGVM pGVM, PVM pVM, VMCPUID idCpu, PGVMM *ppGVMM); 364 365 365 366 #ifdef GVMM_SCHED_WITH_PPT … … 1184 1185 1185 1186 uint32_t hGVM = pGVM->hSelf; 1186 AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_ HANDLE);1187 AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_ HANDLE);1187 AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_VM_HANDLE); 1188 AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_VM_HANDLE); 1188 1189 1189 1190 PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM]; … … 1203 1204 int rc = gvmmR0CreateDestroyLock(pGVMM); 1204 1205 AssertRC(rc); 1205 1206 /** @todo Check that all other EMTs have said bye-bye. */1207 1208 1206 1209 1207 /* Be careful here because we might theoretically be racing someone else cleaning up. */ … … 1217 1215 && pHandle->pGVM->u32Magic == GVM_MAGIC) 1218 1216 { 1219 void *pvObj = pHandle->pvObj; 1220 pHandle->pvObj = NULL; 1221 gvmmR0CreateDestroyUnlock(pGVMM); 1222 1223 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 1224 { 1225 /** @todo Can we busy wait here for all thread-context hooks to be 1226 * deregistered before releasing (destroying) it? Only until we find a 1227 * solution for not deregistering hooks everytime we're leaving HMR0 1228 * context. */ 1229 VMMR0ThreadCtxHookDestroyForEmt(&pVM->aCpus[idCpu]); 1230 } 1231 1232 SUPR0ObjRelease(pvObj, pHandle->pSession); 1217 /* Check that other EMTs have deregistered. */ 1218 uint32_t cNotDeregistered = 0; 1219 for (VMCPUID idCpu = 1; idCpu < pGVM->cCpus; idCpu++) 1220 cNotDeregistered += pGVM->aCpus[idCpu].hEMT != ~(RTNATIVETHREAD)1; /* see GVMMR0DeregisterVCpu for the value */ 1221 if (cNotDeregistered == 0) 1222 { 1223 /* Grab the object pointer. */ 1224 void *pvObj = pHandle->pvObj; 1225 pHandle->pvObj = NULL; 1226 gvmmR0CreateDestroyUnlock(pGVMM); 1227 1228 /** @todo this _must_ be the wrong place. */ 1229 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 1230 { 1231 /** @todo Can we busy wait here for all thread-context hooks to be 1232 * deregistered before releasing (destroying) it? Only until we find a 1233 * solution for not deregistering hooks everytime we're leaving HMR0 1234 * context. */ 1235 VMMR0ThreadCtxHookDestroyForEmt(&pVM->aCpus[idCpu]); 1236 } 1237 1238 SUPR0ObjRelease(pvObj, pHandle->pSession); 1239 } 1240 else 1241 { 1242 gvmmR0CreateDestroyUnlock(pGVMM); 1243 rc = VERR_GVMM_NOT_ALL_EMTS_DEREGISTERED; 1244 } 1233 1245 } 1234 1246 else … … 1444 1456 GVMMR0DECL(int) GVMMR0RegisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu) 1445 1457 { 1446 AssertReturn(idCpu != 0, VERR_ NOT_OWNER);1458 AssertReturn(idCpu != 0, VERR_INVALID_FUNCTION); 1447 1459 1448 1460 /* … … 1483 1495 else 1484 1496 rc = VERR_INVALID_CPU_ID; 1497 } 1498 return rc; 1499 } 1500 1501 1502 /** 1503 * Deregisters the calling thread as the EMT of a Virtual CPU. 1504 * 1505 * Note that VCPU 0 shall call GVMMR0DestroyVM intead of this API. 1506 * 1507 * @returns VBox status code 1508 * @param pGVM The global (ring-0) VM structure. 1509 * @param pVM The cross context VM structure. 1510 * @param idCpu VCPU id to register the current thread as. 1511 */ 1512 GVMMR0DECL(int) GVMMR0DeregisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu) 1513 { 1514 AssertReturn(idCpu != 0, VERR_INVALID_FUNCTION); 1515 1516 /* 1517 * Validate the VM structure, state and handle. 1518 */ 1519 PGVMM pGVMM; 1520 int rc = gvmmR0ByGVMandVMandEMT(pGVM, pVM, idCpu, &pGVMM); 1521 if (RT_SUCCESS(rc)) 1522 { 1523 /* 1524 * Take the destruction lock and recheck the handle state to 1525 * prevent racing GVMMR0DestroyVM. 1526 */ 1527 gvmmR0CreateDestroyLock(pGVMM); 1528 uint32_t hSelf = pGVM->hSelf; 1529 if ( hSelf < RT_ELEMENTS(pGVMM->aHandles) 1530 && pGVMM->aHandles[hSelf].pvObj != NULL 1531 && pGVMM->aHandles[hSelf].pGVM == pGVM) 1532 { 1533 /* 1534 * Do per-EMT cleanups. 1535 */ 1536 VMMR0ThreadCtxHookDestroyForEmt(&pVM->aCpus[idCpu]); 1537 1538 /* 1539 * Invalidate hEMT. We don't use NIL here as that would allow 1540 * GVMMR0RegisterVCpu to be called again, and we don't want that. 1541 */ 1542 AssertCompile(~(RTNATIVETHREAD)1 != NIL_RTNATIVETHREAD); 1543 pGVM->aCpus[idCpu].hEMT = ~(RTNATIVETHREAD)1; 1544 pVM->aCpus[idCpu].hNativeThreadR0 = NIL_RTNATIVETHREAD; 1545 } 1546 1547 gvmmR0CreateDestroyUnlock(pGVMM); 1485 1548 } 1486 1549 return rc; … … 1673 1736 } 1674 1737 } 1675 rc = VERR_INVALID_ HANDLE;1738 rc = VERR_INVALID_VM_HANDLE; 1676 1739 } 1677 1740 else … … 1714 1777 * @thread EMT 1715 1778 * 1716 * @remark 1779 * @remarks This will assert in all failure paths. 1717 1780 */ 1718 1781 static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM) … … 1752 1815 } 1753 1816 1817 1818 /** 1819 * Check that the given GVM and VM structures match up. 1820 * 1821 * The calling thread must be in the same process as the VM. All current lookups 1822 * are by threads inside the same process, so this will not be an issue. 1823 * 1824 * @returns VBox status code. 1825 * @param pGVM The global (ring-0) VM structure. 1826 * @param pVM The cross context VM structure. 1827 * @param idCpu The (alleged) Virtual CPU ID of the calling EMT. 1828 * @param ppGVMM Where to store the pointer to the GVMM instance data. 1829 * @thread EMT 1830 * 1831 * @remarks This will assert in all failure paths. 1832 */ 1833 static int gvmmR0ByGVMandVMandEMT(PGVM pGVM, PVM pVM, VMCPUID idCpu, PGVMM *ppGVMM) 1834 { 1835 /* 1836 * Check the pointers. 1837 */ 1838 AssertPtrReturn(pGVM, VERR_INVALID_POINTER); 1839 1840 AssertPtrReturn(pVM, VERR_INVALID_POINTER); 1841 AssertReturn(((uintptr_t)pVM & PAGE_OFFSET_MASK) == 0, VERR_INVALID_POINTER); 1842 AssertReturn(pGVM->pVM == pVM, VERR_INVALID_VM_HANDLE); 1843 1844 1845 /* 1846 * Get the pGVMM instance and check the VM handle. 1847 */ 1848 PGVMM pGVMM; 1849 GVMM_GET_VALID_INSTANCE(pGVMM, VERR_GVMM_INSTANCE); 1850 1851 uint16_t hGVM = pGVM->hSelf; 1852 AssertReturn( hGVM != NIL_GVM_HANDLE 1853 && hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_VM_HANDLE); 1854 1855 RTPROCESS const pidSelf = RTProcSelf(); 1856 PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM]; 1857 AssertReturn( pHandle->pGVM == pGVM 1858 && pHandle->pVM == pVM 1859 && pHandle->ProcId == pidSelf 1860 && RT_VALID_PTR(pHandle->pvObj), 1861 VERR_INVALID_HANDLE); 1862 1863 /* 1864 * Check the EMT claim. 1865 */ 1866 RTNATIVETHREAD const hAllegedEMT = RTThreadNativeSelf(); 1867 AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID); 1868 AssertReturn(pGVM->aCpus[idCpu].hEMT == hAllegedEMT, VERR_NOT_OWNER); 1869 1870 /* 1871 * Some more VM data consistency checks. 1872 */ 1873 AssertReturn(pVM->cCpus == pGVM->cCpus, VERR_INCONSISTENT_VM_HANDLE); 1874 AssertReturn(pVM->hSelf == hGVM, VERR_INCONSISTENT_VM_HANDLE); 1875 AssertReturn(pVM->pVMR0 == pVM, VERR_INCONSISTENT_VM_HANDLE); 1876 AssertReturn( pVM->enmVMState >= VMSTATE_CREATING 1877 && pVM->enmVMState <= VMSTATE_TERMINATED, VERR_INCONSISTENT_VM_HANDLE); 1878 1879 *ppGVMM = pGVMM; 1880 return VINF_SUCCESS; 1881 } 1754 1882 1755 1883 /** -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r67956 r67987 654 654 int rc = RTThreadCtxHookDestroy(pVCpu->vmm.s.hCtxHook); 655 655 AssertRC(rc); 656 pVCpu->vmm.s.hCtxHook = NIL_RTTHREADCTXHOOK; 656 657 } 657 658 … … 1436 1437 1437 1438 case VMMR0_DO_GVMM_REGISTER_VMCPU: 1438 if (pGVM != NULL && pVM != NULL 1439 if (pGVM != NULL && pVM != NULL) 1439 1440 rc = GVMMR0RegisterVCpu(pGVM, pVM, idCpu); 1441 else 1442 rc = VERR_INVALID_PARAMETER; 1443 VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING); 1444 break; 1445 1446 case VMMR0_DO_GVMM_DEREGISTER_VMCPU: 1447 if (pGVM != NULL && pVM != NULL) 1448 rc = GVMMR0DeregisterVCpu(pGVM, pVM, idCpu); 1440 1449 else 1441 1450 rc = VERR_INVALID_PARAMETER; -
trunk/src/VBox/VMM/VMMR3/VMEmt.cpp
r66156 r67987 248 248 /* 249 249 * Cleanup and exit. 250 * EMT0 does the VM destruction after all other EMTs have deregistered and terminated. 250 251 */ 251 252 Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Rrc enmBefore=%d enmVMState=%d\n", … … 275 276 276 277 int rc2 = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL); 278 AssertLogRelRC(rc2); 279 } 280 /* Deregister the EMT with VMMR0. */ 281 else if ( idCpu != 0 282 && (pVM = pUVM->pVM) != NULL) 283 { 284 int rc2 = SUPR3CallVMMR0Ex(pVM->pVMR0, idCpu, VMMR0_DO_GVMM_DEREGISTER_VMCPU, 0, NULL); 277 285 AssertLogRelRC(rc2); 278 286 }
Note:
See TracChangeset
for help on using the changeset viewer.