Changeset 80163 in vbox
- Timestamp:
- Aug 6, 2019 8:28:12 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r79630 r80163 98 98 /** The VM has been restored. */ 99 99 #define VERR_VM_RESTORED (-1025) 100 /** The requested feature is not supported by NEM. */ 101 #define VERR_NOT_SUP_BY_NEM (-1026) 100 102 /** @} */ 101 103 -
trunk/include/VBox/vmm/pgm.h
r80118 r80163 471 471 VMMDECL(int) PGMHandlerPhysicalReset(PVM pVM, RTGCPHYS GCPhys); 472 472 VMMDECL(bool) PGMHandlerPhysicalIsRegistered(PVM pVM, RTGCPHYS GCPhys); 473 474 /** PGM virtual access handler type registration handle (heap offset, valid475 * cross contexts without needing fixing up). Callbacks and handler type is476 * associated with this and it is shared by all handler registrations. */477 typedef uint32_t PGMVIRTHANDLERTYPE;478 /** Pointer to a PGM virtual handler type registration handle. */479 typedef PGMVIRTHANDLERTYPE *PPGMVIRTHANDLERTYPE;480 /** NIL value for PGM virtual access handler type handle. */481 #define NIL_PGMVIRTHANDLERTYPE UINT32_MAX482 #ifdef VBOX_WITH_RAW_MODE483 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRelease(PVM pVM, PGMVIRTHANDLERTYPE hType);484 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRetain(PVM pVM, PGMVIRTHANDLERTYPE hType);485 VMM_INT_DECL(bool) PGMHandlerVirtualIsRegistered(PVM pVM, RTGCPTR GCPtr);486 #endif487 473 488 474 … … 878 864 const char *pszDesc, 879 865 PPGMPHYSHANDLERTYPE phType); 880 #ifdef VBOX_WITH_RAW_MODE881 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegisterEx(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,882 PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,883 PFNPGMVIRTHANDLER pfnHandlerR3,884 RCPTRTYPE(FNPGMVIRTHANDLER) pfnHandlerRC,885 RCPTRTYPE(FNPGMRCVIRTPFHANDLER) pfnPfHandlerRC,886 const char *pszDesc, PPGMVIRTHANDLERTYPE phType);887 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegister(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,888 PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,889 PFNPGMVIRTHANDLER pfnHandlerR3,890 const char *pszHandlerRC, const char *pszPfHandlerRC, const char *pszDesc,891 PPGMVIRTHANDLERTYPE phType);892 VMMR3_INT_DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PVMCPU pVCpu, PGMVIRTHANDLERTYPE hType, RTGCPTR GCPtr,893 RTGCPTR GCPtrLast, void *pvUserR3, RTRCPTR pvUserRC, const char *pszDesc);894 VMMR3_INT_DECL(int) PGMHandlerVirtualChangeType(PVM pVM, RTGCPTR GCPtr, PGMVIRTHANDLERTYPE hNewType);895 VMMR3_INT_DECL(int) PGMHandlerVirtualDeregister(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, bool fHypervisor);896 #endif897 866 VMMR3DECL(int) PGMR3PoolGrow(PVM pVM); 898 867 -
trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
r80118 r80163 45 45 #include <VBox/param.h> 46 46 #include <VBox/err.h> 47 48 49 /*********************************************************************************************************************************50 * Structures and Typedefs *51 *********************************************************************************************************************************/52 /**53 * Stated structure for PGM_GST_NAME(HandlerVirtualUpdate) that's54 * passed to PGM_GST_NAME(VirtHandlerUpdateOne) during enumeration.55 */56 typedef struct PGMHVUSTATE57 {58 /** Pointer to the VM. */59 PVM pVM;60 /** Pointer to the VMCPU. */61 PVMCPU pVCpu;62 /** The todo flags. */63 RTUINT fTodo;64 /** The CR4 register value. */65 uint32_t cr4;66 } PGMHVUSTATE, *PPGMHVUSTATE;67 47 68 48 … … 3618 3598 static const char s_achHandlerStates[4] = { '-', 't', 'w', 'a' }; 3619 3599 szTmp[cch++] = s_achHandlerStates[PGM_PAGE_GET_HNDL_PHYS_STATE(pPage)]; 3620 szTmp[cch++] = s_achHandlerStates[PGM_PAGE_GET_HNDL_VIRT_STATE(pPage)];3621 3600 } 3622 3601 -
trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
r80134 r80163 369 369 } 370 370 } 371 # if PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE) && !defined(IN_RING0)372 else373 {374 # ifdef PGM_SYNC_N_PAGES375 /*376 * If the region is write protected and we got a page not present fault, then sync377 * the pages. If the fault was caused by a read, then restart the instruction.378 * In case of write access continue to the GC write handler.379 */380 if ( PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < PGM_PAGE_HNDL_PHYS_STATE_ALL381 && !(uErr & X86_TRAP_PF_P))382 {383 rcStrict = PGM_BTH_NAME(SyncPage)(pVCpu, pGstWalk->Pde, pvFault, PGM_SYNC_NR_PAGES, uErr);384 if ( RT_FAILURE(rcStrict)385 || rcStrict == VINF_PGM_SYNCPAGE_MODIFIED_PDE386 || !(uErr & X86_TRAP_PF_RW))387 {388 AssertRC(rcStrict);389 STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eHandlersOutOfSync);390 STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2OutOfSyncHndVirt; });391 return rcStrict;392 }393 }394 # endif395 /*396 * Ok, it's an virtual page access handler.397 *398 * Since it's faster to search by address, we'll do that first399 * and then retry by GCPhys if that fails.400 */401 /** @todo r=bird: perhaps we should consider looking up by physical address directly now?402 * r=svl: true, but lookup on virtual address should remain as a fallback as phys & virt trees might be403 * out of sync, because the page was changed without us noticing it (not-present -> present404 * without invlpg or mov cr3, xxx).405 */406 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, pvFault);407 if (pCur)408 {409 PPGMVIRTHANDLERTYPEINT pCurType = PGMVIRTANDLER_GET_TYPE(pVM, pCur);410 AssertMsg(!(pvFault - pCur->Core.Key < pCur->cb)411 || ( pCurType->enmKind != PGMVIRTHANDLERKIND_WRITE412 || !(uErr & X86_TRAP_PF_P)413 || (pCurType->enmKind == PGMVIRTHANDLERKIND_WRITE && (uErr & X86_TRAP_PF_RW))),414 ("Unexpected trap for virtual handler: %RGv (phys=%RGp) pPage=%R[pgmpage] uErr=%X, enumKind=%d\n",415 pvFault, pGstWalk->Core.GCPhys, pPage, uErr, pCurType->enmKind));416 417 if ( pvFault - pCur->Core.Key < pCur->cb418 && ( uErr & X86_TRAP_PF_RW419 || pCurType->enmKind != PGMVIRTHANDLERKIND_WRITE ) )420 {421 # ifdef IN_RC422 STAM_PROFILE_START(&pCur->Stat, h);423 RTGCPTR GCPtrStart = pCur->Core.Key;424 void *pvUser = pCur->CTX_SUFF(pvUser);425 pgmUnlock(pVM);426 *pfLockTaken = false;427 428 rcStrict = pCurType->CTX_SUFF(pfnPfHandler)(pVM, pVCpu, uErr, pRegFrame, pvFault, GCPtrStart,429 pvFault - GCPtrStart, pvUser);430 431 # ifdef VBOX_WITH_STATISTICS432 pgmLock(pVM);433 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, pvFault);434 if (pCur)435 STAM_PROFILE_STOP(&pCur->Stat, h);436 pgmUnlock(pVM);437 # endif438 # else439 rcStrict = VINF_EM_RAW_EMULATE_INSTR; /** @todo for VMX */440 # endif441 STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eHandlersVirtual);442 STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2HndVirt; });443 return rcStrict;444 }445 /* Unhandled part of a monitored page */446 Log(("Unhandled part of monitored page %RGv\n", pvFault));447 }448 else449 {450 /* Check by physical address. */451 unsigned iPage;452 pCur = pgmHandlerVirtualFindByPhysAddr(pVM, pGstWalk->Core.GCPhys, &iPage);453 if (pCur)454 {455 PPGMVIRTHANDLERTYPEINT pCurType = PGMVIRTANDLER_GET_TYPE(pVM, pCur);456 if ( uErr & X86_TRAP_PF_RW457 || pCurType->enmKind != PGMVIRTHANDLERKIND_WRITE )458 {459 Assert( (pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK)460 == (pGstWalk->Core.GCPhys & X86_PTE_PAE_PG_MASK));461 # ifdef IN_RC462 STAM_PROFILE_START(&pCur->Stat, h);463 RTGCPTR GCPtrStart = pCur->Core.Key;464 void *pvUser = pCur->CTX_SUFF(pvUser);465 pgmUnlock(pVM);466 *pfLockTaken = false;467 468 RTGCPTR off = (iPage << PAGE_SHIFT)469 + (pvFault & PAGE_OFFSET_MASK)470 - (GCPtrStart & PAGE_OFFSET_MASK);471 Assert(off < pCur->cb);472 rcStrict = pCurType->CTX_SUFF(pfnPfHandler)(pVM, pVCpu, uErr, pRegFrame, pvFault, GCPtrStart, off, pvUser);473 474 # ifdef VBOX_WITH_STATISTICS475 pgmLock(pVM);476 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtrStart);477 if (pCur)478 STAM_PROFILE_STOP(&pCur->Stat, h);479 pgmUnlock(pVM);480 # endif481 # else482 rcStrict = VINF_EM_RAW_EMULATE_INSTR; /** @todo for VMX */483 # endif484 STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eHandlersVirtualByPhys);485 STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2HndVirt; });486 return rcStrict;487 }488 }489 }490 }491 # endif /* PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE) */492 371 493 372 /* … … 3815 3694 3816 3695 #if !PGM_TYPE_IS_NESTED_OR_EPT(PGM_SHW_TYPE) && PGM_SHW_TYPE != PGM_TYPE_NONE 3817 3696 # ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT 3818 3697 pgmLock(pVM); 3819 3820 # ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT3821 3698 PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool); 3822 3699 if (pPool->cDirtyPages) 3823 3700 pgmPoolResetDirtyPages(pVM); 3824 # endif3825 3826 /*3827 * Update page access handlers.3828 * The virtual are always flushed, while the physical are only on demand.3829 * WARNING: We are incorrectly not doing global flushing on Virtual Handler updates. We'll3830 * have to look into that later because it will have a bad influence on the performance.3831 * @note SvL: There's no need for that. Just invalidate the virtual range(s).3832 * bird: Yes, but that won't work for aliases.3833 */3834 /** @todo this MUST go away. See @bugref{1557}. */3835 STAM_PROFILE_START(&pVCpu->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3Handlers), h);3836 PGM_GST_NAME(HandlerVirtualUpdate)(pVM, cr4);3837 STAM_PROFILE_STOP(&pVCpu->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3Handlers), h);3838 3701 pgmUnlock(pVM); 3702 # endif 3839 3703 #endif /* !NESTED && !EPT */ 3840 3704 -
trunk/src/VBox/VMM/VMMAll/PGMAllGst.h
r76553 r80163 29 29 PGM_GST_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask); 30 30 PGM_GST_DECL(int, GetPDE)(PVMCPU pVCpu, RTGCPTR GCPtr, PX86PDEPAE pPDE); 31 PGM_GST_DECL(bool, HandlerVirtualUpdate)(PVM pVM, uint32_t cr4);32 31 33 32 #ifdef IN_RING3 /* r3 only for now. */ … … 507 506 508 507 509 #if ( PGM_GST_TYPE == PGM_TYPE_32BIT \510 || PGM_GST_TYPE == PGM_TYPE_PAE \511 || PGM_GST_TYPE == PGM_TYPE_AMD64) \512 && defined(VBOX_WITH_RAW_MODE)513 /**514 * Updates one virtual handler range.515 *516 * @returns 0517 * @param pNode Pointer to a PGMVIRTHANDLER.518 * @param pvUser Pointer to a PGMVHUARGS structure (see PGM.cpp).519 */520 static DECLCALLBACK(int) PGM_GST_NAME(VirtHandlerUpdateOne)(PAVLROGCPTRNODECORE pNode, void *pvUser)521 {522 PPGMHVUSTATE pState = (PPGMHVUSTATE)pvUser;523 PVM pVM = pState->pVM;524 PVMCPU pVCpu = pState->pVCpu;525 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;526 PPGMVIRTHANDLERTYPEINT pCurType = PGMVIRTANDLER_GET_TYPE(pVM, pCur);527 528 Assert(pCurType->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR); NOREF(pCurType);529 530 # if PGM_GST_TYPE == PGM_TYPE_32BIT531 PX86PD pPDSrc = pgmGstGet32bitPDPtr(pVCpu);532 # endif533 534 RTGCPTR GCPtr = pCur->Core.Key;535 # if PGM_GST_TYPE != PGM_TYPE_AMD64536 /* skip all stuff above 4GB if not AMD64 mode. */537 if (RT_UNLIKELY(GCPtr >= _4G))538 return 0;539 # endif540 541 unsigned offPage = GCPtr & PAGE_OFFSET_MASK;542 unsigned iPage = 0;543 while (iPage < pCur->cPages)544 {545 # if PGM_GST_TYPE == PGM_TYPE_32BIT546 X86PDE Pde = pPDSrc->a[GCPtr >> X86_PD_SHIFT];547 # elif PGM_GST_TYPE == PGM_TYPE_PAE548 X86PDEPAE Pde = pgmGstGetPaePDE(pVCpu, GCPtr);549 # elif PGM_GST_TYPE == PGM_TYPE_AMD64550 X86PDEPAE Pde = pgmGstGetLongModePDE(pVCpu, GCPtr);551 # endif552 # if PGM_GST_TYPE == PGM_TYPE_32BIT553 bool const fBigPage = Pde.b.u1Size && (pState->cr4 & X86_CR4_PSE);554 # else555 bool const fBigPage = Pde.b.u1Size;556 # endif557 if ( Pde.n.u1Present558 && ( !fBigPage559 ? GST_IS_PDE_VALID(pVCpu, Pde)560 : GST_IS_BIG_PDE_VALID(pVCpu, Pde)) )561 {562 if (!fBigPage)563 {564 /*565 * Normal page table.566 */567 PGSTPT pPT;568 int rc = PGM_GCPHYS_2_PTR_V2(pVM, pVCpu, GST_GET_PDE_GCPHYS(Pde), &pPT);569 if (RT_SUCCESS(rc))570 {571 for (unsigned iPTE = (GCPtr >> GST_PT_SHIFT) & GST_PT_MASK;572 iPTE < RT_ELEMENTS(pPT->a) && iPage < pCur->cPages;573 iPTE++, iPage++, GCPtr += PAGE_SIZE, offPage = 0)574 {575 GSTPTE Pte = pPT->a[iPTE];576 RTGCPHYS GCPhysNew;577 if (Pte.n.u1Present)578 GCPhysNew = PGM_A20_APPLY(pVCpu, (RTGCPHYS)(pPT->a[iPTE].u & GST_PTE_PG_MASK) + offPage);579 else580 GCPhysNew = NIL_RTGCPHYS;581 if (pCur->aPhysToVirt[iPage].Core.Key != GCPhysNew)582 {583 if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)584 pgmHandlerVirtualClearPage(pVM, pCur, iPage);585 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL586 AssertReleaseMsg(!pCur->aPhysToVirt[iPage].offNextAlias,587 ("{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} GCPhysNew=%RGp\n",588 pCur->aPhysToVirt[iPage].Core.Key, pCur->aPhysToVirt[iPage].Core.KeyLast,589 pCur->aPhysToVirt[iPage].offVirtHandler, pCur->aPhysToVirt[iPage].offNextAlias, GCPhysNew));590 #endif591 pCur->aPhysToVirt[iPage].Core.Key = GCPhysNew;592 pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;593 }594 }595 }596 else597 {598 /* not-present. */599 offPage = 0;600 AssertRC(rc);601 for (unsigned iPTE = (GCPtr >> GST_PT_SHIFT) & GST_PT_MASK;602 iPTE < RT_ELEMENTS(pPT->a) && iPage < pCur->cPages;603 iPTE++, iPage++, GCPtr += PAGE_SIZE)604 {605 if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)606 {607 pgmHandlerVirtualClearPage(pVM, pCur, iPage);608 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL609 AssertReleaseMsg(!pCur->aPhysToVirt[iPage].offNextAlias,610 ("{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",611 pCur->aPhysToVirt[iPage].Core.Key, pCur->aPhysToVirt[iPage].Core.KeyLast,612 pCur->aPhysToVirt[iPage].offVirtHandler, pCur->aPhysToVirt[iPage].offNextAlias));613 #endif614 pCur->aPhysToVirt[iPage].Core.Key = NIL_RTGCPHYS;615 pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;616 }617 }618 }619 }620 else621 {622 /*623 * 2/4MB page.624 */625 RTGCPHYS GCPhys = (RTGCPHYS)GST_GET_PDE_GCPHYS(Pde);626 for (unsigned i4KB = (GCPtr >> GST_PT_SHIFT) & GST_PT_MASK;627 i4KB < PAGE_SIZE / sizeof(GSTPDE) && iPage < pCur->cPages;628 i4KB++, iPage++, GCPtr += PAGE_SIZE, offPage = 0)629 {630 RTGCPHYS GCPhysNew = PGM_A20_APPLY(pVCpu, GCPhys + (i4KB << PAGE_SHIFT) + offPage);631 if (pCur->aPhysToVirt[iPage].Core.Key != GCPhysNew)632 {633 if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)634 pgmHandlerVirtualClearPage(pVM, pCur, iPage);635 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL636 AssertReleaseMsg(!pCur->aPhysToVirt[iPage].offNextAlias,637 ("{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} GCPhysNew=%RGp\n",638 pCur->aPhysToVirt[iPage].Core.Key, pCur->aPhysToVirt[iPage].Core.KeyLast,639 pCur->aPhysToVirt[iPage].offVirtHandler, pCur->aPhysToVirt[iPage].offNextAlias, GCPhysNew));640 #endif641 pCur->aPhysToVirt[iPage].Core.Key = GCPhysNew;642 pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;643 }644 }645 } /* pde type */646 }647 else648 {649 /* not-present / invalid. */650 Log(("VirtHandler: Not present / invalid Pde=%RX64\n", (uint64_t)Pde.u));651 for (unsigned cPages = (GST_PT_MASK + 1) - ((GCPtr >> GST_PT_SHIFT) & GST_PT_MASK);652 cPages && iPage < pCur->cPages;653 iPage++, GCPtr += PAGE_SIZE)654 {655 if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)656 {657 pgmHandlerVirtualClearPage(pVM, pCur, iPage);658 pCur->aPhysToVirt[iPage].Core.Key = NIL_RTGCPHYS;659 pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;660 }661 }662 offPage = 0;663 }664 } /* for pages in virtual mapping. */665 666 return 0;667 }668 #endif /* 32BIT, PAE and AMD64 + VBOX_WITH_RAW_MODE */669 670 671 /**672 * Updates the virtual page access handlers.673 *674 * @returns true if bits were flushed.675 * @returns false if bits weren't flushed.676 * @param pVM The cross context VM structure.677 * @param cr4 The cr4 register value.678 */679 PGM_GST_DECL(bool, HandlerVirtualUpdate)(PVM pVM, uint32_t cr4)680 {681 #if ( PGM_GST_TYPE == PGM_TYPE_32BIT \682 || PGM_GST_TYPE == PGM_TYPE_PAE \683 || PGM_GST_TYPE == PGM_TYPE_AMD64) \684 && defined(VBOX_WITH_RAW_MODE)685 686 /** @todo687 * In theory this is not sufficient: the guest can change a single page in a range with invlpg688 */689 690 /*691 * Resolve any virtual address based access handlers to GC physical addresses.692 * This should be fairly quick.693 */694 RTUINT fTodo = 0;695 696 pgmLock(pVM);697 STAM_PROFILE_START(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualUpdate), a);698 699 for (VMCPUID i = 0; i < pVM->cCpus; i++)700 {701 PGMHVUSTATE State;702 PVMCPU pVCpu = &pVM->aCpus[i];703 704 State.pVM = pVM;705 State.pVCpu = pVCpu;706 State.fTodo = pVCpu->pgm.s.fSyncFlags;707 State.cr4 = cr4;708 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, PGM_GST_NAME(VirtHandlerUpdateOne), &State);709 710 fTodo |= State.fTodo;711 }712 STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualUpdate), a);713 714 715 /*716 * Set / reset bits?717 */718 if (fTodo & PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL)719 {720 STAM_PROFILE_START(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualReset), b);721 Log(("HandlerVirtualUpdate: resets bits\n"));722 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, pgmHandlerVirtualResetOne, pVM);723 724 for (VMCPUID i = 0; i < pVM->cCpus; i++)725 {726 PVMCPU pVCpu = &pVM->aCpus[i];727 pVCpu->pgm.s.fSyncFlags &= ~PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;728 }729 730 STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualReset), b);731 }732 pgmUnlock(pVM);733 734 return !!(fTodo & PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL);735 736 #else /* real / protected */737 NOREF(pVM); NOREF(cr4);738 return false;739 #endif740 }741 742 743 508 #ifdef IN_RING3 744 509 /** -
trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp
r76993 r80163 1666 1666 } 1667 1667 1668 1669 #ifdef VBOX_WITH_RAW_MODE1670 1671 /**1672 * Internal worker for releasing a virtual handler type registration reference.1673 *1674 * @returns New reference count. UINT32_MAX if invalid input (asserted).1675 * @param pVM The cross context VM structure.1676 * @param pType Pointer to the type registration.1677 */1678 DECLINLINE(uint32_t) pgmHandlerVirtualTypeRelease(PVM pVM, PPGMVIRTHANDLERTYPEINT pType)1679 {1680 AssertMsgReturn(pType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, ("%#x\n", pType->u32Magic), UINT32_MAX);1681 uint32_t cRefs = ASMAtomicDecU32(&pType->cRefs);1682 if (cRefs == 0)1683 {1684 pgmLock(pVM);1685 pType->u32Magic = PGMVIRTHANDLERTYPEINT_MAGIC_DEAD;1686 RTListOff32NodeRemove(&pType->ListNode);1687 pgmUnlock(pVM);1688 MMHyperFree(pVM, pType);1689 }1690 return cRefs;1691 }1692 1693 1694 /**1695 * Internal worker for retaining a virtual handler type registration reference.1696 *1697 * @returns New reference count. UINT32_MAX if invalid input (asserted).1698 * @param pVM The cross context VM structure.1699 * @param pType Pointer to the type registration.1700 */1701 DECLINLINE(uint32_t) pgmHandlerVirtualTypeRetain(PVM pVM, PPGMVIRTHANDLERTYPEINT pType)1702 {1703 NOREF(pVM);1704 AssertMsgReturn(pType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, ("%#x\n", pType->u32Magic), UINT32_MAX);1705 uint32_t cRefs = ASMAtomicIncU32(&pType->cRefs);1706 Assert(cRefs < _1M && cRefs > 0);1707 return cRefs;1708 }1709 1710 1711 /**1712 * Releases a reference to a virtual handler type registration.1713 *1714 * @returns New reference count. UINT32_MAX if invalid input (asserted).1715 * @param pVM The cross context VM structure.1716 * @param hType The type regiration handle.1717 */1718 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRelease(PVM pVM, PGMVIRTHANDLERTYPE hType)1719 {1720 if (hType != NIL_PGMVIRTHANDLERTYPE)1721 return pgmHandlerVirtualTypeRelease(pVM, PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hType));1722 return 0;1723 }1724 1725 1726 /**1727 * Retains a reference to a virtual handler type registration.1728 *1729 * @returns New reference count. UINT32_MAX if invalid input (asserted).1730 * @param pVM The cross context VM structure.1731 * @param hType The type regiration handle.1732 */1733 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRetain(PVM pVM, PGMVIRTHANDLERTYPE hType)1734 {1735 return pgmHandlerVirtualTypeRetain(pVM, PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hType));1736 }1737 1738 1739 /**1740 * Check if particular guest's VA is being monitored.1741 *1742 * @returns true or false1743 * @param pVM The cross context VM structure.1744 * @param GCPtr Virtual address.1745 * @remarks Will acquire the PGM lock.1746 * @thread Any.1747 */1748 VMM_INT_DECL(bool) PGMHandlerVirtualIsRegistered(PVM pVM, RTGCPTR GCPtr)1749 {1750 pgmLock(pVM);1751 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtr);1752 pgmUnlock(pVM);1753 1754 return pCur != NULL;1755 }1756 1757 1758 /**1759 * Search for virtual handler with matching physical address1760 *1761 * @returns Pointer to the virtual handler structure if found, otherwise NULL.1762 * @param pVM The cross context VM structure.1763 * @param GCPhys GC physical address to search for.1764 * @param piPage Where to store the pointer to the index of the cached physical page.1765 */1766 PPGMVIRTHANDLER pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, unsigned *piPage)1767 {1768 STAM_PROFILE_START(&pVM->pgm.s.CTX_MID_Z(Stat,VirtHandlerSearchByPhys), a);1769 1770 pgmLock(pVM);1771 PPGMPHYS2VIRTHANDLER pCur;1772 pCur = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, GCPhys);1773 if (pCur)1774 {1775 /* found a match! */1776 PPGMVIRTHANDLER pVirt = (PPGMVIRTHANDLER)((uintptr_t)pCur + pCur->offVirtHandler);1777 *piPage = pCur - &pVirt->aPhysToVirt[0];1778 pgmUnlock(pVM);1779 1780 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1781 AssertRelease(pCur->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD);1782 #endif1783 LogFlow(("PHYS2VIRT: found match for %RGp -> %RGv *piPage=%#x\n", GCPhys, pVirt->Core.Key, *piPage));1784 STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,VirtHandlerSearchByPhys), a);1785 return pVirt;1786 }1787 1788 pgmUnlock(pVM);1789 STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,VirtHandlerSearchByPhys), a);1790 return NULL;1791 }1792 1793 1794 /**1795 * Deal with aliases in phys2virt.1796 *1797 * As pointed out by the various todos, this currently only deals with1798 * aliases where the two ranges match 100%.1799 *1800 * @param pVM The cross context VM structure.1801 * @param pPhys2Virt The node we failed insert.1802 */1803 static void pgmHandlerVirtualInsertAliased(PVM pVM, PPGMPHYS2VIRTHANDLER pPhys2Virt)1804 {1805 /*1806 * First find the node which is conflicting with us.1807 */1808 /** @todo Deal with partial overlapping. (Unlikely situation, so I'm too lazy to do anything about it now.) */1809 /** @todo check if the current head node covers the ground we do. This is highly unlikely1810 * and I'm too lazy to implement this now as it will require sorting the list and stuff like that. */1811 PPGMPHYS2VIRTHANDLER pHead = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);1812 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1813 AssertReleaseMsg(pHead != pPhys2Virt, ("%RGp-%RGp offVirtHandler=%#RX32\n",1814 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler));1815 #endif1816 if (RT_UNLIKELY(!pHead || pHead->Core.KeyLast != pPhys2Virt->Core.KeyLast))1817 {1818 /** @todo do something clever here... */1819 LogRel(("pgmHandlerVirtualInsertAliased: %RGp-%RGp\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));1820 pPhys2Virt->offNextAlias = 0;1821 return;1822 }1823 1824 /*1825 * Insert ourselves as the next node.1826 */1827 if (!(pHead->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))1828 pPhys2Virt->offNextAlias = PGMPHYS2VIRTHANDLER_IN_TREE;1829 else1830 {1831 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pHead + (pHead->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));1832 pPhys2Virt->offNextAlias = ((intptr_t)pNext - (intptr_t)pPhys2Virt)1833 | PGMPHYS2VIRTHANDLER_IN_TREE;1834 }1835 pHead->offNextAlias = ((intptr_t)pPhys2Virt - (intptr_t)pHead)1836 | (pHead->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);1837 Log(("pgmHandlerVirtualInsertAliased: %RGp-%RGp offNextAlias=%#RX32\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias));1838 }1839 1840 1841 /**1842 * Resets one virtual handler range.1843 *1844 * This is called by HandlerVirtualUpdate when it has detected some kind of1845 * problem and have started clearing the virtual handler page states (or1846 * when there have been registration/deregistrations). For this reason this1847 * function will only update the page status if it's lower than desired.1848 *1849 * @returns 01850 * @param pNode Pointer to a PGMVIRTHANDLER.1851 * @param pvUser Pointer to the VM.1852 */1853 DECLCALLBACK(int) pgmHandlerVirtualResetOne(PAVLROGCPTRNODECORE pNode, void *pvUser)1854 {1855 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;1856 PVM pVM = (PVM)pvUser;1857 1858 PGM_LOCK_ASSERT_OWNER(pVM);1859 1860 /*1861 * Iterate the pages and apply the new state.1862 */1863 uint32_t uState = PGMVIRTANDLER_GET_TYPE(pVM, pCur)->uState;1864 PPGMRAMRANGE pRamHint = NULL;1865 RTGCUINTPTR offPage = ((RTGCUINTPTR)pCur->Core.Key & PAGE_OFFSET_MASK);1866 RTGCUINTPTR cbLeft = pCur->cb;1867 for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)1868 {1869 PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];1870 if (pPhys2Virt->Core.Key != NIL_RTGCPHYS)1871 {1872 /*1873 * Update the page state wrt virtual handlers.1874 */1875 PPGMPAGE pPage;1876 int rc = pgmPhysGetPageWithHintEx(pVM, pPhys2Virt->Core.Key, &pPage, &pRamHint);1877 if ( RT_SUCCESS(rc)1878 && PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < uState)1879 PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, uState);1880 else1881 AssertRC(rc);1882 1883 /*1884 * Need to insert the page in the Phys2Virt lookup tree?1885 */1886 if (pPhys2Virt->Core.KeyLast == NIL_RTGCPHYS)1887 {1888 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1889 AssertRelease(!pPhys2Virt->offNextAlias);1890 #endif1891 unsigned cbPhys = cbLeft;1892 if (cbPhys > PAGE_SIZE - offPage)1893 cbPhys = PAGE_SIZE - offPage;1894 else1895 Assert(iPage == pCur->cPages - 1);1896 pPhys2Virt->Core.KeyLast = pPhys2Virt->Core.Key + cbPhys - 1; /* inclusive */1897 pPhys2Virt->offNextAlias = PGMPHYS2VIRTHANDLER_IS_HEAD | PGMPHYS2VIRTHANDLER_IN_TREE;1898 if (!RTAvlroGCPhysInsert(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, &pPhys2Virt->Core))1899 pgmHandlerVirtualInsertAliased(pVM, pPhys2Virt);1900 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1901 else1902 AssertReleaseMsg(RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key) == &pPhys2Virt->Core,1903 ("%RGp-%RGp offNextAlias=%#RX32\n",1904 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias));1905 #endif1906 Log2(("PHYS2VIRT: Insert physical range %RGp-%RGp offNextAlias=%#RX32 %s\n",1907 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));1908 }1909 }1910 cbLeft -= PAGE_SIZE - offPage;1911 offPage = 0;1912 }1913 1914 return 0;1915 }1916 1917 # if defined(VBOX_STRICT) || defined(LOG_ENABLED)1918 1919 /**1920 * Worker for pgmHandlerVirtualDumpPhysPages.1921 *1922 * @returns 0 (continue enumeration).1923 * @param pNode The virtual handler node.1924 * @param pvUser User argument, unused.1925 */1926 static DECLCALLBACK(int) pgmHandlerVirtualDumpPhysPagesCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser)1927 {1928 PPGMPHYS2VIRTHANDLER pCur = (PPGMPHYS2VIRTHANDLER)pNode;1929 PPGMVIRTHANDLER pVirt = (PPGMVIRTHANDLER)((uintptr_t)pCur + pCur->offVirtHandler);1930 NOREF(pvUser); NOREF(pVirt);1931 1932 Log(("PHYS2VIRT: Range %RGp-%RGp for virtual handler: %s\n", pCur->Core.Key, pCur->Core.KeyLast, pVirt->pszDesc));1933 return 0;1934 }1935 1936 1937 /**1938 * Assertion / logging helper for dumping all the1939 * virtual handlers to the log.1940 *1941 * @param pVM The cross context VM structure.1942 */1943 void pgmHandlerVirtualDumpPhysPages(PVM pVM)1944 {1945 RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, true /* from left */,1946 pgmHandlerVirtualDumpPhysPagesCallback, 0);1947 }1948 1949 # endif /* VBOX_STRICT || LOG_ENABLED */1950 #endif /* VBOX_WITH_RAW_MODE */1951 1668 #ifdef VBOX_STRICT 1952 1669 … … 1959 1676 /** The current physical address. */ 1960 1677 RTGCPHYS GCPhys; 1961 /** The state we've calculated. */1962 unsigned uVirtStateFound;1963 /** The state we're matching up to. */1964 unsigned uVirtState;1965 1678 /** Number of errors. */ 1966 1679 unsigned cErrors; … … 1969 1682 } PGMAHAFIS, *PPGMAHAFIS; 1970 1683 1971 # ifdef VBOX_WITH_RAW_MODE1972 1973 # if 0 /* unused */1974 /**1975 * Verify virtual handler by matching physical address.1976 *1977 * @returns 01978 * @param pNode Pointer to a PGMVIRTHANDLER.1979 * @param pvUser Pointer to user parameter.1980 */1981 static DECLCALLBACK(int) pgmHandlerVirtualVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser)1982 {1983 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;1984 PPGMAHAFIS pState = (PPGMAHAFIS)pvUser;1985 1986 for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)1987 {1988 if ((pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) == pState->GCPhys)1989 {1990 unsigned uState = pgmHandlerVirtualCalcState(pCur);1991 if (pState->uVirtState < uState)1992 {1993 error1994 }1995 1996 if (pState->uVirtState == uState)1997 break; //??1998 }1999 }2000 return 0;2001 }2002 # endif /* unused */2003 2004 2005 /**2006 * Verify a virtual handler (enumeration callback).2007 *2008 * Called by PGMAssertHandlerAndFlagsInSync to check the sanity of all2009 * the virtual handlers, esp. that the physical addresses matches up.2010 *2011 * @returns 02012 * @param pNode Pointer to a PGMVIRTHANDLER.2013 * @param pvUser Pointer to a PPGMAHAFIS structure.2014 */2015 static DECLCALLBACK(int) pgmHandlerVirtualVerifyOne(PAVLROGCPTRNODECORE pNode, void *pvUser)2016 {2017 PPGMAHAFIS pState = (PPGMAHAFIS)pvUser;2018 PVM pVM = pState->pVM;2019 PPGMVIRTHANDLER pVirt = (PPGMVIRTHANDLER)pNode;2020 PPGMVIRTHANDLERTYPEINT pType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);2021 2022 /*2023 * Validate the type and calc state.2024 */2025 switch (pType->enmKind)2026 {2027 case PGMVIRTHANDLERKIND_WRITE:2028 case PGMVIRTHANDLERKIND_ALL:2029 break;2030 default:2031 AssertMsgFailed(("unknown/wrong enmKind=%d\n", pType->enmKind));2032 pState->cErrors++;2033 return 0;2034 }2035 const uint32_t uState = pType->uState;2036 2037 /*2038 * Check key alignment.2039 */2040 if ( (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->Core.Key & PAGE_OFFSET_MASK)2041 && pVirt->aPhysToVirt[0].Core.Key != NIL_RTGCPHYS)2042 {2043 AssertMsgFailed(("virt handler phys has incorrect key! %RGp %RGv %s\n",2044 pVirt->aPhysToVirt[0].Core.Key, pVirt->Core.Key, R3STRING(pVirt->pszDesc)));2045 pState->cErrors++;2046 }2047 2048 if ( (pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->Core.KeyLast & PAGE_OFFSET_MASK)2049 && pVirt->aPhysToVirt[pVirt->cPages - 1].Core.Key != NIL_RTGCPHYS)2050 {2051 AssertMsgFailed(("virt handler phys has incorrect key! %RGp %RGv %s\n",2052 pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast, pVirt->Core.KeyLast, R3STRING(pVirt->pszDesc)));2053 pState->cErrors++;2054 }2055 2056 /*2057 * Check pages for sanity and state.2058 */2059 RTGCUINTPTR GCPtr = (RTGCUINTPTR)pVirt->Core.Key;2060 for (unsigned iPage = 0; iPage < pVirt->cPages; iPage++, GCPtr += PAGE_SIZE)2061 {2062 for (VMCPUID i = 0; i < pVM->cCpus; i++)2063 {2064 PVMCPU pVCpu = &pVM->aCpus[i];2065 2066 RTGCPHYS GCPhysGst;2067 uint64_t fGst;2068 int rc = PGMGstGetPage(pVCpu, (RTGCPTR)GCPtr, &fGst, &GCPhysGst);2069 if ( rc == VERR_PAGE_NOT_PRESENT2070 || rc == VERR_PAGE_TABLE_NOT_PRESENT)2071 {2072 if (pVirt->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)2073 {2074 AssertMsgFailed(("virt handler phys out of sync. %RGp GCPhysNew=~0 iPage=%#x %RGv %s\n",2075 pVirt->aPhysToVirt[iPage].Core.Key, iPage, GCPtr, R3STRING(pVirt->pszDesc)));2076 pState->cErrors++;2077 }2078 continue;2079 }2080 2081 AssertRCReturn(rc, 0);2082 if ((pVirt->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) != GCPhysGst)2083 {2084 AssertMsgFailed(("virt handler phys out of sync. %RGp GCPhysGst=%RGp iPage=%#x %RGv %s\n",2085 pVirt->aPhysToVirt[iPage].Core.Key, GCPhysGst, iPage, GCPtr, R3STRING(pVirt->pszDesc)));2086 pState->cErrors++;2087 continue;2088 }2089 2090 PPGMPAGE pPage = pgmPhysGetPage(pVM, GCPhysGst);2091 if (!pPage)2092 {2093 AssertMsgFailed(("virt handler getting ram flags. GCPhysGst=%RGp iPage=%#x %RGv %s\n",2094 GCPhysGst, iPage, GCPtr, R3STRING(pVirt->pszDesc)));2095 pState->cErrors++;2096 continue;2097 }2098 2099 if (PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < uState)2100 {2101 AssertMsgFailed(("virt handler state mismatch. pPage=%R[pgmpage] GCPhysGst=%RGp iPage=%#x %RGv state=%d expected>=%d %s\n",2102 pPage, GCPhysGst, iPage, GCPtr, PGM_PAGE_GET_HNDL_VIRT_STATE(pPage), uState, R3STRING(pVirt->pszDesc)));2103 pState->cErrors++;2104 continue;2105 }2106 } /* for each VCPU */2107 } /* for pages in virtual mapping. */2108 2109 return 0;2110 }2111 2112 # endif /* VBOX_WITH_RAW_MODE */2113 1684 2114 1685 /** … … 2123 1694 PPGM pPGM = &pVM->pgm.s; 2124 1695 PGMAHAFIS State; 2125 State.GCPhys = 0; 2126 State.uVirtState = 0; 2127 State.uVirtStateFound = 0; 1696 State.GCPhys = 0; 2128 1697 State.cErrors = 0; 2129 State.pVM = pVM;1698 State.pVM = pVM; 2130 1699 2131 1700 PGM_LOCK_ASSERT_OWNER(pVM); … … 2207 1776 } 2208 1777 } 2209 2210 /*2211 * Virtual handlers.2212 */2213 if (PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage))2214 {2215 State.uVirtState = PGM_PAGE_GET_HNDL_VIRT_STATE(pPage);2216 2217 /* locate all the matching physical ranges. */2218 State.uVirtStateFound = PGM_PAGE_HNDL_VIRT_STATE_NONE;2219 # ifdef VBOX_WITH_RAW_MODE2220 RTGCPHYS GCPhysKey = State.GCPhys;2221 for (;;)2222 {2223 PPGMPHYS2VIRTHANDLER pPhys2Virt = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,2224 GCPhysKey, true /* above-or-equal */);2225 if ( !pPhys2Virt2226 || (pPhys2Virt->Core.Key & X86_PTE_PAE_PG_MASK) != State.GCPhys)2227 break;2228 2229 /* the head */2230 GCPhysKey = pPhys2Virt->Core.KeyLast;2231 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)((uintptr_t)pPhys2Virt + pPhys2Virt->offVirtHandler);2232 unsigned uState = PGMVIRTANDLER_GET_TYPE(pVM, pCur)->uState;2233 State.uVirtStateFound = RT_MAX(State.uVirtStateFound, uState);2234 2235 /* any aliases */2236 while (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)2237 {2238 pPhys2Virt = (PPGMPHYS2VIRTHANDLER)((uintptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));2239 pCur = (PPGMVIRTHANDLER)((uintptr_t)pPhys2Virt + pPhys2Virt->offVirtHandler);2240 uState = PGMVIRTANDLER_GET_TYPE(pVM, pCur)->uState;2241 State.uVirtStateFound = RT_MAX(State.uVirtStateFound, uState);2242 }2243 2244 /* done? */2245 if ((GCPhysKey & X86_PTE_PAE_PG_MASK) != State.GCPhys)2246 break;2247 }2248 # endif /* VBOX_WITH_RAW_MODE */2249 if (State.uVirtState != State.uVirtStateFound)2250 {2251 AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp uVirtState=%#x uVirtStateFound=%#x\n",2252 State.GCPhys, State.uVirtState, State.uVirtStateFound));2253 State.cErrors++;2254 }2255 }2256 1778 } 2257 1779 } /* foreach page in ram range. */ 2258 1780 } /* foreach ram range. */ 2259 1781 2260 # ifdef VBOX_WITH_RAW_MODE2261 /*2262 * Check that the physical addresses of the virtual handlers matches up2263 * and that they are otherwise sane.2264 */2265 RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOne, &State);2266 # endif2267 2268 1782 /* 2269 1783 * Do the reverse check for physical handlers. -
trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp
r80135 r80163 2501 2501 } 2502 2502 } 2503 2504 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)2505 /*2506 * Deal with any virtual handlers.2507 */2508 if (PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) == PGM_PAGE_HNDL_VIRT_STATE_ALL)2509 {2510 unsigned iPage;2511 PPGMVIRTHANDLER pVirt = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &iPage);2512 AssertReleaseMsg(pVirt, ("GCPhys=%RGp cb=%#x\n", GCPhys, cb));2513 Assert((pVirt->Core.Key & PAGE_OFFSET_MASK) == 0);2514 Assert((pVirt->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK);2515 Assert(GCPhys >= pVirt->aPhysToVirt[iPage].Core.Key && GCPhys <= pVirt->aPhysToVirt[iPage].Core.KeyLast);2516 2517 # ifndef IN_RING32518 if (enmOrigin != PGMACCESSORIGIN_IEM)2519 {2520 /* Cannot reliably handle informational status codes in this context */2521 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);2522 return VERR_PGM_PHYS_WR_HIT_HANDLER;2523 }2524 # endif2525 PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);2526 if (!pPhys)2527 Log5(("pgmPhysReadHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] virt %s\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc) ));2528 else2529 Log(("pgmPhysReadHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] phys/virt %s/%s\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc), R3STRING(pPhys->pszDesc) ));2530 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)2531 + (iPage << PAGE_SHIFT)2532 + (GCPhys & PAGE_OFFSET_MASK);2533 2534 STAM_PROFILE_START(&pVirt->Stat, h);2535 VBOXSTRICTRC rcStrict2 = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, (void *)pvSrc, pvBuf, cb,2536 PGMACCESSTYPE_READ, enmOrigin, pVirt->CTX_SUFF(pvUser));2537 STAM_PROFILE_STOP(&pVirt->Stat, h);2538 2539 /* Merge status codes. */2540 if (rcStrict2 == VINF_SUCCESS)2541 {2542 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)2543 rcStrict = VINF_SUCCESS;2544 }2545 else if (rcStrict2 != VINF_PGM_HANDLER_DO_DEFAULT)2546 {2547 AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict2, false),2548 ("rcStrict2=%Rrc (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n",2549 VBOXSTRICTRC_VAL(rcStrict2), VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pVirt->pszDesc));2550 if (!PGM_PHYS_RW_IS_SUCCESS(rcStrict2))2551 {2552 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);2553 return rcStrict2;2554 }2555 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)2556 rcStrict = rcStrict2;2557 else2558 PGM_PHYS_RW_DO_UPDATE_STRICT_RC(rcStrict, rcStrict2);2559 }2560 }2561 #endif /* !IN_RING0 && VBOX_WITH_RAW_MODE */2562 2503 2563 2504 /* … … 2752 2693 */ 2753 2694 PVMCPU pVCpu = VMMGetCpu(pVM); 2754 if ( !PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage) 2755 || PGM_PAGE_IS_MMIO_OR_SPECIAL_ALIAS(pPage) /* screw virtual handlers on MMIO pages */) 2756 { 2757 PPGMPHYSHANDLER pCur = pgmHandlerPhysicalLookup(pVM, GCPhys); 2758 if (pCur) 2759 { 2760 Assert(GCPhys >= pCur->Core.Key && GCPhys <= pCur->Core.KeyLast); 2695 PPGMPHYSHANDLER pCur = pgmHandlerPhysicalLookup(pVM, GCPhys); 2696 if (pCur) 2697 { 2698 Assert(GCPhys >= pCur->Core.Key && GCPhys <= pCur->Core.KeyLast); 2761 2699 #ifndef IN_RING3 2762 2763 2764 2700 if (enmOrigin != PGMACCESSORIGIN_IEM) 2701 /* Cannot reliably handle informational status codes in this context */ 2702 return VERR_PGM_PHYS_WR_HIT_HANDLER; 2765 2703 #endif 2766 size_t cbRange = pCur->Core.KeyLast - GCPhys + 1; 2767 if (cbRange > cbWrite) 2768 cbRange = cbWrite; 2769 2770 Assert(PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler)); 2771 Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", 2772 GCPhys, cbRange, pPage, R3STRING(pCur->pszDesc) )); 2773 if (!PGM_PAGE_IS_MMIO_OR_SPECIAL_ALIAS(pPage)) 2774 rcStrict = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst, &PgMpLck); 2775 else 2704 size_t cbRange = pCur->Core.KeyLast - GCPhys + 1; 2705 if (cbRange > cbWrite) 2706 cbRange = cbWrite; 2707 2708 Assert(PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler)); 2709 Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", 2710 GCPhys, cbRange, pPage, R3STRING(pCur->pszDesc) )); 2711 if (!PGM_PAGE_IS_MMIO_OR_SPECIAL_ALIAS(pPage)) 2712 rcStrict = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst, &PgMpLck); 2713 else 2714 rcStrict = VINF_SUCCESS; 2715 if (RT_SUCCESS(rcStrict)) 2716 { 2717 PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler); 2718 void *pvUser = pCur->CTX_SUFF(pvUser); 2719 STAM_PROFILE_START(&pCur->Stat, h); 2720 2721 /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */ 2722 PGM_LOCK_ASSERT_OWNER(pVM); 2723 pgmUnlock(pVM); 2724 rcStrict = pfnHandler(pVM, pVCpu, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, enmOrigin, pvUser); 2725 pgmLock(pVM); 2726 2727 #ifdef VBOX_WITH_STATISTICS 2728 pCur = pgmHandlerPhysicalLookup(pVM, GCPhys); 2729 if (pCur) 2730 STAM_PROFILE_STOP(&pCur->Stat, h); 2731 #else 2732 pCur = NULL; /* might not be valid anymore. */ 2733 #endif 2734 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT) 2735 { 2736 if (pvDst) 2737 memcpy(pvDst, pvBuf, cbRange); 2776 2738 rcStrict = VINF_SUCCESS; 2777 if (RT_SUCCESS(rcStrict))2778 {2779 PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler);2780 void *pvUser = pCur->CTX_SUFF(pvUser);2781 STAM_PROFILE_START(&pCur->Stat, h);2782 2783 /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */2784 PGM_LOCK_ASSERT_OWNER(pVM);2785 pgmUnlock(pVM);2786 rcStrict = pfnHandler(pVM, pVCpu, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, enmOrigin, pvUser);2787 pgmLock(pVM);2788 2789 #ifdef VBOX_WITH_STATISTICS2790 pCur = pgmHandlerPhysicalLookup(pVM, GCPhys);2791 if (pCur)2792 STAM_PROFILE_STOP(&pCur->Stat, h);2793 #else2794 pCur = NULL; /* might not be valid anymore. */2795 #endif2796 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)2797 {2798 if (pvDst)2799 memcpy(pvDst, pvBuf, cbRange);2800 rcStrict = VINF_SUCCESS;2801 }2802 else2803 AssertLogRelMsg(PGM_HANDLER_PHYS_IS_VALID_STATUS(rcStrict, true),2804 ("rcStrict=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n",2805 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pCur ? R3STRING(pCur->pszDesc) : ""));2806 2739 } 2807 2740 else 2808 AssertLogRelMsgFailedReturn(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n", 2809 GCPhys, pPage, VBOXSTRICTRC_VAL(rcStrict)), rcStrict); 2810 if (RT_LIKELY(cbRange == cbWrite) || !PGM_PHYS_RW_IS_SUCCESS(rcStrict)) 2811 { 2812 if (pvDst) 2813 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck); 2814 return rcStrict; 2815 } 2816 2817 /* more fun to be had below */ 2818 cbWrite -= cbRange; 2819 GCPhys += cbRange; 2820 pvBuf = (uint8_t *)pvBuf + cbRange; 2821 pvDst = (uint8_t *)pvDst + cbRange; 2822 } 2823 else /* The handler is somewhere else in the page, deal with it below. */ 2824 rcStrict = VINF_SUCCESS; 2825 Assert(!PGM_PAGE_IS_MMIO_OR_ALIAS(pPage)); /* MMIO handlers are all PAGE_SIZEed! */ 2826 } 2827 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE) 2828 /* 2829 * A virtual handler without any interfering physical handlers. 2830 * Hopefully it'll cover the whole write. 2831 */ 2832 else if (!PGM_PAGE_HAS_ACTIVE_PHYSICAL_HANDLERS(pPage)) 2833 { 2834 unsigned iPage; 2835 PPGMVIRTHANDLER pVirt = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &iPage); 2836 if (pVirt) 2837 { 2838 # ifndef IN_RING3 2839 if (enmOrigin != PGMACCESSORIGIN_IEM) 2840 /* Cannot reliably handle informational status codes in this context */ 2841 return VERR_PGM_PHYS_WR_HIT_HANDLER; 2842 # endif 2843 PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt); 2844 size_t cbRange = (PAGE_OFFSET_MASK & pVirt->Core.KeyLast) - (PAGE_OFFSET_MASK & GCPhys) + 1; 2845 if (cbRange > cbWrite) 2846 cbRange = cbWrite; 2847 2848 Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] virt %s\n", 2849 GCPhys, cbRange, pPage, R3STRING(pVirt->pszDesc) )); 2850 rcStrict = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst, &PgMpLck); 2851 if (RT_SUCCESS(rcStrict)) 2852 { 2853 Assert(pVirtType->CTX_SUFF(pfnHandler)); 2854 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK) 2855 + (iPage << PAGE_SHIFT) 2856 + (GCPhys & PAGE_OFFSET_MASK); 2857 2858 STAM_PROFILE_START(&pVirt->Stat, h); 2859 rcStrict = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, pvDst, (void *)pvBuf, cbRange, 2860 PGMACCESSTYPE_WRITE, enmOrigin, pVirt->CTX_SUFF(pvUser)); 2861 STAM_PROFILE_STOP(&pVirt->Stat, h); 2862 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT) 2863 { 2864 memcpy(pvDst, pvBuf, cbRange); 2865 rcStrict = VINF_SUCCESS; 2866 } 2867 else 2868 AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict, true), 2869 ("rcStrict=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", 2870 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, R3STRING(pVirt->pszDesc))); 2871 } 2872 else 2873 AssertLogRelMsgFailedReturn(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n", 2874 GCPhys, pPage, VBOXSTRICTRC_VAL(rcStrict)), rcStrict); 2875 if (RT_LIKELY(cbRange == cbWrite) || !PGM_PHYS_RW_IS_SUCCESS(rcStrict)) 2876 { 2741 AssertLogRelMsg(PGM_HANDLER_PHYS_IS_VALID_STATUS(rcStrict, true), 2742 ("rcStrict=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", 2743 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pCur ? R3STRING(pCur->pszDesc) : "")); 2744 } 2745 else 2746 AssertLogRelMsgFailedReturn(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n", 2747 GCPhys, pPage, VBOXSTRICTRC_VAL(rcStrict)), rcStrict); 2748 if (RT_LIKELY(cbRange == cbWrite) || !PGM_PHYS_RW_IS_SUCCESS(rcStrict)) 2749 { 2750 if (pvDst) 2877 2751 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck); 2878 return rcStrict; 2879 } 2880 2881 /* more fun to be had below */ 2882 cbWrite -= cbRange; 2883 GCPhys += cbRange; 2884 pvBuf = (uint8_t *)pvBuf + cbRange; 2885 pvDst = (uint8_t *)pvDst + cbRange; 2886 } 2887 else /* The handler is somewhere else in the page, deal with it below. */ 2888 rcStrict = VINF_SUCCESS; 2889 } 2890 #endif /* !IN_RING0 && VBOX_WITH_RAW_MODE */ 2891 else 2752 return rcStrict; 2753 } 2754 2755 /* more fun to be had below */ 2756 cbWrite -= cbRange; 2757 GCPhys += cbRange; 2758 pvBuf = (uint8_t *)pvBuf + cbRange; 2759 pvDst = (uint8_t *)pvDst + cbRange; 2760 } 2761 else /* The handler is somewhere else in the page, deal with it below. */ 2892 2762 rcStrict = VINF_SUCCESS; 2893 2894 2895 /* 2896 * Deal with all the odd ends .2763 Assert(!PGM_PAGE_IS_MMIO_OR_ALIAS(pPage)); /* MMIO handlers are all PAGE_SIZEed! */ 2764 2765 /* 2766 * Deal with all the odd ends (used to be deal with virt+phys). 2897 2767 */ 2898 2768 Assert(rcStrict != VINF_PGM_HANDLER_DO_DEFAULT); … … 2908 2778 2909 2779 /* The loop state (big + ugly). */ 2910 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)2911 unsigned iVirtPage = 0;2912 PPGMVIRTHANDLER pVirt = NULL;2913 uint32_t offVirt = PAGE_SIZE;2914 uint32_t offVirtLast = PAGE_SIZE;2915 bool fMoreVirt = PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage);2916 #else2917 uint32_t const offVirt = UINT32_MAX;2918 #endif2919 2920 2780 PPGMPHYSHANDLER pPhys = NULL; 2921 2781 uint32_t offPhys = PAGE_SIZE; … … 2926 2786 for (;;) 2927 2787 { 2928 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)2929 /*2930 * Find the closest handler at or above GCPhys.2931 */2932 if (fMoreVirt && !pVirt)2933 {2934 pVirt = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &iVirtPage);2935 if (pVirt)2936 {2937 offVirt = 0;2938 offVirtLast = (pVirt->aPhysToVirt[iVirtPage].Core.KeyLast & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);2939 }2940 else2941 {2942 PPGMPHYS2VIRTHANDLER pVirtPhys;2943 pVirtPhys = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,2944 GCPhys, true /* fAbove */);2945 if ( pVirtPhys2946 && (pVirtPhys->Core.Key >> PAGE_SHIFT) == (GCPhys >> PAGE_SHIFT))2947 {2948 /* ASSUME that pVirtPhys only covers one page. */2949 Assert((pVirtPhys->Core.Key >> PAGE_SHIFT) == (pVirtPhys->Core.KeyLast >> PAGE_SHIFT));2950 Assert(pVirtPhys->Core.Key > GCPhys);2951 2952 pVirt = (PPGMVIRTHANDLER)((uintptr_t)pVirtPhys + pVirtPhys->offVirtHandler);2953 iVirtPage = pVirtPhys - &pVirt->aPhysToVirt[0]; Assert(iVirtPage == 0);2954 offVirt = (pVirtPhys->Core.Key & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);2955 offVirtLast = (pVirtPhys->Core.KeyLast & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);2956 }2957 else2958 {2959 pVirt = NULL;2960 fMoreVirt = false;2961 offVirt = offVirtLast = PAGE_SIZE;2962 }2963 }2964 }2965 #endif2966 2967 2788 if (fMorePhys && !pPhys) 2968 2789 { … … 2997 2818 VBOXSTRICTRC rcStrict2 = VINF_PGM_HANDLER_DO_DEFAULT; 2998 2819 uint32_t cbRange = (uint32_t)cbWrite; 2999 if (offPhys != 0 && offVirt != 0) 3000 { 3001 if (cbRange > offPhys) 3002 cbRange = offPhys; 3003 if (cbRange > offVirt) 3004 cbRange = offVirt; 3005 Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] miss\n", GCPhys, cbRange, pPage)); 3006 } 2820 3007 2821 /* 3008 2822 * Physical handler. 3009 2823 */ 3010 else if (!offPhys && offVirt)2824 if (!offPhys) 3011 2825 { 3012 2826 #ifndef IN_RING3 … … 3017 2831 if (cbRange > offPhysLast + 1) 3018 2832 cbRange = offPhysLast + 1; 3019 if (cbRange > offVirt)3020 cbRange = offVirt;3021 2833 3022 2834 PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pPhys)->CTX_SUFF(pfnHandler); … … 3043 2855 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pPhys ? R3STRING(pPhys->pszDesc) : "")); 3044 2856 } 3045 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)3046 /*3047 * Virtual handler.3048 */3049 else if (offPhys && !offVirt)3050 {3051 # ifndef IN_RING33052 if (enmOrigin != PGMACCESSORIGIN_IEM)3053 /* Cannot reliably handle informational status codes in this context */3054 return VERR_PGM_PHYS_WR_HIT_HANDLER;3055 # endif3056 if (cbRange > offVirtLast + 1)3057 cbRange = offVirtLast + 1;3058 if (cbRange > offPhys)3059 cbRange = offPhys;3060 3061 PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);3062 Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", GCPhys, cbRange, pPage, R3STRING(pVirt->pszDesc) ));3063 Assert(pVirtType->CTX_SUFF(pfnHandler));3064 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)3065 + (iVirtPage << PAGE_SHIFT)3066 + (GCPhys & PAGE_OFFSET_MASK);3067 STAM_PROFILE_START(&pVirt->Stat, h);3068 rcStrict2 = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE,3069 enmOrigin, pVirt->CTX_SUFF(pvUser));3070 STAM_PROFILE_STOP(&pVirt->Stat, h);3071 AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict2, true),3072 ("rcStrict2=%Rrc (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n", VBOXSTRICTRC_VAL(rcStrict2),3073 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pPhys ? R3STRING(pPhys->pszDesc) : ""));3074 pVirt = NULL;3075 }3076 /*3077 * Both... give the physical one priority.3078 */3079 else3080 {3081 # ifndef IN_RING33082 if (enmOrigin != PGMACCESSORIGIN_IEM)3083 /* Cannot reliably handle informational status codes in this context */3084 return VERR_PGM_PHYS_WR_HIT_HANDLER;3085 # endif3086 Assert(!offPhys && !offVirt);3087 if (cbRange > offVirtLast + 1)3088 cbRange = offVirtLast + 1;3089 if (cbRange > offPhysLast + 1)3090 cbRange = offPhysLast + 1;3091 3092 PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);3093 if (pVirtType->pfnHandlerR3)3094 Log(("pgmPhysWriteHandler: overlapping phys and virt handlers at %RGp %R[pgmpage]; cbRange=%#x\n", GCPhys, pPage, cbRange));3095 Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys/virt %s/%s\n", GCPhys, cbRange, pPage, R3STRING(pPhys->pszDesc), R3STRING(pVirt->pszDesc) ));3096 3097 PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pPhys)->CTX_SUFF(pfnHandler);3098 void *pvUser = pPhys->CTX_SUFF(pvUser);3099 STAM_PROFILE_START(&pPhys->Stat, h);3100 3101 /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */3102 PGM_LOCK_ASSERT_OWNER(pVM);3103 pgmUnlock(pVM);3104 rcStrict2 = pfnHandler(pVM, pVCpu, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, enmOrigin, pvUser);3105 pgmLock(pVM);3106 3107 # ifdef VBOX_WITH_STATISTICS3108 pPhys = pgmHandlerPhysicalLookup(pVM, GCPhys);3109 if (pPhys)3110 STAM_PROFILE_STOP(&pPhys->Stat, h);3111 # else3112 pPhys = NULL; /* might not be valid anymore. */3113 # endif3114 AssertLogRelMsg(PGM_HANDLER_PHYS_IS_VALID_STATUS(rcStrict2, true),3115 ("rcStrict2=%Rrc (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n", VBOXSTRICTRC_VAL(rcStrict2),3116 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pPhys ? R3STRING(pPhys->pszDesc) : ""));3117 if (rcStrict2 == VINF_PGM_HANDLER_DO_DEFAULT || PGM_PHYS_RW_IS_SUCCESS(rcStrict2))3118 {3119 Assert(pVirtType->CTX_SUFF(pfnHandler));3120 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)3121 + (iVirtPage << PAGE_SHIFT)3122 + (GCPhys & PAGE_OFFSET_MASK);3123 pvUser = pVirt->CTX_SUFF(pvUser);3124 3125 STAM_PROFILE_START(&pVirt->Stat, h2);3126 VBOXSTRICTRC rcStrict3 = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, pvDst, (void *)pvBuf, cbRange,3127 PGMACCESSTYPE_WRITE, enmOrigin, pvUser);3128 STAM_PROFILE_STOP(&pVirt->Stat, h2);3129 3130 /* Merge the 3rd status into the 2nd. */3131 if (rcStrict3 == VINF_SUCCESS)3132 {3133 if (rcStrict2 == VINF_PGM_HANDLER_DO_DEFAULT)3134 rcStrict2 = VINF_SUCCESS;3135 }3136 else if (rcStrict3 != VINF_PGM_HANDLER_DO_DEFAULT)3137 {3138 AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict3, true),3139 ("rcStrict3=%Rrc (rcStrict2=%Rrc) (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n",3140 VBOXSTRICTRC_VAL(rcStrict3), VBOXSTRICTRC_VAL(rcStrict2), VBOXSTRICTRC_VAL(rcStrict),3141 GCPhys, pPage, R3STRING(pVirt->pszDesc) ));3142 if (rcStrict2 == VINF_PGM_HANDLER_DO_DEFAULT)3143 rcStrict2 = rcStrict3;3144 else if (!PGM_PHYS_RW_IS_SUCCESS(rcStrict3))3145 rcStrict2 = rcStrict3;3146 else3147 PGM_PHYS_RW_DO_UPDATE_STRICT_RC(rcStrict2, rcStrict3);3148 }3149 }3150 pPhys = NULL;3151 pVirt = NULL;3152 }3153 #endif /* !IN_RING0 && VBOX_WITH_RAW_MODE */3154 3155 2857 3156 2858 /* … … 3187 2889 offPhys -= cbRange; 3188 2890 offPhysLast -= cbRange; 3189 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)3190 offVirt -= cbRange;3191 offVirtLast -= cbRange;3192 #endif3193 2891 } 3194 2892 } -
trunk/src/VBox/VMM/VMMR3/DBGF.cpp
r80050 r80163 2106 2106 /** @todo NEM: NMI injection */ 2107 2107 if (!HMIsEnabled(pVM)) 2108 return VERR_NOT_SUP_ IN_RAW_MODE;2108 return VERR_NOT_SUP_BY_NEM; 2109 2109 2110 2110 VMCPU_FF_SET(&pVM->aCpus[idCpu], VMCPU_FF_INTERRUPT_NMI); -
trunk/src/VBox/VMM/VMMR3/PGM.cpp
r80118 r80163 161 161 * 162 162 * 163 * @subsection sec_pgm_handlers_virt Virtual Access Handlers 163 * @subsection sec_pgm_handlers_virt Virtual Access Handlers (obsolete) 164 164 * 165 165 * We currently implement three types of virtual access handlers: ALL, WRITE … … 1346 1346 PGM_REG_COUNTER(&pStats->StatR3RamRangeTlbMisses, "/PGM/R3/RamRange/TlbMisses", "TLB misses."); 1347 1347 1348 PGM_REG_PROFILE(&pStats->StatRZSyncCR3HandlerVirtualUpdate, "/PGM/RZ/SyncCR3/Handlers/VirtualUpdate", "Profiling of the virtual handler updates.");1349 PGM_REG_PROFILE(&pStats->StatRZSyncCR3HandlerVirtualReset, "/PGM/RZ/SyncCR3/Handlers/VirtualReset", "Profiling of the virtual handler resets.");1350 PGM_REG_PROFILE(&pStats->StatR3SyncCR3HandlerVirtualUpdate, "/PGM/R3/SyncCR3/Handlers/VirtualUpdate", "Profiling of the virtual handler updates.");1351 PGM_REG_PROFILE(&pStats->StatR3SyncCR3HandlerVirtualReset, "/PGM/R3/SyncCR3/Handlers/VirtualReset", "Profiling of the virtual handler resets.");1352 1353 1348 PGM_REG_COUNTER(&pStats->StatRZPhysHandlerReset, "/PGM/RZ/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called."); 1354 1349 PGM_REG_COUNTER(&pStats->StatR3PhysHandlerReset, "/PGM/R3/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called."); … … 1357 1352 PGM_REG_COUNTER(&pStats->StatRZPhysHandlerLookupMisses, "/PGM/RZ/PhysHandlerLookupMisses", "The number of cache misses when looking up physical handlers."); 1358 1353 PGM_REG_COUNTER(&pStats->StatR3PhysHandlerLookupMisses, "/PGM/R3/PhysHandlerLookupMisses", "The number of cache misses when looking up physical handlers."); 1359 PGM_REG_PROFILE(&pStats->StatRZVirtHandlerSearchByPhys, "/PGM/RZ/VirtHandlerSearchByPhys", "Profiling of pgmHandlerVirtualFindByPhysAddr.");1360 PGM_REG_PROFILE(&pStats->StatR3VirtHandlerSearchByPhys, "/PGM/R3/VirtHandlerSearchByPhys", "Profiling of pgmHandlerVirtualFindByPhysAddr.");1361 1354 1362 1355 PGM_REG_COUNTER(&pStats->StatRZPageReplaceShared, "/PGM/RZ/Page/ReplacedShared", "Times a shared page was replaced."); … … 1444 1437 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2GuestTrap, "/PGM/CPU%u/RZ/Trap0e/Time2/GuestTrap", "Profiling of the Trap0eHandler body when the cause is a guest trap."); 1445 1438 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerPhysical", "Profiling of the Trap0eHandler body when the cause is a physical handler."); 1446 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndVirt, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerVirtual", "Profiling of the Trap0eHandler body when the cause is a virtual handler.");1447 1439 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndUnhandled, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerUnhandled", "Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page."); 1448 1440 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2InvalidPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/InvalidPhys", "Profiling of the Trap0eHandler body when the cause is access to an invalid physical guest address."); … … 1452 1444 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSync, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSync", "Profiling of the Trap0eHandler body when the cause is an out-of-sync page."); 1453 1445 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndPhys", "Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page."); 1454 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndVirt, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndVirt", "Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page.");1455 1446 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndObs, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncObsHnd", "Profiling of the Trap0eHandler body when the cause is an obsolete handler page."); 1456 1447 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2SyncPT, "/PGM/CPU%u/RZ/Trap0e/Time2/SyncPT", "Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT."); … … 1464 1455 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysAllOpt, "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysAllOpt", "Number of the physical all-access handler traps using the optimization."); 1465 1456 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysWrite, "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysWrite", "Number of traps due to physical write-access handlers."); 1466 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersVirtual, "/PGM/CPU%u/RZ/Trap0e/Handlers/Virtual", "Number of traps due to virtual access handlers.");1467 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersVirtualByPhys, "/PGM/CPU%u/RZ/Trap0e/Handlers/VirtualByPhys", "Number of traps due to virtual access handlers by physical address.");1468 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersVirtualUnmarked,"/PGM/CPU%u/RZ/Trap0e/Handlers/VirtualUnmarked","Number of traps due to virtual access handlers by virtual address (without proper physical flags).");1469 1457 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersUnhandled, "/PGM/CPU%u/RZ/Trap0e/Handlers/Unhandled", "Number of traps due to access outside range of monitored page(s)."); 1470 1458 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersInvalid, "/PGM/CPU%u/RZ/Trap0e/Handlers/Invalid", "Number of traps due to access to invalid physical memory."); … … 2197 2185 pVCpu->pgm.s.GCPhysA20Mask = ~((RTGCPHYS)!pVCpu->pgm.s.fA20Enabled << 20); 2198 2186 #ifdef PGM_WITH_A20 2199 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;2200 2187 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3); 2201 2188 pgmR3RefreshShadowModeAfterA20Change(pVCpu); -
trunk/src/VBox/VMM/VMMR3/PGMHandler.cpp
r80007 r80163 333 333 } 334 334 335 #ifdef VBOX_WITH_RAW_MODE336 337 /**338 * Register a virtual page access handler type, extended version.339 *340 * @returns VBox status code.341 * @param pVM The cross context VM structure.342 * @param enmKind The kind of access handler.343 * @param fRelocUserRC Whether the pvUserRC argument should be344 * automatically relocated or not.345 * @param pfnInvalidateR3 Pointer to the ring-3 invalidation handler callback.346 * Warning! This callback stopped working in VBox v1.2!347 * @param pfnHandlerR3 Pointer to the ring-3 handler callback.348 * @param pfnHandlerRC Pointer to the raw-mode context handler callback.349 * @param pfnPfHandlerRC Pointer to the raw-mode context \#PF handler350 * callback.351 * @param pszDesc The type description.352 * @param phType Where to return the type handle (cross context353 * safe).354 * @remarks No virtual handlers when executing using HM (i.e. ring-0).355 */356 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegisterEx(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,357 PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,358 PFNPGMVIRTHANDLER pfnHandlerR3,359 RCPTRTYPE(FNPGMVIRTHANDLER) pfnHandlerRC,360 RCPTRTYPE(FNPGMRCVIRTPFHANDLER) pfnPfHandlerRC,361 const char *pszDesc, PPGMVIRTHANDLERTYPE phType)362 {363 AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_NOT_AVAILABLE); /* Only supported/relevant for raw-mode. */364 AssertReturn( enmKind == PGMVIRTHANDLERKIND_WRITE365 || enmKind == PGMVIRTHANDLERKIND_ALL366 || enmKind == PGMVIRTHANDLERKIND_HYPERVISOR,367 VERR_INVALID_PARAMETER);368 if (enmKind != PGMVIRTHANDLERKIND_HYPERVISOR)369 {370 AssertPtrNullReturn(pfnInvalidateR3, VERR_INVALID_POINTER);371 AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);372 AssertReturn(pfnHandlerRC != NIL_RTRCPTR, VERR_INVALID_POINTER);373 }374 else375 {376 AssertReturn(pfnInvalidateR3 == NULL, VERR_INVALID_POINTER);377 AssertReturn(pfnHandlerR3 == NULL, VERR_INVALID_POINTER);378 AssertReturn(pfnHandlerRC == NIL_RTR0PTR, VERR_INVALID_POINTER);379 }380 AssertReturn(pfnPfHandlerRC != NIL_RTRCPTR, VERR_INVALID_POINTER);381 AssertPtrReturn(pszDesc, VERR_INVALID_POINTER);382 383 PPGMVIRTHANDLERTYPEINT pType;384 int rc = MMHyperAlloc(pVM, sizeof(*pType), 0, MM_TAG_PGM_HANDLER_TYPES, (void **)&pType);385 if (RT_SUCCESS(rc))386 {387 pType->u32Magic = PGMVIRTHANDLERTYPEINT_MAGIC;388 pType->cRefs = 1;389 pType->enmKind = enmKind;390 pType->fRelocUserRC = fRelocUserRC;391 pType->uState = enmKind == PGMVIRTHANDLERKIND_ALL392 ? PGM_PAGE_HNDL_VIRT_STATE_ALL : PGM_PAGE_HNDL_VIRT_STATE_WRITE;393 pType->pfnInvalidateR3 = pfnInvalidateR3;394 pType->pfnHandlerR3 = pfnHandlerR3;395 pType->pfnHandlerRC = pfnHandlerRC;396 pType->pfnPfHandlerRC = pfnPfHandlerRC;397 pType->pszDesc = pszDesc;398 399 pgmLock(pVM);400 RTListOff32Append(&pVM->pgm.s.CTX_SUFF(pTrees)->HeadVirtHandlerTypes, &pType->ListNode);401 pgmUnlock(pVM);402 403 *phType = MMHyperHeapPtrToOffset(pVM, pType);404 LogFlow(("PGMR3HandlerVirtualTypeRegisterEx: %p/%#x: enmKind=%d pfnInvalidateR3=%RHv pfnHandlerR3=%RHv pfnPfHandlerRC=%RRv pszDesc=%s\n",405 pType, *phType, enmKind, pfnInvalidateR3, pfnHandlerR3, pfnPfHandlerRC, pszDesc));406 return VINF_SUCCESS;407 }408 *phType = NIL_PGMVIRTHANDLERTYPE;409 return rc;410 }411 412 413 /**414 * Register a physical page access handler type.415 *416 * @returns VBox status code.417 * @param pVM The cross context VM structure.418 * @param enmKind The kind of access handler.419 * @param fRelocUserRC Whether the pvUserRC argument should be420 * automatically relocated or not.421 * @param pfnInvalidateR3 Pointer to the ring-3 invalidateion callback422 * (optional, can be NULL).423 * @param pfnHandlerR3 Pointer to the ring-3 handler callback.424 * @param pszHandlerRC The name of the raw-mode context handler callback425 * (in VMMRC.rc).426 * @param pszPfHandlerRC The name of the raw-mode context \#PF handler (in427 * VMMRC.rc).428 * @param pszDesc The type description.429 * @param phType Where to return the type handle (cross context430 * safe).431 * @remarks No virtual handlers when executing using HM (i.e. ring-0).432 */433 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegister(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,434 PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,435 PFNPGMVIRTHANDLER pfnHandlerR3,436 const char *pszHandlerRC, const char *pszPfHandlerRC, const char *pszDesc,437 PPGMVIRTHANDLERTYPE phType)438 {439 LogFlow(("PGMR3HandlerVirtualTypeRegister: enmKind=%d pfnInvalidateR3=%RHv pfnHandlerR3=%RHv pszPfHandlerRC=%s pszDesc=%s\n",440 enmKind, pfnInvalidateR3, pfnHandlerR3, pszPfHandlerRC, pszDesc));441 442 /*443 * Validate input.444 */445 AssertPtrNullReturn(pszHandlerRC, VERR_INVALID_POINTER);446 AssertPtrReturn(pszPfHandlerRC, VERR_INVALID_POINTER);447 448 /*449 * Resolve the GC handler.450 */451 RTRCPTR pfnHandlerRC = NIL_RTRCPTR;452 int rc = VINF_SUCCESS;453 if (pszHandlerRC)454 rc = PDMR3LdrGetSymbolRCLazy(pVM, VMMRC_MAIN_MODULE_NAME, NULL /*pszSearchPath*/, pszHandlerRC, &pfnHandlerRC);455 if (RT_SUCCESS(rc))456 {457 RTRCPTR pfnPfHandlerRC = NIL_RTRCPTR;458 rc = PDMR3LdrGetSymbolRCLazy(pVM, VMMRC_MAIN_MODULE_NAME, NULL /*pszSearchPath*/, pszPfHandlerRC, &pfnPfHandlerRC);459 if (RT_SUCCESS(rc))460 return PGMR3HandlerVirtualTypeRegisterEx(pVM, enmKind, fRelocUserRC,461 pfnInvalidateR3, pfnHandlerR3,462 pfnHandlerRC, pfnPfHandlerRC,463 pszDesc, phType);464 465 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", VMMRC_MAIN_MODULE_NAME, pszPfHandlerRC, rc));466 }467 else468 AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", VMMRC_MAIN_MODULE_NAME, pszHandlerRC, rc));469 return rc;470 }471 472 473 /**474 * Register a access handler for a virtual range.475 *476 * @returns VBox status code.477 * @param pVM The cross context VM structure.478 * @param pVCpu The cross context virtual CPU structure of the479 * calling EMT.480 * @param hType The handler type.481 * @param GCPtr Start address.482 * @param GCPtrLast Last address (inclusive).483 * @param pvUserR3 The ring-3 context user argument.484 * @param pvUserRC The raw-mode context user argument. Whether this is485 * automatically relocated or not depends on the type.486 * @param pszDesc Pointer to description string. This must not be freed.487 */488 VMMR3_INT_DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PVMCPU pVCpu, PGMVIRTHANDLERTYPE hType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,489 void *pvUserR3, RTRCPTR pvUserRC, const char *pszDesc)490 {491 AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_NOT_AVAILABLE); /* Only supported/relevant for raw-mode. */492 PPGMVIRTHANDLERTYPEINT pType = PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hType);493 Log(("PGMR3HandlerVirtualRegister: GCPhys=%RGp GCPhysLast=%RGp pvUserR3=%RHv pvUserGC=%RRv hType=%#x (%d, %s) pszDesc=%RHv:%s\n",494 GCPtr, GCPtrLast, pvUserR3, pvUserRC, hType, pType->enmKind, R3STRING(pType->pszDesc), pszDesc, R3STRING(pszDesc)));495 496 /*497 * Validate input.498 */499 AssertReturn(pType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, VERR_INVALID_HANDLE);500 AssertMsgReturn(GCPtr < GCPtrLast, ("GCPtr >= GCPtrLast (%RGp >= %RGp)\n", GCPtr, GCPtrLast), VERR_INVALID_PARAMETER);501 switch (pType->enmKind)502 {503 case PGMVIRTHANDLERKIND_ALL:504 /* Simplification for PGMPhysRead and others: Full pages. */505 AssertReleaseMsgReturn( (GCPtr & PAGE_OFFSET_MASK) == 0506 && (GCPtrLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK,507 ("PGMVIRTHANDLERKIND_ALL: GCPtr=%RGv GCPtrLast=%RGv\n", GCPtr, GCPtrLast),508 VERR_NOT_IMPLEMENTED);509 break;510 case PGMVIRTHANDLERKIND_WRITE:511 case PGMVIRTHANDLERKIND_HYPERVISOR:512 break;513 default:514 AssertMsgFailedReturn(("Invalid enmKind=%d!\n", pType->enmKind), VERR_INVALID_PARAMETER);515 }516 AssertMsgReturn( (RTRCUINTPTR)pvUserRC < 0x10000517 || MMHyperR3ToRC(pVM, MMHyperRCToR3(pVM, pvUserRC)) == pvUserRC,518 ("Not RC pointer! pvUserRC=%RRv\n", pvUserRC),519 VERR_INVALID_PARAMETER);520 521 /*522 * Allocate and initialize a new entry.523 */524 unsigned cPages = (RT_ALIGN(GCPtrLast + 1, PAGE_SIZE) - (GCPtr & PAGE_BASE_GC_MASK)) >> PAGE_SHIFT;525 PPGMVIRTHANDLER pNew;526 int rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMVIRTHANDLER, aPhysToVirt[cPages]), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew); /** @todo r=bird: incorrect member name PhysToVirt? */527 if (RT_FAILURE(rc))528 return rc;529 530 pNew->Core.Key = GCPtr;531 pNew->Core.KeyLast = GCPtrLast;532 533 pNew->hType = hType;534 pNew->pvUserRC = pvUserRC;535 pNew->pvUserR3 = pvUserR3;536 pNew->pszDesc = pszDesc ? pszDesc : pType->pszDesc;537 pNew->cb = GCPtrLast - GCPtr + 1;538 pNew->cPages = cPages;539 /* Will be synced at next guest execution attempt. */540 while (cPages-- > 0)541 {542 pNew->aPhysToVirt[cPages].Core.Key = NIL_RTGCPHYS;543 pNew->aPhysToVirt[cPages].Core.KeyLast = NIL_RTGCPHYS;544 pNew->aPhysToVirt[cPages].offVirtHandler = -(int32_t)RT_UOFFSETOF_DYN(PGMVIRTHANDLER, aPhysToVirt[cPages]);545 pNew->aPhysToVirt[cPages].offNextAlias = 0;546 }547 548 /*549 * Try to insert it into the tree.550 *551 * The current implementation doesn't allow multiple handlers for552 * the same range this makes everything much simpler and faster.553 */554 AVLROGCPTRTREE *pRoot = pType->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR555 ? &pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers556 : &pVM->pgm.s.CTX_SUFF(pTrees)->HyperVirtHandlers;557 pgmLock(pVM);558 if (*pRoot != 0)559 {560 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(pRoot, pNew->Core.Key, true);561 if ( !pCur562 || GCPtr > pCur->Core.KeyLast563 || GCPtrLast < pCur->Core.Key)564 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(pRoot, pNew->Core.Key, false);565 if ( pCur566 && GCPtr <= pCur->Core.KeyLast567 && GCPtrLast >= pCur->Core.Key)568 {569 /*570 * The LDT sometimes conflicts with the IDT and LDT ranges while being571 * updated on linux. So, we don't assert simply log it.572 */573 Log(("PGMR3HandlerVirtualRegister: Conflict with existing range %RGv-%RGv (%s), req. %RGv-%RGv (%s)\n",574 pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc, GCPtr, GCPtrLast, pszDesc));575 MMHyperFree(pVM, pNew);576 pgmUnlock(pVM);577 return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;578 }579 }580 if (RTAvlroGCPtrInsert(pRoot, &pNew->Core))581 {582 if (pType->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR)583 {584 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;585 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);586 }587 PGMHandlerVirtualTypeRetain(pVM, hType);588 pgmUnlock(pVM);589 590 #ifdef VBOX_WITH_STATISTICS591 rc = STAMR3RegisterF(pVM, &pNew->Stat, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pNew->pszDesc,592 "/PGM/VirtHandler/Calls/%RGv-%RGv", pNew->Core.Key, pNew->Core.KeyLast);593 AssertRC(rc);594 #endif595 return VINF_SUCCESS;596 }597 598 pgmUnlock(pVM);599 AssertFailed();600 MMHyperFree(pVM, pNew);601 return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;602 603 }604 605 606 /**607 * Changes the type of a virtual handler.608 *609 * The new and old type must have the same access kind.610 *611 * @returns VBox status code.612 * @param pVM The cross context VM structure.613 * @param GCPtr Start address of the virtual handler.614 * @param hNewType The new handler type.615 */616 VMMR3_INT_DECL(int) PGMHandlerVirtualChangeType(PVM pVM, RTGCPTR GCPtr, PGMVIRTHANDLERTYPE hNewType)617 {618 PPGMVIRTHANDLERTYPEINT pNewType = PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hNewType);619 AssertReturn(pNewType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, VERR_INVALID_HANDLE);620 621 pgmLock(pVM);622 PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.pTreesR3->VirtHandlers, GCPtr);623 if (pCur)624 {625 PGMVIRTHANDLERTYPE hOldType = pCur->hType;626 PPGMVIRTHANDLERTYPEINT pOldType = PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hOldType);627 if (pOldType != pNewType)628 {629 AssertReturnStmt(pNewType->enmKind == pOldType->enmKind, pgmUnlock(pVM), VERR_ACCESS_DENIED);630 PGMHandlerVirtualTypeRetain(pVM, hNewType);631 pCur->hType = hNewType;632 PGMHandlerVirtualTypeRelease(pVM, hOldType);633 }634 pgmUnlock(pVM);635 return VINF_SUCCESS;636 }637 pgmUnlock(pVM);638 AssertMsgFailed(("Range %#x not found!\n", GCPtr));639 return VERR_INVALID_PARAMETER;640 }641 642 643 /**644 * Deregister an access handler for a virtual range.645 *646 * @returns VBox status code.647 * @param pVM The cross context VM structure.648 * @param pVCpu The cross context virtual CPU structure of the calling649 * EMT.650 * @param GCPtr Start address.651 * @param fHypervisor Set if PGMVIRTHANDLERKIND_HYPERVISOR, false if not.652 * @thread EMT(pVCpu)653 */654 VMMR3_INT_DECL(int) PGMHandlerVirtualDeregister(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, bool fHypervisor)655 {656 pgmLock(pVM);657 658 PPGMVIRTHANDLER pCur;659 if (!fHypervisor)660 {661 /*662 * Normal guest handler.663 */664 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtr);665 AssertMsgReturnStmt(pCur, ("GCPtr=%RGv\n", GCPtr), pgmUnlock(pVM), VERR_INVALID_PARAMETER);666 Assert(PGMVIRTANDLER_GET_TYPE(pVM, pCur)->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR);667 668 Log(("PGMHandlerVirtualDeregister: Removing Virtual (%d) Range %RGv-%RGv %s\n",669 PGMVIRTANDLER_GET_TYPE(pVM, pCur)->enmKind, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));670 671 /* Reset the flags and remove phys2virt nodes. */672 for (uint32_t iPage = 0; iPage < pCur->cPages; iPage++)673 if (pCur->aPhysToVirt[iPage].offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE)674 pgmHandlerVirtualClearPage(pVM, pCur, iPage);675 676 /* Schedule CR3 sync. */677 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;678 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);679 }680 else681 {682 /*683 * Hypervisor one (hypervisor relocation or termination only).684 */685 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->HyperVirtHandlers, GCPtr);686 AssertMsgReturnStmt(pCur, ("GCPtr=%RGv\n", GCPtr), pgmUnlock(pVM), VERR_INVALID_PARAMETER);687 Assert(PGMVIRTANDLER_GET_TYPE(pVM, pCur)->enmKind == PGMVIRTHANDLERKIND_HYPERVISOR);688 689 Log(("PGMHandlerVirtualDeregister: Removing Hyper Virtual Range %RGv-%RGv %s\n",690 pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));691 }692 693 pgmUnlock(pVM);694 695 /*696 * Free it.697 */698 #ifdef VBOX_WITH_STATISTICS699 STAMR3DeregisterF(pVM->pUVM, "/PGM/VirtHandler/Calls/%RGv-%RGv", pCur->Core.Key, pCur->Core.KeyLast);700 #endif701 PGMHandlerVirtualTypeRelease(pVM, pCur->hType);702 MMHyperFree(pVM, pCur);703 704 return VINF_SUCCESS;705 }706 707 #endif /* VBOX_WITH_RAW_MODE */708 709 335 710 336 /** -
trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp
r80161 r80163 4794 4794 NEMR3NotifySetA20(pVCpu, fEnable); 4795 4795 #ifdef PGM_WITH_A20 4796 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;4797 4796 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3); 4798 4797 pgmR3RefreshShadowModeAfterA20Change(pVCpu); -
trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp
r80074 r80163 3174 3174 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL); 3175 3175 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3); 3176 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;3177 3176 /** @todo For guest PAE, we might get the wrong 3178 3177 * aGCPhysGstPaePDs values now. We should used the … … 3261 3260 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL); 3262 3261 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3); 3263 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;3264 3262 } 3265 3263 } -
trunk/src/VBox/VMM/include/PGMInline.h
r80135 r80163 1261 1261 1262 1262 1263 #ifdef VBOX_WITH_RAW_MODE1264 /**1265 * Clears one physical page of a virtual handler.1266 *1267 * @param pVM The cross context VM structure.1268 * @param pCur Virtual handler structure.1269 * @param iPage Physical page index.1270 *1271 * @remark Only used when PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL is being set, so no1272 * need to care about other handlers in the same page.1273 */1274 DECLINLINE(void) pgmHandlerVirtualClearPage(PVM pVM, PPGMVIRTHANDLER pCur, unsigned iPage)1275 {1276 const PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];1277 1278 /*1279 * Remove the node from the tree (it's supposed to be in the tree if we get here!).1280 */1281 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1282 AssertReleaseMsg(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,1283 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",1284 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));1285 # endif1286 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD)1287 {1288 /* We're the head of the alias chain. */1289 PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);1290 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1291 AssertReleaseMsg(pRemove != NULL,1292 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",1293 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));1294 AssertReleaseMsg(pRemove == pPhys2Virt,1295 ("wanted: pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"1296 " got: pRemove=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",1297 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,1298 pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));1299 # endif1300 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)1301 {1302 /* Insert the next list in the alias chain into the tree. */1303 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));1304 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1305 AssertReleaseMsg(pNext->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,1306 ("pNext=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",1307 pNext, pNext->Core.Key, pNext->Core.KeyLast, pNext->offVirtHandler, pNext->offNextAlias));1308 # endif1309 pNext->offNextAlias |= PGMPHYS2VIRTHANDLER_IS_HEAD;1310 bool fRc = RTAvlroGCPhysInsert(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, &pNext->Core);1311 AssertRelease(fRc);1312 }1313 }1314 else1315 {1316 /* Locate the previous node in the alias chain. */1317 PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);1318 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1319 AssertReleaseMsg(pPrev != pPhys2Virt,1320 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",1321 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));1322 # endif1323 for (;;)1324 {1325 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));1326 if (pNext == pPhys2Virt)1327 {1328 /* unlink. */1329 LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%RGp-%RGp]\n",1330 pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));1331 if (!(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))1332 pPrev->offNextAlias &= ~PGMPHYS2VIRTHANDLER_OFF_MASK;1333 else1334 {1335 PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));1336 pPrev->offNextAlias = ((intptr_t)pNewNext - (intptr_t)pPrev)1337 | (pPrev->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);1338 }1339 break;1340 }1341 1342 /* next */1343 if (pNext == pPrev)1344 {1345 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL1346 AssertReleaseMsg(pNext != pPrev,1347 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",1348 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));1349 # endif1350 break;1351 }1352 pPrev = pNext;1353 }1354 }1355 Log2(("PHYS2VIRT: Removing %RGp-%RGp %#RX32 %s\n",1356 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));1357 pPhys2Virt->offNextAlias = 0;1358 pPhys2Virt->Core.KeyLast = NIL_RTGCPHYS; /* require reinsert */1359 1360 /*1361 * Clear the ram flags for this page.1362 */1363 PPGMPAGE pPage = pgmPhysGetPage(pVM, pPhys2Virt->Core.Key);1364 AssertReturnVoid(pPage);1365 PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, PGM_PAGE_HNDL_VIRT_STATE_NONE);1366 }1367 #endif /* VBOX_WITH_RAW_MODE */1368 1369 1370 1263 /** 1371 1264 * Internal worker for finding a 'in-use' shadow page give by it's physical address. -
trunk/src/VBox/VMM/include/PGMInternal.h
r80135 r80163 694 694 695 695 696 #ifdef VBOX_WITH_RAW_MODE697 698 /**699 * Cache node for the physical addresses covered by a virtual handler.700 */701 typedef struct PGMPHYS2VIRTHANDLER702 {703 /** Core node for the tree based on physical ranges. */704 AVLROGCPHYSNODECORE Core;705 /** Offset from this struct to the PGMVIRTHANDLER structure. */706 int32_t offVirtHandler;707 /** Offset of the next alias relative to this one.708 * Bit 0 is used for indicating whether we're in the tree.709 * Bit 1 is used for indicating that we're the head node.710 */711 int32_t offNextAlias;712 } PGMPHYS2VIRTHANDLER;713 /** Pointer to a phys to virtual handler structure. */714 typedef PGMPHYS2VIRTHANDLER *PPGMPHYS2VIRTHANDLER;715 716 /** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the717 * node is in the tree. */718 # define PGMPHYS2VIRTHANDLER_IN_TREE RT_BIT(0)719 /** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the720 * node is in the head of an alias chain.721 * The PGMPHYS2VIRTHANDLER_IN_TREE is always set if this bit is set. */722 # define PGMPHYS2VIRTHANDLER_IS_HEAD RT_BIT(1)723 /** The mask to apply to PGMPHYS2VIRTHANDLER::offNextAlias to get the offset. */724 # define PGMPHYS2VIRTHANDLER_OFF_MASK (~(int32_t)3)725 726 727 /**728 * Virtual page access handler type registration.729 */730 typedef struct PGMVIRTANDLERTYPEINT731 {732 /** Number of references. */733 uint32_t volatile cRefs;734 /** Magic number (PGMVIRTHANDLERTYPEINT_MAGIC). */735 uint32_t u32Magic;736 /** Link of handler types anchored in PGMTREES::HeadVirtHandlerTypes. */737 RTLISTOFF32NODE ListNode;738 /** The kind of accesses we're handling. */739 PGMVIRTHANDLERKIND enmKind;740 /** The PGM_PAGE_HNDL_PHYS_STATE_XXX value corresponding to enmKind. */741 uint32_t uState;742 /** Whether the pvUserRC argument should be automatically relocated or not. */743 bool fRelocUserRC;744 bool afPadding[HC_ARCH_BITS == 64 ? 7 : 3];745 /** Pointer to RC callback function. */746 RCPTRTYPE(PFNPGMVIRTHANDLER) pfnHandlerRC;747 /** Pointer to RC callback function for \#PFs. */748 RCPTRTYPE(PFNPGMRCVIRTPFHANDLER) pfnPfHandlerRC;749 /** Pointer to the R3 callback function for invalidation. */750 R3PTRTYPE(PFNPGMR3VIRTINVALIDATE) pfnInvalidateR3;751 /** Pointer to R3 callback function. */752 R3PTRTYPE(PFNPGMVIRTHANDLER) pfnHandlerR3;753 /** Description / Name. For easing debugging. */754 R3PTRTYPE(const char *) pszDesc;755 } PGMVIRTHANDLERTYPEINT;756 /** Pointer to a virtual access handler type registration. */757 typedef PGMVIRTHANDLERTYPEINT *PPGMVIRTHANDLERTYPEINT;758 /** Magic value for the virtual handler callbacks (Sir Arthur Charles Clarke). */759 # define PGMVIRTHANDLERTYPEINT_MAGIC UINT32_C(0x19171216)760 /** Magic value for the virtual handler callbacks. */761 # define PGMVIRTHANDLERTYPEINT_MAGIC_DEAD UINT32_C(0x20080319)762 763 /**764 * Converts a handle to a pointer.765 * @returns PPGMVIRTHANDLERTYPEINT766 * @param a_pVM The cross context VM structure.767 * @param a_hType Vitual access handler type handle.768 */769 # define PGMVIRTHANDLERTYPEINT_FROM_HANDLE(a_pVM, a_hType) ((PPGMVIRTHANDLERTYPEINT)MMHyperHeapOffsetToPtr(a_pVM, a_hType))770 771 772 /**773 * Virtual page access handler structure.774 *775 * This is used to keep track of virtual address ranges776 * which are being monitored in some kind of way.777 */778 typedef struct PGMVIRTHANDLER779 {780 /** Core node for the tree based on virtual ranges. */781 AVLROGCPTRNODECORE Core;782 /** Size of the range (in bytes). */783 uint32_t cb;784 /** Number of cache pages. */785 uint32_t cPages;786 /** Registered handler type handle (heap offset). */787 PGMVIRTHANDLERTYPE hType;788 /** User argument for RC handlers. */789 RCPTRTYPE(void *) pvUserRC;790 /** User argument for R3 handlers. */791 R3PTRTYPE(void *) pvUserR3;792 /** Description / Name. For easing debugging. */793 R3PTRTYPE(const char *) pszDesc;794 # ifdef VBOX_WITH_STATISTICS795 /** Profiling of this handler. */796 STAMPROFILE Stat;797 # endif798 /** Array of cached physical addresses for the monitored ranged. */799 PGMPHYS2VIRTHANDLER aPhysToVirt[HC_ARCH_BITS == 32 ? 1 : 2];800 } PGMVIRTHANDLER;801 /** Pointer to a virtual page access handler structure. */802 typedef PGMVIRTHANDLER *PPGMVIRTHANDLER;803 804 /**805 * Gets the type record for a virtual handler (no reference added).806 * @returns PPGMVIRTHANDLERTYPEINT807 * @param a_pVM The cross context VM structure.808 * @param a_pVirtHandler Pointer to the virtual handler structure809 * (PGMVIRTHANDLER).810 */811 # define PGMVIRTANDLER_GET_TYPE(a_pVM, a_pVirtHandler) PGMVIRTHANDLERTYPEINT_FROM_HANDLE(a_pVM, (a_pVirtHandler)->hType)812 813 #endif /* VBOX_WITH_RAW_MODE */814 815 816 696 /** 817 697 * A Physical Guest Page tracking structure. … … 840 720 /** 7:6 - Unused. */ 841 721 uint64_t u2Unused0 : 2; 842 /** 9:8 - The physical handler state (PGM_PAGE_HNDL_VIRT_STATE_*). */843 uint64_t u2 HandlerVirtStateY: 2;722 /** 9:8 - Unused (was used by PGM_PAGE_HNDL_VIRT_STATE_*). */ 723 uint64_t u2Unused1 : 2; 844 724 /** 11:10 - NEM state bits. */ 845 725 uint64_t u2NemStateY : 2; … … 1205 1085 #define PGM_PAGE_GET_PDE_TYPE(a_pPage) ( (a_pPage)->s.u2PDETypeY ) 1206 1086 1207 /** Enabled optimized access handler tests.1208 * These optimizations makes ASSUMPTIONS about the state values and the s11209 * layout. When enabled, the compiler should normally generate more compact1210 * code.1211 */1212 #define PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS 11213 1214 1087 /** @name Physical Access Handler State values (PGMPAGE::u2HandlerPhysStateY). 1215 1088 * … … 1289 1162 1290 1163 /** 1291 * Checks if the page has any virtual access handlers.1292 * @returns true/false1293 * @param a_pPage Pointer to the physical guest page tracking structure.1294 */1295 #define PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS(a_pPage) \1296 ( PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) != PGM_PAGE_HNDL_VIRT_STATE_NONE )1297 1298 /**1299 1164 * Same as PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS - can't disable pages in 1300 1165 * virtual handlers. … … 1311 1176 * @param a_pPage Pointer to the physical guest page tracking structure. 1312 1177 */ 1313 #ifdef PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS 1314 # define PGM_PAGE_HAS_ANY_HANDLERS(a_pPage) \ 1315 ( ((a_pPage)->au32[0] & UINT16_C(0x0303)) != 0 ) 1316 #else 1317 # define PGM_PAGE_HAS_ANY_HANDLERS(a_pPage) \ 1318 ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) != PGM_PAGE_HNDL_PHYS_STATE_NONE \ 1319 || PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) != PGM_PAGE_HNDL_VIRT_STATE_NONE ) 1320 #endif 1178 #define PGM_PAGE_HAS_ANY_HANDLERS(a_pPage) \ 1179 ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) != PGM_PAGE_HNDL_PHYS_STATE_NONE ) 1321 1180 1322 1181 /** … … 1325 1184 * @param a_pPage Pointer to the physical guest page tracking structure. 1326 1185 */ 1327 #ifdef PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS 1328 # define PGM_PAGE_HAS_ACTIVE_HANDLERS(a_pPage) \ 1329 ( ((a_pPage)->au32[0] & UINT16_C(0x0202)) != 0 ) 1330 #else 1331 # define PGM_PAGE_HAS_ACTIVE_HANDLERS(a_pPage) \ 1332 ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) >= PGM_PAGE_HNDL_PHYS_STATE_WRITE \ 1333 || PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) >= PGM_PAGE_HNDL_VIRT_STATE_WRITE ) 1334 #endif 1186 #define PGM_PAGE_HAS_ACTIVE_HANDLERS(a_pPage) \ 1187 (PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) >= PGM_PAGE_HNDL_PHYS_STATE_WRITE ) 1335 1188 1336 1189 /** … … 1339 1192 * @param a_pPage Pointer to the physical guest page tracking structure. 1340 1193 */ 1341 #ifdef PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS 1342 # define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(a_pPage) \ 1343 ( ( ((a_pPage)->au8[0] | (a_pPage)->au8[1]) & UINT8_C(0x3) ) \ 1344 == PGM_PAGE_HNDL_PHYS_STATE_ALL ) 1345 #else 1346 # define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(a_pPage) \ 1347 ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) == PGM_PAGE_HNDL_PHYS_STATE_ALL \ 1348 || PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) == PGM_PAGE_HNDL_VIRT_STATE_ALL ) 1349 #endif 1194 #define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(a_pPage) \ 1195 ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) == PGM_PAGE_HNDL_PHYS_STATE_ALL ) 1350 1196 1351 1197 … … 3235 3081 STAMCOUNTER StatR3RamRangeTlbHits; /**< R3: RAM range TLB hits. */ 3236 3082 STAMCOUNTER StatR3RamRangeTlbMisses; /**< R3: RAM range TLB misses. */ 3237 STAMPROFILE StatRZSyncCR3HandlerVirtualReset; /**< RC/R0: Profiling of the virtual handler resets. */3238 STAMPROFILE StatRZSyncCR3HandlerVirtualUpdate; /**< RC/R0: Profiling of the virtual handler updates. */3239 STAMPROFILE StatR3SyncCR3HandlerVirtualReset; /**< R3: Profiling of the virtual handler resets. */3240 STAMPROFILE StatR3SyncCR3HandlerVirtualUpdate; /**< R3: Profiling of the virtual handler updates. */3241 3083 STAMCOUNTER StatR3PhysHandlerReset; /**< R3: The number of times PGMHandlerPhysicalReset is called. */ 3242 3084 STAMCOUNTER StatRZPhysHandlerReset; /**< RC/R0: The number of times PGMHandlerPhysicalReset is called. */ … … 3245 3087 STAMCOUNTER StatRZPhysHandlerLookupHits; /**< RC/R0: Number of cache hits when lookup up physical handlers. */ 3246 3088 STAMCOUNTER StatRZPhysHandlerLookupMisses; /**< RC/R0: Number of cache misses when looking up physical handlers */ 3247 STAMPROFILE StatRZVirtHandlerSearchByPhys; /**< RC/R0: Profiling of pgmHandlerVirtualFindByPhysAddr. */3248 STAMPROFILE StatR3VirtHandlerSearchByPhys; /**< R3: Profiling of pgmHandlerVirtualFindByPhysAddr. */3249 3089 STAMCOUNTER StatRZPageReplaceShared; /**< RC/R0: Times a shared page has been replaced by a private one. */ 3250 3090 STAMCOUNTER StatRZPageReplaceZero; /**< RC/R0: Times the zero page has been replaced by a private one. */ … … 3762 3602 STAMPROFILE StatRZTrap0eTime2GuestTrap; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a guest trap. */ 3763 3603 STAMPROFILE StatRZTrap0eTime2HndPhys; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a physical handler. */ 3764 STAMPROFILE StatRZTrap0eTime2HndVirt; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a virtual handler. */3765 3604 STAMPROFILE StatRZTrap0eTime2HndUnhandled; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page. */ 3766 3605 STAMPROFILE StatRZTrap0eTime2InvalidPhys; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is access to an invalid physical guest address. */ … … 3770 3609 STAMPROFILE StatRZTrap0eTime2OutOfSync; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync page. */ 3771 3610 STAMPROFILE StatRZTrap0eTime2OutOfSyncHndPhys; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page. */ 3772 STAMPROFILE StatRZTrap0eTime2OutOfSyncHndVirt; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page. */3773 3611 STAMPROFILE StatRZTrap0eTime2OutOfSyncHndObs; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an obsolete handler page. */ 3774 3612 STAMPROFILE StatRZTrap0eTime2SyncPT; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT. */ … … 3782 3620 STAMCOUNTER StatRZTrap0eHandlersPhysAllOpt; /**< RC/R0: Number of the physical all-access handler traps using the optimization. */ 3783 3621 STAMCOUNTER StatRZTrap0eHandlersPhysWrite; /**< RC/R0: Number of traps due to write-physical access handlers. */ 3784 STAMCOUNTER StatRZTrap0eHandlersVirtual; /**< RC/R0: Number of traps due to virtual access handlers. */3785 STAMCOUNTER StatRZTrap0eHandlersVirtualByPhys; /**< RC/R0: Number of traps due to virtual access handlers found by physical address. */3786 STAMCOUNTER StatRZTrap0eHandlersVirtualUnmarked;/**< RC/R0: Number of traps due to virtual access handlers found by virtual address (without proper physical flags). */3787 3622 STAMCOUNTER StatRZTrap0eHandlersUnhandled; /**< RC/R0: Number of traps due to access outside range of monitored page(s). */ 3788 3623 STAMCOUNTER StatRZTrap0eHandlersInvalid; /**< RC/R0: Number of traps due to access to invalid physical memory. */ … … 4157 3992 * @{ 4158 3993 */ 4159 /** Updates the virtual access handler state bit in PGMPAGE. */ 4160 #define PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL RT_BIT(0) 3994 /* 0 used to be PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL */ 4161 3995 /** Always sync CR3. */ 4162 3996 #define PGM_SYNC_ALWAYS RT_BIT(1) -
trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp
r80018 r80163 438 438 439 439 /* 440 * Check that the optimized access macros for PGMPAGE works correctly. 440 * Check that the optimized access macros for PGMPAGE works correctly (kind of 441 * obsolete after dropping raw-mode). 441 442 */ 442 443 PGMPAGE Page; … … 456 457 PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_WRITE); 457 458 CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE); 458 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);459 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);460 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == false);461 462 PGM_PAGE_CLEAR(&Page);463 PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_ALL);464 CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_ALL);465 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);466 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);467 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == true);468 469 PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_WRITE);470 CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_WRITE);471 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);472 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);473 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == false);474 475 476 PGM_PAGE_CLEAR(&Page);477 PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_ALL);478 PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_WRITE);479 CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_ALL);480 CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_WRITE);481 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);482 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);483 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == true);484 485 PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_WRITE);486 PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_ALL);487 CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);488 CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_ALL);489 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);490 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);491 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == true);492 493 PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_WRITE);494 PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_WRITE);495 CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);496 CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_WRITE);497 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);498 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);499 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == false);500 501 PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_NONE);502 CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);503 CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_NONE);504 459 CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true); 505 460 CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
Note:
See TracChangeset
for help on using the changeset viewer.