VirtualBox

Changeset 67987 in vbox


Ignore:
Timestamp:
Jul 17, 2017 11:24:30 AM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
116996
Message:

GVMMR0: Added EMT deregistration API to complement the registration one.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r66535 r67987  
    9191/** This VirtualBox build does not support raw-mode. */
    9292#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)
    9395/** @} */
    9496
     
    23492351/** Internal processing error \#2 in the GVMM code. */
    23502352#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)
    23512355/** @} */
    23522356
  • trunk/include/VBox/vmm/gvmm.h

    r67955 r67987  
    165165GVMMR0DECL(int)     GVMMR0DestroyVM(PGVM pGVM, PVM pVM);
    166166GVMMR0DECL(int)     GVMMR0RegisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu);
     167GVMMR0DECL(int)     GVMMR0DeregisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu);
    167168GVMMR0DECL(PGVM)    GVMMR0ByHandle(uint32_t hGVM);
    168169GVMMR0DECL(int)     GVMMR0ByVM(PVM pVM, PGVM *ppGVM);
  • trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp

    r67956 r67987  
    362362static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM);
    363363static int gvmmR0ByGVMandVM(PGVM pGVM, PVM pVM, PGVMM *ppGVMM, bool fTakeUsedLock);
     364static int gvmmR0ByGVMandVMandEMT(PGVM pGVM, PVM pVM, VMCPUID idCpu, PGVMM *ppGVMM);
    364365
    365366#ifdef GVMM_SCHED_WITH_PPT
     
    11841185
    11851186    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);
    11881189
    11891190    PGVMHANDLE      pHandle = &pGVMM->aHandles[hGVM];
     
    12031204    int rc = gvmmR0CreateDestroyLock(pGVMM);
    12041205    AssertRC(rc);
    1205 
    1206 /** @todo Check that all other EMTs have said bye-bye. */
    1207 
    12081206
    12091207    /* Be careful here because we might theoretically be racing someone else cleaning up. */
     
    12171215        &&  pHandle->pGVM->u32Magic == GVM_MAGIC)
    12181216    {
    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        }
    12331245    }
    12341246    else
     
    14441456GVMMR0DECL(int) GVMMR0RegisterVCpu(PGVM pGVM, PVM pVM, VMCPUID idCpu)
    14451457{
    1446     AssertReturn(idCpu != 0, VERR_NOT_OWNER);
     1458    AssertReturn(idCpu != 0, VERR_INVALID_FUNCTION);
    14471459
    14481460    /*
     
    14831495        else
    14841496            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 */
     1512GVMMR0DECL(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);
    14851548    }
    14861549    return rc;
     
    16731736                }
    16741737            }
    1675             rc = VERR_INVALID_HANDLE;
     1738            rc = VERR_INVALID_VM_HANDLE;
    16761739        }
    16771740        else
     
    17141777 * @thread  EMT
    17151778 *
    1716  * @remark  This will assert in all failure paths.
     1779 * @remarks This will assert in all failure paths.
    17171780 */
    17181781static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM)
     
    17521815}
    17531816
     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 */
     1833static 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}
    17541882
    17551883/**
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r67956 r67987  
    654654    int rc = RTThreadCtxHookDestroy(pVCpu->vmm.s.hCtxHook);
    655655    AssertRC(rc);
     656    pVCpu->vmm.s.hCtxHook = NIL_RTTHREADCTXHOOK;
    656657}
    657658
     
    14361437
    14371438        case VMMR0_DO_GVMM_REGISTER_VMCPU:
    1438             if (pGVM != NULL && pVM != NULL )
     1439            if (pGVM != NULL && pVM != NULL)
    14391440                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);
    14401449            else
    14411450                rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/VMM/VMMR3/VMEmt.cpp

    r66156 r67987  
    248248    /*
    249249     * Cleanup and exit.
     250     * EMT0 does the VM destruction after all other EMTs have deregistered and terminated.
    250251     */
    251252    Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Rrc enmBefore=%d enmVMState=%d\n",
     
    275276
    276277        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);
    277285        AssertLogRelRC(rc2);
    278286    }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette