VirtualBox

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

Last change on this file since 2217 was 1997, checked in by vboxsync, 18 years ago

Better search for innocent conflicts

  • Property svn:keywords set to Id
File size: 21.5 KB
Line 
1/* $Id: PGMHandler.cpp 1997 2007-04-09 14:01:18Z vboxsync $ */
2/** @file
3 * PGM - Page Manager / Monitor, Access Handlers.
4 */
5
6/*
7 * Copyright (C) 2006 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 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_PGM
27#include <VBox/dbgf.h>
28#include <VBox/pgm.h>
29#include <VBox/cpum.h>
30#include <VBox/iom.h>
31#include <VBox/sup.h>
32#include <VBox/mm.h>
33#include <VBox/pdm.h>
34#include <VBox/em.h>
35#include <VBox/stam.h>
36#include <VBox/csam.h>
37#include <VBox/rem.h>
38#include <VBox/dbgf.h>
39#include <VBox/rem.h>
40#include <VBox/selm.h>
41#include <VBox/ssm.h>
42#include "PGMInternal.h"
43#include <VBox/vm.h>
44#include <VBox/dbg.h>
45
46#include <VBox/log.h>
47#include <iprt/assert.h>
48#include <iprt/alloc.h>
49#include <iprt/asm.h>
50#include <iprt/thread.h>
51#include <iprt/string.h>
52#include <VBox/param.h>
53#include <VBox/err.h>
54#include <VBox/hwaccm.h>
55
56
57/*******************************************************************************
58* Internal Functions *
59*******************************************************************************/
60static DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser);
61static DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser);
62static DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser);
63static DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
64
65
66
67/**
68 * Register a access handler for a physical range.
69 *
70 * @returns VBox status code.
71 * @param pVM VM handle.
72 * @param enmType Handler type. Any of the PGMPHYSHANDLERTYPE_PHYSICAL* enums.
73 * @param GCPhys Start physical address.
74 * @param GCPhysLast Last physical address. (inclusive)
75 * @param pfnHandlerR3 The R3 handler.
76 * @param pvUserR3 User argument to the R3 handler.
77 * @param pszModR0 The R0 handler module. NULL means default R0 module.
78 * @param pszHandlerR0 The R0 handler symbol name.
79 * @param pvUserR0 User argument to the R0 handler.
80 * @param pszModGC The GC handler module. NULL means default GC module.
81 * @param pszHandlerGC The GC handler symbol name.
82 * @param pvUserGC User argument to the GC handler.
83 * This must be a GC pointer because it will be relocated!
84 * @param pszDesc Pointer to description string. This must not be freed.
85 */
86PGMR3DECL(int) PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
87 PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3,
88 const char *pszModR0, const char *pszHandlerR0, RTHCPTR pvUserR0,
89 const char *pszModGC, const char *pszHandlerGC, RTGCPTR pvUserGC, const char *pszDesc)
90{
91 LogFlow(("PGMR3HandlerPhysicalRegister: enmType=%d GCPhys=%VGv GCPhysLast=%VGv pfnHandlerR3=%VHv pvUserHC=%VHv pszModGC=%p:{%s} pszHandlerGC=%p:{%s} pvUser=%VGv pszDesc=%s\n",
92 enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pszModGC, pszModGC, pszHandlerGC, pszHandlerGC, pvUserGC, pszDesc));
93
94 /*
95 * Validate input.
96 */
97 if (!pszModGC)
98 pszModGC = VMMGC_MAIN_MODULE_NAME;
99
100 if (!pszModR0)
101 pszModR0 = VMMR0_MAIN_MODULE_NAME;
102
103 if ( !pszModGC || !*pszModGC || !pszHandlerGC || !*pszHandlerGC
104 || !pszModR0 || !*pszModR0 || !pszHandlerR0 || !*pszHandlerR0)
105 {
106 AssertMsgFailed(("pfnHandlerGC or/and pszModGC is missing\n"));
107 return VERR_INVALID_PARAMETER;
108 }
109
110 /*
111 * Resolve the R0 handler.
112 */
113 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0 = NIL_RTR0PTR;
114 int rc = VINF_SUCCESS;
115 if (HWACCMR3IsAllowed(pVM))
116 rc = PDMR3GetSymbolR0Lazy(pVM, pszModR0, pszHandlerR0, (void **)&pfnHandlerR0);
117 if (VBOX_SUCCESS(rc))
118 {
119 /*
120 * Resolve the GC handler.
121 */
122 RTGCPTR pfnHandlerGC;
123 rc = PDMR3GetSymbolGCLazy(pVM, pszModGC, pszHandlerGC, &pfnHandlerGC);
124
125 if (VBOX_SUCCESS(rc))
126 return PGMHandlerPhysicalRegisterEx(pVM, enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3,
127 pfnHandlerR0, pvUserR0, pfnHandlerGC, pvUserGC, pszDesc);
128
129 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Vrc.\n", pszModGC, pszHandlerGC, rc));
130 }
131 else
132 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Vrc.\n", pszModR0, pszHandlerR0, rc));
133
134 return rc;
135}
136
137
138/**
139 * Updates the physical page access handlers.
140 *
141 * @param pVM VM handle.
142 * @remark Only used when restoring a saved state.
143 */
144void pgmR3HandlerPhysicalUpdateAll(PVM pVM)
145{
146 LogFlow(("pgmHandlerPhysicalUpdateAll:\n"));
147
148 /*
149 * Clear and set.
150 * (the right -> left on the setting pass is just bird speculating on cache hits)
151 */
152 pgmLock(pVM);
153 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, true, pgmR3HandlerPhysicalOneClear, pVM);
154 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, false, pgmR3HandlerPhysicalOneSet, pVM);
155 pgmUnlock(pVM);
156}
157
158
159/**
160 * Clears all the page level flags for one physical handler range.
161 *
162 * @returns 0
163 * @param pNode Pointer to a PGMPHYSHANDLER.
164 * @param pvUser VM handle.
165 */
166static DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser)
167{
168 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
169 PPGMRAMRANGE pRamHint = NULL;
170 RTGCPHYS GCPhys = pCur->Core.Key;
171 RTUINT cPages = pCur->cPages;
172 PPGM pPGM = &((PVM)pvUser)->pgm.s;
173 for (;;)
174 {
175 PGMRamFlagsClearByGCPhysWithHint(pPGM, GCPhys, MM_RAM_FLAGS_PHYSICAL_HANDLER | MM_RAM_FLAGS_PHYSICAL_WRITE | MM_RAM_FLAGS_PHYSICAL_ALL, &pRamHint);
176 if (--cPages == 0)
177 return 0;
178 GCPhys += PAGE_SIZE;
179 }
180}
181
182
183/**
184 * Sets all the page level flags for one physical handler range.
185 *
186 * @returns 0
187 * @param pNode Pointer to a PGMPHYSHANDLER.
188 * @param pvUser VM handle.
189 */
190static DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser)
191{
192 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
193 unsigned fFlags = pgmHandlerPhysicalCalcFlags(pCur);
194 PPGMRAMRANGE pRamHint = NULL;
195 RTGCPHYS GCPhys = pCur->Core.Key;
196 RTUINT cPages = pCur->cPages;
197 PPGM pPGM = &((PVM)pvUser)->pgm.s;
198 for (;;)
199 {
200 PGMRamFlagsSetByGCPhysWithHint(pPGM, GCPhys, fFlags, &pRamHint);
201 if (--cPages == 0)
202 return 0;
203 GCPhys += PAGE_SIZE;
204 }
205}
206
207
208
209/**
210 * Register a access handler for a virtual range.
211 *
212 * @returns VBox status code.
213 * @param pVM VM handle.
214 * @param enmType Handler type. Any of the PGMVIRTHANDLERTYPE_* enums.
215 * @param GCPtr Start address.
216 * @param GCPtrLast Last address (inclusive).
217 * @param pfnInvalidateHC The HC invalidate callback (can be 0)
218 * @param pfnHandlerHC The HC handler.
219 * @param pszHandlerGC The GC handler symbol name.
220 * @param pszModGC The GC handler module.
221 * @param pszDesc Pointer to description string. This must not be freed.
222 */
223/** @todo rename this function to PGMR3HandlerVirtualRegister */
224PGMR3DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
225 PFNPGMHCVIRTINVALIDATE pfnInvalidateHC,
226 PFNPGMHCVIRTHANDLER pfnHandlerHC,
227 const char *pszHandlerGC, const char *pszModGC,
228 const char *pszDesc)
229{
230 LogFlow(("PGMR3HandlerVirtualRegisterEx: enmType=%d GCPtr=%VGv GCPtrLast=%VGv pszHandlerGC=%p:{%s} pszModGC=%p:{%s} pszDesc=%s\n",
231 enmType, GCPtr, GCPtrLast, pszHandlerGC, pszHandlerGC, pszModGC, pszModGC, pszDesc));
232
233 /*
234 * Validate input.
235 */
236 if (!pszModGC)
237 pszModGC = VMMGC_MAIN_MODULE_NAME;
238 if (!pszModGC || !*pszModGC || !pszHandlerGC || !*pszHandlerGC)
239 {
240 AssertMsgFailed(("pfnHandlerGC or/and pszModGC is missing\n"));
241 return VERR_INVALID_PARAMETER;
242 }
243
244 /*
245 * Resolve the GC handler.
246 */
247 RTGCPTR pfnHandlerGC;
248 int rc = PDMR3GetSymbolGCLazy(pVM, pszModGC, pszHandlerGC, &pfnHandlerGC);
249 if (VBOX_SUCCESS(rc))
250 return PGMHandlerVirtualRegisterEx(pVM, enmType, GCPtr, GCPtrLast, pfnInvalidateHC, pfnHandlerHC, pfnHandlerGC, pszDesc);
251
252 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Vrc.\n", pszModGC, pszHandlerGC, rc));
253 return rc;
254}
255
256
257/**
258 * Register an access handler for a virtual range.
259 *
260 * @returns VBox status code.
261 * @param pVM VM handle.
262 * @param enmType Handler type. Any of the PGMVIRTHANDLERTYPE_* enums.
263 * @param GCPtr Start address.
264 * @param GCPtrLast Last address (inclusive).
265 * @param pfnInvalidateHC The HC invalidate callback (can be 0)
266 * @param pfnHandlerHC The HC handler.
267 * @param pfnHandlerGC The GC handler.
268 * @param pszDesc Pointer to description string. This must not be freed.
269 */
270/** @todo rename this to PGMR3HandlerVirtualRegisterEx. */
271PGMDECL(int) PGMHandlerVirtualRegisterEx(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
272 PFNPGMHCVIRTINVALIDATE pfnInvalidateHC,
273 PFNPGMHCVIRTHANDLER pfnHandlerHC, RTGCPTR pfnHandlerGC,
274 HCPTRTYPE(const char *) pszDesc)
275{
276 Log(("PGMR3HandlerVirtualRegister: enmType=%d GCPtr=%RGv GCPtrLast=%RGv pfnHandlerGC=%RGv pszDesc=%s\n", enmType, GCPtr, GCPtrLast, pfnHandlerGC, pszDesc));
277
278 /*
279 * Validate input.
280 */
281 switch (enmType)
282 {
283 case PGMVIRTHANDLERTYPE_NORMAL:
284 case PGMVIRTHANDLERTYPE_ALL:
285 case PGMVIRTHANDLERTYPE_WRITE:
286 case PGMVIRTHANDLERTYPE_EIP:
287 if (!pfnHandlerHC)
288 {
289 AssertMsgFailed(("No HC handler specified!!\n"));
290 return VERR_INVALID_PARAMETER;
291 }
292 break;
293
294 case PGMVIRTHANDLERTYPE_HYPERVISOR:
295 if (pfnHandlerHC)
296 {
297 AssertMsgFailed(("HC handler specified for hypervisor range!?!\n"));
298 return VERR_INVALID_PARAMETER;
299 }
300 break;
301 default:
302 AssertMsgFailed(("Invalid enmType! enmType=%d\n", enmType));
303 return VERR_INVALID_PARAMETER;
304 }
305 if (GCPtrLast < GCPtr)
306 {
307 AssertMsgFailed(("GCPtrLast < GCPtr (%#x < %#x)\n", GCPtrLast, GCPtr));
308 return VERR_INVALID_PARAMETER;
309 }
310 if (!pfnHandlerGC)
311 {
312 AssertMsgFailed(("pfnHandlerGC is missing\n"));
313 return VERR_INVALID_PARAMETER;
314 }
315
316 /*
317 * Allocate and initialize a new entry.
318 */
319 unsigned cPages = (RT_ALIGN((RTGCUINTPTR)GCPtrLast + 1, PAGE_SIZE) - ((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK)) >> PAGE_SHIFT;
320 PPGMVIRTHANDLER pNew;
321 int rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[cPages]), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew); /** @todo r=bird: incorrect member name PhysToVirt? */
322 if (VBOX_FAILURE(rc))
323 return rc;
324
325 pNew->Core.Key = GCPtr;
326 pNew->Core.KeyLast = GCPtrLast;
327
328 pNew->enmType = enmType;
329 pNew->pfnInvalidateHC = pfnInvalidateHC;
330 pNew->pfnHandlerGC = pfnHandlerGC;
331 pNew->pfnHandlerHC = pfnHandlerHC;
332 pNew->pszDesc = pszDesc;
333 pNew->GCPtr = GCPtr;
334 pNew->GCPtrLast = GCPtrLast;
335 pNew->cb = GCPtrLast - GCPtr + 1;
336 pNew->cPages = cPages;
337 /* Will be synced at next guest execution attempt. */
338 while (cPages-- > 0)
339 {
340 pNew->aPhysToVirt[cPages].Core.Key = NIL_RTGCPHYS;
341 pNew->aPhysToVirt[cPages].Core.KeyLast = NIL_RTGCPHYS;
342 pNew->aPhysToVirt[cPages].offVirtHandler = -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[cPages]);
343 pNew->aPhysToVirt[cPages].offNextAlias = 0;
344 }
345
346 /*
347 * Try to insert it into the tree.
348 *
349 * The current implementation doesn't allow multiple handlers for
350 * the same range this makes everything much simpler and faster.
351 */
352 pgmLock(pVM);
353 if (pVM->pgm.s.pTreesHC->VirtHandlers != 0)
354 {
355 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, pNew->Core.Key, true);
356 if (!pCur || GCPtr > pCur->GCPtrLast || GCPtrLast < pCur->GCPtr)
357 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, pNew->Core.Key, false);
358 if (pCur && GCPtr <= pCur->GCPtrLast && GCPtrLast >= pCur->GCPtr)
359 {
360 /*
361 * The LDT sometimes conflicts with the IDT and LDT ranges while being
362 * updated on linux. So, we don't assert simply log it.
363 */
364 Log(("PGMR3HandlerVirtualRegister: Conflict with existing range %RGv-%RGv (%s), req. %RGv-%RGv (%s)\n",
365 pCur->GCPtr, pCur->GCPtrLast, pCur->pszDesc, GCPtr, GCPtrLast, pszDesc));
366 MMHyperFree(pVM, pNew);
367 pgmUnlock(pVM);
368 return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
369 }
370 }
371 if (RTAvlroGCPtrInsert(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, &pNew->Core))
372 {
373 if (enmType != PGMVIRTHANDLERTYPE_HYPERVISOR)
374 {
375 pVM->pgm.s.fPhysCacheFlushPending = true;
376 pVM->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;
377 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
378 }
379 pgmUnlock(pVM);
380
381#ifdef VBOX_WITH_STATISTICS
382 char szPath[256];
383 RTStrPrintf(szPath, sizeof(szPath), "/PGM/VirtHandler/Calls/%VGv-%VGv", pNew->GCPtr, pNew->GCPtrLast);
384 rc = STAMR3Register(pVM, &pNew->Stat, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szPath, STAMUNIT_TICKS_PER_CALL, pszDesc);
385 AssertRC(rc);
386#endif
387 return VINF_SUCCESS;
388 }
389 pgmUnlock(pVM);
390 AssertFailed();
391 MMHyperFree(pVM, pNew);
392 return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
393}
394
395
396/**
397 * Modify the page invalidation callback handler for a registered virtual range
398 * (add more when needed)
399 *
400 * @returns VBox status code.
401 * @param pVM VM handle.
402 * @param GCPtr Start address.
403 * @param pfnInvalidateHC The HC invalidate callback (can be 0)
404 */
405PGMDECL(int) PGMHandlerVirtualChangeInvalidateCallback(PVM pVM, RTGCPTR GCPtr, PFNPGMHCVIRTINVALIDATE pfnInvalidateHC)
406{
407 pgmLock(pVM);
408 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.pTreesHC->VirtHandlers, GCPtr);
409 if (pCur)
410 {
411 pCur->pfnInvalidateHC = pfnInvalidateHC;
412 pgmUnlock(pVM);
413 return VINF_SUCCESS;
414 }
415 pgmUnlock(pVM);
416 AssertMsgFailed(("Range %#x not found!\n", GCPtr));
417 return VERR_INVALID_PARAMETER;
418}
419
420
421/**
422 * Deregister an access handler for a virtual range.
423 *
424 * @returns VBox status code.
425 * @param pVM VM handle.
426 * @param GCPtr Start address.
427 */
428PGMDECL(int) PGMHandlerVirtualDeregister(PVM pVM, RTGCPTR GCPtr)
429{
430 /*
431 * Find the handler.
432 * We naturally assume GCPtr is a unique specification.
433 */
434 pgmLock(pVM);
435 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, GCPtr);
436 if (pCur)
437 {
438 Log(("PGMR3HandlerVirtualDeregister: Removing Virtual (%d) Range %#x-%#x %s\n", pCur->enmType,
439 pCur->GCPtr, pCur->GCPtrLast, pCur->pszDesc));
440
441 /*
442 * Reset the flags and remove phys2virt nodes.
443 */
444 PPGM pPGM = &pVM->pgm.s;
445 for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
446 if (pCur->aPhysToVirt[iPage].offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE)
447 pgmHandlerVirtualClearPage(pPGM, pCur, iPage);
448
449 /*
450 * Schedule CR3 sync (if required) and the memory.
451 */
452 STAM_DEREG(pVM, &pCur->Stat);
453 if (pCur->enmType != PGMVIRTHANDLERTYPE_HYPERVISOR)
454 {
455 pVM->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;
456 VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
457 }
458 MMHyperFree(pVM, pCur);
459 pgmUnlock(pVM);
460 return VINF_SUCCESS;
461 }
462 pgmUnlock(pVM);
463 AssertMsgFailed(("Range %#x not found!\n", GCPtr));
464 return VERR_INVALID_PARAMETER;
465}
466
467
468/**
469 * Arguments for pgmR3InfoHandlersPhysicalOne and pgmR3InfoHandlersVirtualOne.
470 */
471typedef struct PGMHANDLERINFOARG
472{
473 /** The output helpers.*/
474 PCDBGFINFOHLP pHlp;
475 /** Set if statistics should be dumped. */
476 bool fStats;
477} PGMHANDLERINFOARG, *PPGMHANDLERINFOARG;
478
479
480/**
481 * Info callback for 'pgmhandlers'.
482 *
483 * @param pHlp The output helpers.
484 * @param pszArgs The arguments. phys or virt.
485 */
486DECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
487{
488 /*
489 * Test input.
490 */
491 PGMHANDLERINFOARG Args = { pHlp, true };
492 bool fPhysical = !pszArgs || !*pszArgs;
493 bool fVirtual = fPhysical;
494 if (!fPhysical)
495 {
496 fPhysical = strstr(pszArgs, "phys") != NULL;
497 fVirtual = strstr(pszArgs, "virt") != NULL;
498 Args.fStats = strstr(pszArgs, "nost") == NULL;
499 }
500
501 /*
502 * Dump the handlers.
503 */
504 if (fPhysical)
505 {
506 pHlp->pfnPrintf(pHlp,
507 "Physical handlers: (PhysHandlers=%d (%#x))\n"
508 "From - To (incl) HandlerHC UserHC HandlerGC UserGC Type Description\n",
509 pVM->pgm.s.pTreesHC->PhysHandlers, pVM->pgm.s.pTreesHC->PhysHandlers);
510 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesHC->PhysHandlers, true, pgmR3InfoHandlersPhysicalOne, &Args);
511 }
512
513 if (fVirtual)
514 {
515 pHlp->pfnPrintf(pHlp,
516 "Virtual handlers:\n"
517 "From - To (excl) HandlerHC HandlerGC Type Description\n");
518 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesHC->VirtHandlers, true, pgmR3InfoHandlersVirtualOne, &Args);
519 }
520}
521
522
523/**
524 * Displays one physical handler range.
525 *
526 * @returns 0
527 * @param pNode Pointer to a PGMPHYSHANDLER.
528 * @param pvUser Pointer to command helper functions.
529 */
530static DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser)
531{
532 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
533 PPGMHANDLERINFOARG pArgs= (PPGMHANDLERINFOARG)pvUser;
534 PCDBGFINFOHLP pHlp = pArgs->pHlp;
535 const char *pszType;
536 switch (pCur->enmType)
537 {
538 case PGMPHYSHANDLERTYPE_MMIO: pszType = "MMIO "; break;
539 case PGMPHYSHANDLERTYPE_PHYSICAL: pszType = "Natural"; break;
540 case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE: pszType = "Write "; break;
541 case PGMPHYSHANDLERTYPE_PHYSICAL_ALL: pszType = "All "; break;
542 default: pszType = "????"; break;
543 }
544 pHlp->pfnPrintf(pHlp,
545 "%VGp - %VGp %VHv %VHv %VGv %VGv %s %s\n",
546 pCur->Core.Key, pCur->Core.KeyLast, pCur->pfnHandlerR3, pCur->pvUserR3, pCur->pfnHandlerGC, pCur->pvUserGC, pszType, pCur->pszDesc);
547#ifdef VBOX_WITH_STATISTICS
548 if (pArgs->fStats)
549 pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
550 pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
551 pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
552#endif
553 return 0;
554}
555
556
557/**
558 * Displays one virtual handler range.
559 *
560 * @returns 0
561 * @param pNode Pointer to a PGMVIRTHANDLER.
562 * @param pvUser Pointer to command helper functions.
563 */
564static DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
565{
566 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
567 PPGMHANDLERINFOARG pArgs= (PPGMHANDLERINFOARG)pvUser;
568 PCDBGFINFOHLP pHlp = pArgs->pHlp;
569 const char *pszType;
570 switch (pCur->enmType)
571 {
572 case PGMVIRTHANDLERTYPE_NORMAL: pszType = "Natural"; break;
573 case PGMVIRTHANDLERTYPE_WRITE: pszType = "Write "; break;
574 case PGMVIRTHANDLERTYPE_ALL: pszType = "All "; break;
575 case PGMVIRTHANDLERTYPE_EIP: pszType = "EIP "; break;
576 case PGMVIRTHANDLERTYPE_HYPERVISOR: pszType = "WriteHyp "; break;
577 default: pszType = "????"; break;
578 }
579 pHlp->pfnPrintf(pHlp, "%08x - %08x %08x %08x %s %s\n",
580 pCur->GCPtr, pCur->GCPtrLast, pCur->pfnHandlerHC, pCur->pfnHandlerGC, pszType, pCur->pszDesc);
581#ifdef VBOX_WITH_STATISTICS
582 if (pArgs->fStats)
583 pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
584 pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
585 pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
586#endif
587 return 0;
588}
589
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