- Timestamp:
- Sep 25, 2007 10:27:37 PM (17 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 1 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
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 966 * @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 *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; 290 407 } 291 292 SUPR0MemFree(pSession, (uintptr_t)paPagesR0);293 408 } 294 409 } … … 320 435 return rc; 321 436 } 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. 327 446 * 328 447 * @returns VBox status code. 329 448 * @param pVM Where to store the pointer to the VM structure. 330 449 * 331 * @thread EMT .450 * @thread EMT if it's associated with the VM, otherwise any thread. 332 451 */ 333 452 GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM) 334 453 { 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 339 458 340 459 /* … … 350 469 351 470 PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM]; 352 AssertReturn(pHandle->hEMT != NIL_RTNATIVETHREAD, VERR_WRONG_ORDER);353 471 AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER); 354 472 355 473 RTNATIVETHREAD hSelf = RTThreadNativeSelf(); 356 AssertReturn(pHandle->hEMT == hSelf , VERR_NOT_OWNER);474 AssertReturn(pHandle->hEMT == hSelf || pHandle->hEMT == NIL_RTNATIVETHREAD, VERR_NOT_OWNER); 357 475 358 476 /* 359 477 * Lookup the handle and destroy the object. 360 * Since the lock isn't recursive , we have to make sure nobody can361 * 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... 362 480 */ 363 481 int rc = RTSemFastMutexRequest(pGVMM->Lock); 364 482 AssertRC(rc); 365 483 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. */ 367 485 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) 370 492 { 371 493 void *pvObj = pHandle->pvObj; … … 373 495 RTSemFastMutexRelease(pGVMM->Lock); 374 496 375 SUPR0ObjRelease(pvObj, p VM->pSession);497 SUPR0ObjRelease(pvObj, pHandle->pSession); 376 498 } 377 499 else 378 500 { 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); 379 503 RTSemFastMutexRelease(pGVMM->Lock); 380 504 rc = VERR_INTERNAL_ERROR; … … 385 509 386 510 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 may392 * 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->pVM432 && !pHandle->pvObj433 && 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 and440 * 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 else459 {460 /*461 * The user wasn't permitted to create this VM.462 * Must use gvmmR0HandleObjDestructor via SUPR0ObjRelease to do the463 * 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 else479 rc = VERR_INTERNAL_ERROR;480 }481 else482 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 506 511 /** 507 512 * Handle destructor. … … 512 517 static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle) 513 518 { 514 SUPR0Printf("gvmmR0HandleObjDestructor: %p %p %p\n", pvObj, pvGVMM, pvHandle);519 LogFlow(("gvmmR0HandleObjDestructor: %p %p %p\n", pvObj, pvGVMM, pvHandle)); 515 520 516 521 /* … … 579 584 580 585 /* 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); 590 593 591 594 /* 592 * Free the VM structure.595 * Do the GVMM cleanup - must be done last. 593 596 */ 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. */ 598 627 599 628 /* … … 601 630 */ 602 631 pHandle->iNext = pGVMM->iFreeHead; 603 pHandle->fFreeVM = false;604 632 pGVMM->iFreeHead = iHandle; 633 ASMAtomicXchgPtr((void * volatile *)&pHandle->pGVM, NULL); 605 634 ASMAtomicXchgPtr((void * volatile *)&pHandle->pVM, NULL); 606 635 ASMAtomicXchgPtr((void * volatile *)&pHandle->pvObj, NULL); … … 614 643 615 644 /** 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 */ 655 GVMMR0DECL(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 */ 715 GVMMR0DECL(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. 617 769 * 618 770 * @returns The GVM pointer on success, NULL on failure. … … 621 773 GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM) 622 774 { 623 PGVMM pGVMM = g_pGVMM;624 AssertPtrReturn(pGVMM, NULL);775 PGVMM pGVMM; 776 GVMM_GET_VALID_INSTANCE(pGVMM, NULL); 625 777 626 778 /* … … 633 785 * Look it up. 634 786 */ 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 */ 804 GVMMR0DECL(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; 640 830 } 641 831 … … 649 839 GVMMR0DECL(PVM) GVMMR0GetVMByHandle(uint32_t hGVM) 650 840 { 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; 668 843 } 669 844 … … 683 858 { 684 859 /* 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. 686 862 */ 687 863 PGVMM pGVMM = g_pGVMM; 688 if (!VALID_PTR(pGVMM)) 864 if ( !VALID_PTR(pGVMM) 865 || pGVMM->u32Magic != GVMM_MAGIC) 689 866 return NULL; 690 867 … … 693 870 694 871 /* 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). 696 873 */ 697 874 for (unsigned i = 1; i < RT_ELEMENTS(pGVMM->aHandles); i++) -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r5026 r5031 139 139 * @param pVM The VM instance in question. 140 140 * @param uVersion The minimum module version required. 141 * @thread EMT. 141 142 */ 142 143 static int VMMR0Init(PVM pVM, unsigned uVersion) … … 193 194 194 195 /* 195 * Try register the VM with GVMM.196 * Associate the ring-0 EMT thread with the GVM. 196 197 */ 197 int rc = GVMMR0 RegisterVM(pVM);198 int rc = GVMMR0AssociateEMTWithVM(pVM); 198 199 if (RT_SUCCESS(rc)) 199 200 { … … 213 214 return rc; 214 215 } 215 216 GVMMR0DeregisterVM(pVM);217 216 } 218 217 … … 229 228 * 230 229 * @param pVM The VM instance in question. 230 * @thread EMT. 231 231 */ 232 232 static int VMMR0Term(PVM pVM) 233 233 { 234 234 /* 235 * Deregister the VM and thelogger.235 * Deregister the logger. 236 236 */ 237 GVMMR0D eregisterVM(pVM);237 GVMMR0DisassociateEMTFromVM(pVM); 238 238 RTLogSetDefaultInstanceThread(NULL, 0); 239 239 return VINF_SUCCESS; … … 642 642 * @param pVM The VM to operate on. 643 643 * @param enmOperation Which operation to execute. 644 * @param pReq 644 * @param pReqHdr This points to a SUPVMMR0REQHDR packet. Optional. 645 645 * @param u64Arg Some simple constant argument. 646 646 * @remarks Assume called with interrupts _enabled_. 647 647 */ 648 static int vmmR0EntryExWorker(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq , uint64_t u64Arg)648 static int vmmR0EntryExWorker(PVM pVM, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReqHdr, uint64_t u64Arg) 649 649 { 650 650 switch (enmOperation) 651 651 { 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 652 666 /* 653 667 * Initialize the R0 part of a VM instance.
Note:
See TracChangeset
for help on using the changeset viewer.