third_party/virtualbox/src/VBox/VMM/VMMR3/VM.cpp
/**
 * Creates the UVM.
 *
 * This will not initialize the support library even if vmR3DestroyUVM
 * will terminate that.
 *
 * @returns VBox status code.
 * @param   cCpus               Number of virtual CPUs
 * @param   pVmm2UserMethods    Pointer to the optional VMM -> User method
 *                              table.
 * @param   ppUVM               Where to store the UVM pointer.
 */
Creates the UVM.
This will not initialize the support library even if vmR3DestroyUVM
will terminate that.

@returns VBox status code.
@param   cCpus               Number of virtual CPUs
@param   pVmm2UserMethods    Pointer to the optional VMM -> User method
table.
@param   ppUVM               Where to store the UVM pointer.
Creates the UVM . This will not initialize the support library even if vmR3DestroyUVM will terminate that . @returns VBox status code . @param cCpus Number of virtual CPUs @param pVmm2UserMethods Pointer to the optional VMM - > User method table . @param ppUVM Where to store the UVM pointer .
static int vmR3CreateUVM(uint32_t cCpus, PCVMM2USERMETHODS pVmm2UserMethods, PUVM *ppUVM)
{
    uint32_t i;
    PUVM pUVM = (PUVM)RTMemPageAllocZ(RT_UOFFSETOF_DYN(UVM, aCpus[cCpus]));
    AssertReturn(pUVM, VERR_NO_MEMORY);
    pUVM->u32Magic          = UVM_MAGIC;
    pUVM->cCpus             = cCpus;
    pUVM->pVmm2UserMethods  = pVmm2UserMethods;
    AssertCompile(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding));
    pUVM->vm.s.cUvmRefs      = 1;
    pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState;
    pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError;
    pUVM->vm.s.ppAtRuntimeErrorNext = &pUVM->vm.s.pAtRuntimeError;
    pUVM->vm.s.enmHaltMethod = VMHALTMETHOD_BOOTSTRAP;
    RTUuidClear(&pUVM->vm.s.Uuid);
    for (i = 0; i < cCpus; i++)
    {
        pUVM->aCpus[i].pUVM   = pUVM;
        pUVM->aCpus[i].idCpu  = i;
    }
    int rc = RTTlsAllocEx(&pUVM->vm.s.idxTLS, NULL);
    AssertRC(rc);
    if (RT_SUCCESS(rc))
    {
        for (i = 0; i < cCpus; i++)
            pUVM->aCpus[i].vm.s.EventSemWait = NIL_RTSEMEVENT;
        for (i = 0; i < cCpus; i++)
        {
            rc = RTSemEventCreate(&pUVM->aCpus[i].vm.s.EventSemWait);
            if (RT_FAILURE(rc))
                break;
        }
        if (RT_SUCCESS(rc))
        {
            rc = RTCritSectInit(&pUVM->vm.s.AtStateCritSect);
            if (RT_SUCCESS(rc))
            {
                rc = RTCritSectInit(&pUVM->vm.s.AtErrorCritSect);
                if (RT_SUCCESS(rc))
                {
                    rc = PDMR3InitUVM(pUVM);
                    if (RT_SUCCESS(rc))
                    {
                        rc = STAMR3InitUVM(pUVM);
                        if (RT_SUCCESS(rc))
                        {
                            rc = MMR3InitUVM(pUVM);
                            if (RT_SUCCESS(rc))
                            {
                                for (i = 0; i < cCpus; i++)
                                {
                                    rc = RTThreadCreateF(&pUVM->aCpus[i].vm.s.ThreadEMT, vmR3EmulationThread, &pUVM->aCpus[i],
                                                         _1M, RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE,
                                                         cCpus > 1 ? "EMT-%u" : "EMT", i);
                                    if (RT_FAILURE(rc))
                                        break;
                                    pUVM->aCpus[i].vm.s.NativeThreadEMT = RTThreadGetNative(pUVM->aCpus[i].vm.s.ThreadEMT);
                                }
                                if (RT_SUCCESS(rc))
                                {
                                    *ppUVM = pUVM;
                                    return VINF_SUCCESS;
                                }
                                while (i-- > 0)
                                {
                                }
                                MMR3TermUVM(pUVM);
                            }
                            STAMR3TermUVM(pUVM);
                        }
                        PDMR3TermUVM(pUVM);
                    }
                    RTCritSectDelete(&pUVM->vm.s.AtErrorCritSect);
                }
                RTCritSectDelete(&pUVM->vm.s.AtStateCritSect);
            }
        }
        for (i = 0; i < cCpus; i++)
        {
            RTSemEventDestroy(pUVM->aCpus[i].vm.s.EventSemWait);
            pUVM->aCpus[i].vm.s.EventSemWait = NIL_RTSEMEVENT;
        }
        RTTlsFree(pUVM->vm.s.idxTLS);
    }
    RTMemPageFree(pUVM, RT_UOFFSETOF_DYN(UVM, aCpus[pUVM->cCpus]));
    return rc;
}
static int vmR3CreateUVM ( uint32_t cCpus , PCVMM2USERMETHODS pVmm2UserMethods , PUVM * ppUVM ) { uint32_t i ; PUVM pUVM = ( PUVM ) RTMemPageAllocZ ( RT_UOFFSETOF_DYN ( UVM , aCpus [ cCpus ] ) ) ; AssertReturn ( pUVM , VERR_NO_MEMORY ) ; pUVM -> u32Magic = UVM_MAGIC ; pUVM -> cCpus = cCpus ; pUVM -> pVmm2UserMethods = pVmm2UserMethods ; AssertCompile ( sizeof ( pUVM -> vm . s ) <= sizeof ( pUVM -> vm . padding ) ) ; pUVM -> vm . s . cUvmRefs = 1 ; pUVM -> vm . s . ppAtStateNext = & pUVM -> vm . s . pAtState ; pUVM -> vm . s . ppAtErrorNext = & pUVM -> vm . s . pAtError ; pUVM -> vm . s . ppAtRuntimeErrorNext = & pUVM -> vm . s . pAtRuntimeError ; pUVM -> vm . s . enmHaltMethod = VMHALTMETHOD_BOOTSTRAP ; RTUuidClear ( & pUVM -> vm . s . Uuid ) ; for ( i = 0 ; i < cCpus ; i ++ ) { pUVM -> aCpus [ i ] . pUVM = pUVM ; pUVM -> aCpus [ i ] . idCpu = i ; } int rc = RTTlsAllocEx ( & pUVM -> vm . s . idxTLS , NULL ) ; AssertRC ( rc ) ; if ( RT_SUCCESS ( rc ) ) { for ( i = 0 ; i < cCpus ; i ++ ) pUVM -> aCpus [ i ] . vm . s . EventSemWait = NIL_RTSEMEVENT ; for ( i = 0 ; i < cCpus ; i ++ ) { rc = RTSemEventCreate ( & pUVM -> aCpus [ i ] . vm . s . EventSemWait ) ; if ( RT_FAILURE ( rc ) ) break ; } if ( RT_SUCCESS ( rc ) ) { rc = RTCritSectInit ( & pUVM -> vm . s . AtStateCritSect ) ; if ( RT_SUCCESS ( rc ) ) { rc = RTCritSectInit ( & pUVM -> vm . s . AtErrorCritSect ) ; if ( RT_SUCCESS ( rc ) ) { rc = PDMR3InitUVM ( pUVM ) ; if ( RT_SUCCESS ( rc ) ) { rc = STAMR3InitUVM ( pUVM ) ; if ( RT_SUCCESS ( rc ) ) { rc = MMR3InitUVM ( pUVM ) ; if ( RT_SUCCESS ( rc ) ) { for ( i = 0 ; i < cCpus ; i ++ ) { rc = RTThreadCreateF ( & pUVM -> aCpus [ i ] . vm . s . ThreadEMT , vmR3EmulationThread , & pUVM -> aCpus [ i ] , _1M , RTTHREADTYPE_EMULATION , RTTHREADFLAGS_WAITABLE , cCpus > 1 ? " " : " " , i ) ; if ( RT_FAILURE ( rc ) ) break ; pUVM -> aCpus [ i ] . vm . s . NativeThreadEMT = RTThreadGetNative ( pUVM -> aCpus [ i ] . vm . s . ThreadEMT ) ; } if ( RT_SUCCESS ( rc ) ) { * ppUVM = pUVM ; return VINF_SUCCESS ; } while ( i -- > 0 ) { } MMR3TermUVM ( pUVM ) ; } STAMR3TermUVM ( pUVM ) ; } PDMR3TermUVM ( pUVM ) ; } RTCritSectDelete ( & pUVM -> vm . s . AtErrorCritSect ) ; } RTCritSectDelete ( & pUVM -> vm . s . AtStateCritSect ) ; } } for ( i = 0 ; i < cCpus ; i ++ ) { RTSemEventDestroy ( pUVM -> aCpus [ i ] . vm . s . EventSemWait ) ; pUVM -> aCpus [ i ] . vm . s . EventSemWait = NIL_RTSEMEVENT ; } RTTlsFree ( pUVM -> vm . s . idxTLS ) ; } RTMemPageFree ( pUVM , RT_UOFFSETOF_DYN ( UVM , aCpus [ pUVM -> cCpus ] ) ) ; return rc ; }
Creates the UVM.
Creates the UVM .
/*
     * Create and initialize the UVM.
     */ /* Initialize the VMCPU array in the UVM. */ /* Allocate a TLS entry to store the VMINTUSERPERVMCPU pointer. */ /* Allocate a halt method event semaphore for each VCPU. */ /*
                     * Init fundamental (sub-)components - STAM, MMR3Heap and PDMLdr.
                     */ /*
                                 * Start the emulation threads for all VMCPUs.
                                 */ /* bail out. */ /** @todo rainy day: terminate the EMTs. */