GVMMR0.cpp revision eb3d4bdcfedc1f41576ce8a3a53da32380002272
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * GVMM - Global VM Manager.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Copyright (C) 2007 InnoTek Systemberatung GmbH
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * available from http://www.virtualbox.org. This file is free software;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * General Public License as published by the Free Software Foundation,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** @page pg_GVMM GVMM - The Global VM Manager
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The Global VM Manager lives in ring-0. It's main function at the moment
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * is to manage a list of all running VMs, keep a ring-0 only structure (GVM)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * for each of them, and assign them unique identifiers (so GMM can track
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * page owners). The idea for the future is to add an idle priority kernel
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * thread that can take care of tasks like page sharing.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The GVMM will create a ring-0 object for each VM when it's registered,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * this is both for session cleanup purposes and for having a point where
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * it's possible to implement usage polices later (in SUPR0ObjRegister).
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Header Files *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Structures and Typedefs *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Global VM handle.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsynctypedef struct GVMHANDLE
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The index of the next handle in the list (free or used). (0 is nil.) */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** Our own index / handle value. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The pointer to the ring-0 only (aka global) VM structure. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The ring-0 mapping of the shared VM instance data. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /** The virtual machine object. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The session this VM is associated with. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The ring-0 handle of the EMT thread.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * This is used for assertions and similar cases where we need to find the VM handle. */
787c7e6ef15f993c455c374f5158e7bb753b1c33vboxsync/** Pointer to a global VM handle. */
787c7e6ef15f993c455c374f5158e7bb753b1c33vboxsync * The GVMM instance data.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsynctypedef struct GVMM
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** Eyecatcher / magic. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The index of the head of the free handle chain. (0 is nil.) */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The index of the head of the active handle chain. (0 is nil.) */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The number of VMs. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync// /** The number of halted EMT threads. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync// uint16_t volatile cHaltedEMTs;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The lock used to serialize VM creation, destruction and associated events that
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * isn't performance critical. Owners may acquire the list lock. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The lock used to serialize used list updates and accesses.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This indirectly includes scheduling since the scheduler will have to walk the
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * used list to examin running VMs. Owners may not acquire any other locks. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The handle array.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The size of this array defines the maximum number of currently running VMs.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The first entry is unused as it represents the NIL handle. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The number of VMs that means we no longer considers ourselves along on a CPU/Core.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @gcfgm /GVMM/cVMsMeansCompany 32-bit 0..UINT32_MAX
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The minimum sleep time for when we're alone, in nano seconds.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @gcfgm /GVMM/MinSleepAlone 32-bit 0..100000000
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The minimum sleep time for when we've got company, in nano seconds.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @gcfgm /GVMM/MinSleepCompany 32-bit 0..100000000
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The limit for the first round of early wakeups, given in nano seconds.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @gcfgm /GVMM/EarlyWakeUp1 32-bit 0..100000000
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** The limit for the second round of early wakeups, given in nano seconds.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @gcfgm /GVMM/EarlyWakeUp2 32-bit 0..100000000
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** Pointer to the GVMM instance data. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** The GVMM::u32Magic value (Charlie Haden). */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Global Variables *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** Pointer to the GVMM instance data.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * (Just my general dislike for global variables.) */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** Macro for obtaining and validating the g_pGVMM pointer.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * On failure it will return from the invoking function with the specified return value.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pGVMM The name of the pGVMM variable.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param rc The return value on failure. Use VERR_INTERNAL_ERROR for
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * VBox status codes.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgReturn((pGVMM)->u32Magic == GVMM_MAGIC, ("%p - %#x\n", (pGVMM), (pGVMM)->u32Magic), (rc)); \
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync } while (0)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** Macro for obtaining and validating the g_pGVMM pointer, void function variant.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * On failure it will return from the invoking function.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pGVMM The name of the pGVMM variable.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgReturnVoid((pGVMM)->u32Magic == GVMM_MAGIC, ("%p - %#x\n", (pGVMM), (pGVMM)->u32Magic)); \
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync } while (0)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Internal Functions *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic int gvmmR0ByVM(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM, bool fTakeUsedLock);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic int gvmmR0ByVMAndEMT(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM);
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync * Initializes the GVMM.
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync * This is called while owninng the loader sempahore (see supdrvIOCtl_LdrLoad()).
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Allocate and initialize the instance data.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync int rc = RTSemFastMutexCreate(&pGVMM->CreateDestroyLock);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* the nil handle */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* the tail */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* the rest */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync while (i-- > 1)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* The default configuration values. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pGVMM->cVMsMeansCompany = 1; /** @todo should be adjusted to relative to the cpu count or something... */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pGVMM->nsMinSleepAlone = 750000 /* ns (0.750 ms) */; /** @todo this should be adjusted to be 75% (or something) of the scheduler granularity... */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pGVMM->nsMinSleepCompany = 15000 /* ns (0.015 ms) */;
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * Terminates the GVM.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * This is called while owning the loader semaphore (see supdrvLdrFree()).
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * And unless something is wrong, there should be absolutely no VMs
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * registered at this point.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync SUPR0Printf("GVMMR0Term: iUsedHead=%#x! (cVMs=%#x)\n", pGVMM->iUsedHead, pGVMM->cVMs);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * A quick hack for setting global config values.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pSession The session handle. Used for authentication.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pszName The variable name.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param u64Value The new value.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncGVMMR0DECL(int) GVMMR0SetConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t u64Value)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Validate input.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * String switch time!
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (strncmp(pszName, "/GVMM/", sizeof("/GVMM/") - 1))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync return VERR_CFGM_VALUE_NOT_FOUND; /* borrow status codes from CFGM... */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * A quick hack for getting global config values.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pSession The session handle. Used for authentication.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pszName The variable name.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param u64Value The new value.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncGVMMR0DECL(int) GVMMR0QueryConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t *pu64Value)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Validate input.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * String switch time!
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (strncmp(pszName, "/GVMM/", sizeof("/GVMM/") - 1))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync return VERR_CFGM_VALUE_NOT_FOUND; /* borrow status codes from CFGM... */
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync * Request wrapper for the GVMMR0CreateVM API.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pReq The request buffer.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncGVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Validate the request.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Execute it.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Allocates the VM structure and registers it with GVM.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @returns VBox status code.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @param pSession The support driver session.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @param ppVM Where to store the pointer to the VM structure.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @thread Any thread.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncGVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync LogFlow(("GVMMR0CreateVM: pSession=%p\n", pSession));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync AssertReturn(RTThreadNativeSelf() != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * The whole allocation process is protected by the lock.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync int rc = RTSemFastMutexRequest(pGVMM->CreateDestroyLock);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Allocate a handle first so we don't waste resources unnecessarily.
cad8876b46f9e366c4a1007a40c27ca1df078950vboxsync /* consistency checks, a bit paranoid as always. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pHandle->pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_VM, gvmmR0HandleObjDestructor, pGVMM, pHandle);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Move the handle from the free to used list and perform permission checks.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pSession, NULL);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Allocate the global VM structure (GVM) and initialize it.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* GMMR0InitPerVMData(pGVM); - later */
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync * Allocate the shared VM structure and associated page array.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync const size_t cPages = RT_ALIGN(sizeof(VM), PAGE_SIZE) >> PAGE_SHIFT;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = RTR0MemObjAllocLow(&pGVM->gvmm.s.VMMemObj, cPages << PAGE_SHIFT, false /* fExecutable */);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync PVM pVM = (PVM)RTR0MemObjAddress(pGVM->gvmm.s.VMMemObj); AssertPtr(pVM);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = RTR0MemObjAllocPage(&pGVM->gvmm.s.VMPagesMemObj, cPages * sizeof(SUPPAGE), false /* fExecutable */);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync PSUPPAGE paPages = (PSUPPAGE)RTR0MemObjAddress(pGVM->gvmm.s.VMPagesMemObj); AssertPtr(paPages);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync paPages[iPage].Phys = RTR0MemObjGetPagePhysAddr(pGVM->gvmm.s.VMMemObj, iPage);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Map them into ring-3.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = RTR0MemObjMapUser(&pGVM->gvmm.s.VMMapObj, pGVM->gvmm.s.VMMemObj, (RTR3PTR)-1, 0,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVM->pVMR3 = RTR0MemObjAddressR3(pGVM->gvmm.s.VMMapObj);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = RTR0MemObjMapUser(&pGVM->gvmm.s.VMPagesMapObj, pGVM->gvmm.s.VMPagesMemObj, (RTR3PTR)-1, 0,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pVM->paVMPagesR3 = RTR0MemObjAddressR3(pGVM->gvmm.s.VMPagesMapObj);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* complete the handle - take the UsedLock sem just to be careful. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Log(("GVMMR0CreateVM: pVM=%p pVMR3=%p pGVM=%p hGVM=%d\n", pVM, pVM->pVMR3, pGVM, iHandle));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync RTR0MemObjFree(pGVM->gvmm.s.VMMapObj, false /* fFreeMappings */);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync RTR0MemObjFree(pGVM->gvmm.s.VMPagesMemObj, false /* fFreeMappings */);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync RTR0MemObjFree(pGVM->gvmm.s.VMMemObj, false /* fFreeMappings */);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* else: The user wasn't permitted to create this VM. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The handle will be freed by gvmmR0HandleObjDestructor as we release the
787c7e6ef15f993c455c374f5158e7bb753b1c33vboxsync * object reference here. A little extra mess because of non-recursive lock.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync SUPR0Printf("GVMMR0CreateVM: failed, rc=%d\n", rc);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Initializes the per VM data belonging to GVMM.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pGVM Pointer to the global VM structure.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertCompile(RT_SIZEOFMEMB(GVM,gvmm.s) <= RT_SIZEOFMEMB(GVM,gvmm.padding));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Assert(RT_SIZEOFMEMB(GVM,gvmm.s) <= RT_SIZEOFMEMB(GVM,gvmm.padding));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Associates an EMT thread with a VM.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This is called early during the ring-0 VM initialization so assertions later in
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * the process can be handled gracefully.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pVM The VM instance data (aka handle), ring-0 mapping of course.
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync * @thread EMT.
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync LogFlow(("GVMMR0AssociateEMTWithVM: pVM=%p\n", pVM));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync * Validate the VM structure, state and handle.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgReturn(pVM->enmVMState == VMSTATE_CREATING, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_NOT_SUPPORTED);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_HANDLE);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_HANDLE);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Take the lock, validate the handle and update the structure members.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync int rc = RTSemFastMutexRequest(pGVMM->CreateDestroyLock);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync LogFlow(("GVMMR0AssociateEMTWithVM: returns %Vrc (hEMT=%RTnthrd)\n", rc, hEMT));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Does the VM initialization.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pVM Pointer to the shared VM structure.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Validate the VM structure, state and handle.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (pGVM->gvmm.s.HaltEventMulti == NIL_RTSEMEVENTMULTI)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync rc = RTSemEventMultiCreate(&pGVM->gvmm.s.HaltEventMulti);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Disassociates the EMT thread from a VM.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This is called last in the ring-0 VM termination. After this point anyone is
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * allowed to destroy the VM. Ideally, we should associate the VM with the thread
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * that's going to call GVMMR0DestroyVM for optimal security, but that's impractical
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * at present.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pVM The VM instance data (aka handle), ring-0 mapping of course.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @thread EMT.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncGVMMR0DECL(int) GVMMR0DisassociateEMTFromVM(PVM pVM)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync LogFlow(("GVMMR0DisassociateEMTFromVM: pVM=%p\n", pVM));
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Validate the VM structure, state and handle.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertMsgReturn(pVM->enmVMState >= VMSTATE_CREATING && pVM->enmVMState <= VMSTATE_DESTROYING, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_NOT_SUPPORTED);
return rc;
AssertMsgReturn(pVM->enmVMState >= VMSTATE_CREATING && pVM->enmVMState <= VMSTATE_TERMINATED, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
return rc;
if ( !iHandle
while (!iPrev)
if (RT_UNLIKELY(c-- <= 0))
iPrev = 0;
if (!iPrev)
/* The VM and VM pages mappings/allocations. */
return VERR_INVALID_POINTER;
return VERR_INVALID_POINTER;
return VERR_INVALID_HANDLE;
if (fTakeUsedLock)
return VERR_INVALID_HANDLE;
return VERR_INVALID_HANDLE;
return VERR_INVALID_HANDLE;
return VERR_INVALID_HANDLE;
return VERR_INVALID_HANDLE;
return VINF_SUCCESS;
return pGVM;
return NULL;
AssertMsgReturn(pHandle->hEMT == hAllegedEMT, ("hEMT %x hAllegedEMT %x\n", pHandle->hEMT, hAllegedEMT), VERR_NOT_OWNER);
return VINF_SUCCESS;
* This is used by the assertion machinery in VMMR0.cpp to avoid causing
return NULL;
return NULL;
unsigned cWoken = 0;
unsigned cHalted = 0;
unsigned cTodo2nd = 0;
unsigned cTodo3rd = 0;
if (u64)
cWoken++;
cHalted++;
cTodo2nd++;
cTodo3rd++;
if (cTodo2nd)
cWoken++;
if (cTodo3rd)
cWoken++;
return cWoken;
return rc;
return rc;
return rc;
if (!fYield)
return rc;
if (pVM)
return rc;
return VINF_SUCCESS;
AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
if (pVM)
return rc;
return VINF_SUCCESS;
AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);