Changeset 5031
- Timestamp:
- 09/26/07 00:27:37 (1 year ago)
- Files:
-
- trunk/include/VBox/gvm.h (added)
- trunk/include/VBox/gvmm.h (modified) (2 diffs)
- trunk/include/VBox/log.h (modified) (2 diffs)
- trunk/include/VBox/pdmapi.h (modified) (2 diffs)
- trunk/include/VBox/vmm.h (modified) (1 diff)
- trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c (modified) (1 diff)
- trunk/src/VBox/HostDrivers/Support/SUPLib.cpp (modified) (1 diff)
- trunk/src/VBox/HostDrivers/Support/SUPR0.def (modified) (2 diffs)
- trunk/src/VBox/VMM/PDM.cpp (modified) (1 diff)
- trunk/src/VBox/VMM/PDMLdr.cpp (modified) (5 diffs)
- trunk/src/VBox/VMM/VM.cpp (modified) (11 diffs)
- trunk/src/VBox/VMM/VMEmt.cpp (modified) (1 diff)
- trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp (modified) (21 diffs)
- trunk/src/VBox/VMM/VMMR0/GVMMR0Internal.h (added)
- trunk/src/VBox/VMM/VMMR0/VMMR0.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/VBox/gvmm.h
r5026 r5031 22 22 #include <VBox/cdefs.h> 23 23 #include <VBox/types.h> 24 #include <VBox/sup.h> 24 25 25 26 /** @defgroup grp_GVMM GVMM - The Global VM Manager. … … 46 47 #define NIL_GVM_HANDLE 0 47 48 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); 49 GVMMR0DECL(int) GVMMR0Init(void); 50 GVMMR0DECL(void) GVMMR0Term(void); 51 52 GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM); 53 GVMMR0DECL(int) GVMMR0CreateVMReq(PSUPVMMR0REQHDR pReqHdr); 54 GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM); 55 GVMMR0DECL(int) GVMMR0AssociateEMTWithVM(PVM pVM); 56 GVMMR0DECL(int) GVMMR0DisassociateEMTFromVM(PVM pVM); 57 GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM); 58 GVMMR0DECL(PGVM) GVMMR0ByVM(PVM pVM); 59 GVMMR0DECL(PVM) GVMMR0GetVMByHandle(uint32_t hGVM); 60 GVMMR0DECL(PVM) GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT); 61 62 /** 63 * Request packet for calling GVMMR0CreateVM. 64 */ 65 typedef 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. */ 77 typedef GVMMCREATEVMREQ *PGVMMCREATEVMREQ; 55 78 56 79 trunk/include/VBox/log.h
r4236 r5031 169 169 /** EM group. */ 170 170 LOG_GROUP_EM, 171 /** GMM group. */ 172 LOG_GROUP_GMM, 171 173 /** GUI group. */ 172 174 LOG_GROUP_GUI, 175 /** GVMM group. */ 176 LOG_GROUP_GVMM, 173 177 /** HGCM group */ 174 178 LOG_GROUP_HGCM, … … 343 347 "DRV_VUSB", \ 344 348 "EM", \ 349 "GMM", \ 345 350 "GUI", \ 351 "GVMM", \ 346 352 "HGCM", \ 347 353 "HWACCM", \ trunk/include/VBox/pdmapi.h
r4071 r5031 1 1 /** @file 2 2 * 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 5 5 * is currently including pdm.h. So, pdm.h is for including all of the 6 6 * PDM stuff, while pdmapi.h is for the core stuff. … … 101 101 * @{ 102 102 */ 103 104 PDMR3DECL(int) PDMR3LdrLoadVMMR0(void **ppvOpaque); 105 PDMR3DECL(void) PDMR3LdrLoadVMMR0Part2(PVM pVM, void *pvOpaque); 103 106 104 107 /** trunk/include/VBox/vmm.h
r4970 r5031 356 356 VMMR0_DO_NOP = SUP_VMMR0_DO_NOP, 357 357 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, 358 362 /** Call VMMR0 Per VM Init. */ 359 363 VMMR0_DO_VMMR0_INIT, trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
r4971 r5031 99 99 { "RTMemAllocZ", (void *)RTMemAllocZ }, 100 100 { "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 }, 101 116 /* These doesn't work yet on linux - use fast mutexes! 102 117 { "RTSemMutexCreate", (void *)RTSemMutexCreate }, trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r4987 r5031 525 525 { 526 526 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER); 527 AssertReturn(pReqHdr->u32Magic != SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);527 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC); 528 528 const size_t cbReq = pReqHdr->cbReq; 529 529 trunk/src/VBox/HostDrivers/Support/SUPR0.def
r4974 r5031 14 14 ; distribution. VirtualBox OSE is distributed in the hope that it will 15 15 ; be useful, but WITHOUT ANY WARRANTY of any kind. 16 ; 16 17 17 18 LIBRARY SUPR0.dll … … 35 36 RTMemAllocZ 36 37 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 37 52 ; broken - RTSemMutexCreate 38 53 ; broken - RTSemMutexRequest trunk/src/VBox/VMM/PDM.cpp
r4188 r5031 149 149 { 150 150 LogFlow(("PDMR3Init\n")); 151 151 152 /* 152 153 * Assert alignment and sizes. trunk/src/VBox/VMM/PDMLdr.cpp
r4071 r5031 69 69 70 70 /** 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 */ 81 PDMR3DECL(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 */ 131 PDMR3DECL(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 /** 71 159 * Init the module loader part of PDM. 72 160 * … … 76 164 * @returns VBox stutus code. 77 165 * @param pVM VM handle. 166 * @param pvVMMR0Mod The opqaue returned by PDMR3LdrLoadVMMR0. 78 167 */ 79 168 int pdmR3LdrInit(PVM pVM) … … 85 174 86 175 /* 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); 93 179 #endif 94 180 } 181 95 182 96 183 /** … … 521 608 pCur = pCur->pNext; 522 609 } 610 AssertReturn(!strcmp(pszName, VMMR0_MAIN_MODULE_NAME), VERR_INTERNAL_ERROR); 523 611 524 612 /* … … 938 1026 char szPath[RTPATH_MAX]; 939 1027 int rc; 940 941 rc = fShared ? RTPathSharedLibs(szPath, sizeof(szPath)) 1028 1029 rc = fShared ? RTPathSharedLibs(szPath, sizeof(szPath)) 942 1030 : RTPathAppPrivateArch(szPath, sizeof(szPath)); 943 1031 if (!VBOX_SUCCESS(rc)) trunk/src/VBox/VMM/VM.cpp
r4958 r5031 23 23 #include <VBox/cfgm.h> 24 24 #include <VBox/vmm.h> 25 #include <VBox/gvmm.h> 25 26 #include <VBox/mm.h> 26 27 #include <VBox/cpum.h> … … 175 176 176 177 /* 177 * Init support library .178 * Init support library and load the VMMR0.r0 module. 178 179 */ 179 180 PSUPDRVSESSION pSession = 0; … … 181 182 if (VBOX_SUCCESS(rc)) 182 183 { 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)) 193 191 { 194 Log(("VMR3Create: Allocated pVM=%p pVMR0=%p\n", pVM, pVMR0));195 196 192 /* 197 * Do basic init of the VM structure.193 * Request GVMM to create a new VM for us. 198 194 */ 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)) 217 203 { 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 218 209 /* 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. 221 211 */ 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); 226 224 if (VBOX_SUCCESS(rc)) 227 225 { 228 226 /* 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. 230 228 */ 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"); 233 233 if (VBOX_SUCCESS(rc)) 234 234 { 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); 237 241 if (VBOX_SUCCESS(rc)) 238 242 { 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)); 242 253 } 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); 244 282 } 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); 274 286 } 275 287 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); 277 294 AssertRC(rc2); 278 295 } 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 } 287 302 } 288 303 else 289 304 { 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)); 295 307 } 296 RTMemFree(paPages);297 308 298 309 /* terminate SUPLib */ … … 302 313 else 303 314 { 304 const char *pszError;305 315 /* 306 316 * An error occurred at support library initialization time (before the … … 308 318 * initial callback, as the callback list doesn't exist yet. 309 319 */ 320 const char *pszError; 310 321 switch (rc) 311 322 { … … 369 380 static void vmR3CallVMAtError(PFNVMATERROR pfnVMAtError, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, ...) 370 381 { 382 if (!pfnVMAtError) 383 return; 371 384 va_list va; 372 385 va_start(va, pszError); … … 874 887 } 875 888 889 876 890 /** 877 891 * Suspends a running VM. … … 950 964 * @returns VBox error code on failure. 951 965 * @param pVM The VM to resume. 952 * @thread EMT966 * @thread EMT 953 967 */ 954 968 static DECLCALLBACK(int) vmR3Resume(PVM pVM) … … 1460 1474 rc = HWACCMR3Term(pVM); 1461 1475 AssertRC(rc); 1462 rc = VMMR3Term(pVM);1476 rc = PGMR3Term(pVM); 1463 1477 AssertRC(rc); 1464 rc = PGMR3Term(pVM);1478 rc = VMMR3Term(pVM); /* Terminates the ring-0 code! */ 1465 1479 AssertRC(rc); 1466 1480 rc = CPUMR3Term(pVM); … … 1490 1504 { 1491 1505 /* 1492 * Free the event semaphores associated with the request packets. s1506 * Free the event semaphores associated with the request packets. 1493 1507 */ 1494 1508 unsigned cReqs = 0; … … 1535 1549 1536 1550 /* 1537 * Free the VM structure.1538 */ 1539 rc = SUP LowFree(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); 1540 1554 AssertRC(rc); 1541 1555 rc = SUPTerm(); trunk/src/VBox/VMM/VMEmt.cpp
r4295 r5031 86 86 break; 87 87 } 88 elseif (pVM->vm.s.pReqs)88 if (pVM->vm.s.pReqs) 89 89 { 90 90 /* trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
r5026 r5031 35 35 * Header Files * 36 36 *******************************************************************************/ 37 #define LOG_GROUP LOG_GROUP_GVM 37 #define LOG_GROUP LOG_GROUP_GVMM 38 38 #include <VBox/gvmm.h> 39 /* #include "GVMMInternal.h" */ 39 #include "GVMMR0Internal.h" 40 #include <VBox/gvm.h> 40 41 #include <VBox/vm.h> 41 42 #include <VBox/err.h> 42 43 #include <iprt/alloc.h> 43 44 #include <iprt/semaphore.h> 44 #include < iprt/log.h>45 #include <VBox/log.h> 45 46 #include <iprt/thread.h> 46 47 #include <iprt/param.h> 47 48 #include <iprt/string.h> 49 #include <iprt/assert.h> 50 #include <iprt/mem.h> 51 #include <iprt/memobj.h> 48 52 49 53 … … 61 65 /** Our own index / handle value. */ 62 66 uint16_t iSelf; 63 /** Whether to free the VM structure or not. */64 bool fFreeVM;65 67 /** The pointer to the ring-0 only (aka global) VM structure. */ 66 68 PGVM pGVM; … … 111 113 static PGVMM g_pGVMM = NULL; 112 114 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 113 141 114 142 /******************************************************************************* … … 201 229 202 230 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 */ 237 GVMMR0DECL(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 204 267 /** 205 268 * Allocates the VM structure and registers it with GVM. … … 209 272 * @param ppVM Where to store the pointer to the VM structure. 210 273 * 211 * @thread EMT.274 * @thread Any thread. 212 275 */ 213 276 GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM) 214 277 { 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); 218 281 219 282 AssertPtrReturn(ppVM, VERR_INVALID_POINTER); 220 283 *ppVM = NULL; 221 284 222 RTNATIVETHREAD hEMT = RTThreadNativeSelf(); 223 AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR); 285 AssertReturn(RTThreadNativeSelf() != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR); 224 286 225 287 /* … … 235 297 if (iHandle) 236 298 { 237 PGVM MHANDLE pHandle = &pGVMM->aHandles[iHandle];299 PGVMHANDLE pHandle = &pGVMM->aHandles[iHandle]; 238 300 239 301 /* consistency checks, a bit paranoid as always. */ 240 302 if ( !pHandle->pVM 241 /*&& !pHandle->pGVM */303 && !pHandle->pGVM 242 304 && !pHandle->pvObj 243 305 && pHandle->iSelf == iHandle) … … 253 315 pGVMM->iUsedHead = iHandle; 254 316 255 pHandle->fFreeVM = true;256 317 pHandle->pVM = NULL; 257 pHandle->pGVM = NULL; /* to be allocated */318 pHandle->pGVM = NULL; 258 319 pHandle->pSession = pSession; 259 pHandle->hEMT = hEMT;320 pHandle->hEMT = NIL_RTNATIVETHREAD; 260 321 261 322 rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pSession, NULL); … … 263 324 { 264 325 /* 265 * Allocate and initialize the VM structure.326 * Allocate the global VM structure (GVM) and initialize it. 266 327 */ 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) 272 330 { 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 */); 276 351 if (RT_SUCCESS(rc)) 277 352 { 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); 279 355 pVM->enmVMState = VMSTATE_CREATING; 280 pVM->paVMPagesR3 = paPagesR3;281 pVM->pVMR3 = pVMR3;282 356 pVM->pVMR0 = pVM; 283 357 pVM->pSession = pSession; 284 358 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  

