VirtualBox

Changeset 5031

Show
Ignore:
Timestamp:
09/26/07 00:27:37 (1 year 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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/VBox/gvmm.h

    r5026 r5031  
    2222#include <VBox/cdefs.h> 
    2323#include <VBox/types.h> 
     24#include <VBox/sup.h> 
    2425 
    2526/** @defgroup grp_GVMM  GVMM - The Global VM Manager. 
     
    4647#define NIL_GVM_HANDLE 0 
    4748 
    48 GVMMR0DECL(int)  GVMMR0Init(void); 
    49 GVMMR0DECL(void) GVMMR0Term(void); 
    50 GVMMR0DECL(int)  GVMMR0RegisterVM(PVM pVM); 
    51 GVMMR0DECL(int)  GVMMR0DeregisterVM(PVM pVM); 
    52 GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM); 
    53 GVMMR0DECL(PVM)  GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT); 
    54 GVMMR0DECL(PVM)  GVMMR0GetVMByHandle(uint32_t hGVM); 
     49GVMMR0DECL(int)     GVMMR0Init(void); 
     50GVMMR0DECL(void)    GVMMR0Term(void); 
     51 
     52GVMMR0DECL(int)     GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM); 
     53GVMMR0DECL(int)     GVMMR0CreateVMReq(PSUPVMMR0REQHDR pReqHdr); 
     54GVMMR0DECL(int)     GVMMR0DestroyVM(PVM pVM); 
     55GVMMR0DECL(int)     GVMMR0AssociateEMTWithVM(PVM pVM); 
     56GVMMR0DECL(int)     GVMMR0DisassociateEMTFromVM(PVM pVM); 
     57GVMMR0DECL(PGVM)    GVMMR0ByHandle(uint32_t hGVM); 
     58GVMMR0DECL(PGVM)    GVMMR0ByVM(PVM pVM); 
     59GVMMR0DECL(PVM)     GVMMR0GetVMByHandle(uint32_t hGVM); 
     60GVMMR0DECL(PVM)     GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT); 
     61 
     62/** 
     63 * Request packet for calling GVMMR0CreateVM. 
     64 */ 
     65typedef struct GVMMCREATEVMREQ 
     66
     67    /** The request header. */ 
     68    SUPVMMR0REQHDR  Hdr; 
     69    /** The support driver session. (IN) */ 
     70    PSUPDRVSESSION  pSession; 
     71    /** Pointer to the ring-3 mapping of the shared VM structure on return. (OUT) */ 
     72    PVMR3           pVMR3; 
     73    /** Pointer to the ring-0 mapping of the shared VM structure on return. (OUT) */ 
     74    PVMR0           pVMR0; 
     75} GVMMCREATEVMREQ; 
     76/** Pointer to a GVMMR0CreateVM request packet. */ 
     77typedef GVMMCREATEVMREQ *PGVMMCREATEVMREQ; 
    5578 
    5679 
  • trunk/include/VBox/log.h

    r4236 r5031  
    169169    /** EM group. */ 
    170170    LOG_GROUP_EM, 
     171    /** GMM group. */ 
     172    LOG_GROUP_GMM, 
    171173    /** GUI group. */ 
    172174    LOG_GROUP_GUI, 
     175    /** GVMM group. */ 
     176    LOG_GROUP_GVMM, 
    173177    /** HGCM group */ 
    174178    LOG_GROUP_HGCM, 
     
    343347    "DRV_VUSB",     \ 
    344348    "EM",           \ 
     349    "GMM",          \ 
    345350    "GUI",          \ 
     351    "GVMM",         \ 
    346352    "HGCM",         \ 
    347353    "HWACCM",       \ 
  • trunk/include/VBox/pdmapi.h

    r4071 r5031  
    11/** @file 
    22 * PDM - Pluggable Device Manager, Core API. 
    3  *  
    4  * The 'Core API' has been put in a different header because everyone  
     3 * 
     4 * The 'Core API' has been put in a different header because everyone 
    55 * is currently including pdm.h. So, pdm.h is for including all of the 
    66 * PDM stuff, while pdmapi.h is for the core stuff. 
     
    101101 * @{ 
    102102 */ 
     103 
     104PDMR3DECL(int)  PDMR3LdrLoadVMMR0(void **ppvOpaque); 
     105PDMR3DECL(void) PDMR3LdrLoadVMMR0Part2(PVM pVM, void *pvOpaque); 
    103106 
    104107/** 
  • trunk/include/VBox/vmm.h

    r4970 r5031  
    356356    VMMR0_DO_NOP = SUP_VMMR0_DO_NOP, 
    357357 
     358    /** Ask GVMM to create a new VM. */ 
     359    VMMR0_DO_GVMM_CREATE_VM, 
     360    /** Ask GVMM to destroy the VM. */ 
     361    VMMR0_DO_GVMM_DESTROY_VM, 
    358362    /** Call VMMR0 Per VM Init. */ 
    359363    VMMR0_DO_VMMR0_INIT, 
  • 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