VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp@ 5026

Last change on this file since 5026 was 5026, checked in by vboxsync, 17 years ago

GVM -> GVMM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 21.7 KB
Line 
1/* $Id: GVMMR0.cpp 5026 2007-09-25 15:49:09Z vboxsync $ */
2/** @file
3 * GVMM - Global VM Manager.
4 */
5
6/*
7 * Copyright (C) 2007 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 */
18
19
20/** @page pg_GVMM GVMM - The Global VM Manager
21 *
22 * The Global VM Manager lives in ring-0. It's main function at the moment
23 * is to manage a list of all running VMs, keep a ring-0 only structure (GVM)
24 * for each of them, and assign them unique identifiers (so GMM can track
25 * page owners). The idea for the future is to add an idle priority kernel
26 * thread that can take care of tasks like page sharing.
27 *
28 * The GVMM will create a ring-0 object for each VM when it's registered,
29 * this is both for session cleanup purposes and for having a point where
30 * it's possible to implement usage polices later (in SUPR0ObjRegister).
31 */
32
33
34/*******************************************************************************
35* Header Files *
36*******************************************************************************/
37#define LOG_GROUP LOG_GROUP_GVM
38#include <VBox/gvmm.h>
39/* #include "GVMMInternal.h" */
40#include <VBox/vm.h>
41#include <VBox/err.h>
42#include <iprt/alloc.h>
43#include <iprt/semaphore.h>
44#include <iprt/log.h>
45#include <iprt/thread.h>
46#include <iprt/param.h>
47#include <iprt/string.h>
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53
54/**
55 * Global VM handle.
56 */
57typedef struct GVMHANDLE
58{
59 /** The index of the next handle in the list (free or used). (0 is nil.) */
60 uint16_t volatile iNext;
61 /** Our own index / handle value. */
62 uint16_t iSelf;
63 /** Whether to free the VM structure or not. */
64 bool fFreeVM;
65 /** The pointer to the ring-0 only (aka global) VM structure. */
66 PGVM pGVM;
67 /** The ring-0 mapping of the shared VM instance data. */
68 PVM pVM;
69 /** The virtual machine object. */
70 void *pvObj;
71 /** The session this VM is associated with. */
72 PSUPDRVSESSION pSession;
73 /** The ring-0 handle of the EMT thread.
74 * This is used for assertions and similar cases where we need to find the VM handle. */
75 RTNATIVETHREAD hEMT;
76} GVMHANDLE;
77/** Pointer to a global VM handle. */
78typedef GVMHANDLE *PGVMHANDLE;
79
80/**
81 * The GVMM instance data.
82 */
83typedef struct GVMM
84{
85 /** Eyecatcher / magic. */
86 uint32_t u32Magic;
87 /** The index of the head of the free handle chain. (0 is nil.) */
88 uint16_t volatile iFreeHead;
89 /** The index of the head of the active handle chain. (0 is nil.) */
90 uint16_t volatile iUsedHead;
91 /** The lock used to serialize registration and deregistration. */
92 RTSEMFASTMUTEX Lock;
93 /** The handle array.
94 * The size of this array defines the maximum number of currently running VMs.
95 * The first entry is unused as it represents the NIL handle. */
96 GVMHANDLE aHandles[128];
97} GVMM;
98/** Pointer to the GVMM instance data. */
99typedef GVMM *PGVMM;
100
101/** The GVMM::u32Magic value (Charlie Haden). */
102#define GVMM_MAGIC 0x19370806
103
104
105
106/*******************************************************************************
107* Global Variables *
108*******************************************************************************/
109/** Pointer to the GVMM instance data.
110 * (Just my general dislike for global variables.) */
111static PGVMM g_pGVMM = NULL;
112
113
114/*******************************************************************************
115* Internal Functions *
116*******************************************************************************/
117static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle);
118
119
120/**
121 * Initializes the GVMM.
122 *
123 * This is called while owninng the loader sempahore (see supdrvIOCtl_LdrLoad()).
124 *
125 * @returns VBox status code.
126 */
127GVMMR0DECL(int) GVMMR0Init(void)
128{
129 SUPR0Printf("GVMMR0Init:\n");
130
131 /*
132 * Allocate and initialize the instance data.
133 */
134 PGVMM pGVMM = (PGVMM)RTMemAllocZ(sizeof(*pGVMM));
135 if (!pGVMM)
136 return VERR_NO_MEMORY;
137 int rc = RTSemFastMutexCreate(&pGVMM->Lock);
138 if (RT_SUCCESS(rc))
139 {
140 pGVMM->u32Magic = GVMM_MAGIC;
141 pGVMM->iUsedHead = 0;
142 pGVMM->iFreeHead = 1;
143
144 /* the nil handle */
145 pGVMM->aHandles[0].iSelf = 0;
146 pGVMM->aHandles[0].iNext = 0;
147
148 /* the tail */
149 unsigned i = RT_ELEMENTS(pGVMM->aHandles);
150 pGVMM->aHandles[i].iSelf = i;
151 pGVMM->aHandles[i].iNext = 0; /* nil */
152
153 /* the rest */
154 while (i-- > 1)
155 {
156 pGVMM->aHandles[i].iSelf = i;
157 pGVMM->aHandles[i].iNext = i + 1;
158 }
159
160 g_pGVMM = pGVMM;
161 SUPR0Printf("GVMMR0Init: pGVMM=%p\n", pGVMM);
162 return VINF_SUCCESS;
163 }
164
165 RTMemFree(pGVMM);
166 return rc;
167}
168
169
170/**
171 * Terminates the GVM.
172 *
173 * This is called while owning the loader semaphore (see supdrvLdrFree()).
174 * And unless something is wrong, there should be absolutely no VMs
175 * registered at this point.
176 */
177GVMMR0DECL(void) GVMMR0Term(void)
178{
179 SUPR0Printf("GVMMR0Term:\n");
180
181 PGVMM pGVMM = g_pGVMM;
182 g_pGVMM = NULL;
183 if (RT_UNLIKELY(!VALID_PTR(pGVMM)))
184 {
185 SUPR0Printf("GVMMR0Term: pGVMM=%p\n", pGVMM);
186 return;
187 }
188
189 RTSemFastMutexDestroy(pGVMM->Lock);
190 pGVMM->Lock = NIL_RTSEMFASTMUTEX;
191 pGVMM->u32Magic++;
192 pGVMM->iFreeHead = 0;
193 if (pGVMM->iUsedHead)
194 {
195 SUPR0Printf("GVMMR0Term: iUsedHead=%#x!\n", pGVMM->iUsedHead);
196 pGVMM->iUsedHead = 0;
197 }
198
199 RTMemFree(pGVMM);
200}
201
202
203#if 0 /* not currently used */
204/**
205 * Allocates the VM structure and registers it with GVM.
206 *
207 * @returns VBox status code.
208 * @param pSession The support driver session.
209 * @param ppVM Where to store the pointer to the VM structure.
210 *
211 * @thread EMT.
212 */
213GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, PVM *ppVM)
214{
215 SUPR0Printf("GVMMR0CreateVM: pSession=%p\n", pSession);
216 PGVMM pGVMM = g_pGVMM;
217 AssertPtrReturn(pGVMM, VERR_INTERNAL_ERROR);
218
219 AssertPtrReturn(ppVM, VERR_INVALID_POINTER);
220 *ppVM = NULL;
221
222 RTNATIVETHREAD hEMT = RTThreadNativeSelf();
223 AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_INTERNAL_ERROR);
224
225 /*
226 * The whole allocation process is protected by the lock.
227 */
228 int rc = RTSemFastMutexRequest(pGVMM->Lock);
229 AssertRCReturn(rc, rc);
230
231 /*
232 * Allocate a handle first so we don't waste resources unnecessarily.
233 */
234 uint16_t iHandle = pGVMM->iFreeHead;
235 if (iHandle)
236 {
237 PGVMMHANDLE pHandle = &pGVMM->aHandles[iHandle];
238
239 /* consistency checks, a bit paranoid as always. */
240 if ( !pHandle->pVM
241 /*&& !pHandle->pGVM */
242 && !pHandle->pvObj
243 && pHandle->iSelf == iHandle)
244 {
245 pHandle->pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_VM, gvmmR0HandleObjDestructor, pGVMM, pHandle);
246 if (pHandle->pvObj)
247 {
248 /*
249 * Move the handle from the free to used list and perform permission checks.
250 */
251 pGVMM->iFreeHead = pHandle->iNext;
252 pHandle->iNext = pGVMM->iUsedHead;
253 pGVMM->iUsedHead = iHandle;
254
255 pHandle->fFreeVM = true;
256 pHandle->pVM = NULL;
257 pHandle->pGVM = NULL; /* to be allocated */
258 pHandle->pSession = pSession;
259 pHandle->hEMT = hEMT;
260
261 rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pSession, NULL);
262 if (RT_SUCCESS(rc))
263 {
264 /*
265 * Allocate and initialize the VM structure.
266 */
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))
272 {
273 PVM pVM;
274 PVMR3 pVMR3;
275 rc = SUPR0LowAlloc(pSession, cPages, (void **)&pVM, &pVMR3, paPagesR0);
276 if (RT_SUCCESS(rc))
277 {
278 memset(pVM, 0, cPages * PAGE_SIZE);
279 pVM->enmVMState = VMSTATE_CREATING;
280 pVM->paVMPagesR3 = paPagesR3;
281 pVM->pVMR3 = pVMR3;
282 pVM->pVMR0 = pVM;
283 pVM->pSession = pSession;
284 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;
290 }
291
292 SUPR0MemFree(pSession, (uintptr_t)paPagesR0);
293 }
294 }
295 /* else: The user wasn't permitted to create this VM. */
296
297 /*
298 * The handle will be freed by gvmmR0HandleObjDestructor as we release the
299 * object reference here. A little extra mess because of non-recursive lock.
300 */
301 void *pvObj = pHandle->pvObj;
302 pHandle->pvObj = NULL;
303 RTSemFastMutexRelease(pGVMM->Lock);
304
305 SUPR0ObjRelease(pvObj, pSession);
306
307 SUPR0Printf("GVMMR0CreateVM: failed, rc=%d\n", rc);
308 return rc;
309 }
310
311 rc = VERR_NO_MEMORY;
312 }
313 else
314 rc = VERR_INTERNAL_ERROR;
315 }
316 else
317 rc = VERR_GVM_TOO_MANY_VMS;
318
319 RTSemFastMutexRelease(pGVMM->Lock);
320 return rc;
321}
322#endif /* not used yet. */
323
324
325/**
326 * Deregistres the VM and destroys the VM structure.
327 *
328 * @returns VBox status code.
329 * @param pVM Where to store the pointer to the VM structure.
330 *
331 * @thread EMT.
332 */
333GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM)
334{
335 SUPR0Printf("GVMMR0DestroyVM: pVM=%p\n", pVM);
336
337 PGVMM pGVMM = g_pGVMM;
338 AssertPtrReturn(pGVMM, VERR_INTERNAL_ERROR);
339
340 /*
341 * Validate the VM structure, state and caller.
342 */
343 AssertPtrReturn(pVM, VERR_INVALID_POINTER);
344 AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
345 AssertMsgReturn(pVM->enmVMState >= VMSTATE_CREATING && pVM->enmVMState <= VMSTATE_TERMINATED, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
346
347 uint32_t hGVM = pVM->hSelf;
348 AssertReturn(hGVM != NIL_GVM_HANDLE, VERR_INVALID_HANDLE);
349 AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), VERR_INVALID_HANDLE);
350
351 PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM];
352 AssertReturn(pHandle->hEMT != NIL_RTNATIVETHREAD, VERR_WRONG_ORDER);
353 AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER);
354
355 RTNATIVETHREAD hSelf = RTThreadNativeSelf();
356 AssertReturn(pHandle->hEMT == hSelf, VERR_NOT_OWNER);
357
358 /*
359 * Lookup the handle and destroy the object.
360 * Since the lock isn't recursive, we have to make sure nobody can
361 * race us as we leave the lock and call SUPR0ObjRelease.
362 */
363 int rc = RTSemFastMutexRequest(pGVMM->Lock);
364 AssertRC(rc);
365
366 /* be very careful here because we might be racing someone else cleaning up... */
367 if ( pHandle->pVM == pVM
368 && pHandle->hEMT == hSelf
369 && VALID_PTR(pHandle->pvObj))
370 {
371 void *pvObj = pHandle->pvObj;
372 pHandle->pvObj = NULL;
373 RTSemFastMutexRelease(pGVMM->Lock);
374
375 SUPR0ObjRelease(pvObj, pVM->pSession);
376 }
377 else
378 {
379 RTSemFastMutexRelease(pGVMM->Lock);
380 rc = VERR_INTERNAL_ERROR;
381 }
382
383 return rc;
384}
385
386
387#if 1 /* this approach is unsafe wrt to the freeing of pVM. Keeping it as a possible fallback for 1.5.x. */
388/**
389 * Register the specified VM with the GGVM.
390 *
391 * Permission polices and resource consumption polices may or may
392 * not be checked that this poin, be ready to deald nicely with failure.
393 *
394 * @returns VBox status code.
395 *
396 * @param pVM The VM instance data (aka handle), ring-0 mapping of ccourse.
397 * The VM::hGVM field may be updated by this call.
398 * @thread EMT.
399 */
400GVMMR0DECL(int) GVMMR0RegisterVM(PVM pVM)
401{
402 SUPR0Printf("GVMMR0RegisterVM: pVM=%p\n", pVM);
403 PGVMM pGVMM = g_pGVMM;
404 AssertPtrReturn(pGVMM, VERR_INTERNAL_ERROR);
405
406 /*
407 * Validate the VM structure and state.
408 */
409 AssertPtrReturn(pVM, VERR_INVALID_POINTER);
410 AssertReturn(!((uintptr_t)pVM & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
411 AssertMsgReturn(pVM->enmVMState == VMSTATE_CREATING, ("%d\n", pVM->enmVMState), VERR_WRONG_ORDER);
412
413 RTNATIVETHREAD hEMT = RTThreadNativeSelf();
414 AssertReturn(hEMT != NIL_RTNATIVETHREAD, VERR_NOT_SUPPORTED);
415
416 /*
417 * Take the lock and call the worker function.
418 */
419 int rc = RTSemFastMutexRequest(pGVMM->Lock);
420 AssertRCReturn(rc, rc);
421
422 /*
423 * Allocate a handle.
424 */
425 uint16_t iHandle = pGVMM->iFreeHead;
426 if (iHandle)
427 {
428 PGVMHANDLE pHandle = &pGVMM->aHandles[iHandle];
429
430 /* consistency checks, a bit paranoid as always. */
431 if ( !pHandle->pVM
432 && !pHandle->pvObj
433 && pHandle->iSelf == iHandle)
434 {
435 pHandle->pvObj = SUPR0ObjRegister(pVM->pSession, SUPDRVOBJTYPE_VM, gvmmR0HandleObjDestructor, pGVMM, pHandle);
436 if (pHandle->pvObj)
437 {
438 /*
439 * Move the handle from the free to used list and
440 * perform permission checks.
441 */
442 pGVMM->iFreeHead = pHandle->iNext;
443 pHandle->iNext = pGVMM->iUsedHead;
444 pGVMM->iUsedHead = iHandle;
445
446 pHandle->fFreeVM = false;
447 pHandle->pVM = pVM;
448 pHandle->pGVM = NULL; /** @todo to be allocated */
449 pHandle->pSession = pVM->pSession;
450 pHandle->hEMT = hEMT;
451
452 rc = SUPR0ObjVerifyAccess(pHandle->pvObj, pVM->pSession, NULL);
453 if (RT_SUCCESS(rc))
454 {
455 pVM->hSelf = iHandle;
456 RTSemFastMutexRelease(pGVMM->Lock);
457 }
458 else
459 {
460 /*
461 * The user wasn't permitted to create this VM.
462 * Must use gvmmR0HandleObjDestructor via SUPR0ObjRelease to do the
463 * cleanups. The lock isn't recursive, thus the extra mess.
464 */
465 void *pvObj = pHandle->pvObj;
466 pHandle->pvObj = NULL;
467 RTSemFastMutexRelease(pGVMM->Lock);
468
469 SUPR0ObjRelease(pvObj, pVM->pSession);
470 }
471 if (RT_FAILURE(rc))
472 SUPR0Printf("GVMMR0RegisterVM: permission denied, rc=%d\n", rc);
473 return rc;
474 }
475
476 rc = VERR_NO_MEMORY;
477 }
478 else
479 rc = VERR_INTERNAL_ERROR;
480 }
481 else
482 rc = VERR_GVM_TOO_MANY_VMS;
483
484 RTSemFastMutexRelease(pGVMM->Lock);
485 SUPR0Printf("GVMMR0RegisterVM: failed, rc=%d, iHandle=%d\n", rc, iHandle);
486 return rc;
487}
488
489
490/**
491 * Deregister a VM previously registered using the GVMMR0RegisterVM API.
492 *
493 *
494 * @returns VBox status code.
495 * @param pVM The VM handle.
496 * @thread EMT.
497 */
498GVMMR0DECL(int) GVMMR0DeregisterVM(PVM pVM)
499{
500 SUPR0Printf("GVMMR0DeregisterVM: pVM=%p\n", pVM);
501 return GVMMR0DestroyVM(pVM);
502}
503#endif /* ... */
504
505
506/**
507 * Handle destructor.
508 *
509 * @param pvGVMM The GVM instance pointer.
510 * @param pvHandle The handle pointer.
511 */
512static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle)
513{
514 SUPR0Printf("gvmmR0HandleObjDestructor: %p %p %p\n", pvObj, pvGVMM, pvHandle);
515
516 /*
517 * Some quick, paranoid, input validation.
518 */
519 PGVMHANDLE pHandle = (PGVMHANDLE)pvHandle;
520 AssertPtr(pHandle);
521 PGVMM pGVMM = (PGVMM)pvGVMM;
522 Assert(pGVMM == g_pGVMM);
523 const uint16_t iHandle = pHandle - &pGVMM->aHandles[0];
524 if ( !iHandle
525 || iHandle >= RT_ELEMENTS(pGVMM->aHandles)
526 || iHandle != pHandle->iSelf)
527 {
528 SUPR0Printf("GVM: handle %d is out of range or corrupt (iSelf=%d)!\n", iHandle, pHandle->iSelf);
529 return;
530 }
531
532 int rc = RTSemFastMutexRequest(pGVMM->Lock);
533 AssertRC(rc);
534
535 /*
536 * This is a tad slow but a doubly linked list is too much hazzle.
537 */
538 if (RT_UNLIKELY(pHandle->iNext >= RT_ELEMENTS(pGVMM->aHandles)))
539 {
540 SUPR0Printf("GVM: used list index %d is out of range!\n", pHandle->iNext);
541 RTSemFastMutexRelease(pGVMM->Lock);
542 return;
543 }
544
545 if (pGVMM->iUsedHead == iHandle)
546 pGVMM->iUsedHead = pHandle->iNext;
547 else
548 {
549 uint16_t iPrev = pGVMM->iUsedHead;
550 int c = RT_ELEMENTS(pGVMM->aHandles) + 2;
551 while (!iPrev)
552 {
553 if (RT_UNLIKELY(iPrev >= RT_ELEMENTS(pGVMM->aHandles)))
554 {
555 SUPR0Printf("GVM: used list index %d is out of range!\n");
556 RTSemFastMutexRelease(pGVMM->Lock);
557 return;
558 }
559 if (RT_UNLIKELY(c-- <= 0))
560 {
561 iPrev = 0;
562 break;
563 }
564
565 if (pGVMM->aHandles[iPrev].iNext == iHandle)
566 break;
567 iPrev = pGVMM->aHandles[iPrev].iNext;
568 }
569 if (!iPrev)
570 {
571 SUPR0Printf("GVM: can't find the handle previous previous of %d!\n", pHandle->iSelf);
572 RTSemFastMutexRelease(pGVMM->Lock);
573 return;
574 }
575
576 pGVMM->aHandles[iPrev].iNext = pHandle->iNext;
577 }
578 pHandle->iNext = 0;
579
580 /*
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);
590
591 /*
592 * Free the VM structure.
593 */
594 ASMAtomicXchgU32((uint32_t volatile *)&pVM->hSelf, NIL_GVM_HANDLE);
595 SUPR0MemFree(pHandle->pSession, pVM->paVMPagesR3);
596 SUPR0LowFree(pHandle->pSession, (uintptr_t)pVM);
597 }
598
599 /*
600 * Free the handle.
601 */
602 pHandle->iNext = pGVMM->iFreeHead;
603 pHandle->fFreeVM = false;
604 pGVMM->iFreeHead = iHandle;
605 ASMAtomicXchgPtr((void * volatile *)&pHandle->pVM, NULL);
606 ASMAtomicXchgPtr((void * volatile *)&pHandle->pvObj, NULL);
607 ASMAtomicXchgPtr((void * volatile *)&pHandle->pSession, NULL);
608 ASMAtomicXchgSize(&pHandle->hEMT, NIL_RTNATIVETHREAD);
609
610 RTSemFastMutexRelease(pGVMM->Lock);
611 SUPR0Printf("gvmmR0HandleObjDestructor: returns\n");
612}
613
614
615/**
616 * Lookup a GVM pointer by its handle.
617 *
618 * @returns The GVM pointer on success, NULL on failure.
619 * @param hGVM The global VM handle. Asserts on bad handle.
620 */
621GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM)
622{
623 PGVMM pGVMM = g_pGVMM;
624 AssertPtrReturn(pGVMM, NULL);
625
626 /*
627 * Validate.
628 */
629 AssertReturn(hGVM != NIL_GVM_HANDLE, NULL);
630 AssertReturn(hGVM < RT_ELEMENTS(pGVMM->aHandles), NULL);
631
632 /*
633 * Look it up.
634 */
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;
640}
641
642
643/**
644 * Lookup a VM by its global handle.
645 *
646 * @returns The VM handle on success, NULL on failure.
647 * @param hGVM The global VM handle. Asserts on bad handle.
648 */
649GVMMR0DECL(PVM) GVMMR0GetVMByHandle(uint32_t hGVM)
650{
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;
668}
669
670
671/**
672 * Looks up the VM belonging to the specified EMT thread.
673 *
674 * This is used by the assertion machinery in VMMR0.cpp to avoid causing
675 * unnecessary kernel panics when the EMT thread hits an assertion. The
676 * call may or not be an EMT thread.
677 *
678 * @returns The VM handle on success, NULL on failure.
679 * @param hEMT The native thread handle of the EMT.
680 * NIL_RTNATIVETHREAD means the current thread
681 */
682GVMMR0DECL(PVM) GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT)
683{
684 /*
685 * Be very careful here as we're called in AssertMsgN context.
686 */
687 PGVMM pGVMM = g_pGVMM;
688 if (!VALID_PTR(pGVMM))
689 return NULL;
690
691 if (hEMT == NIL_RTNATIVETHREAD)
692 hEMT = RTThreadNativeSelf();
693
694 /*
695 * Search the handles, we don't dare take the lock (assert).
696 */
697 for (unsigned i = 1; i < RT_ELEMENTS(pGVMM->aHandles); i++)
698 if ( pGVMM->aHandles[i].hEMT == hEMT
699 && pGVMM->aHandles[i].iSelf == i
700 && VALID_PTR(pGVMM->aHandles[i].pvObj)
701 && VALID_PTR(pGVMM->aHandles[i].pVM))
702 return pGVMM->aHandles[i].pVM;
703
704 return NULL;
705}
706
707
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette