VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PGMHandler.cpp@ 80163

Last change on this file since 80163 was 80163, checked in by vboxsync, 6 years ago

VMM: Kicking out raw-mode - PGM Virt Handlers, ++. bugref:9517

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 20.4 KB
Line 
1/* $Id: PGMHandler.cpp 80163 2019-08-06 20:28:12Z vboxsync $ */
2/** @file
3 * PGM - Page Manager / Monitor, Access Handlers.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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_PGM
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/pgm.h>
25#include <VBox/vmm/cpum.h>
26#include <VBox/vmm/iom.h>
27#include <VBox/sup.h>
28#include <VBox/vmm/mm.h>
29#include <VBox/vmm/em.h>
30#include <VBox/vmm/stam.h>
31#ifdef VBOX_WITH_REM
32# include <VBox/vmm/rem.h>
33#endif
34#include <VBox/vmm/dbgf.h>
35#ifdef VBOX_WITH_REM
36# include <VBox/vmm/rem.h>
37#endif
38#include <VBox/vmm/selm.h>
39#include <VBox/vmm/ssm.h>
40#include "PGMInternal.h"
41#include <VBox/vmm/vm.h>
42#include "PGMInline.h"
43#include <VBox/dbg.h>
44
45#include <VBox/log.h>
46#include <iprt/assert.h>
47#include <iprt/alloc.h>
48#include <iprt/asm.h>
49#include <iprt/thread.h>
50#include <iprt/string.h>
51#include <VBox/param.h>
52#include <VBox/err.h>
53#include <VBox/vmm/hm.h>
54
55
56/*********************************************************************************************************************************
57* Internal Functions *
58*********************************************************************************************************************************/
59static DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser);
60static DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser);
61static DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser);
62#ifdef VBOX_WITH_RAW_MODE
63static DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
64#endif
65
66
67
68
69/**
70 * Register a physical page access handler type, extended version.
71 *
72 * @returns VBox status code.
73 * @param pVM The cross context VM structure.
74 * @param enmKind The kind of access handler.
75 * @param pfnHandlerR3 Pointer to the ring-3 handler callback.
76 * @param pfnHandlerR0 Pointer to the ring-0 handler callback.
77 * @param pfnPfHandlerR0 Pointer to the ring-0 \#PF handler callback.
78 * @param pfnHandlerRC Pointer to the raw-mode context handler callback.
79 * @param pfnPfHandlerRC Pointer to the raw-mode context \#PF handler
80 * callback.
81 * @param pszDesc The type description.
82 * @param phType Where to return the type handle (cross context
83 * safe).
84 */
85VMMR3_INT_DECL(int) PGMR3HandlerPhysicalTypeRegisterEx(PVM pVM, PGMPHYSHANDLERKIND enmKind,
86 PFNPGMPHYSHANDLER pfnHandlerR3,
87 R0PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR0,
88 R0PTRTYPE(PFNPGMRZPHYSPFHANDLER) pfnPfHandlerR0,
89 RCPTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerRC,
90 RCPTRTYPE(PFNPGMRZPHYSPFHANDLER) pfnPfHandlerRC,
91 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
92{
93 AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);
94 AssertReturn(pfnHandlerR0 != NIL_RTR0PTR, VERR_INVALID_POINTER);
95 AssertReturn(pfnPfHandlerR0 != NIL_RTR0PTR, VERR_INVALID_POINTER);
96 AssertReturn(pfnHandlerRC != NIL_RTRCPTR || !VM_IS_RAW_MODE_ENABLED(pVM), VERR_INVALID_POINTER);
97 AssertReturn(pfnPfHandlerRC != NIL_RTRCPTR || !VM_IS_RAW_MODE_ENABLED(pVM), VERR_INVALID_POINTER);
98 AssertPtrReturn(pszDesc, VERR_INVALID_POINTER);
99 AssertReturn( enmKind == PGMPHYSHANDLERKIND_WRITE
100 || enmKind == PGMPHYSHANDLERKIND_ALL
101 || enmKind == PGMPHYSHANDLERKIND_MMIO,
102 VERR_INVALID_PARAMETER);
103
104 PPGMPHYSHANDLERTYPEINT pType;
105 int rc = MMHyperAlloc(pVM, sizeof(*pType), 0, MM_TAG_PGM_HANDLER_TYPES, (void **)&pType);
106 if (RT_SUCCESS(rc))
107 {
108 pType->u32Magic = PGMPHYSHANDLERTYPEINT_MAGIC;
109 pType->cRefs = 1;
110 pType->enmKind = enmKind;
111 pType->uState = enmKind == PGMPHYSHANDLERKIND_WRITE
112 ? PGM_PAGE_HNDL_PHYS_STATE_WRITE : PGM_PAGE_HNDL_PHYS_STATE_ALL;
113 pType->pfnHandlerR3 = pfnHandlerR3;
114 pType->pfnHandlerR0 = pfnHandlerR0;
115 pType->pfnPfHandlerR0 = pfnPfHandlerR0;
116 pType->pfnHandlerRC = pfnHandlerRC;
117 pType->pfnPfHandlerRC = pfnPfHandlerRC;
118 pType->pszDesc = pszDesc;
119
120 pgmLock(pVM);
121 RTListOff32Append(&pVM->pgm.s.CTX_SUFF(pTrees)->HeadPhysHandlerTypes, &pType->ListNode);
122 pgmUnlock(pVM);
123
124 *phType = MMHyperHeapPtrToOffset(pVM, pType);
125 LogFlow(("PGMR3HandlerPhysicalTypeRegisterEx: %p/%#x: enmKind=%d pfnHandlerR3=%RHv pfnHandlerR0=%RHv pfnHandlerRC=%RRv pszDesc=%s\n",
126 pType, *phType, enmKind, pfnHandlerR3, pfnPfHandlerR0, pfnPfHandlerRC, pszDesc));
127 return VINF_SUCCESS;
128 }
129 *phType = NIL_PGMPHYSHANDLERTYPE;
130 return rc;
131}
132
133
134/**
135 * Register a physical page access handler type.
136 *
137 * @returns VBox status code.
138 * @param pVM The cross context VM structure.
139 * @param enmKind The kind of access handler.
140 * @param pfnHandlerR3 Pointer to the ring-3 handler callback.
141 * @param pszModR0 The name of the ring-0 module, NULL is an alias for
142 * the main ring-0 module.
143 * @param pszHandlerR0 The name of the ring-0 handler, NULL if the ring-3
144 * handler should be called.
145 * @param pszPfHandlerR0 The name of the ring-0 \#PF handler, NULL if the
146 * ring-3 handler should be called.
147 * @param pszModRC The name of the raw-mode context module, NULL is an
148 * alias for the main RC module.
149 * @param pszHandlerRC The name of the raw-mode context handler, NULL if
150 * the ring-3 handler should be called.
151 * @param pszPfHandlerRC The name of the raw-mode context \#PF handler, NULL
152 * if the ring-3 handler should be called.
153 * @param pszDesc The type description.
154 * @param phType Where to return the type handle (cross context
155 * safe).
156 */
157VMMR3DECL(int) PGMR3HandlerPhysicalTypeRegister(PVM pVM, PGMPHYSHANDLERKIND enmKind,
158 R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
159 const char *pszModR0, const char *pszHandlerR0, const char *pszPfHandlerR0,
160 const char *pszModRC, const char *pszHandlerRC, const char *pszPfHandlerRC,
161 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
162{
163 LogFlow(("PGMR3HandlerPhysicalTypeRegister: enmKind=%d pfnHandlerR3=%RHv pszModR0=%s pszHandlerR0=%s pszPfHandlerR0=%s pszModRC=%s pszHandlerRC=%s pszPfHandlerRC=%s pszDesc=%s\n",
164 enmKind, pfnHandlerR3, pszModR0, pszHandlerR0, pszPfHandlerR0, pszModRC, pszHandlerRC, pszPfHandlerRC, pszDesc));
165
166 /*
167 * Validate input.
168 */
169 AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);
170 AssertPtrNullReturn(pszModR0, VERR_INVALID_POINTER);
171 AssertPtrNullReturn(pszHandlerR0, VERR_INVALID_POINTER);
172 AssertPtrNullReturn(pszPfHandlerR0, VERR_INVALID_POINTER);
173 AssertPtrNullReturn(pszModRC, VERR_INVALID_POINTER);
174 AssertPtrNullReturn(pszHandlerRC, VERR_INVALID_POINTER);
175 AssertPtrNullReturn(pszPfHandlerRC, VERR_INVALID_POINTER);
176
177 /*
178 * Resolve the R0 handlers.
179 */
180 R0PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR0 = NIL_RTR0PTR;
181 int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pszHandlerR0 ? pszModR0 : NULL, NULL /*pszSearchPath*/,
182 pszHandlerR0 ? pszHandlerR0 : "pgmPhysHandlerRedirectToHC", &pfnHandlerR0);
183 if (RT_SUCCESS(rc))
184 {
185 R0PTRTYPE(PFNPGMR0PHYSPFHANDLER) pfnPfHandlerR0 = NIL_RTR0PTR;
186 rc = PDMR3LdrGetSymbolR0Lazy(pVM, pszPfHandlerR0 ? pszModR0 : NULL, NULL /*pszSearchPath*/,
187 pszPfHandlerR0 ? pszPfHandlerR0 : "pgmPhysPfHandlerRedirectToHC", &pfnPfHandlerR0);
188 if (RT_SUCCESS(rc))
189 {
190 /*
191 * Resolve the GC handler.
192 */
193 RTRCPTR pfnHandlerRC = NIL_RTRCPTR;
194 RTRCPTR pfnPfHandlerRC = NIL_RTRCPTR;
195 if (VM_IS_RAW_MODE_ENABLED(pVM))
196 {
197 rc = PDMR3LdrGetSymbolRCLazy(pVM, pszHandlerRC ? pszModRC : NULL, NULL /*pszSearchPath*/,
198 pszHandlerRC ? pszHandlerRC : "pgmPhysHandlerRedirectToHC", &pfnHandlerRC);
199 if (RT_SUCCESS(rc))
200 {
201 rc = PDMR3LdrGetSymbolRCLazy(pVM, pszPfHandlerRC ? pszModRC : NULL, NULL /*pszSearchPath*/,
202 pszPfHandlerRC ? pszPfHandlerRC : "pgmPhysPfHandlerRedirectToHC", &pfnPfHandlerRC);
203 AssertMsgRC(rc, ("Failed to resolve %s.%s, rc=%Rrc.\n", pszPfHandlerRC ? pszModRC : VMMRC_MAIN_MODULE_NAME,
204 pszPfHandlerRC ? pszPfHandlerRC : "pgmPhysPfHandlerRedirectToHC", rc));
205 }
206 else
207 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszHandlerRC ? pszModRC : VMMRC_MAIN_MODULE_NAME,
208 pszHandlerRC ? pszHandlerRC : "pgmPhysHandlerRedirectToHC", rc));
209
210 }
211 if (RT_SUCCESS(rc))
212 return PGMR3HandlerPhysicalTypeRegisterEx(pVM, enmKind, pfnHandlerR3,
213 pfnHandlerR0, pfnPfHandlerR0,
214 pfnHandlerRC, pfnPfHandlerRC,
215 pszDesc, phType);
216 }
217 else
218 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszPfHandlerR0 ? pszModR0 : VMMR0_MAIN_MODULE_NAME,
219 pszPfHandlerR0 ? pszPfHandlerR0 : "pgmPhysHandlerRedirectToHC", rc));
220 }
221 else
222 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszHandlerR0 ? pszModR0 : VMMR0_MAIN_MODULE_NAME,
223 pszHandlerR0 ? pszHandlerR0 : "pgmPhysHandlerRedirectToHC", rc));
224
225 return rc;
226}
227
228
229/**
230 * Updates the physical page access handlers.
231 *
232 * @param pVM The cross context VM structure.
233 * @remark Only used when restoring a saved state.
234 */
235void pgmR3HandlerPhysicalUpdateAll(PVM pVM)
236{
237 LogFlow(("pgmHandlerPhysicalUpdateAll:\n"));
238
239 /*
240 * Clear and set.
241 * (the right -> left on the setting pass is just bird speculating on cache hits)
242 */
243 pgmLock(pVM);
244 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, true, pgmR3HandlerPhysicalOneClear, pVM);
245 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, false, pgmR3HandlerPhysicalOneSet, pVM);
246 pgmUnlock(pVM);
247}
248
249
250/**
251 * Clears all the page level flags for one physical handler range.
252 *
253 * @returns 0
254 * @param pNode Pointer to a PGMPHYSHANDLER.
255 * @param pvUser Pointer to the VM.
256 */
257static DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser)
258{
259 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
260 PPGMRAMRANGE pRamHint = NULL;
261 RTGCPHYS GCPhys = pCur->Core.Key;
262 RTUINT cPages = pCur->cPages;
263 PVM pVM = (PVM)pvUser;
264 for (;;)
265 {
266 PPGMPAGE pPage;
267 int rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pPage, &pRamHint);
268 if (RT_SUCCESS(rc))
269 {
270 PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_NONE);
271
272 /* Tell NEM about the protection change. */
273 if (VM_IS_NEM_ENABLED(pVM))
274 {
275 uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage);
276 PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
277 NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
278 pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
279 PGM_PAGE_SET_NEM_STATE(pPage, u2State);
280 }
281 }
282 else
283 AssertRC(rc);
284
285 if (--cPages == 0)
286 return 0;
287 GCPhys += PAGE_SIZE;
288 }
289}
290
291
292/**
293 * Sets all the page level flags for one physical handler range.
294 *
295 * @returns 0
296 * @param pNode Pointer to a PGMPHYSHANDLER.
297 * @param pvUser Pointer to the VM.
298 */
299static DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser)
300{
301 PVM pVM = (PVM)pvUser;
302 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
303 PPGMPHYSHANDLERTYPEINT pCurType = PGMPHYSHANDLER_GET_TYPE(pVM, pCur);
304 unsigned uState = pCurType->uState;
305 PPGMRAMRANGE pRamHint = NULL;
306 RTGCPHYS GCPhys = pCur->Core.Key;
307 RTUINT cPages = pCur->cPages;
308 for (;;)
309 {
310 PPGMPAGE pPage;
311 int rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pPage, &pRamHint);
312 if (RT_SUCCESS(rc))
313 {
314 PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, uState);
315
316 /* Tell NEM about the protection change. */
317 if (VM_IS_NEM_ENABLED(pVM))
318 {
319 uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage);
320 PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
321 NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
322 pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
323 PGM_PAGE_SET_NEM_STATE(pPage, u2State);
324 }
325 }
326 else
327 AssertRC(rc);
328
329 if (--cPages == 0)
330 return 0;
331 GCPhys += PAGE_SIZE;
332 }
333}
334
335
336/**
337 * Arguments for pgmR3InfoHandlersPhysicalOne and pgmR3InfoHandlersVirtualOne.
338 */
339typedef struct PGMHANDLERINFOARG
340{
341 /** The output helpers.*/
342 PCDBGFINFOHLP pHlp;
343 /** Pointer to the cross context VM handle. */
344 PVM pVM;
345 /** Set if statistics should be dumped. */
346 bool fStats;
347} PGMHANDLERINFOARG, *PPGMHANDLERINFOARG;
348
349
350/**
351 * Info callback for 'pgmhandlers'.
352 *
353 * @param pVM The cross context VM structure.
354 * @param pHlp The output helpers.
355 * @param pszArgs The arguments. phys or virt.
356 */
357DECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
358{
359 /*
360 * Test input.
361 */
362 PGMHANDLERINFOARG Args = { pHlp, pVM, /* .fStats = */ true };
363 bool fPhysical = !pszArgs || !*pszArgs;
364 bool fVirtual = fPhysical;
365 bool fHyper = fPhysical;
366 if (!fPhysical)
367 {
368 bool fAll = strstr(pszArgs, "all") != NULL;
369 fPhysical = fAll || strstr(pszArgs, "phys") != NULL;
370 fVirtual = fAll || strstr(pszArgs, "virt") != NULL;
371 fHyper = fAll || strstr(pszArgs, "hyper")!= NULL;
372 Args.fStats = strstr(pszArgs, "nost") == NULL;
373 }
374
375 /*
376 * Dump the handlers.
377 */
378 if (fPhysical)
379 {
380 pHlp->pfnPrintf(pHlp,
381 "Physical handlers: (PhysHandlers=%d (%#x))\n"
382 "%*s %*s %*s %*s HandlerGC UserGC Type Description\n",
383 pVM->pgm.s.pTreesR3->PhysHandlers, pVM->pgm.s.pTreesR3->PhysHandlers,
384 - (int)sizeof(RTGCPHYS) * 2, "From",
385 - (int)sizeof(RTGCPHYS) * 2 - 3, "- To (incl)",
386 - (int)sizeof(RTHCPTR) * 2 - 1, "HandlerHC",
387 - (int)sizeof(RTHCPTR) * 2 - 1, "UserHC");
388 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3InfoHandlersPhysicalOne, &Args);
389 }
390
391#ifdef VBOX_WITH_RAW_MODE
392 if (fVirtual)
393 {
394 pHlp->pfnPrintf(pHlp,
395 "Virtual handlers:\n"
396 "%*s %*s %*s %*s Type Description\n",
397 - (int)sizeof(RTGCPTR) * 2, "From",
398 - (int)sizeof(RTGCPTR) * 2 - 3, "- To (excl)",
399 - (int)sizeof(RTHCPTR) * 2 - 1, "HandlerHC",
400 - (int)sizeof(RTRCPTR) * 2 - 1, "HandlerGC");
401 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->VirtHandlers, true, pgmR3InfoHandlersVirtualOne, &Args);
402 }
403
404 if (fHyper)
405 {
406 pHlp->pfnPrintf(pHlp,
407 "Hypervisor Virtual handlers:\n"
408 "%*s %*s %*s %*s Type Description\n",
409 - (int)sizeof(RTGCPTR) * 2, "From",
410 - (int)sizeof(RTGCPTR) * 2 - 3, "- To (excl)",
411 - (int)sizeof(RTHCPTR) * 2 - 1, "HandlerHC",
412 - (int)sizeof(RTRCPTR) * 2 - 1, "HandlerGC");
413 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->HyperVirtHandlers, true, pgmR3InfoHandlersVirtualOne, &Args);
414 }
415#endif
416}
417
418
419/**
420 * Displays one physical handler range.
421 *
422 * @returns 0
423 * @param pNode Pointer to a PGMPHYSHANDLER.
424 * @param pvUser Pointer to command helper functions.
425 */
426static DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser)
427{
428 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
429 PPGMHANDLERINFOARG pArgs = (PPGMHANDLERINFOARG)pvUser;
430 PCDBGFINFOHLP pHlp = pArgs->pHlp;
431 PPGMPHYSHANDLERTYPEINT pCurType = PGMPHYSHANDLER_GET_TYPE(pArgs->pVM, pCur);
432 const char *pszType;
433 switch (pCurType->enmKind)
434 {
435 case PGMPHYSHANDLERKIND_MMIO: pszType = "MMIO "; break;
436 case PGMPHYSHANDLERKIND_WRITE: pszType = "Write "; break;
437 case PGMPHYSHANDLERKIND_ALL: pszType = "All "; break;
438 default: pszType = "????"; break;
439 }
440 pHlp->pfnPrintf(pHlp,
441 "%RGp - %RGp %RHv %RHv %RRv %RRv %s %s\n",
442 pCur->Core.Key, pCur->Core.KeyLast, pCurType->pfnHandlerR3, pCur->pvUserR3, pCurType->pfnPfHandlerRC, pCur->pvUserRC,
443 pszType, pCur->pszDesc);
444#ifdef VBOX_WITH_STATISTICS
445 if (pArgs->fStats)
446 pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
447 pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
448 pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
449#endif
450 return 0;
451}
452
453
454#ifdef VBOX_WITH_RAW_MODE
455/**
456 * Displays one virtual handler range.
457 *
458 * @returns 0
459 * @param pNode Pointer to a PGMVIRTHANDLER.
460 * @param pvUser Pointer to command helper functions.
461 */
462static DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
463{
464 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
465 PPGMHANDLERINFOARG pArgs = (PPGMHANDLERINFOARG)pvUser;
466 PCDBGFINFOHLP pHlp = pArgs->pHlp;
467 PPGMVIRTHANDLERTYPEINT pCurType = PGMVIRTANDLER_GET_TYPE(pArgs->pVM, pCur);
468 const char *pszType;
469 switch (pCurType->enmKind)
470 {
471 case PGMVIRTHANDLERKIND_WRITE: pszType = "Write "; break;
472 case PGMVIRTHANDLERKIND_ALL: pszType = "All "; break;
473 case PGMVIRTHANDLERKIND_HYPERVISOR: pszType = "WriteHyp "; break;
474 default: pszType = "????"; break;
475 }
476 pHlp->pfnPrintf(pHlp, "%RGv - %RGv %RHv %RRv %s %s\n",
477 pCur->Core.Key, pCur->Core.KeyLast, pCurType->pfnHandlerR3, pCurType->pfnPfHandlerRC, pszType, pCur->pszDesc);
478# ifdef VBOX_WITH_STATISTICS
479 if (pArgs->fStats)
480 pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
481 pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
482 pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
483# endif
484 return 0;
485}
486#endif /* VBOX_WITH_RAW_MODE */
487
Note: See TracBrowser for help on using the repository browser.

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