VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/DBGFOS.cpp@ 54218

Last change on this file since 54218 was 54218, checked in by vboxsync, 10 years ago

DBGF,DBGC: Added dmesg command and implemented it for linux guests.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.2 KB
Line 
1/* $Id: DBGFOS.cpp 54218 2015-02-16 15:17:05Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Guest OS Diggers.
4 */
5
6/*
7 * Copyright (C) 2008-2013 Oracle Corporation
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 (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGF
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/mm.h>
25#include "DBGFInternal.h"
26#include <VBox/vmm/uvm.h>
27#include <VBox/err.h>
28#include <VBox/log.h>
29
30#include <iprt/assert.h>
31#include <iprt/thread.h>
32#include <iprt/param.h>
33
34
35/*******************************************************************************
36* Defined Constants And Macros *
37*******************************************************************************/
38
39#define DBGF_OS_READ_LOCK(pUVM) \
40 do { int rcLock = RTCritSectRwEnterShared(&pUVM->dbgf.s.OSCritSect); AssertRC(rcLock); } while (0)
41#define DBGF_OS_READ_UNLOCK(pUVM) \
42 do { int rcLock = RTCritSectRwLeaveShared(&pUVM->dbgf.s.OSCritSect); AssertRC(rcLock); } while (0)
43
44#define DBGF_OS_WRITE_LOCK(pUVM) \
45 do { int rcLock = RTCritSectRwEnterExcl(&pUVM->dbgf.s.OSCritSect); AssertRC(rcLock); } while (0)
46#define DBGF_OS_WRITE_UNLOCK(pUVM) \
47 do { int rcLock = RTCritSectRwLeaveExcl(&pUVM->dbgf.s.OSCritSect); AssertRC(rcLock); } while (0)
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53/**
54 * EMT interface wrappers.
55 *
56 * The diggers expects to be called on an EMT. To avoid the debugger+Main having
57 *
58 * Since the user (debugger/Main) shouldn't be calling directly into the digger code, but rather
59 */
60typedef struct DBGFOSEMTWRAPPER
61{
62 /** Pointer to the next list entry. */
63 struct DBGFOSEMTWRAPPER *pNext;
64 /** The interface type. */
65 DBGFOSINTERFACE enmIf;
66 /** The digger interface pointer. */
67 union
68 {
69 /** Generic void pointer. */
70 void *pv;
71 /** DBGFOSINTERFACE_DMESG.*/
72 PDBGFOSIDMESG pDmesg;
73 } uDigger;
74 /** The user mode VM handle. */
75 PUVM pUVM;
76 /** The wrapper interface union (consult enmIf). */
77 union
78 {
79 /** DBGFOSINTERFACE_DMESG.*/
80 DBGFOSIDMESG Dmesg;
81 } uWrapper;
82} DBGFOSEMTWRAPPER;
83/** Pointer to an EMT interface wrapper. */
84typedef DBGFOSEMTWRAPPER *PDBGFOSEMTWRAPPER;
85
86
87/**
88 * Internal init routine called by DBGFR3Init().
89 *
90 * @returns VBox status code.
91 * @param pUVM The user mode VM handle.
92 */
93int dbgfR3OSInit(PUVM pUVM)
94{
95 return RTCritSectRwInit(&pUVM->dbgf.s.OSCritSect);
96}
97
98
99/**
100 * Internal cleanup routine called by DBGFR3Term().
101 *
102 * @param pUVM The user mode VM handle.
103 */
104void dbgfR3OSTerm(PUVM pUVM)
105{
106 RTCritSectRwDelete(&pUVM->dbgf.s.OSCritSect);
107
108 /*
109 * Terminate the current one.
110 */
111 if (pUVM->dbgf.s.pCurOS)
112 {
113 pUVM->dbgf.s.pCurOS->pReg->pfnTerm(pUVM, pUVM->dbgf.s.pCurOS->abData);
114 pUVM->dbgf.s.pCurOS = NULL;
115 }
116
117 /*
118 * Destroy all the instances.
119 */
120 while (pUVM->dbgf.s.pOSHead)
121 {
122 PDBGFOS pOS = pUVM->dbgf.s.pOSHead;
123 pUVM->dbgf.s.pOSHead = pOS->pNext;
124 if (pOS->pReg->pfnDestruct)
125 pOS->pReg->pfnDestruct(pUVM, pOS->abData);
126
127 PDBGFOSEMTWRAPPER pFree = pOS->pWrapperHead;
128 while ((pFree = pOS->pWrapperHead) != NULL)
129 {
130 pOS->pWrapperHead = pFree->pNext;
131 pFree->pNext = NULL;
132 MMR3HeapFree(pFree);
133 }
134
135 MMR3HeapFree(pOS);
136 }
137}
138
139
140/**
141 * EMT worker function for DBGFR3OSRegister.
142 *
143 * @returns VBox status code.
144 * @param pUVM The user mode VM handle.
145 * @param pReg The registration structure.
146 */
147static DECLCALLBACK(int) dbgfR3OSRegister(PUVM pUVM, PDBGFOSREG pReg)
148{
149 /* more validations. */
150 DBGF_OS_READ_LOCK(pUVM);
151 PDBGFOS pOS;
152 for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
153 if (!strcmp(pOS->pReg->szName, pReg->szName))
154 {
155 DBGF_OS_READ_UNLOCK(pUVM);
156 Log(("dbgfR3OSRegister: %s -> VERR_ALREADY_LOADED\n", pReg->szName));
157 return VERR_ALREADY_LOADED;
158 }
159 DBGF_OS_READ_UNLOCK(pUVM);
160
161 /*
162 * Allocate a new structure, call the constructor and link it into the list.
163 */
164 pOS = (PDBGFOS)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_OS, RT_OFFSETOF(DBGFOS, abData[pReg->cbData]));
165 AssertReturn(pOS, VERR_NO_MEMORY);
166 pOS->pReg = pReg;
167
168 int rc = pOS->pReg->pfnConstruct(pUVM, pOS->abData);
169 if (RT_SUCCESS(rc))
170 {
171 DBGF_OS_WRITE_LOCK(pUVM);
172 pOS->pNext = pUVM->dbgf.s.pOSHead;
173 pUVM->dbgf.s.pOSHead = pOS;
174 DBGF_OS_WRITE_UNLOCK(pUVM);
175 }
176 else
177 {
178 if (pOS->pReg->pfnDestruct)
179 pOS->pReg->pfnDestruct(pUVM, pOS->abData);
180 MMR3HeapFree(pOS);
181 }
182
183 return VINF_SUCCESS;
184}
185
186
187/**
188 * Registers a guest OS digger.
189 *
190 * This will instantiate an instance of the digger and add it
191 * to the list for us in the next call to DBGFR3OSDetect().
192 *
193 * @returns VBox status code.
194 * @param pUVM The user mode VM handle.
195 * @param pReg The registration structure.
196 * @thread Any.
197 */
198VMMR3DECL(int) DBGFR3OSRegister(PUVM pUVM, PCDBGFOSREG pReg)
199{
200 /*
201 * Validate intput.
202 */
203 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
204
205 AssertPtrReturn(pReg, VERR_INVALID_POINTER);
206 AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
207 AssertReturn(pReg->u32EndMagic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
208 AssertReturn(!pReg->fFlags, VERR_INVALID_PARAMETER);
209 AssertReturn(pReg->cbData < _2G, VERR_INVALID_PARAMETER);
210 AssertReturn(pReg->szName[0], VERR_INVALID_NAME);
211 AssertReturn(RTStrEnd(&pReg->szName[0], sizeof(pReg->szName)), VERR_INVALID_NAME);
212 AssertPtrReturn(pReg->pfnConstruct, VERR_INVALID_POINTER);
213 AssertPtrNullReturn(pReg->pfnDestruct, VERR_INVALID_POINTER);
214 AssertPtrReturn(pReg->pfnProbe, VERR_INVALID_POINTER);
215 AssertPtrReturn(pReg->pfnInit, VERR_INVALID_POINTER);
216 AssertPtrReturn(pReg->pfnRefresh, VERR_INVALID_POINTER);
217 AssertPtrReturn(pReg->pfnTerm, VERR_INVALID_POINTER);
218 AssertPtrReturn(pReg->pfnQueryVersion, VERR_INVALID_POINTER);
219 AssertPtrReturn(pReg->pfnQueryInterface, VERR_INVALID_POINTER);
220
221 /*
222 * Pass it on to EMT(0).
223 */
224 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSRegister, 2, pUVM, pReg);
225}
226
227
228/**
229 * EMT worker function for DBGFR3OSDeregister.
230 *
231 * @returns VBox status code.
232 * @param pUVM The user mode VM handle.
233 * @param pReg The registration structure.
234 */
235static DECLCALLBACK(int) dbgfR3OSDeregister(PUVM pUVM, PDBGFOSREG pReg)
236{
237 /*
238 * Unlink it.
239 */
240 bool fWasCurOS = false;
241 PDBGFOS pOSPrev = NULL;
242 PDBGFOS pOS;
243 DBGF_OS_WRITE_LOCK(pUVM);
244 for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOSPrev = pOS, pOS = pOS->pNext)
245 if (pOS->pReg == pReg)
246 {
247 if (pOSPrev)
248 pOSPrev->pNext = pOS->pNext;
249 else
250 pUVM->dbgf.s.pOSHead = pOS->pNext;
251 if (pUVM->dbgf.s.pCurOS == pOS)
252 {
253 pUVM->dbgf.s.pCurOS = NULL;
254 fWasCurOS = true;
255 }
256 break;
257 }
258 DBGF_OS_WRITE_UNLOCK(pUVM);
259 if (!pOS)
260 {
261 Log(("DBGFR3OSDeregister: %s -> VERR_NOT_FOUND\n", pReg->szName));
262 return VERR_NOT_FOUND;
263 }
264
265 /*
266 * Terminate it if it was the current OS, then invoke the
267 * destructor and clean up.
268 */
269 if (fWasCurOS)
270 pOS->pReg->pfnTerm(pUVM, pOS->abData);
271 if (pOS->pReg->pfnDestruct)
272 pOS->pReg->pfnDestruct(pUVM, pOS->abData);
273
274 PDBGFOSEMTWRAPPER pFree = pOS->pWrapperHead;
275 while ((pFree = pOS->pWrapperHead) != NULL)
276 {
277 pOS->pWrapperHead = pFree->pNext;
278 pFree->pNext = NULL;
279 MMR3HeapFree(pFree);
280 }
281
282 MMR3HeapFree(pOS);
283
284 return VINF_SUCCESS;
285}
286
287
288/**
289 * Deregisters a guest OS digger previously registered by DBGFR3OSRegister.
290 *
291 * @returns VBox status code.
292 *
293 * @param pUVM The user mode VM handle.
294 * @param pReg The registration structure.
295 * @thread Any.
296 */
297VMMR3DECL(int) DBGFR3OSDeregister(PUVM pUVM, PCDBGFOSREG pReg)
298{
299 /*
300 * Validate input.
301 */
302 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
303 AssertPtrReturn(pReg, VERR_INVALID_POINTER);
304 AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
305 AssertReturn(pReg->u32EndMagic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
306 AssertReturn(RTStrEnd(&pReg->szName[0], sizeof(pReg->szName)), VERR_INVALID_NAME);
307
308 DBGF_OS_READ_LOCK(pUVM);
309 PDBGFOS pOS;
310 for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
311 if (pOS->pReg == pReg)
312 break;
313 DBGF_OS_READ_UNLOCK(pUVM);
314
315 if (!pOS)
316 {
317 Log(("DBGFR3OSDeregister: %s -> VERR_NOT_FOUND\n", pReg->szName));
318 return VERR_NOT_FOUND;
319 }
320
321 /*
322 * Pass it on to EMT(0).
323 */
324 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSDeregister, 2, pUVM, pReg);
325}
326
327
328/**
329 * EMT worker function for DBGFR3OSDetect.
330 *
331 * @returns VBox status code.
332 * @retval VINF_SUCCESS if successfully detected.
333 * @retval VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
334 *
335 * @param pUVM The user mode VM handle.
336 * @param pszName Where to store the OS name. Empty string if not detected.
337 * @param cchName Size of the buffer.
338 */
339static DECLCALLBACK(int) dbgfR3OSDetect(PUVM pUVM, char *pszName, size_t cchName)
340{
341 /*
342 * Cycle thru the detection routines.
343 */
344 DBGF_OS_WRITE_LOCK(pUVM);
345
346 PDBGFOS const pOldOS = pUVM->dbgf.s.pCurOS;
347 pUVM->dbgf.s.pCurOS = NULL;
348
349 for (PDBGFOS pNewOS = pUVM->dbgf.s.pOSHead; pNewOS; pNewOS = pNewOS->pNext)
350 if (pNewOS->pReg->pfnProbe(pUVM, pNewOS->abData))
351 {
352 int rc;
353 pUVM->dbgf.s.pCurOS = pNewOS;
354 if (pOldOS == pNewOS)
355 rc = pNewOS->pReg->pfnRefresh(pUVM, pNewOS->abData);
356 else
357 {
358 if (pOldOS)
359 pOldOS->pReg->pfnTerm(pUVM, pNewOS->abData);
360 rc = pNewOS->pReg->pfnInit(pUVM, pNewOS->abData);
361 }
362 if (pszName && cchName)
363 strncat(pszName, pNewOS->pReg->szName, cchName);
364
365 DBGF_OS_WRITE_UNLOCK(pUVM);
366 return rc;
367 }
368
369 /* not found */
370 if (pOldOS)
371 pOldOS->pReg->pfnTerm(pUVM, pOldOS->abData);
372
373 DBGF_OS_WRITE_UNLOCK(pUVM);
374 return VINF_DBGF_OS_NOT_DETCTED;
375}
376
377
378/**
379 * Detects the guest OS and try dig out symbols and useful stuff.
380 *
381 * When called the 2nd time, symbols will be updated that if the OS
382 * is the same.
383 *
384 * @returns VBox status code.
385 * @retval VINF_SUCCESS if successfully detected.
386 * @retval VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
387 *
388 * @param pUVM The user mode VM handle.
389 * @param pszName Where to store the OS name. Empty string if not detected.
390 * @param cchName Size of the buffer.
391 * @thread Any.
392 */
393VMMR3DECL(int) DBGFR3OSDetect(PUVM pUVM, char *pszName, size_t cchName)
394{
395 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
396 if (pszName && cchName)
397 *pszName = '\0';
398 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
399
400 /*
401 * Pass it on to EMT(0).
402 */
403 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSDetect, 3, pUVM, pszName, cchName);
404}
405
406
407/**
408 * EMT worker function for DBGFR3OSQueryNameAndVersion
409 *
410 * @returns VBox status code.
411 * @param pUVM The user mode VM handle.
412 * @param pszName Where to store the OS name. Optional.
413 * @param cchName The size of the name buffer.
414 * @param pszVersion Where to store the version string. Optional.
415 * @param cchVersion The size of the version buffer.
416 */
417static DECLCALLBACK(int) dbgfR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
418{
419 /*
420 * Any known OS?
421 */
422 DBGF_OS_READ_LOCK(pUVM);
423
424 if (pUVM->dbgf.s.pCurOS)
425 {
426 int rc = VINF_SUCCESS;
427 if (pszName && cchName)
428 {
429 size_t cch = strlen(pUVM->dbgf.s.pCurOS->pReg->szName);
430 if (cchName > cch)
431 memcpy(pszName, pUVM->dbgf.s.pCurOS->pReg->szName, cch + 1);
432 else
433 {
434 memcpy(pszName, pUVM->dbgf.s.pCurOS->pReg->szName, cchName - 1);
435 pszName[cchName - 1] = '\0';
436 rc = VINF_BUFFER_OVERFLOW;
437 }
438 }
439
440 if (pszVersion && cchVersion)
441 {
442 int rc2 = pUVM->dbgf.s.pCurOS->pReg->pfnQueryVersion(pUVM, pUVM->dbgf.s.pCurOS->abData, pszVersion, cchVersion);
443 if (RT_FAILURE(rc2) || rc == VINF_SUCCESS)
444 rc = rc2;
445 }
446
447 DBGF_OS_READ_UNLOCK(pUVM);
448 return rc;
449 }
450
451 DBGF_OS_READ_UNLOCK(pUVM);
452 return VERR_DBGF_OS_NOT_DETCTED;
453}
454
455
456/**
457 * Queries the name and/or version string for the guest OS.
458 *
459 * It goes without saying that this querying is done using the current
460 * guest OS digger and not additions or user configuration.
461 *
462 * @returns VBox status code.
463 * @param pUVM The user mode VM handle.
464 * @param pszName Where to store the OS name. Optional.
465 * @param cchName The size of the name buffer.
466 * @param pszVersion Where to store the version string. Optional.
467 * @param cchVersion The size of the version buffer.
468 * @thread Any.
469 */
470VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
471{
472 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
473 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
474 AssertPtrNullReturn(pszVersion, VERR_INVALID_POINTER);
475
476 /*
477 * Initialize the output up front.
478 */
479 if (pszName && cchName)
480 *pszName = '\0';
481 if (pszVersion && cchVersion)
482 *pszVersion = '\0';
483
484 /*
485 * Pass it on to EMT(0).
486 */
487 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/,
488 (PFNRT)dbgfR3OSQueryNameAndVersion, 5, pUVM, pszName, cchName, pszVersion, cchVersion);
489}
490
491
492/**
493 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog, Generic EMT wrapper.}
494 */
495static DECLCALLBACK(int) dbgfR3OSEmtIDmesg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages,
496 char *pszBuf, size_t cbBuf, size_t *pcbActual)
497{
498 PDBGFOSEMTWRAPPER pWrapper = RT_FROM_MEMBER(pThis, DBGFOSEMTWRAPPER, uWrapper.Dmesg);
499 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
500 AssertReturn(pUVM == pWrapper->pUVM, VERR_INVALID_VM_HANDLE);
501 AssertReturn(!fFlags, VERR_INVALID_FLAGS);
502 AssertReturn(cMessages > 0, VERR_INVALID_PARAMETER);
503 if (cbBuf)
504 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
505 AssertPtrNullReturn(pcbActual, VERR_INVALID_POINTER);
506
507 return VMR3ReqPriorityCallWaitU(pWrapper->pUVM, 0 /*idDstCpu*/,
508 (PFNRT)pWrapper->uDigger.pDmesg->pfnQueryKernelLog, 7,
509 pWrapper->uDigger.pDmesg, pUVM, fFlags, cMessages, pszBuf, cbBuf, pcbActual);
510
511}
512
513
514/**
515 * EMT worker for DBGFR3OSQueryInterface.
516 *
517 * @param pUVM The user mode VM handle.
518 * @param enmIf The interface identifier.
519 * @param ppvIf Where to store the interface pointer on success.
520 */
521static DECLCALLBACK(void) dbgfR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf, void **ppvIf)
522{
523 AssertPtrReturnVoid(ppvIf);
524 *ppvIf = NULL;
525 AssertReturnVoid(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END);
526 UVM_ASSERT_VALID_EXT_RETURN_VOID(pUVM);
527
528 /*
529 * Forward the query to the current OS.
530 */
531 DBGF_OS_READ_LOCK(pUVM);
532 PDBGFOS pOS = pUVM->dbgf.s.pCurOS;
533 if (pOS)
534 {
535 void *pvDiggerIf;
536 pvDiggerIf = pOS->pReg->pfnQueryInterface(pUVM, pUVM->dbgf.s.pCurOS->abData, enmIf);
537 if (pvDiggerIf)
538 {
539 /*
540 * Do we have an EMT wrapper for this interface already?
541 *
542 * We ASSUME the interfaces are static and not dynamically allocated
543 * for each QueryInterface call.
544 */
545 PDBGFOSEMTWRAPPER pWrapper = pOS->pWrapperHead;
546 while ( pWrapper != NULL
547 && ( pWrapper->uDigger.pv != pvDiggerIf
548 && pWrapper->enmIf != enmIf) )
549 pWrapper = pWrapper->pNext;
550 if (pWrapper)
551 {
552 *ppvIf = &pWrapper->uWrapper;
553 DBGF_OS_READ_UNLOCK(pUVM);
554 return;
555 }
556 DBGF_OS_READ_UNLOCK(pUVM);
557
558 /*
559 * Create a wrapper.
560 */
561 int rc = MMR3HeapAllocExU(pUVM, MM_TAG_DBGF_OS, sizeof(*pWrapper), (void **)&pWrapper);
562 if (RT_FAILURE(rc))
563 return;
564 pWrapper->uDigger.pv = pvDiggerIf;
565 pWrapper->pUVM = pUVM;
566 pWrapper->enmIf = enmIf;
567 switch (enmIf)
568 {
569 case DBGFOSINTERFACE_DMESG:
570 pWrapper->uWrapper.Dmesg.u32Magic = DBGFOSIDMESG_MAGIC;
571 pWrapper->uWrapper.Dmesg.pfnQueryKernelLog = dbgfR3OSEmtIDmesg_QueryKernelLog;
572 pWrapper->uWrapper.Dmesg.u32EndMagic = DBGFOSIDMESG_MAGIC;
573 break;
574 default:
575 AssertFailed();
576 MMR3HeapFree(pWrapper);
577 return;
578 }
579
580 DBGF_OS_WRITE_LOCK(pUVM);
581 if (pUVM->dbgf.s.pCurOS == pOS)
582 {
583 pWrapper->pNext = pOS->pWrapperHead;
584 pOS->pWrapperHead = pWrapper;
585 *ppvIf = &pWrapper->uWrapper;
586 DBGF_OS_WRITE_UNLOCK(pUVM);
587 }
588 else
589 {
590 DBGF_OS_WRITE_UNLOCK(pUVM);
591 MMR3HeapFree(pWrapper);
592 }
593 return;
594 }
595 }
596 DBGF_OS_READ_UNLOCK(pUVM);
597}
598
599
600/**
601 * Query an optional digger interface.
602 *
603 * @returns Pointer to the digger interface on success, NULL if the interfaces isn't
604 * available or no active guest OS digger.
605 * @param pUVM The user mode VM handle.
606 * @param enmIf The interface identifier.
607 * @thread Any.
608 */
609VMMR3DECL(void *) DBGFR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf)
610{
611 AssertMsgReturn(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END, ("%d\n", enmIf), NULL);
612
613 /*
614 * Pass it on to an EMT.
615 */
616 void *pvIf = NULL;
617 VMR3ReqPriorityCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3OSQueryInterface, 3, pUVM, enmIf, &pvIf);
618 return pvIf;
619}
620
621
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