GVMMR0.cpp revision 5c318078b230f9867de2e1cc64a8407411a89f83
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * GVMM - Global VM Manager.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * Copyright (C) 2007 Sun Microsystems, Inc.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * additional information or have any questions.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @page pg_GVMM GVMM - The Global VM Manager
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The Global VM Manager lives in ring-0. It's main function at the moment
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * is to manage a list of all running VMs, keep a ring-0 only structure (GVM)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * for each of them, and assign them unique identifiers (so GMM can track
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * page owners). The idea for the future is to add an idle priority kernel
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * thread that can take care of tasks like page sharing.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The GVMM will create a ring-0 object for each VM when it's registered,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * this is both for session cleanup purposes and for having a point where
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * it's possible to implement usage polices later (in SUPR0ObjRegister).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Header Files *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Structures and Typedefs *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Global VM handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef struct GVMHANDLE
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The index of the next handle in the list (free or used). (0 is nil.) */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Our own index / handle value. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The pointer to the ring-0 only (aka global) VM structure. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The ring-0 mapping of the shared VM instance data. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /** The virtual machine object. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /** The session this VM is associated with. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /** The ring-0 handle of the EMT thread.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This is used for assertions and similar cases where we need to find the VM handle. */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/** Pointer to a global VM handle. */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * The GVMM instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef struct GVMM
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Eyecatcher / magic. */
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync /** The index of the head of the free handle chain. (0 is nil.) */
0c4004948fca34f2db87e7b38013137e9472c306vboxsync /** The index of the head of the active handle chain. (0 is nil.) */
0c4004948fca34f2db87e7b38013137e9472c306vboxsync /** The number of VMs. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync// /** The number of halted EMT threads. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync// uint16_t volatile cHaltedEMTs;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The lock used to serialize VM creation, destruction and associated events that
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync * isn't performance critical. Owners may acquire the list lock. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The lock used to serialize used list updates and accesses.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This indirectly includes scheduling since the scheduler will have to walk the
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * used list to examin running VMs. Owners may not acquire any other locks. */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /** The handle array.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * The size of this array defines the maximum number of currently running VMs.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The first entry is unused as it represents the NIL handle. */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /** @gcfgm{/GVMM/cVMsMeansCompany, 32-bit, 0, UINT32_MAX, 1}
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * The number of VMs that means we no longer consider ourselves alone on a CPU/Core.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @gcfgm{/GVMM/MinSleepAlone,32-bit, 0, 100000000, 750000, ns}
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * The minimum sleep time for when we're alone, in nano seconds.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /** @gcfgm{/GVMM/MinSleepCompany,32-bit,0, 100000000, 15000, ns}
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * The minimum sleep time for when we've got company, in nano seconds.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /** @gcfgm{/GVMM/EarlyWakeUp1, 32-bit, 0, 100000000, 25000, ns}
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * The limit for the first round of early wakeups, given in nano seconds.
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync /** @gcfgm{/GVMM/EarlyWakeUp2, 32-bit, 0, 100000000, 50000, ns}
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync * The limit for the second round of early wakeups, given in nano seconds.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/** Pointer to the GVMM instance data. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** The GVMM::u32Magic value (Charlie Haden). */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Global Variables *
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync*******************************************************************************/
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/** Pointer to the GVMM instance data.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * (Just my general dislike for global variables.) */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/** Macro for obtaining and validating the g_pGVMM pointer.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * On failure it will return from the invoking function with the specified return value.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @param pGVMM The name of the pGVMM variable.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @param rc The return value on failure. Use VERR_INTERNAL_ERROR for
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * VBox status codes.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync AssertMsgReturn((pGVMM)->u32Magic == GVMM_MAGIC, ("%p - %#x\n", (pGVMM), (pGVMM)->u32Magic), (rc)); \
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync } while (0)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/** Macro for obtaining and validating the g_pGVMM pointer, void function variant.
93f91841f87620d1cb6d0238b3d0d5e52cd3b9a4vboxsync * On failure it will return from the invoking function.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @param pGVMM The name of the pGVMM variable.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync AssertMsgReturnVoid((pGVMM)->u32Magic == GVMM_MAGIC, ("%p - %#x\n", (pGVMM), (pGVMM)->u32Magic)); \
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync } while (0)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Internal Functions *
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic int gvmmR0ByVM(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM, bool fTakeUsedLock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int gvmmR0ByVMAndEMT(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * Initializes the GVMM.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * This is called while owninng the loader sempahore (see supdrvIOCtl_LdrLoad()).
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @returns VBox status code.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * Allocate and initialize the instance data.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync int rc = RTSemFastMutexCreate(&pGVMM->CreateDestroyLock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* the nil handle */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /* the tail */
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync /* the rest */
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync while (i-- > 1)
0dd6dfbebcda0af90da4413aaea5f3b9d1817556vboxsync /* The default configuration values. */
0dd6dfbebcda0af90da4413aaea5f3b9d1817556vboxsync pGVMM->cVMsMeansCompany = 1; /** @todo should be adjusted to relative to the cpu count or something... */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync pGVMM->nsMinSleepAlone = 750000 /* ns (0.750 ms) */; /** @todo this should be adjusted to be 75% (or something) of the scheduler granularity... */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pGVMM->nsMinSleepCompany = 15000 /* ns (0.015 ms) */;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Terminates the GVM.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * This is called while owning the loader semaphore (see supdrvLdrFree()).
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * And unless something is wrong, there should be absolutely no VMs
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * registered at this point.
0dd6dfbebcda0af90da4413aaea5f3b9d1817556vboxsync SUPR0Printf("GVMMR0Term: iUsedHead=%#x! (cVMs=%#x)\n", pGVMM->iUsedHead, pGVMM->cVMs);
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * A quick hack for setting global config values.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * @returns VBox status code.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * @param pSession The session handle. Used for authentication.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * @param pszName The variable name.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * @param u64Value The new value.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsyncGVMMR0DECL(int) GVMMR0SetConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t u64Value)
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * Validate input.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * String switch time!
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (strncmp(pszName, "/GVMM/", sizeof("/GVMM/") - 1))
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync return VERR_CFGM_VALUE_NOT_FOUND; /* borrow status codes from CFGM... */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * A quick hack for getting global config values.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pSession The session handle. Used for authentication.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * @param pszName The variable name.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param u64Value The new value.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncGVMMR0DECL(int) GVMMR0QueryConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t *pu64Value)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Validate input.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * String switch time!
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (strncmp(pszName, "/GVMM/", sizeof("/GVMM/") - 1))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_CFGM_VALUE_NOT_FOUND; /* borrow status codes from CFGM... */
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * Try acquire the 'used' lock.
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * @returns IPRT status code, see RTSemFastMutexRequest.
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * @param pGVMM The GVMM instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogFlow(("gvmmR0UsedLock(%p)->%Rrc\n", pGVMM, rc));
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * Release the 'used' lock.
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * @returns IPRT status code, see RTSemFastMutexRelease.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * @param pGVMM The GVMM instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Try acquire the 'create & destroy' lock.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns IPRT status code, see RTSemFastMutexRequest.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pGVMM The GVMM instance data.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncDECLINLINE(int) gvmmR0CreateDestroyLock(PGVMM pGVMM)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync LogFlow(("++gvmmR0CreateDestroyLock(%p)\n", pGVMM));
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync int rc = RTSemFastMutexRequest(pGVMM->CreateDestroyLock);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync LogFlow(("gvmmR0CreateDestroyLock(%p)->%Rrc\n", pGVMM, rc));
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * Release the 'create & destroy' lock.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @returns IPRT status code, see RTSemFastMutexRequest.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @param pGVMM The GVMM instance data.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncDECLINLINE(int) gvmmR0CreateDestroyUnlock(PGVMM pGVMM)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync LogFlow(("--gvmmR0CreateDestroyUnlock(%p)\n", pGVMM));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTSemFastMutexRelease(pGVMM->CreateDestroyLock);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * Request wrapper for the GVMMR0CreateVM API.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pReq The request buffer.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncGVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq)
0db6a029780d9f9b347500e117320a8d5661efe5vboxsync * Validate the request.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * Execute it.
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * Allocates the VM structure and registers it with GVM.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * The caller will become the VM owner and there by the EMT.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * @returns VBox status code.
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync * @param pSession The support driver session.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * @param ppVM Where to store the pointer to the VM structure.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * @thread EMT.
0c4004948fca34f2db87e7b38013137e9472c306vboxsyncGVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM)
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync LogFlow(("GVMMR0CreateVM: pSession=%p\n", pSession));
0c4004948fca34f2db87e7b38013137e9472c306vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
0c4004948fca34f2db87e7b38013137e9472c306vboxsync AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR);
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * The whole allocation process is protected by the lock.
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * Allocate a handle first so we don't waste resources unnecessarily.
8f0fc87a72dee210b62acc9dd859a4bebf8bfb33vboxsync /* consistency checks, a bit paranoid as always. */
8f0fc87a72dee210b62acc9dd859a4bebf8bfb33vboxsync pHandle->pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_VM, gvmmR0HandleObjDestructor, pGVMM, pHandle);
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * Move the handle from the free to used list and perform permission checks.
8f0fc87a72dee210b62acc9dd859a4bebf8bfb33vboxsync rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pSession, NULL);
8f0fc87a72dee210b62acc9dd859a4bebf8bfb33vboxsync * Allocate the global VM structure (GVM) and initialize it.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* GMMR0InitPerVMData(pGVM); - later */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Allocate the shared VM structure and associated page array.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const size_t cPages = RT_ALIGN(sizeof(VM), PAGE_SIZE) >> PAGE_SHIFT;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = RTR0MemObjAllocLow(&pGVM->gvmm.s.VMMemObj, cPages << PAGE_SHIFT, false /* fExecutable */);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PVM pVM = (PVM)RTR0MemObjAddress(pGVM->gvmm.s.VMMemObj); AssertPtr(pVM);
26947320577c481b4afefdb0afbb855181e5b2e8vboxsync rc = RTR0MemObjAllocPage(&pGVM->gvmm.s.VMPagesMemObj, cPages * sizeof(SUPPAGE), false /* fExecutable */);
26947320577c481b4afefdb0afbb855181e5b2e8vboxsync PSUPPAGE paPages = (PSUPPAGE)RTR0MemObjAddress(pGVM->gvmm.s.VMPagesMemObj); AssertPtr(paPages);
26947320577c481b4afefdb0afbb855181e5b2e8vboxsync paPages[iPage].Phys = RTR0MemObjGetPagePhysAddr(pGVM->gvmm.s.VMMemObj, iPage);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Map them into ring-3.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTR0MemObjMapUser(&pGVM->gvmm.s.VMMapObj, pGVM->gvmm.s.VMMemObj, (RTR3PTR)-1, 0,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync pVM->pVMR3 = RTR0MemObjAddressR3(pGVM->gvmm.s.VMMapObj);
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync /** @todo SMP - need to get the cpu count and initialize all the VM pointers. */
a8139954a84d6e9090dd3a8371aa788351d45bc3vboxsync rc = RTR0MemObjMapUser(&pGVM->gvmm.s.VMPagesMapObj, pGVM->gvmm.s.VMPagesMemObj, (RTR3PTR)-1, 0,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
a8139954a84d6e9090dd3a8371aa788351d45bc3vboxsync pVM->paVMPagesR3 = RTR0MemObjAddressR3(pGVM->gvmm.s.VMPagesMapObj);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /* complete the handle - take the UsedLock sem just to be careful. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Log(("GVMMR0CreateVM: pVM=%p pVMR3=%p pGVM=%p hGVM=%d\n", pVM, pVM->pVMR3, pGVM, iHandle));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR0MemObjFree(pGVM->gvmm.s.VMMapObj, false /* fFreeMappings */);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR0MemObjFree(pGVM->gvmm.s.VMPagesMemObj, false /* fFreeMappings */);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR0MemObjFree(pGVM->gvmm.s.VMMemObj, false /* fFreeMappings */);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* else: The user wasn't permitted to create this VM. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The handle will be freed by gvmmR0HandleObjDestructor as we release the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * object reference here. A little extra mess because of non-recursive lock.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync SUPR0Printf("GVMMR0CreateVM: failed, rc=%d\n", rc);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * Initializes the per VM data belonging to GVMM.
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * @param pGVM Pointer to the global VM structure.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertCompile(RT_SIZEOFMEMB(GVM,gvmm.s) <= RT_SIZEOFMEMB(GVM,gvmm.padding));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Assert(RT_SIZEOFMEMB(GVM,gvmm.s) <= RT_SIZEOFMEMB(GVM,gvmm.padding));
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync * Does the VM initialization.
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync * @returns VBox status code.
44a2ecaf2d0fc196ab76cab13b3f909299e386d1vboxsync * @param pVM Pointer to the shared VM structure.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Validate the VM structure, state and handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pGVM->gvmm.s.HaltEventMulti == NIL_RTSEMEVENTMULTI)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTSemEventMultiCreate(&pGVM->gvmm.s.HaltEventMulti);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Destroys the VM, freeing all associated resources (the ring-0 ones anyway).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This is call from the vmR3DestroyFinalBit and from a error path in VMR3Create,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * and the caller is not the EMT thread, unfortunately. For security reasons, it
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * would've been nice if the caller was actually the EMT thread or that we somehow
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * could've associated the calling thread with the VM up front.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync * @param pVM Where to store the pointer to the VM structure.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @thread EMT if it's associated with the VM, otherwise any thread.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
cba6719bd64ec749967bbe931230452664109857vboxsync * Validate the VM structure, state and caller.
d7125f3a1b435761c393f9ec406e85a73ae2a3e7vboxsync AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgReturn(pVM->enmVMState >= VMSTATE_CREATING && pVM->enmVMState <= VMSTATE_TERMINATED, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
cba6719bd64ec749967bbe931230452664109857vboxsync AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_HANDLE);
cba6719bd64ec749967bbe931230452664109857vboxsync AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_HANDLE);
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);