VirtualBox

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

Last change on this file since 19420 was 19141, checked in by vboxsync, 16 years ago

Action flags breakup.
Fixed PGM saved state loading of 2.2.2 images.
Reduced hacks in PATM state loading (fixups).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 23.4 KB
Line 
1/* $Id: PGMHandler.cpp 19141 2009-04-23 13:52:18Z vboxsync $ */
2/** @file
3 * PGM - Page Manager / Monitor, Access Handlers.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
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/em.h>
34#include <VBox/stam.h>
35#include <VBox/csam.h>
36#include <VBox/rem.h>
37#include <VBox/dbgf.h>
38#include <VBox/rem.h>
39#include <VBox/selm.h>
40#include <VBox/ssm.h>
41#include "PGMInternal.h"
42#include <VBox/vm.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/hwaccm.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);
62static DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
63
64
65
66/**
67 * Register a access handler for a physical range.
68 *
69 * @returns VBox status code.
70 * @param pVM VM handle.
71 * @param enmType Handler type. Any of the PGMPHYSHANDLERTYPE_PHYSICAL* enums.
72 * @param GCPhys Start physical address.
73 * @param GCPhysLast Last physical address. (inclusive)
74 * @param pfnHandlerR3 The R3 handler.
75 * @param pvUserR3 User argument to the R3 handler.
76 * @param pszModR0 The R0 handler module. NULL means the default R0 module.
77 * @param pszHandlerR0 The R0 handler symbol name.
78 * @param pvUserR0 User argument to the R0 handler.
79 * @param pszModRC The RC handler module. NULL means the default RC
80 * module.
81 * @param pszHandlerRC The RC handler symbol name.
82 * @param pvUserRC User argument to the RC handler. Values less than
83 * 0x10000 will not be relocated.
84 * @param pszDesc Pointer to description string. This must not be freed.
85 */
86VMMR3DECL(int) PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
87 PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3,
88 const char *pszModR0, const char *pszHandlerR0, RTR0PTR pvUserR0,
89 const char *pszModRC, const char *pszHandlerRC, RTRCPTR pvUserRC, const char *pszDesc)
90{
91 LogFlow(("PGMR3HandlerPhysicalRegister: enmType=%d GCPhys=%RGp GCPhysLast=%RGp pfnHandlerR3=%RHv pvUserHC=%RHv pszModR0=%s pszHandlerR0=%s pvUserR0=%RHv pszModRC=%s pszHandlerRC=%s pvUser=%RRv pszDesc=%s\n",
92 enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pszModR0, pszHandlerR0, pvUserR0, pszHandlerRC, pszModRC, pvUserRC, pszDesc));
93
94 /*
95 * Validate input.
96 */
97 if (!pszModRC)
98 pszModRC = VMMGC_MAIN_MODULE_NAME;
99 if (!pszModR0)
100 pszModR0 = VMMR0_MAIN_MODULE_NAME;
101 AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);
102 AssertPtrReturn(pszHandlerR0, VERR_INVALID_POINTER);
103 AssertPtrReturn(pszHandlerRC, VERR_INVALID_POINTER);
104
105 /*
106 * Resolve the R0 handler.
107 */
108 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0 = NIL_RTR0PTR;
109 int rc = VINF_SUCCESS;
110 rc = PDMR3LdrGetSymbolR0Lazy(pVM, pszModR0, pszHandlerR0, &pfnHandlerR0);
111 if (RT_SUCCESS(rc))
112 {
113 /*
114 * Resolve the GC handler.
115 */
116 RTRCPTR pfnHandlerRC = NIL_RTRCPTR;
117 rc = PDMR3LdrGetSymbolRCLazy(pVM, pszModRC, pszHandlerRC, &pfnHandlerRC);
118 if (RT_SUCCESS(rc))
119 return PGMHandlerPhysicalRegisterEx(pVM, enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3,
120 pfnHandlerR0, pvUserR0, pfnHandlerRC, pvUserRC, pszDesc);
121
122 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszModRC, pszHandlerRC, rc));
123 }
124 else
125 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszModR0, pszHandlerR0, rc));
126
127 return rc;
128}
129
130
131/**
132 * Updates the physical page access handlers.
133 *
134 * @param pVM VM handle.
135 * @remark Only used when restoring a saved state.
136 */
137void pgmR3HandlerPhysicalUpdateAll(PVM pVM)
138{
139 LogFlow(("pgmHandlerPhysicalUpdateAll:\n"));
140
141 /*
142 * Clear and set.
143 * (the right -> left on the setting pass is just bird speculating on cache hits)
144 */
145 pgmLock(pVM);
146 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, true, pgmR3HandlerPhysicalOneClear, pVM);
147 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, false, pgmR3HandlerPhysicalOneSet, pVM);
148 pgmUnlock(pVM);
149}
150
151
152/**
153 * Clears all the page level flags for one physical handler range.
154 *
155 * @returns 0
156 * @param pNode Pointer to a PGMPHYSHANDLER.
157 * @param pvUser VM handle.
158 */
159static DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser)
160{
161 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
162 PPGMRAMRANGE pRamHint = NULL;
163 RTGCPHYS GCPhys = pCur->Core.Key;
164 RTUINT cPages = pCur->cPages;
165 PPGM pPGM = &((PVM)pvUser)->pgm.s;
166 for (;;)
167 {
168 PPGMPAGE pPage;
169 int rc = pgmPhysGetPageWithHintEx(pPGM, GCPhys, &pPage, &pRamHint);
170 if (RT_SUCCESS(rc))
171 PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_NONE);
172 else
173 AssertRC(rc);
174
175 if (--cPages == 0)
176 return 0;
177 GCPhys += PAGE_SIZE;
178 }
179}
180
181
182/**
183 * Sets all the page level flags for one physical handler range.
184 *
185 * @returns 0
186 * @param pNode Pointer to a PGMPHYSHANDLER.
187 * @param pvUser VM handle.
188 */
189static DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser)
190{
191 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
192 unsigned uState = pgmHandlerPhysicalCalcState(pCur);
193 PPGMRAMRANGE pRamHint = NULL;
194 RTGCPHYS GCPhys = pCur->Core.Key;
195 RTUINT cPages = pCur->cPages;
196 PPGM pPGM = &((PVM)pvUser)->pgm.s;
197 for (;;)
198 {
199 PPGMPAGE pPage;
200 int rc = pgmPhysGetPageWithHintEx(pPGM, GCPhys, &pPage, &pRamHint);
201 if (RT_SUCCESS(rc))
202 PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, uState);
203 else
204 AssertRC(rc);
205
206 if (--cPages == 0)
207 return 0;
208 GCPhys += PAGE_SIZE;
209 }
210}
211
212
213/**
214 * Register a access handler for a virtual range.
215 *
216 * @returns VBox status code.
217 * @param pVM VM handle.
218 * @param enmType Handler type. Any of the PGMVIRTHANDLERTYPE_* enums.
219 * @param GCPtr Start address.
220 * @param GCPtrLast Last address (inclusive).
221 * @param pfnInvalidateR3 The R3 invalidate callback (can be 0)
222 * @param pfnHandlerR3 The R3 handler.
223 * @param pszHandlerRC The RC handler symbol name.
224 * @param pszModRC The RC handler module.
225 * @param pszDesc Pointer to description string. This must not be freed.
226 */
227VMMR3DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
228 PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,
229 PFNPGMR3VIRTHANDLER pfnHandlerR3,
230 const char *pszHandlerRC, const char *pszModRC,
231 const char *pszDesc)
232{
233 LogFlow(("PGMR3HandlerVirtualRegisterEx: enmType=%d GCPtr=%RGv GCPtrLast=%RGv pszHandlerRC=%p:{%s} pszModRC=%p:{%s} pszDesc=%s\n",
234 enmType, GCPtr, GCPtrLast, pszHandlerRC, pszHandlerRC, pszModRC, pszModRC, pszDesc));
235
236 /*
237 * Validate input.
238 */
239 if (!pszModRC)
240 pszModRC = VMMGC_MAIN_MODULE_NAME;
241 if (!pszModRC || !*pszModRC || !pszHandlerRC || !*pszHandlerRC)
242 {
243 AssertMsgFailed(("pfnHandlerGC or/and pszModRC is missing\n"));
244 return VERR_INVALID_PARAMETER;
245 }
246
247 /*
248 * Resolve the GC handler.
249 */
250 RTRCPTR pfnHandlerRC;
251 int rc = PDMR3LdrGetSymbolRCLazy(pVM, pszModRC, pszHandlerRC, &pfnHandlerRC);
252 if (RT_SUCCESS(rc))
253 return PGMR3HandlerVirtualRegisterEx(pVM, enmType, GCPtr, GCPtrLast, pfnInvalidateR3, pfnHandlerR3, pfnHandlerRC, pszDesc);
254
255 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", pszModRC, pszHandlerRC, rc));
256 return rc;
257}
258
259
260/**
261 * Register an access handler for a virtual range.
262 *
263 * @returns VBox status code.
264 * @param pVM VM handle.
265 * @param enmType Handler type. Any of the PGMVIRTHANDLERTYPE_* enums.
266 * @param GCPtr Start address.
267 * @param GCPtrLast Last address (inclusive).
268 * @param pfnInvalidateR3 The R3 invalidate callback (can be 0)
269 * @param pfnHandlerR3 The R3 handler.
270 * @param pfnHandlerRC The RC handler.
271 * @param pszDesc Pointer to description string. This must not be freed.
272 * @thread EMT
273 */
274/** @todo create a template for virtual handlers (see async i/o), we're wasting space
275 * duplicating the function pointers now. (Or we will once we add the missing callbacks.) */
276VMMDECL(int) PGMR3HandlerVirtualRegisterEx(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
277 R3PTRTYPE(PFNPGMR3VIRTINVALIDATE) pfnInvalidateR3,
278 R3PTRTYPE(PFNPGMR3VIRTHANDLER) pfnHandlerR3,
279 RCPTRTYPE(PFNPGMRCVIRTHANDLER) pfnHandlerRC,
280 R3PTRTYPE(const char *) pszDesc)
281{
282 Log(("PGMR3HandlerVirtualRegister: enmType=%d GCPtr=%RGv GCPtrLast=%RGv pfnInvalidateR3=%RHv pfnHandlerR3=%RHv pfnHandlerRC=%RRv pszDesc=%s\n",
283 enmType, GCPtr, GCPtrLast, pfnInvalidateR3, pfnHandlerR3, pfnHandlerRC, pszDesc));
284
285 /*
286 * Validate input.
287 */
288 switch (enmType)
289 {
290 case PGMVIRTHANDLERTYPE_ALL:
291 AssertReleaseMsgReturn( (GCPtr & PAGE_OFFSET_MASK) == 0
292 && (GCPtrLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK,
293 ("PGMVIRTHANDLERTYPE_ALL: GCPtr=%RGv GCPtrLast=%RGv\n", GCPtr, GCPtrLast),
294 VERR_NOT_IMPLEMENTED);
295 break;
296 case PGMVIRTHANDLERTYPE_WRITE:
297 if (!pfnHandlerR3)
298 {
299 AssertMsgFailed(("No HC handler specified!!\n"));
300 return VERR_INVALID_PARAMETER;
301 }
302 break;
303
304 case PGMVIRTHANDLERTYPE_HYPERVISOR:
305 if (pfnHandlerR3)
306 {
307 AssertMsgFailed(("R3 handler specified for hypervisor range!?!\n"));
308 return VERR_INVALID_PARAMETER;
309 }
310 break;
311 default:
312 AssertMsgFailed(("Invalid enmType! enmType=%d\n", enmType));
313 return VERR_INVALID_PARAMETER;
314 }
315 if (GCPtrLast < GCPtr)
316 {
317 AssertMsgFailed(("GCPtrLast < GCPtr (%#x < %#x)\n", GCPtrLast, GCPtr));
318 return VERR_INVALID_PARAMETER;
319 }
320 if (!pfnHandlerRC)
321 {
322 AssertMsgFailed(("pfnHandlerRC is missing\n"));
323 return VERR_INVALID_PARAMETER;
324 }
325
326 /*
327 * Allocate and initialize a new entry.
328 */
329 unsigned cPages = (RT_ALIGN(GCPtrLast + 1, PAGE_SIZE) - (GCPtr & PAGE_BASE_GC_MASK)) >> PAGE_SHIFT;
330 PPGMVIRTHANDLER pNew;
331 int rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[cPages]), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew); /** @todo r=bird: incorrect member name PhysToVirt? */
332 if (RT_FAILURE(rc))
333 return rc;
334
335 pNew->Core.Key = GCPtr;
336 pNew->Core.KeyLast = GCPtrLast;
337
338 pNew->enmType = enmType;
339 pNew->pfnInvalidateR3 = pfnInvalidateR3;
340 pNew->pfnHandlerRC = pfnHandlerRC;
341 pNew->pfnHandlerR3 = pfnHandlerR3;
342 pNew->pszDesc = pszDesc;
343 pNew->cb = GCPtrLast - GCPtr + 1;
344 pNew->cPages = cPages;
345 /* Will be synced at next guest execution attempt. */
346 while (cPages-- > 0)
347 {
348 pNew->aPhysToVirt[cPages].Core.Key = NIL_RTGCPHYS;
349 pNew->aPhysToVirt[cPages].Core.KeyLast = NIL_RTGCPHYS;
350 pNew->aPhysToVirt[cPages].offVirtHandler = -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[cPages]);
351 pNew->aPhysToVirt[cPages].offNextAlias = 0;
352 }
353
354 /*
355 * Try to insert it into the tree.
356 *
357 * The current implementation doesn't allow multiple handlers for
358 * the same range this makes everything much simpler and faster.
359 */
360 AVLROGCPTRTREE *pRoot = enmType != PGMVIRTHANDLERTYPE_HYPERVISOR
361 ? &pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers
362 : &pVM->pgm.s.CTX_SUFF(pTrees)->HyperVirtHandlers;
363 pgmLock(pVM);
364 if (*pRoot != 0)
365 {
366 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(pRoot, pNew->Core.Key, true);
367 if ( !pCur
368 || GCPtr > pCur->Core.KeyLast
369 || GCPtrLast < pCur->Core.Key)
370 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(pRoot, pNew->Core.Key, false);
371 if ( pCur
372 && GCPtr <= pCur->Core.KeyLast
373 && GCPtrLast >= pCur->Core.Key)
374 {
375 /*
376 * The LDT sometimes conflicts with the IDT and LDT ranges while being
377 * updated on linux. So, we don't assert simply log it.
378 */
379 Log(("PGMR3HandlerVirtualRegister: Conflict with existing range %RGv-%RGv (%s), req. %RGv-%RGv (%s)\n",
380 pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc, GCPtr, GCPtrLast, pszDesc));
381 MMHyperFree(pVM, pNew);
382 pgmUnlock(pVM);
383 return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
384 }
385 }
386 if (RTAvlroGCPtrInsert(pRoot, &pNew->Core))
387 {
388 if (enmType != PGMVIRTHANDLERTYPE_HYPERVISOR)
389 {
390 pVM->pgm.s.fPhysCacheFlushPending = true;
391 for (unsigned i=0;i<pVM->cCPUs;i++)
392 {
393 PVMCPU pVCpu = &pVM->aCpus[i];
394
395 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
396 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
397 }
398 pVM->pgm.s.fGlobalSyncFlags |= PGM_GLOBAL_SYNC_CLEAR_PGM_POOL;
399 }
400 pgmUnlock(pVM);
401
402#ifdef VBOX_WITH_STATISTICS
403 char szPath[256];
404 RTStrPrintf(szPath, sizeof(szPath), "/PGM/VirtHandler/Calls/%RGv-%RGv", pNew->Core.Key, pNew->Core.KeyLast);
405 rc = STAMR3Register(pVM, &pNew->Stat, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szPath, STAMUNIT_TICKS_PER_CALL, pszDesc);
406 AssertRC(rc);
407#endif
408 return VINF_SUCCESS;
409 }
410
411 pgmUnlock(pVM);
412 AssertFailed();
413 MMHyperFree(pVM, pNew);
414 return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
415}
416
417
418/**
419 * Modify the page invalidation callback handler for a registered virtual range.
420 * (add more when needed)
421 *
422 * @returns VBox status code.
423 * @param pVM VM handle.
424 * @param GCPtr Start address.
425 * @param pfnInvalidateR3 The R3 invalidate callback (can be 0)
426 * @remarks Doesn't work with the hypervisor access handler type.
427 */
428VMMDECL(int) PGMHandlerVirtualChangeInvalidateCallback(PVM pVM, RTGCPTR GCPtr, PFNPGMR3VIRTINVALIDATE pfnInvalidateR3)
429{
430 pgmLock(pVM);
431 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.pTreesR3->VirtHandlers, GCPtr);
432 if (pCur)
433 {
434 pCur->pfnInvalidateR3 = pfnInvalidateR3;
435 pgmUnlock(pVM);
436 return VINF_SUCCESS;
437 }
438 pgmUnlock(pVM);
439 AssertMsgFailed(("Range %#x not found!\n", GCPtr));
440 return VERR_INVALID_PARAMETER;
441}
442
443/**
444 * Deregister an access handler for a virtual range.
445 *
446 * @returns VBox status code.
447 * @param pVM VM handle.
448 * @param GCPtr Start address.
449 * @thread EMT
450 */
451VMMDECL(int) PGMHandlerVirtualDeregister(PVM pVM, RTGCPTR GCPtr)
452{
453 pgmLock(pVM);
454
455 /*
456 * Find the handler.
457 * We naturally assume GCPtr is a unique specification.
458 */
459 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtr);
460 if (RT_LIKELY(pCur))
461 {
462 Log(("PGMHandlerVirtualDeregister: Removing Virtual (%d) Range %RGv-%RGv %s\n", pCur->enmType,
463 pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
464 Assert(pCur->enmType != PGMVIRTHANDLERTYPE_HYPERVISOR);
465
466 /*
467 * Reset the flags and remove phys2virt nodes.
468 */
469 PPGM pPGM = &pVM->pgm.s;
470 for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
471 if (pCur->aPhysToVirt[iPage].offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE)
472 pgmHandlerVirtualClearPage(pPGM, pCur, iPage);
473
474 /*
475 * Schedule CR3 sync.
476 */
477 for (unsigned i=0;i<pVM->cCPUs;i++)
478 {
479 PVMCPU pVCpu = &pVM->aCpus[i];
480
481 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
482 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
483 }
484 pVM->pgm.s.fGlobalSyncFlags |= PGM_GLOBAL_SYNC_CLEAR_PGM_POOL;
485 }
486 else
487 {
488 /* must be a hypervisor one then. */
489 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->HyperVirtHandlers, GCPtr);
490 if (RT_UNLIKELY(!pCur))
491 {
492 pgmUnlock(pVM);
493 AssertMsgFailed(("Range %#x not found!\n", GCPtr));
494 return VERR_INVALID_PARAMETER;
495 }
496
497 Log(("PGMHandlerVirtualDeregister: Removing Hyper Virtual (%d) Range %RGv-%RGv %s\n", pCur->enmType,
498 pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
499 Assert(pCur->enmType == PGMVIRTHANDLERTYPE_HYPERVISOR);
500 }
501
502 pgmUnlock(pVM);
503
504 STAM_DEREG(pVM, &pCur->Stat);
505 MMHyperFree(pVM, pCur);
506
507 return VINF_SUCCESS;
508}
509
510
511/**
512 * Arguments for pgmR3InfoHandlersPhysicalOne and pgmR3InfoHandlersVirtualOne.
513 */
514typedef struct PGMHANDLERINFOARG
515{
516 /** The output helpers.*/
517 PCDBGFINFOHLP pHlp;
518 /** Set if statistics should be dumped. */
519 bool fStats;
520} PGMHANDLERINFOARG, *PPGMHANDLERINFOARG;
521
522
523/**
524 * Info callback for 'pgmhandlers'.
525 *
526 * @param pHlp The output helpers.
527 * @param pszArgs The arguments. phys or virt.
528 */
529DECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
530{
531 /*
532 * Test input.
533 */
534 PGMHANDLERINFOARG Args = { pHlp, /* .fStats = */ true };
535 bool fPhysical = !pszArgs || !*pszArgs;
536 bool fVirtual = fPhysical;
537 bool fHyper = fPhysical;
538 if (!fPhysical)
539 {
540 bool fAll = strstr(pszArgs, "all") != NULL;
541 fPhysical = fAll || strstr(pszArgs, "phys") != NULL;
542 fVirtual = fAll || strstr(pszArgs, "virt") != NULL;
543 fHyper = fAll || strstr(pszArgs, "hyper")!= NULL;
544 Args.fStats = strstr(pszArgs, "nost") == NULL;
545 }
546
547 /*
548 * Dump the handlers.
549 */
550 if (fPhysical)
551 {
552 pHlp->pfnPrintf(pHlp,
553 "Physical handlers: (PhysHandlers=%d (%#x))\n"
554 "From - To (incl) HandlerHC UserHC HandlerGC UserGC Type Description\n",
555 pVM->pgm.s.pTreesR3->PhysHandlers, pVM->pgm.s.pTreesR3->PhysHandlers);
556 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3InfoHandlersPhysicalOne, &Args);
557 }
558
559 if (fVirtual)
560 {
561 pHlp->pfnPrintf(pHlp,
562 "Virtual handlers:\n"
563 "From - To (excl) HandlerHC HandlerGC Type Description\n");
564 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->VirtHandlers, true, pgmR3InfoHandlersVirtualOne, &Args);
565 }
566
567 if (fHyper)
568 {
569 pHlp->pfnPrintf(pHlp,
570 "Hypervisor Virtual handlers:\n"
571 "From - To (excl) HandlerHC HandlerGC Type Description\n");
572 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->HyperVirtHandlers, true, pgmR3InfoHandlersVirtualOne, &Args);
573 }
574}
575
576
577/**
578 * Displays one physical handler range.
579 *
580 * @returns 0
581 * @param pNode Pointer to a PGMPHYSHANDLER.
582 * @param pvUser Pointer to command helper functions.
583 */
584static DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser)
585{
586 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
587 PPGMHANDLERINFOARG pArgs= (PPGMHANDLERINFOARG)pvUser;
588 PCDBGFINFOHLP pHlp = pArgs->pHlp;
589 const char *pszType;
590 switch (pCur->enmType)
591 {
592 case PGMPHYSHANDLERTYPE_MMIO: pszType = "MMIO "; break;
593 case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE: pszType = "Write "; break;
594 case PGMPHYSHANDLERTYPE_PHYSICAL_ALL: pszType = "All "; break;
595 default: pszType = "????"; break;
596 }
597 pHlp->pfnPrintf(pHlp,
598 "%RGp - %RGp %RHv %RHv %RRv %RRv %s %s\n",
599 pCur->Core.Key, pCur->Core.KeyLast, pCur->pfnHandlerR3, pCur->pvUserR3, pCur->pfnHandlerRC, pCur->pvUserRC, pszType, pCur->pszDesc);
600#ifdef VBOX_WITH_STATISTICS
601 if (pArgs->fStats)
602 pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
603 pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
604 pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
605#endif
606 return 0;
607}
608
609
610/**
611 * Displays one virtual handler range.
612 *
613 * @returns 0
614 * @param pNode Pointer to a PGMVIRTHANDLER.
615 * @param pvUser Pointer to command helper functions.
616 */
617static DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
618{
619 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
620 PPGMHANDLERINFOARG pArgs= (PPGMHANDLERINFOARG)pvUser;
621 PCDBGFINFOHLP pHlp = pArgs->pHlp;
622 const char *pszType;
623 switch (pCur->enmType)
624 {
625 case PGMVIRTHANDLERTYPE_WRITE: pszType = "Write "; break;
626 case PGMVIRTHANDLERTYPE_ALL: pszType = "All "; break;
627 case PGMVIRTHANDLERTYPE_HYPERVISOR: pszType = "WriteHyp "; break;
628 default: pszType = "????"; break;
629 }
630 pHlp->pfnPrintf(pHlp, "%RGv - %RGv %RHv %RRv %s %s\n",
631 pCur->Core.Key, pCur->Core.KeyLast, pCur->pfnHandlerR3, pCur->pfnHandlerRC, pszType, pCur->pszDesc);
632#ifdef VBOX_WITH_STATISTICS
633 if (pArgs->fStats)
634 pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
635 pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
636 pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
637#endif
638 return 0;
639}
640
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