VirtualBox

Changeset 5031 in vbox for trunk/src


Ignore:
Timestamp:
Sep 25, 2007 10:27:37 PM (17 years ago)
Author:
vboxsync
Message:

Use GVMMR3CreateVM. the new GVM structure is a ring-0 only VM structure. the old VM structure is the shared ring-0, ring-3 and GC VM structure.

Location:
trunk/src/VBox
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c

    r4971 r5031  
    9999    { "RTMemAllocZ",                            (void *)RTMemAllocZ },
    100100    { "RTMemFree",                              (void *)RTMemFree },
     101    /*{ "RTMemDup",                               (void *)RTMemDup },*/
     102    { "RTMemRealloc",                           (void *)RTMemRealloc },
     103    { "RTR0MemObjAllocLow",                     (void *)RTR0MemObjAllocLow },
     104    { "RTR0MemObjAllocPage",                    (void *)RTR0MemObjAllocPage },
     105    { "RTR0MemObjAllocPhys",                    (void *)RTR0MemObjAllocPhys },
     106    { "RTR0MemObjAllocPhysNC",                  (void *)RTR0MemObjAllocPhysNC },
     107    { "RTR0MemObjLockUser",                     (void *)RTR0MemObjLockUser },
     108    { "RTR0MemObjMapKernel",                    (void *)RTR0MemObjMapKernel },
     109    { "RTR0MemObjMapUser",                      (void *)RTR0MemObjMapUser },
     110    { "RTR0MemObjAddress",                      (void *)RTR0MemObjAddress },
     111    { "RTR0MemObjAddressR3",                    (void *)RTR0MemObjAddressR3 },
     112    { "RTR0MemObjSize",                         (void *)RTR0MemObjSize },
     113    { "RTR0MemObjIsMapping",                    (void *)RTR0MemObjIsMapping },
     114    { "RTR0MemObjGetPagePhysAddr",              (void *)RTR0MemObjGetPagePhysAddr },
     115    { "RTR0MemObjFree",                         (void *)RTR0MemObjFree },
    101116/* These doesn't work yet on linux - use fast mutexes!
    102117    { "RTSemMutexCreate",                       (void *)RTSemMutexCreate },
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r4987 r5031  
    525525    {
    526526        AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
    527         AssertReturn(pReqHdr->u32Magic != SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
     527        AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
    528528        const size_t cbReq = pReqHdr->cbReq;
    529529
  • trunk/src/VBox/HostDrivers/Support/SUPR0.def

    r4974 r5031  
    1414;  distribution. VirtualBox OSE is distributed in the hope that it will
    1515;  be useful, but WITHOUT ANY WARRANTY of any kind.
     16;
    1617
    1718LIBRARY SUPR0.dll
     
    3536    RTMemAllocZ
    3637    RTMemFree
     38    RTMemRealloc
     39    RTR0MemObjAllocLow
     40    RTR0MemObjAllocPage
     41    RTR0MemObjAllocPhys
     42    RTR0MemObjAllocPhysNC
     43    RTR0MemObjLockUser
     44    RTR0MemObjMapKernel
     45    RTR0MemObjMapUser
     46    RTR0MemObjAddress
     47    RTR0MemObjAddressR3
     48    RTR0MemObjSize
     49    RTR0MemObjIsMapping
     50    RTR0MemObjGetPagePhysAddr
     51    RTR0MemObjFree
    3752    ; broken - RTSemMutexCreate
    3853    ; broken - RTSemMutexRequest
  • trunk/src/VBox/VMM/PDM.cpp

    r4188 r5031  
    149149{
    150150    LogFlow(("PDMR3Init\n"));
     151
    151152    /*
    152153     * Assert alignment and sizes.
  • trunk/src/VBox/VMM/PDMLdr.cpp

    r4071 r5031  
    6969
    7070/**
     71 * Loads the VMMR0.r0 module before the VM is created.
     72 *
     73 * The opqaue VMMR0 module pointer is passed on to PDMR3Init later in
     74 * the init process or PDMR3LdrUnloadVMMR0 in case of some init failure before PDMR3Init.
     75 *
     76 * @returns VBox status code.
     77 * @param   ppvOpaque       Where to return the opaque VMMR0.r0 module handle one success.
     78 *
     79 * @remarks Yes, this is a kind of hacky and should go away. See @todo in VMR3Create.
     80 */
     81PDMR3DECL(int) PDMR3LdrLoadVMMR0(void **ppvOpaque)
     82{
     83    *ppvOpaque = NULL;
     84
     85    /*
     86     * Resolve the filename and allocate the module list node.
     87     */
     88    char *pszFilename = pdmR3FileR0(VMMR0_MAIN_MODULE_NAME);
     89    PPDMMOD pModule = (PPDMMOD)RTMemAllocZ(sizeof(*pModule) + strlen(pszFilename));
     90    if (!pModule)
     91    {
     92        RTMemTmpFree(pszFilename);
     93        return VERR_NO_MEMORY;
     94    }
     95    strcpy(pModule->szName, VMMR0_MAIN_MODULE_NAME);
     96    pModule->eType = PDMMOD_TYPE_R0;
     97    strcpy(pModule->szFilename, pszFilename);
     98    RTMemTmpFree(pszFilename);
     99
     100    /*
     101     * Ask the support library to load it.
     102     */
     103    void *pvImageBase;
     104    int rc = SUPLoadModule(pModule->szFilename, pModule->szName, &pvImageBase);
     105    if (RT_SUCCESS(rc))
     106    {
     107        pModule->hLdrMod = NIL_RTLDRMOD;
     108        pModule->ImageBase = (uintptr_t)pvImageBase;
     109        *ppvOpaque = pModule;
     110
     111        Log(("PDMR3LdrLoadVMMR0: Loaded %s at %VGvx (%s)\n", pModule->szName, (RTGCPTR)pModule->ImageBase, pModule->szFilename));
     112        return VINF_SUCCESS;
     113    }
     114
     115    LogRel(("PDMR3LdrLoadVMMR0: rc=%Vrc szName=%s szFilename=%s\n", rc, pModule->szName, pModule->szFilename));
     116    RTMemFree(pModule);
     117    return rc;
     118}
     119
     120
     121/**
     122 * Register the VMMR0.r0 module with the created VM or unload it if
     123 * we failed to create the VM (pVM == NULL).
     124 *
     125 * @param   pVM         The VM pointer. NULL if we failed to create the VM and
     126 *                      the module should be unloaded and freed.
     127 * @param   pvOpaque    The value returned by PDMR3LDrLoadVMMR0().
     128 *
     129 * @remarks Yes, this is a kind of hacky and should go away. See @todo in VMR3Create.
     130 */
     131PDMR3DECL(void) PDMR3LdrLoadVMMR0Part2(PVM pVM, void *pvOpaque)
     132{
     133    PPDMMOD pModule = (PPDMMOD)pvOpaque;
     134    AssertPtrReturnVoid(pModule);
     135
     136    if (pVM)
     137    {
     138        /*
     139         * Register the R0 module loaded by PDMR3LdrLoadVMMR0
     140         */
     141        Assert(!pVM->pdm.s.pModules);
     142        pModule->pNext = pVM->pdm.s.pModules;
     143        pVM->pdm.s.pModules = pModule;
     144    }
     145    else
     146    {
     147        /*
     148         * Failed, unload the module.
     149         */
     150        int rc2 = SUPFreeModule((void *)(uintptr_t)pModule->ImageBase);
     151        AssertRC(rc2);
     152        pModule->ImageBase = 0;
     153        RTMemFree(pvOpaque);
     154    }
     155}
     156
     157
     158/**
    71159 * Init the module loader part of PDM.
    72160 *
     
    76164 * @returns VBox stutus code.
    77165 * @param   pVM         VM handle.
     166 * @param   pvVMMR0Mod  The opqaue returned by PDMR3LdrLoadVMMR0.
    78167 */
    79168int pdmR3LdrInit(PVM pVM)
     
    85174
    86175    /*
    87      * Load the mandatory R0 and GC modules.
    88      */
    89     int rc = pdmR3LoadR0(pVM, NULL, "VMMR0.r0");
    90     if (VBOX_SUCCESS(rc))
    91         rc = PDMR3LoadGC(pVM, NULL, VMMGC_MAIN_MODULE_NAME);
    92     return rc;
     176     * Load the mandatory GC module, the VMMR0.r0 is loaded before VM creation.
     177     */
     178    return PDMR3LoadGC(pVM, NULL, VMMGC_MAIN_MODULE_NAME);
    93179#endif
    94180}
     181
    95182
    96183/**
     
    521608        pCur = pCur->pNext;
    522609    }
     610    AssertReturn(!strcmp(pszName, VMMR0_MAIN_MODULE_NAME), VERR_INTERNAL_ERROR);
    523611
    524612    /*
     
    9381026    char szPath[RTPATH_MAX];
    9391027    int  rc;
    940    
    941     rc = fShared ? RTPathSharedLibs(szPath, sizeof(szPath)) 
     1028
     1029    rc = fShared ? RTPathSharedLibs(szPath, sizeof(szPath))
    9421030                 : RTPathAppPrivateArch(szPath, sizeof(szPath));
    9431031    if (!VBOX_SUCCESS(rc))
  • trunk/src/VBox/VMM/VM.cpp

    r4958 r5031  
    2323#include <VBox/cfgm.h>
    2424#include <VBox/vmm.h>
     25#include <VBox/gvmm.h>
    2526#include <VBox/mm.h>
    2627#include <VBox/cpum.h>
     
    175176
    176177    /*
    177      * Init support library.
     178     * Init support library and load the VMMR0.r0 module.
    178179     */
    179180    PSUPDRVSESSION pSession = 0;
     
    181182    if (VBOX_SUCCESS(rc))
    182183    {
    183         /*
    184          * Allocate memory for the VM structure.
    185          */
    186         PVMR0 pVMR0 = NIL_RTR0PTR;
    187         PVM pVM = NULL;
    188         const unsigned cPages = RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT;
    189         PSUPPAGE paPages = (PSUPPAGE)RTMemAllocZ(cPages * sizeof(SUPPAGE));
    190         AssertReturn(paPages, VERR_NO_MEMORY);
    191         rc = SUPLowAlloc(cPages, (void **)&pVM, &pVMR0, &paPages[0]);
    192         if (VBOX_SUCCESS(rc))
     184        /** @todo This is isn't very nice, it would be preferrable to move the loader bits
     185         * out of the VM structure and into a ring-3 only thing. There's a big deal of the
     186         * error path that we now won't unload the VMMR0.r0 module in. This isn't such a
     187         * big deal right now, but I'll have to get back to this later. (bird) */
     188        void *pvVMMR0Opaque;
     189        rc = PDMR3LdrLoadVMMR0(&pvVMMR0Opaque);
     190        if (RT_SUCCESS(rc))
    193191        {
    194             Log(("VMR3Create: Allocated pVM=%p pVMR0=%p\n", pVM, pVMR0));
    195 
    196192            /*
    197              * Do basic init of the VM structure.
     193             * Request GVMM to create a new VM for us.
    198194             */
    199             memset(pVM, 0, sizeof(*pVM));
    200             pVM->pVMR0 = pVMR0;
    201             pVM->pVMR3 = pVM;
    202             pVM->paVMPagesR3 = paPages;
    203             pVM->pSession = pSession;
    204             pVM->vm.s.offVM = RT_OFFSETOF(VM, vm.s);
    205             pVM->vm.s.ppAtResetNext = &pVM->vm.s.pAtReset;
    206             pVM->vm.s.ppAtStateNext = &pVM->vm.s.pAtState;
    207             pVM->vm.s.ppAtErrorNext = &pVM->vm.s.pAtError;
    208             pVM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;
    209             rc = RTSemEventCreate(&pVM->vm.s.EventSemWait);
    210             AssertRCReturn(rc, rc);
    211 
    212             /*
    213              * Initialize STAM.
    214              */
    215             rc = STAMR3Init(pVM);
    216             if (VBOX_SUCCESS(rc))
     195            GVMMCREATEVMREQ CreateVMReq;
     196            CreateVMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     197            CreateVMReq.Hdr.cbReq = sizeof(CreateVMReq);
     198            CreateVMReq.pSession = pSession;
     199            CreateVMReq.pVMR0 = NIL_RTR0PTR;
     200            CreateVMReq.pVMR3 = NULL;
     201            rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
     202            if (RT_SUCCESS(rc))
    217203            {
     204                PVM pVM = CreateVMReq.pVMR3;
     205                AssertRelease(VALID_PTR(pVM));
     206                Log(("VMR3Create: Created pVM=%p pVMR0=%p\n", pVM, pVM->pVMR0));
     207                PDMR3LdrLoadVMMR0Part2(pVM, pvVMMR0Opaque);
     208
    218209                /*
    219                  * Create the EMT thread and make it do VM initialization and go sleep
    220                  * in EM waiting for requests.
     210                 * Do basic init of the VM structure.
    221211                 */
    222                 VMEMULATIONTHREADARGS Args;
    223                 Args.pVM = pVM;
    224                 rc = RTThreadCreate(&pVM->ThreadEMT, &vmR3EmulationThread, &Args, _1M,
    225                                     RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "EMT");
     212                pVM->vm.s.offVM = RT_OFFSETOF(VM, vm.s);
     213                pVM->vm.s.ppAtResetNext = &pVM->vm.s.pAtReset;
     214                pVM->vm.s.ppAtStateNext = &pVM->vm.s.pAtState;
     215                pVM->vm.s.ppAtErrorNext = &pVM->vm.s.pAtError;
     216                pVM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;
     217                rc = RTSemEventCreate(&pVM->vm.s.EventSemWait);
     218                AssertRCReturn(rc, rc);
     219
     220                /*
     221                 * Initialize STAM.
     222                 */
     223                rc = STAMR3Init(pVM);
    226224                if (VBOX_SUCCESS(rc))
    227225                {
    228226                    /*
    229                      * Issue a VM Create request and wait for it to complete.
     227                     * Create the EMT thread, it will start up and wait for requests to process.
    230228                     */
    231                     PVMREQ pReq;
    232                     rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Create, 5, pVM, pfnVMAtError, pvUserVM, pfnCFGMConstructor, pvUserCFGM);
     229                    VMEMULATIONTHREADARGS Args;
     230                    Args.pVM = pVM;
     231                    rc = RTThreadCreate(&pVM->ThreadEMT, vmR3EmulationThread, &Args, _1M,
     232                                        RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "EMT");
    233233                    if (VBOX_SUCCESS(rc))
    234234                    {
    235                         rc = pReq->iStatus;
    236                         VMR3ReqFree(pReq);
     235                        /*
     236                         * Issue a VM Create request and wait for it to complete.
     237                         */
     238                        PVMREQ pReq;
     239                        rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Create, 5,
     240                                         pVM, pfnVMAtError, pvUserVM, pfnCFGMConstructor, pvUserCFGM);
    237241                        if (VBOX_SUCCESS(rc))
    238242                        {
    239                             *ppVM = pVM;
    240                             LogFlow(("VMR3Create: returns VINF_SUCCESS *ppVM=%p\n", pVM));
    241                             return VINF_SUCCESS;
     243                            rc = pReq->iStatus;
     244                            VMR3ReqFree(pReq);
     245                            if (VBOX_SUCCESS(rc))
     246                            {
     247                                *ppVM = pVM;
     248                                LogFlow(("VMR3Create: returns VINF_SUCCESS *ppVM=%p\n", pVM));
     249                                return VINF_SUCCESS;
     250                            }
     251
     252                            AssertMsgFailed(("vmR3Create failed rc=%Vrc\n", rc));
    242253                        }
    243                         AssertMsgFailed(("vmR3Create failed rc=%Vrc\n", rc));
     254                        else
     255                            AssertMsgFailed(("VMR3ReqCall failed rc=%Vrc\n", rc));
     256
     257                        /*
     258                         * An error occurred during VM creation. Set the error message directly
     259                         * using the initial callback, as the callback list doesn't exist yet.
     260                         */
     261                        const char *pszError;
     262                        switch (rc)
     263                        {
     264                            case VERR_VMX_IN_VMX_ROOT_MODE:
     265#ifdef RT_OS_LINUX
     266                                pszError = N_("VirtualBox can't operate in VMX root mode. "
     267                                              "Please disable the KVM kernel extension, recompile your kernel and reboot");
     268#else
     269                                pszError = N_("VirtualBox can't operate in VMX root mode");
     270#endif
     271                                break;
     272                            default:
     273                                pszError = N_("Unknown error creating VM (%Vrc)");
     274                                AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc));
     275                        }
     276                        vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, pszError, rc);
     277
     278                        /* Forcefully terminate the emulation thread. */
     279                        VM_FF_SET(pVM, VM_FF_TERMINATE);
     280                        VMR3NotifyFF(pVM, false);
     281                        RTThreadWait(pVM->ThreadEMT, 1000, NULL);
    244282                    }
    245                     else
    246                         AssertMsgFailed(("VMR3ReqCall failed rc=%Vrc\n", rc));
    247 
    248                     const char *pszError;
    249                     /*
    250                      * An error occurred during VM creation. Set the error message directly
    251                      * using the initial callback, as the callback list doesn't exist yet.
    252                      */
    253                     switch (rc)
    254                     {
    255                     case VERR_VMX_IN_VMX_ROOT_MODE:
    256 #ifdef RT_OS_LINUX
    257                         pszError = N_("VirtualBox can't operate in VMX root mode. "
    258                                               "Please disable the KVM kernel extension, recompile "
    259                                       "your kernel and reboot");
    260 #else
    261                         pszError = N_("VirtualBox can't operate in VMX root mode");
    262 #endif
    263                         break;
    264                     default:
    265                         pszError = N_("Unknown error creating VM (%Vrc)");
    266                         AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc));
    267                     }
    268                     vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, pszError, rc);
    269 
    270                     /* Forcefully terminate the emulation thread. */
    271                     VM_FF_SET(pVM, VM_FF_TERMINATE);
    272                     VMR3NotifyFF(pVM, false);
    273                     RTThreadWait(pVM->ThreadEMT, 1000, NULL);
     283
     284                    int rc2 = STAMR3Term(pVM);
     285                    AssertRC(rc2);
    274286                }
    275287
    276                 int rc2 = STAMR3Term(pVM);
     288                /* cleanup the heap. */
     289                int rc2 = MMR3Term(pVM);
     290                AssertRC(rc2);
     291
     292                /* Tell GVMM that it can destroy the VM now. */
     293                rc2 = SUPCallVMMR0Ex(CreateVMReq.pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
    277294                AssertRC(rc2);
    278295            }
    279 
    280             /* cleanup the heap. */
    281             int rc2 = MMR3Term(pVM);
    282             AssertRC(rc2);
    283 
    284             /* free the VM memory */
    285             rc2 = SUPLowFree(pVM, cPages);
    286             AssertRC(rc2);
     296            else
     297            {
     298                PDMR3LdrLoadVMMR0Part2(NULL, pvVMMR0Opaque);
     299                vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, N_("VM creation failed"));
     300                AssertMsgFailed(("GMMR0CreateVMReq returned %Rrc\n", rc));
     301            }
    287302        }
    288303        else
    289304        {
    290             rc = VERR_NO_MEMORY;
    291             vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS,
    292                               N_("Failed to allocate %d bytes of low memory for the VM structure"),
    293                               RT_ALIGN(sizeof(*pVM), PAGE_SIZE));
    294             AssertMsgFailed(("Failed to allocate %d bytes of low memory for the VM structure!\n", RT_ALIGN(sizeof(*pVM), PAGE_SIZE)));
     305            vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, N_("Failed to load VMMR0.r0"));
     306            AssertMsgFailed(("PDMR3LdrLoadVMMR0 returned %Rrc\n", rc));
    295307        }
    296         RTMemFree(paPages);
    297308
    298309        /* terminate SUPLib */
     
    302313    else
    303314    {
    304         const char *pszError;
    305315        /*
    306316         * An error occurred at support library initialization time (before the
     
    308318         * initial callback, as the callback list doesn't exist yet.
    309319         */
     320        const char *pszError;
    310321        switch (rc)
    311322        {
     
    369380static void vmR3CallVMAtError(PFNVMATERROR pfnVMAtError, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, ...)
    370381{
     382    if (!pfnVMAtError)
     383        return;
    371384    va_list va;
    372385    va_start(va, pszError);
     
    874887}
    875888
     889
    876890/**
    877891 * Suspends a running VM.
     
    950964 * @returns VBox error code on failure.
    951965 * @param   pVM         The VM to resume.
    952  * @thread      EMT
     966 * @thread  EMT
    953967 */
    954968static DECLCALLBACK(int) vmR3Resume(PVM pVM)
     
    14601474    rc = HWACCMR3Term(pVM);
    14611475    AssertRC(rc);
    1462     rc = VMMR3Term(pVM);
     1476    rc = PGMR3Term(pVM);
    14631477    AssertRC(rc);
    1464     rc = PGMR3Term(pVM);
     1478    rc = VMMR3Term(pVM); /* Terminates the ring-0 code! */
    14651479    AssertRC(rc);
    14661480    rc = CPUMR3Term(pVM);
     
    14901504{
    14911505    /*
    1492      * Free the event semaphores associated with the request packets.s
     1506     * Free the event semaphores associated with the request packets.
    14931507     */
    14941508    unsigned cReqs = 0;
     
    15351549
    15361550    /*
    1537      * Free the VM structure.
    1538      */
    1539     rc = SUPLowFree(pVM, RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT);
     1551     * Tell GVMM that it can destroy the VM now.
     1552     */
     1553    rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
    15401554    AssertRC(rc);
    15411555    rc = SUPTerm();
  • trunk/src/VBox/VMM/VMEmt.cpp

    r4295 r5031  
    8686            break;
    8787        }
    88         else if (pVM->vm.s.pReqs)
     88        if (pVM->vm.s.pReqs)
    8989        {
    9090            /*
  • trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp

    r5026 r5031  
    3535*   Header Files                                                               *
    3636*******************************************************************************/
    37 #define LOG_GROUP LOG_GROUP_GVM
     37#define LOG_GROUP LOG_GROUP_GVMM
    3838#include <VBox/gvmm.h>
    39 /* #include "GVMMInternal.h" */
     39#include "GVMMR0Internal.h"
     40#include <VBox/gvm.h>
    4041#include <VBox/vm.h>
    4142#include <VBox/err.h>
    4243#include <iprt/alloc.h>
    4344#include <iprt/semaphore.h>
    44 #include <iprt/log.h>
     45#include <VBox/log.h>
    4546#include <iprt/thread.h>
    4647#include <iprt/param.h>
    4748#include <iprt/string.h>
     49#include <iprt/assert.h>
     50#include <iprt/mem.h>
     51#include <iprt/memobj.h>
    4852
    4953
     
    6165    /** Our own index / handle value. */
    6266    uint16_t            iSelf;
    63     /** Whether to free the VM structure or not. */
    64     bool                fFreeVM;
    6567    /** The pointer to the ring-0 only (aka global) VM structure. */
    6668    PGVM                pGVM;
     
    111113static PGVMM g_pGVMM = NULL;
    112114
     115/** Macro for obtaining and validating the g_pGVMM pointer.
     116 * On failure it will return from the invoking function with the specified return value.
     117 *
     118 * @param   pGVMM   The name of the pGVMM variable.
     119 * @param   rc      The return value on failure. Use VERR_INTERNAL_ERROR for
     120 *                  VBox status codes.
     121 */
     122#define GVMM_GET_VALID_INSTANCE(pGVMM, rc) \
     123    do { \
     124        (pGVMM) = g_pGVMM;\
     125        AssertPtrReturn((pGVMM), (rc)); \
     126        AssertMsgReturn((pGVMM)->u32Magic == GVMM_MAGIC, ("%p - %#x\n", (pGVMM), (pGVMM)->u32Magic), (rc)); \
     127    } while (0)
     128
     129/** Macro for obtaining and validating the g_pGVMM pointer, void function variant.
     130 * On failure it will return from the invoking function.
     131 *
     132 * @param   pGVMM   The name of the pGVMM variable.
     133 */
     134#define GVMM_GET_VALID_INSTANCE_VOID(pGVMM) \
     135    do { \
     136        (pGVMM) = g_pGVMM;\
     137        AssertPtrReturnVoid((pGVMM)); \
     138        AssertMsgReturnVoid((pGVMM)->u32Magic == GVMM_MAGIC, ("%p - %#x\n", (pGVMM), (pGVMM)->u32Magic)); \
     139    } while (0)
     140
    113141
    114142/*******************************************************************************
     
    201229
    202230
    203 #if 0 /* not currently used */
     231/**
     232 * Request wrapper for the GVMMR0CreateVM API.
     233 *
     234 * @returns VBox status code.
     235 * @param   pReqHdr     The request buffer.
     236 */
     237GVMMR0DECL(int) GVMMR0CreateVMReq(PSUPVMMR0REQHDR pReqHdr)
     238{
     239    PGVMMCREATEVMREQ pReq = (PGVMMCREATEVMREQ)pReqHdr;
     240
     241    /*
     242     * Validate the request.
     243     */
     244    if (!VALID_PTR(pReq))
     245        return VERR_INVALID_POINTER;
     246    if (pReq->Hdr.cbReq != sizeof(*pReq))
     247        return VERR_INVALID_PARAMETER;
     248    if (!VALID_PTR(pReq->pSession))
     249        return VERR_INVALID_POINTER;
     250
     251    /*
     252     * Execute it.
     253     */
     254    PVM pVM;
     255    pReq->pVMR0 = NULL;
     256    pReq->pVMR3 = NIL_RTR3PTR;
     257    int rc = GVMMR0CreateVM(pReq->pSession, &pVM);
     258    if (RT_SUCCESS(rc))
     259    {
     260        pReq->pVMR0 = pVM;
     261        pReq->pVMR3 = pVM->pVMR3;
     262    }
     263    return rc;
     264}
     265
     266
    204267/**
    205268 * Allocates the VM structure and registers it with GVM.
     
    209272 * @param   ppVM        Where to store the pointer to the VM structure.
    210273 *
    211  * @thread  EMT.
     274 * @thread  Any thread.
    212275 */
    213276GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM)
    214277{
    215     SUPR0Printf("GVMMR0CreateVM: pSession=%p\n", pSession);
    216     PGVMM pGVMM = g_pGVMM;
    217     AssertPtrReturn(pGVMM, VERR_INTERNAL_ERROR);
     278    LogFlow(("GVMMR0CreateVM: pSession=%p\n", pSession));
     279    PGVMM pGVMM;
     280    GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
    218281
    219282    AssertPtrReturn(ppVM, VERR_INVALID_POINTER);
    220283    *ppVM = NULL;
    221284
    222     RTNATIVETHREAD hEMT = RTThreadNativeSelf();
    223     AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR);
     285    AssertReturn(RTThreadNativeSelf() != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR);
    224286
    225287    /*
     
    235297    if (iHandle)
    236298    {
    237         PGVMMHANDLE pHandle = &pGVMM->aHandles[iHandle];
     299        PGVMHANDLE pHandle = &pGVMM->aHandles[iHandle];
    238300
    239301        /* consistency checks, a bit paranoid as always. */
    240302        if (    !pHandle->pVM
    241             /*&&  !pHandle->pGVM */
     303            &&  !pHandle->pGVM
    242304            &&  !pHandle->pvObj
    243305            &&  pHandle->iSelf == iHandle)
     
    253315                pGVMM->iUsedHead = iHandle;
    254316
    255                 pHandle->fFreeVM = true;
    256317                pHandle->pVM = NULL;
    257                 pHandle->pGVM = NULL; /* to be allocated */
     318                pHandle->pGVM = NULL;
    258319                pHandle->pSession = pSession;
    259                 pHandle->hEMT = hEMT;
     320                pHandle->hEMT = NIL_RTNATIVETHREAD;
    260321
    261322                rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pSession, NULL);
     
    263324                {
    264325                    /*
    265                      * Allocate and initialize the VM structure.
     326                     * Allocate the global VM structure (GVM) and initialize it.
    266327                     */
    267                     RTR3PTR     paPagesR3;
    268                     PRTHCPHYS   paPagesR0;
    269                     size_t      cPages = RT_ALIGN_Z(sizeof(VM), PAGE_SIZE) >> PAGE_SHIFT;
    270                     rc = SUPR0MemAlloc(pSession, cPages * sizeof(RTHCPHYS), (void **)&paPagesR0, &paPagesR3);
    271                     if (RT_SUCCESS(rc))
     328                    PGVM pGVM = (PGVM)RTMemAllocZ(sizeof(*pGVM));
     329                    if (pGVM)
    272330                    {
    273                         PVM pVM;
    274                         PVMR3 pVMR3;
    275                         rc = SUPR0LowAlloc(pSession, cPages, (void **)&pVM, &pVMR3, paPagesR0);
     331                        pGVM->u32Magic = GVM_MAGIC;
     332                        pGVM->hSelf = iHandle;
     333                        pGVM->hEMT = NIL_RTNATIVETHREAD;
     334                        pGVM->pVM = NULL;
     335
     336                        /* gvmmR0InitPerVMData: */
     337                        AssertCompile(RT_SIZEOFMEMB(GVM,gvmm.s) <= RT_SIZEOFMEMB(GVM,gvmm.padding));
     338                        Assert(RT_SIZEOFMEMB(GVM,gvmm.s) <= RT_SIZEOFMEMB(GVM,gvmm.padding));
     339                        pGVM->gvmm.s.VMMemObj = NIL_RTR0MEMOBJ;
     340                        pGVM->gvmm.s.VMMapObj = NIL_RTR0MEMOBJ;
     341                        pGVM->gvmm.s.VMPagesMemObj = NIL_RTR0MEMOBJ;
     342                        pGVM->gvmm.s.VMPagesMapObj = NIL_RTR0MEMOBJ;
     343
     344                        /* GVMMR0InitPerVMData(pGVM); - later */
     345
     346                        /*
     347                         * Allocate the shared VM structure and associated page array.
     348                         */
     349                        const size_t cPages = RT_ALIGN(sizeof(VM), PAGE_SIZE) >> PAGE_SHIFT;
     350                        rc = RTR0MemObjAllocLow(&pGVM->gvmm.s.VMMemObj, cPages << PAGE_SHIFT, false /* fExecutable */);
    276351                        if (RT_SUCCESS(rc))
    277352                        {
    278                             memset(pVM, 0, cPages * PAGE_SIZE);
     353                            PVM pVM = (PVM)RTR0MemObjAddress(pGVM->gvmm.s.VMMemObj); AssertPtr(pVM);
     354                            memset(pVM, 0, cPages << PAGE_SHIFT);
    279355                            pVM->enmVMState = VMSTATE_CREATING;
    280                             pVM->paVMPagesR3 = paPagesR3;
    281                             pVM->pVMR3 = pVMR3;
    282356                            pVM->pVMR0 = pVM;
    283357                            pVM->pSession = pSession;
    284358                            pVM->hSelf = iHandle;
    285                             RTSemFastMutexRelease(pGVMM->Lock);
    286 
    287                             *ppVM = pVM;
    288                             SUPR0Printf("GVMMR0CreateVM: pVM=%p pVMR3=%p\n", pVM, pVMR3);
    289                             return VINF_SUCCESS;
     359
     360                            rc = RTR0MemObjAllocPage(&pGVM->gvmm.s.VMPagesMemObj, cPages * sizeof(SUPPAGE), false /* fExecutable */);
     361                            if (RT_SUCCESS(rc))
     362                            {
     363                                PSUPPAGE paPages = (PSUPPAGE)RTR0MemObjAddress(pGVM->gvmm.s.VMPagesMemObj); AssertPtr(paPages);
     364                                for (size_t iPage = 0; iPage < cPages; iPage++)
     365                                {
     366                                    paPages[iPage].uReserved = 0;
     367                                    paPages[iPage].Phys = RTR0MemObjGetPagePhysAddr(pGVM->gvmm.s.VMMemObj, iPage);
     368                                    Assert(paPages[iPage].Phys != NIL_RTHCPHYS);
     369                                }
     370
     371                                /*
     372                                 * Map them into ring-3.
     373                                 */
     374                                rc = RTR0MemObjMapUser(&pGVM->gvmm.s.VMMapObj, pGVM->gvmm.s.VMMemObj, (RTR3PTR)-1, 0,
     375                                                       RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
     376                                if (RT_SUCCESS(rc))
     377                                {
     378                                    pVM->pVMR3 = RTR0MemObjAddressR3(pGVM->gvmm.s.VMMapObj);
     379                                    AssertPtr((void *)pVM->pVMR3);
     380
     381                                    rc = RTR0MemObjMapUser(&pGVM->gvmm.s.VMPagesMapObj, pGVM->gvmm.s.VMPagesMemObj, (RTR3PTR)-1, 0,
     382                                                           RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
     383                                    if (RT_SUCCESS(rc))
     384                                    {
     385                                        pVM->paVMPagesR3 = RTR0MemObjAddressR3(pGVM->gvmm.s.VMPagesMapObj);
     386                                        AssertPtr((void *)pVM->paVMPagesR3);
     387
     388                                        /* complete the handle. */
     389                                        pHandle->pVM = pVM;
     390                                        pHandle->pGVM = pGVM;
     391
     392                                        RTSemFastMutexRelease(pGVMM->Lock);
     393
     394                                        *ppVM = pVM;
     395                                        SUPR0Printf("GVMMR0CreateVM: pVM=%p pVMR3=%p pGVM=%p hGVM=%d\n", pVM, pVM->pVMR3, pGVM, iHandle);
     396                                        return VINF_SUCCESS;
     397                                    }
     398
     399                                    RTR0MemObjFree(pGVM->gvmm.s.VMMapObj, false /* fFreeMappings */);
     400                                    pGVM->gvmm.s.VMMapObj = NIL_RTR0MEMOBJ;
     401                                }
     402                                RTR0MemObjFree(pGVM->gvmm.s.VMPagesMemObj, false /* fFreeMappings */);
     403                                pGVM->gvmm.s.VMPagesMemObj = NIL_RTR0MEMOBJ;
     404                            }
     405                            RTR0MemObjFree(pGVM->gvmm.s.VMMemObj, false /* fFreeMappings */);
     406                            pGVM->gvmm.s.VMMemObj = NIL_RTR0MEMOBJ;
    290407                        }
    291 
    292                         SUPR0MemFree(pSession, (uintptr_t)paPagesR0);
    293408                    }
    294409                }
     
    320435    return rc;
    321436}
    322 #endif /* not used yet. */
    323 
    324 
    325 /**
    326  * Deregistres the VM and destroys the VM structure.
     437
     438
     439/**
     440 * Destroys the VM, freeing all associated resources (the ring-0 ones anyway).
     441 *
     442 * This is call from the vmR3DestroyFinalBit and from a error path in VMR3Create,
     443 * and the caller is not the EMT thread, unfortunately. For security reasons, it
     444 * would've been nice if the caller was actually the EMT thread or that we somehow
     445 * could've associated the calling thread with the VM up front.
    327446 *
    328447 * @returns VBox status code.
    329448 * @param   pVM         Where to store the pointer to the VM structure.
    330449 *
    331  * @thread  EMT.
     450 * @thread  EMT if it's associated with the VM, otherwise any thread.
    332451 */
    333452GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM)
    334453{
    335     SUPR0Printf("GVMMR0DestroyVM: pVM=%p\n", pVM);
    336 
    337     PGVMM pGVMM = g_pGVMM;
    338     AssertPtrReturn(pGVMM, VERR_INTERNAL_ERROR);
     454    LogFlow(("GVMMR0DestroyVM: pVM=%p\n", pVM));
     455    PGVMM pGVMM;
     456    GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
     457
    339458
    340459    /*
     
    350469
    351470    PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
    352     AssertReturn(pHandle->hEMT != NIL_RTNATIVETHREAD, VERR_WRONG_ORDER);
    353471    AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER);
    354472
    355473    RTNATIVETHREAD hSelf = RTThreadNativeSelf();
    356     AssertReturn(pHandle->hEMT == hSelf, VERR_NOT_OWNER);
     474    AssertReturn(pHandle->hEMT == hSelf || pHandle->hEMT == NIL_RTNATIVETHREAD, VERR_NOT_OWNER);
    357475
    358476    /*
    359477     * Lookup the handle and destroy the object.
    360      * Since the lock isn't recursive, we have to make sure nobody can
    361      * race us as we leave the lock and call SUPR0ObjRelease.
     478     * Since the lock isn't recursive and we'll have to leave it before dereferencing the
     479     * object, we take some precautions against racing callers just in case...
    362480     */
    363481    int rc = RTSemFastMutexRequest(pGVMM->Lock);
    364482    AssertRC(rc);
    365483
    366     /* be very careful here because we might be racing someone else cleaning up... */
     484    /* be careful here because we might theoretically be racing someone else cleaning up. */
    367485    if (    pHandle->pVM == pVM
    368         &&  pHandle->hEMT == hSelf
    369         &&  VALID_PTR(pHandle->pvObj))
     486        &&  (   pHandle->hEMT == hSelf
     487             || pHandle->hEMT == NIL_RTNATIVETHREAD)
     488        &&  VALID_PTR(pHandle->pvObj)
     489        &&  VALID_PTR(pHandle->pSession)
     490        &&  VALID_PTR(pHandle->pGVM)
     491        &&  pHandle->pGVM->u32Magic == GVM_MAGIC)
    370492    {
    371493        void *pvObj = pHandle->pvObj;
     
    373495        RTSemFastMutexRelease(pGVMM->Lock);
    374496
    375         SUPR0ObjRelease(pvObj, pVM->pSession);
     497        SUPR0ObjRelease(pvObj, pHandle->pSession);
    376498    }
    377499    else
    378500    {
     501        SUPR0Printf("GVMMR0DestroyVM: pHandle=%p:{.pVM=%p, hEMT=%p, .pvObj=%p} pVM=%p hSelf=%p\n",
     502                    pHandle, pHandle->pVM, pHandle->hEMT, pHandle->pvObj, pVM, hSelf);
    379503        RTSemFastMutexRelease(pGVMM->Lock);
    380504        rc = VERR_INTERNAL_ERROR;
     
    385509
    386510
    387 #if 1 /* this approach is unsafe wrt to the freeing of pVM. Keeping it as a possible fallback for 1.5.x. */
    388 /**
    389  * Register the specified VM with the GGVM.
    390  *
    391  * Permission polices and resource consumption polices may or may
    392  * not be checked that this poin, be ready to deald nicely with failure.
    393  *
    394  * @returns VBox status code.
    395  *
    396  * @param   pVM         The VM instance data (aka handle), ring-0 mapping of ccourse.
    397  *                      The VM::hGVM field may be updated by this call.
    398  * @thread  EMT.
    399  */
    400 GVMMR0DECL(int) GVMMR0RegisterVM(PVM pVM)
    401 {
    402     SUPR0Printf("GVMMR0RegisterVM: pVM=%p\n", pVM);
    403     PGVMM pGVMM = g_pGVMM;
    404     AssertPtrReturn(pGVMM, VERR_INTERNAL_ERROR);
    405 
    406     /*
    407      * Validate the VM structure and state.
    408      */
    409     AssertPtrReturn(pVM, VERR_INVALID_POINTER);
    410     AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
    411     AssertMsgReturn(pVM->enmVMState == VMSTATE_CREATING, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
    412 
    413     RTNATIVETHREAD hEMT = RTThreadNativeSelf();
    414     AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_NOT_SUPPORTED);
    415 
    416     /*
    417      * Take the lock and call the worker function.
    418      */
    419     int rc = RTSemFastMutexRequest(pGVMM->Lock);
    420     AssertRCReturn(rc, rc);
    421 
    422     /*
    423      * Allocate a handle.
    424      */
    425     uint16_t iHandle = pGVMM->iFreeHead;
    426     if (iHandle)
    427     {
    428         PGVMHANDLE pHandle = &pGVMM->aHandles[iHandle];
    429 
    430         /* consistency checks, a bit paranoid as always. */
    431         if (    !pHandle->pVM
    432             &&  !pHandle->pvObj
    433             &&  pHandle->iSelf == iHandle)
    434         {
    435             pHandle->pvObj = SUPR0ObjRegister(pVM->pSession, SUPDRVOBJTYPE_VM, gvmmR0HandleObjDestructor, pGVMM, pHandle);
    436             if (pHandle->pvObj)
    437             {
    438                 /*
    439                  * Move the handle from the free to used list and
    440                  * perform permission checks.
    441                  */
    442                 pGVMM->iFreeHead = pHandle->iNext;
    443                 pHandle->iNext = pGVMM->iUsedHead;
    444                 pGVMM->iUsedHead = iHandle;
    445 
    446                 pHandle->fFreeVM = false;
    447                 pHandle->pVM = pVM;
    448                 pHandle->pGVM = NULL; /** @todo to be allocated */
    449                 pHandle->pSession = pVM->pSession;
    450                 pHandle->hEMT = hEMT;
    451 
    452                 rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pVM->pSession, NULL);
    453                 if (RT_SUCCESS(rc))
    454                 {
    455                     pVM->hSelf = iHandle;
    456                     RTSemFastMutexRelease(pGVMM->Lock);
    457                 }
    458                 else
    459                 {
    460                     /*
    461                      * The user wasn't permitted to create this VM.
    462                      * Must use gvmmR0HandleObjDestructor via SUPR0ObjRelease to do the
    463                      * cleanups. The lock isn't recursive, thus the extra mess.
    464                      */
    465                     void *pvObj = pHandle->pvObj;
    466                     pHandle->pvObj = NULL;
    467                     RTSemFastMutexRelease(pGVMM->Lock);
    468 
    469                     SUPR0ObjRelease(pvObj, pVM->pSession);
    470                 }
    471                 if (RT_FAILURE(rc))
    472                     SUPR0Printf("GVMMR0RegisterVM: permission denied, rc=%d\n", rc);
    473                 return rc;
    474             }
    475 
    476             rc = VERR_NO_MEMORY;
    477         }
    478         else
    479             rc = VERR_INTERNAL_ERROR;
    480     }
    481     else
    482         rc = VERR_GVM_TOO_MANY_VMS;
    483 
    484     RTSemFastMutexRelease(pGVMM->Lock);
    485     SUPR0Printf("GVMMR0RegisterVM: failed, rc=%d, iHandle=%d\n", rc, iHandle);
    486     return rc;
    487 }
    488 
    489 
    490 /**
    491  * Deregister a VM previously registered using the GVMMR0RegisterVM API.
    492  *
    493  *
    494  * @returns VBox status code.
    495  * @param   pVM         The VM handle.
    496  * @thread  EMT.
    497  */
    498 GVMMR0DECL(int) GVMMR0DeregisterVM(PVM pVM)
    499 {
    500     SUPR0Printf("GVMMR0DeregisterVM: pVM=%p\n", pVM);
    501     return GVMMR0DestroyVM(pVM);
    502 }
    503 #endif /* ... */
    504 
    505 
    506511/**
    507512 * Handle destructor.
     
    512517static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle)
    513518{
    514     SUPR0Printf("gvmmR0HandleObjDestructor: %p %p %p\n", pvObj, pvGVMM, pvHandle);
     519    LogFlow(("gvmmR0HandleObjDestructor: %p %p %p\n", pvObj, pvGVMM, pvHandle));
    515520
    516521    /*
     
    579584
    580585    /*
    581      * Do the global cleanup round, currently only GMM.
    582      * Can't trust the VM pointer unless it was allocated in ring-0...
    583      */
    584     PVM pVM = pHandle->pVM;
    585     if (    VALID_PTR(pVM)
    586         &&  VALID_PTR(pHandle->pSession)
    587         &&  pHandle->fFreeVM)
    588     {
    589         /// @todo GMMR0CleanupVM(pVM);
     586     * Do the global cleanup round.
     587     */
     588    PGVM pGVM = pHandle->pGVM;
     589    if (    VALID_PTR(pGVM)
     590        &&  pGVM->u32Magic == GVM_MAGIC)
     591    {
     592        /// @todo GMMR0CleanupVM(pGVM);
    590593
    591594        /*
    592          * Free the VM structure.
     595         * Do the GVMM cleanup - must be done last.
    593596         */
    594         ASMAtomicXchgU32((uint32_t volatile *)&pVM->hSelf, NIL_GVM_HANDLE);
    595         SUPR0MemFree(pHandle->pSession, pVM->paVMPagesR3);
    596         SUPR0LowFree(pHandle->pSession, (uintptr_t)pVM);
    597     }
     597        /* The VM and VM pages mappings/allocations. */
     598        if (pGVM->gvmm.s.VMPagesMapObj != NIL_RTR0MEMOBJ)
     599        {
     600            rc = RTR0MemObjFree(pGVM->gvmm.s.VMPagesMapObj, false /* fFreeMappings */); AssertRC(rc);
     601            pGVM->gvmm.s.VMPagesMapObj = NIL_RTR0MEMOBJ;
     602        }
     603
     604        if (pGVM->gvmm.s.VMMapObj != NIL_RTR0MEMOBJ)
     605        {
     606            rc = RTR0MemObjFree(pGVM->gvmm.s.VMMapObj, false /* fFreeMappings */); AssertRC(rc);
     607            pGVM->gvmm.s.VMMapObj = NIL_RTR0MEMOBJ;
     608        }
     609
     610        if (pGVM->gvmm.s.VMPagesMemObj != NIL_RTR0MEMOBJ)
     611        {
     612            rc = RTR0MemObjFree(pGVM->gvmm.s.VMPagesMemObj, false /* fFreeMappings */); AssertRC(rc);
     613            pGVM->gvmm.s.VMPagesMemObj = NIL_RTR0MEMOBJ;
     614        }
     615
     616        if (pGVM->gvmm.s.VMMemObj != NIL_RTR0MEMOBJ)
     617        {
     618            rc = RTR0MemObjFree(pGVM->gvmm.s.VMMemObj, false /* fFreeMappings */); AssertRC(rc);
     619            pGVM->gvmm.s.VMMemObj = NIL_RTR0MEMOBJ;
     620        }
     621
     622        /* the GVM structure itself. */
     623        pGVM->u32Magic++;
     624        RTMemFree(pGVM);
     625    }
     626    /* else: GVMMR0CreateVM cleanup.  */
    598627
    599628    /*
     
    601630     */
    602631    pHandle->iNext = pGVMM->iFreeHead;
    603     pHandle->fFreeVM = false;
    604632    pGVMM->iFreeHead = iHandle;
     633    ASMAtomicXchgPtr((void * volatile *)&pHandle->pGVM, NULL);
    605634    ASMAtomicXchgPtr((void * volatile *)&pHandle->pVM, NULL);
    606635    ASMAtomicXchgPtr((void * volatile *)&pHandle->pvObj, NULL);
     
    614643
    615644/**
    616  * Lookup a GVM pointer by its handle.
     645 * Associates an EMT thread with a VM.
     646 *
     647 * This is called early during the ring-0 VM initialization so assertions later in
     648 * the process can be handled gracefully.
     649 *
     650 * @returns VBox status code.
     651 *
     652 * @param   pVM         The VM instance data (aka handle), ring-0 mapping of course.
     653 * @thread  EMT.
     654 */
     655GVMMR0DECL(int) GVMMR0AssociateEMTWithVM(PVM pVM)
     656{
     657    LogFlow(("GVMMR0AssociateEMTWithVM: pVM=%p\n", pVM));
     658    PGVMM pGVMM;
     659    GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
     660
     661    /*
     662     * Validate the VM structure, state and handle.
     663     */
     664    AssertPtrReturn(pVM, VERR_INVALID_POINTER);
     665    AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
     666    AssertMsgReturn(pVM->enmVMState == VMSTATE_CREATING, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
     667
     668    RTNATIVETHREAD hEMT = RTThreadNativeSelf();
     669    AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_NOT_SUPPORTED);
     670
     671    const uint16_t hGVM = pVM->hSelf;
     672    AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_HANDLE);
     673    AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_HANDLE);
     674
     675    PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
     676    AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER);
     677
     678    /*
     679     * Take the lock, validate the handle and update the structure members.
     680     */
     681    int rc = RTSemFastMutexRequest(pGVMM->Lock);
     682    AssertRCReturn(rc, rc);
     683
     684    if (    pHandle->pVM == pVM
     685        &&  VALID_PTR(pHandle->pvObj)
     686        &&  VALID_PTR(pHandle->pSession)
     687        &&  VALID_PTR(pHandle->pGVM)
     688        &&  pHandle->pGVM->u32Magic == GVM_MAGIC)
     689    {
     690        pHandle->hEMT = hEMT;
     691        pHandle->pGVM->hEMT = hEMT;
     692    }
     693    else
     694        rc = VERR_INTERNAL_ERROR;
     695
     696    RTSemFastMutexRelease(pGVMM->Lock);
     697    LogFlow(("GVMMR0AssociateEMTWithVM: returns %Vrc (hEMT=%RTnthrd)\n", rc, hEMT));
     698    return rc;
     699}
     700
     701
     702/**
     703 * Disassociates the EMT thread from a VM.
     704 *
     705 * This is called last in the ring-0 VM termination. After this point anyone is
     706 * allowed to destroy the VM. Ideally, we should associate the VM with the thread
     707 * that's going to call GVMMR0DestroyVM for optimal security, but that's impractical
     708 * at present.
     709 *
     710 * @returns VBox status code.
     711 *
     712 * @param   pVM         The VM instance data (aka handle), ring-0 mapping of course.
     713 * @thread  EMT.
     714 */
     715GVMMR0DECL(int) GVMMR0DisassociateEMTFromVM(PVM pVM)
     716{
     717    LogFlow(("GVMMR0DisassociateEMTFromVM: pVM=%p\n", pVM));
     718    PGVMM pGVMM;
     719    GVMM_GET_VALID_INSTANCE(pGVMM, VERR_INTERNAL_ERROR);
     720
     721    /*
     722     * Validate the VM structure, state and handle.
     723     */
     724    AssertPtrReturn(pVM, VERR_INVALID_POINTER);
     725    AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
     726    AssertMsgReturn(pVM->enmVMState >= VMSTATE_CREATING && pVM->enmVMState <= VMSTATE_DESTROYING, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
     727
     728    RTNATIVETHREAD hEMT = RTThreadNativeSelf();
     729    AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_NOT_SUPPORTED);
     730
     731    const uint16_t hGVM = pVM->hSelf;
     732    AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_HANDLE);
     733    AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_HANDLE);
     734
     735    PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
     736    AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER);
     737
     738    /*
     739     * Take the lock, validate the handle and update the structure members.
     740     */
     741    int rc = RTSemFastMutexRequest(pGVMM->Lock);
     742    AssertRCReturn(rc, rc);
     743
     744    if (    VALID_PTR(pHandle->pvObj)
     745        &&  VALID_PTR(pHandle->pSession)
     746        &&  VALID_PTR(pHandle->pGVM)
     747        &&  pHandle->pGVM->u32Magic == GVM_MAGIC)
     748    {
     749        if (    pHandle->pVM == pVM
     750            &&  pHandle->hEMT == hEMT)
     751        {
     752            pHandle->hEMT = NIL_RTNATIVETHREAD;
     753            pHandle->pGVM->hEMT = NIL_RTNATIVETHREAD;
     754        }
     755        else
     756            rc = VERR_NOT_OWNER;
     757    }
     758    else
     759        rc = VERR_INVALID_HANDLE;
     760
     761    RTSemFastMutexRelease(pGVMM->Lock);
     762    LogFlow(("GVMMR0DisassociateEMTFromVM: returns %Vrc (hEMT=%RTnthrd)\n", rc, hEMT));
     763    return rc;
     764}
     765
     766
     767/**
     768 * Lookup a GVM structure by its handle.
    617769 *
    618770 * @returns The GVM pointer on success, NULL on failure.
     
    621773GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM)
    622774{
    623     PGVMM pGVMM = g_pGVMM;
    624     AssertPtrReturn(pGVMM, NULL);
     775    PGVMM pGVMM;
     776    GVMM_GET_VALID_INSTANCE(pGVMM, NULL);
    625777
    626778    /*
     
    633785     * Look it up.
    634786     */
    635     AssertReturn(VALID_PTR(pGVMM->aHandles[hGVM].pvObj), NULL);
    636     AssertReturn(pGVMM->aHandles[hGVM].hEMT != NIL_RTNATIVETHREAD, NULL);
    637     Assert(VALID_PTR(pGVMM->aHandles[hGVM].pVM));
    638 
    639     return pGVMM->aHandles[hGVM].pGVM;
     787    PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
     788    AssertPtrReturn(pHandle->pVM, NULL);
     789    AssertPtrReturn(pHandle->pvObj, NULL);
     790    PGVM pGVM = pHandle->pGVM;
     791    AssertPtrReturn(pGVM, NULL);
     792    AssertReturn(pGVM->pVM == pHandle->pVM, NULL);
     793
     794    return pHandle->pGVM;
     795}
     796
     797
     798/**
     799 * Lookup a GVM structure by the shared VM structure.
     800 *
     801 * @returns The GVM pointer on success, NULL on failure.
     802 * @param   pVM     The shared VM structure (the ring-0 mapping).
     803 */
     804GVMMR0DECL(PGVM) GVMMR0ByVM(PVM pVM)
     805{
     806    PGVMM pGVMM;
     807    GVMM_GET_VALID_INSTANCE(pGVMM, NULL);
     808
     809    /*
     810     * Validate.
     811     */
     812    AssertPtrReturn(pVM, NULL);
     813    AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), NULL);
     814
     815    uint16_t hGVM = pVM->hSelf;
     816    AssertReturn(hGVM != NIL_GVM_HANDLE, NULL);
     817    AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), NULL);
     818
     819    /*
     820     * Look it up.
     821     */
     822    PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
     823    AssertReturn(pHandle->pVM == pVM, NULL);
     824    AssertPtrReturn(pHandle->pvObj, NULL);
     825    PGVM pGVM = pHandle->pGVM;
     826    AssertPtrReturn(pGVM, NULL);
     827    AssertReturn(pGVM->pVM == pVM, NULL);
     828
     829    return pGVM;
    640830}
    641831
     
    649839GVMMR0DECL(PVM) GVMMR0GetVMByHandle(uint32_t hGVM)
    650840{
    651     PGVMM pGVMM = g_pGVMM;
    652     AssertPtrReturn(pGVMM, NULL);
    653 
    654     /*
    655      * Validate.
    656      */
    657     AssertReturn(hGVM != NIL_GVM_HANDLE, NULL);
    658     AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), NULL);
    659 
    660     /*
    661      * Look it up.
    662      */
    663     AssertReturn(VALID_PTR(pGVMM->aHandles[hGVM].pvObj), NULL);
    664     AssertReturn(pGVMM->aHandles[hGVM].hEMT != NIL_RTNATIVETHREAD, NULL);
    665     Assert(VALID_PTR(pGVMM->aHandles[hGVM].pVM));
    666 
    667     return pGVMM->aHandles[hGVM].pVM;
     841    PGVM pGVM = GVMMR0ByHandle(hGVM);
     842    return pGVM ? pGVM->pVM : NULL;
    668843}
    669844
     
    683858{
    684859    /*
    685      * Be very careful here as we're called in AssertMsgN context.
     860     * No Assertions here as we're usually called in a AssertMsgN or
     861     * RTAssert* context.
    686862     */
    687863    PGVMM pGVMM = g_pGVMM;
    688     if (!VALID_PTR(pGVMM))
     864    if (    !VALID_PTR(pGVMM)
     865        ||  pGVMM->u32Magic != GVMM_MAGIC)
    689866        return NULL;
    690867
     
    693870
    694871    /*
    695      * Search the handles, we don't dare take the lock (assert).
     872     * Search the handles in a linear fashion as we don't dare take the lock (assert).
    696873     */
    697874    for (unsigned i = 1; i < RT_ELEMENTS(pGVMM->aHandles); i++)
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r5026 r5031  
    139139 * @param   pVM         The VM instance in question.
    140140 * @param   uVersion    The minimum module version required.
     141 * @thread  EMT.
    141142 */
    142143static int VMMR0Init(PVM pVM, unsigned uVersion)
     
    193194
    194195    /*
    195      * Try register the VM with GVMM.
     196     * Associate the ring-0 EMT thread with the GVM.
    196197     */
    197     int rc = GVMMR0RegisterVM(pVM);
     198    int rc = GVMMR0AssociateEMTWithVM(pVM);
    198199    if (RT_SUCCESS(rc))
    199200    {
     
    213214                return rc;
    214215        }
    215 
    216         GVMMR0DeregisterVM(pVM);
    217216    }
    218217
     
    229228 *
    230229 * @param   pVM         The VM instance in question.
     230 * @thread  EMT.
    231231 */
    232232static int VMMR0Term(PVM pVM)
    233233{
    234234    /*
    235      * Deregister the VM and the logger.
     235     * Deregister the logger.
    236236     */
    237     GVMMR0DeregisterVM(pVM);
     237    GVMMR0DisassociateEMTFromVM(pVM);
    238238    RTLogSetDefaultInstanceThread(NULL, 0);
    239239    return VINF_SUCCESS;
     
    642642 * @param   pVM             The VM to operate on.
    643643 * @param   enmOperation    Which operation to execute.
    644  * @param   pReq            This points to a SUPVMMR0REQHDR packet. Optional.
     644 * @param   pReqHdr         This points to a SUPVMMR0REQHDR packet. Optional.
    645645 * @param   u64Arg          Some simple constant argument.
    646646 * @remarks Assume called with interrupts _enabled_.
    647647 */
    648 static int vmmR0EntryExWorker(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg)
     648static int vmmR0EntryExWorker(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReqHdr, uint64_t u64Arg)
    649649{
    650650    switch (enmOperation)
    651651    {
     652        /*
     653         * GVM requests
     654         */
     655        case VMMR0_DO_GVMM_CREATE_VM:
     656            if (pVM || u64Arg)
     657                return VERR_INVALID_PARAMETER;
     658            SUPR0Printf("-> GVMMR0CreateVMReq\n");
     659            return GVMMR0CreateVMReq(pReqHdr);
     660
     661        case VMMR0_DO_GVMM_DESTROY_VM:
     662            if (pReqHdr || u64Arg)
     663                return VERR_INVALID_PARAMETER;
     664            return GVMMR0DestroyVM(pVM);
     665
    652666        /*
    653667         * Initialize the R0 part of a VM instance.
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