Changeset 81333 in vbox
- Timestamp:
- Oct 17, 2019 11:49:39 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/iom.h
r81197 r81333 155 155 #define IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE UINT32_C(0x00000200) 156 156 157 /** Pass the absolute physical address (GC) to the callback rather than the 158 * relative one. 159 * @note New-style only, is implicit in old-style interface. */ 160 #define IOMMMIO_FLAGS_ABS UINT32_C(0x00001000) 161 157 162 /** Mask of valid flags. */ 158 #define IOMMMIO_FLAGS_VALID_MASK UINT32_C(0x0000 0373)163 #define IOMMMIO_FLAGS_VALID_MASK UINT32_C(0x00001373) 159 164 /** @} */ 160 165 … … 399 404 * @param pvUser User argument. 400 405 * @param off Offset into the mapping of the read, 401 * or the physical address if IOM _MMIO_F_ABS is active.406 * or the physical address if IOMMMIO_FLAGS_ABS is active. 402 407 * @param pv Where to store the result. 403 408 * @param cb Number of bytes read. … … 416 421 * @param pvUser User argument. 417 422 * @param off Offset into the mapping of the write, 418 * or the physical address if IOM _MMIO_F_ABS is active.423 * or the physical address if IOMMMIO_FLAGS_ABS is active. 419 424 * @param pv Where to fetch the result. 420 425 * @param cb Number of bytes to write. … … 433 438 * @param pvUser User argument. 434 439 * @param off Offset into the mapping of the fill, 435 * or the physical address if IOM _MMIO_F_ABS is active.440 * or the physical address if IOMMMIO_FLAGS_ABS is active. 436 441 * @param u32Item Byte/Word/Dword data to fill. 437 442 * @param cbItem Size of data in u32Item parameter, restricted to 1/2/4 bytes. … … 456 461 VMMDECL(int) IOMMMIOMapMMIOHCPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags); 457 462 VMMDECL(int) IOMMMIOResetRegion(PVMCC pVM, RTGCPHYS GCPhys); 458 VMMDECL(bool) IOMIsLockWriteOwner(PVM pVM); 463 464 VMM_INT_DECL(VBOXSTRICTRC) IOMMmioPhysHandler(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, RTGCPHYS GCPhysFault); 465 VMM_INT_DECL(int) IOMMmioMapMmio2Page(PVMCC pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion, 466 uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags); 467 VMM_INT_DECL(int) IOMMmioMapMmioHCPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags); 468 VMM_INT_DECL(int) IOMMmioResetRegion(PVMCC pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion); 469 459 470 460 471 /** @name IOM_IOPORT_F_XXX - Flags for IOMR3IoPortCreate() and PDMDevHlpIoPortCreateEx(). … … 464 475 /** Valid flags for IOMR3IoPortCreate(). */ 465 476 #define IOM_IOPORT_F_VALID_MASK UINT32_C(0x00000001) 466 /** @} */467 468 /** @name IOM_MMIO_F_XXX - Flags for IOMR3MmioCreate() and PDMDevHlpMmioCreateEx().469 * @{ */470 /** Pass the absolute physical address (GC) to the callback rather than the471 * relative one. */472 #define IOM_MMIO_F_ABS RT_BIT_32(0)473 /** Valid flags for IOMR3IoPortCreate(). */474 #define IOM_MMIO_F_VALID_MASK UINT32_C(0x00000001)475 477 /** @} */ 476 478 … … 574 576 VMMR0_INT_DECL(int) IOMR0IoPortGrowRegistrationTables(PGVM pGVM, uint64_t cMinEntries); 575 577 VMMR0_INT_DECL(int) IOMR0IoPortGrowStatisticsTable(PGVM pGVM, uint64_t cMinEntries); 578 VMMR0_INT_DECL(int) IOMR0IoPortSyncStatisticsIndices(PGVM pGVM); 576 579 577 580 VMMR0_INT_DECL(int) IOMR0MmioSetUpContext(PGVM pGVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite, … … 579 582 VMMR0_INT_DECL(int) IOMR0MmioGrowRegistrationTables(PGVM pGVM, uint64_t cMinEntries); 580 583 VMMR0_INT_DECL(int) IOMR0MmioGrowStatisticsTable(PGVM pGVM, uint64_t cMinEntries); 584 VMMR0_INT_DECL(int) IOMR0MmioSyncStatisticsIndices(PGVM pGVM); 585 581 586 /** @} */ 582 587 #endif /* IN_RING0 || DOXYGEN_RUNNING */ -
trunk/include/VBox/vmm/pdmdev.h
r81160 r81333 2418 2418 * @param pDevIns The device instance to register the ports with. 2419 2419 * @param cbRegion The size of the region in bytes. 2420 * @param fFlags Reserved, MBZ.2420 * @param fFlags Flags, IOMMMIO_FLAGS_XXX. 2421 2421 * @param pPciDev The PCI device the range is associated with, if 2422 2422 * applicable. -
trunk/include/VBox/vmm/vmm.h
r81167 r81333 419 419 /** Grow the MMIO statistics tables. */ 420 420 VMMR0_DO_IOM_GROW_MMIO_STATS, 421 /** Synchronize statistics indices for I/O ports and MMIO regions. */ 422 VMMR0_DO_IOM_SYNC_STATS_INDICES, 421 423 422 424 /** Official call we use for testing Ring-0 APIs. */ -
trunk/src/VBox/VMM/Makefile.kmk
r81197 r81333 181 181 VMMAll/IOMAll.cpp \ 182 182 VMMAll/IOMAllMMIO.cpp \ 183 VMMAll/IOMAllMmioNew.cpp \ 183 184 VMMAll/MMAll.cpp \ 184 185 VMMAll/MMAllHyper.cpp \ … … 510 511 VMMAll/IOMAll.cpp \ 511 512 VMMAll/IOMAllMMIO.cpp \ 513 VMMAll/IOMAllMmioNew.cpp \ 512 514 VMMAll/MMAll.cpp \ 513 515 VMMAll/MMAllHyper.cpp \ -
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r81136 r81333 37 37 #include <iprt/string.h> 38 38 #include "IOMInline.h" 39 40 41 /**42 * Check if this VCPU currently owns the IOM lock exclusively.43 *44 * @returns bool owner/not owner45 * @param pVM The cross context VM structure.46 */47 VMMDECL(bool) IOMIsLockWriteOwner(PVM pVM)48 {49 #ifdef IOM_WITH_CRIT_SECT_RW50 return PDMCritSectRwIsInitialized(&pVM->iom.s.CritSect)51 && PDMCritSectRwIsWriteOwner(&pVM->iom.s.CritSect);52 #else53 return PDMCritSectIsOwner(&pVM->iom.s.CritSect);54 #endif55 }56 39 57 40 -
trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
r81153 r81333 67 67 AssertReturn(cbBuf <= sizeof(pVCpu->iom.s.PendingMmioWrite.abValue), VERR_IOM_MMIO_IPE_2); 68 68 pVCpu->iom.s.PendingMmioWrite.cbValue = (uint32_t)cbBuf; 69 pVCpu->iom.s.PendingMmioWrite.idxMmioRegionHint = UINT32_MAX; 69 70 memcpy(pVCpu->iom.s.PendingMmioWrite.abValue, pvBuf, cbBuf); 70 71 } … … 584 585 * @param pvUser Pointer to the MMIO ring-3 range entry. 585 586 */ 586 static VBOXSTRICTRC iomMmioCommonPfHandler(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore,587 587 VBOXSTRICTRC iomMmioCommonPfHandlerOld(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore, 588 RTGCPHYS GCPhysFault, void *pvUser) 588 589 { 589 590 RT_NOREF_PV(uErrorCode); … … 596 597 597 598 STAM_PROFILE_START(&pVM->iom.s.StatRZMMIOHandler, a); 598 Log(("iomMmioCommonPfHandler : GCPhys=%RGp uErr=%#x rip=%RGv\n", GCPhysFault, uErrorCode, (RTGCPTR)pCtxCore->rip));599 Log(("iomMmioCommonPfHandlerOld: GCPhys=%RGp uErr=%#x rip=%RGv\n", GCPhysFault, uErrorCode, (RTGCPTR)pCtxCore->rip)); 599 600 600 601 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser; … … 617 618 # else 618 619 STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a); 619 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOFailures);620 620 return VINF_IOM_R3_MMIO_READ_WRITE; 621 621 # endif … … 645 645 646 646 STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a); 647 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOFailures);648 647 iomMmioReleaseRange(pVM, pRange); 649 648 return VINF_IOM_R3_MMIO_READ_WRITE; … … 694 693 LogFlow(("iomMmioPfHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n", 695 694 GCPhysFault, (uint32_t)uErrorCode, pvFault, (RTGCPTR)pCtxCore->rip)); NOREF(pvFault); 696 return iomMmioCommonPfHandler (pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pvUser);695 return iomMmioCommonPfHandlerOld(pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pvUser); 697 696 } 698 697 … … 727 726 IOM_UNLOCK_SHARED(pVM); 728 727 729 VBOXSTRICTRC rcStrict = iomMmioCommonPfHandler (pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pRange);728 VBOXSTRICTRC rcStrict = iomMmioCommonPfHandlerOld(pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pRange); 730 729 731 730 iomMmioReleaseRange(pVM, pRange); -
trunk/src/VBox/VMM/VMMAll/IOMAllMmioNew.cpp
r81196 r81333 21 21 *********************************************************************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_IOM 23 #define VMCPU_INCL_CPUM_GST_CTX 23 24 #include <VBox/vmm/iom.h> 24 25 #include <VBox/vmm/cpum.h> … … 47 48 48 49 50 /********************************************************************************************************************************* 51 * Defined Constants And Macros * 52 *********************************************************************************************************************************/ 53 /** @def IOM_MMIO_STATS_COMMA_DECL 54 * Parameter list declaration for statistics entry pointer. */ 55 /** @def IOM_MMIO_STATS_COMMA_ARG 56 * Statistics entry pointer argument. */ 57 #ifdef VBOX_WITH_STATISTICS 58 # define IOM_MMIO_STATS_COMMA_DECL , PIOMMMIOSTATSENTRY pStats 59 # define IOM_MMIO_STATS_COMMA_ARG , pStats 60 #else 61 # define IOM_MMIO_STATS_COMMA_DECL 62 # define IOM_MMIO_STATS_COMMA_ARG 63 #endif 64 65 49 66 50 67 #ifndef IN_RING3 … … 57 74 * @param pvBuf The bytes being written. 58 75 * @param cbBuf How many bytes. 59 * @param pRange The range, if resolved. 60 */ 61 static VBOXSTRICTRC iomMmioRing3WritePending(PVMCPU pVCpu, RTGCPHYS GCPhys, void const *pvBuf, size_t cbBuf, PIOMMMIORANGE pRange) 62 { 63 Log5(("iomMmioRing3WritePending: %RGp LB %#x\n", GCPhys, cbBuf)); 76 * @param idxRegEntry The MMIO registration index (handle) if available, 77 * otherwise UINT32_MAX. 78 */ 79 static VBOXSTRICTRC iomMmioRing3WritePending(PVMCPU pVCpu, RTGCPHYS GCPhys, void const *pvBuf, size_t cbBuf, 80 uint32_t idxRegEntry) 81 { 82 Log5(("iomMmioRing3WritePending: %RGp LB %#x (idx=%#x)\n", GCPhys, cbBuf, idxRegEntry)); 64 83 if (pVCpu->iom.s.PendingMmioWrite.cbValue == 0) 65 84 { 66 pVCpu->iom.s.PendingMmioWrite.GCPhys = GCPhys;85 pVCpu->iom.s.PendingMmioWrite.GCPhys = GCPhys; 67 86 AssertReturn(cbBuf <= sizeof(pVCpu->iom.s.PendingMmioWrite.abValue), VERR_IOM_MMIO_IPE_2); 68 pVCpu->iom.s.PendingMmioWrite.cbValue = (uint32_t)cbBuf; 87 pVCpu->iom.s.PendingMmioWrite.cbValue = (uint32_t)cbBuf; 88 pVCpu->iom.s.PendingMmioWrite.idxMmioRegionHint = idxRegEntry; 69 89 memcpy(pVCpu->iom.s.PendingMmioWrite.abValue, pvBuf, cbBuf); 70 90 } … … 89 109 90 110 VMCPU_FF_SET(pVCpu, VMCPU_FF_IOM); 91 RT_NOREF_PV(pRange);92 111 return VINF_IOM_R3_MMIO_COMMIT_WRITE; 93 112 } … … 107 126 * @param pVM The cross context VM structure. 108 127 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 109 * @param pR ange The range to write to.128 * @param pRegEntry The MMIO entry for the current context. 110 129 * @param GCPhys The physical address to start writing. 111 130 * @param pvValue Where to store the value. 112 131 * @param cbValue The size of the value to write. 113 132 */ 114 static VBOXSTRICTRC iomMMIODoComplicatedWrite(PVM pVM, PVMCPU pVCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, 115 void const *pvValue, unsigned cbValue) 116 { 117 RT_NOREF_PV(pVCpu); 118 AssertReturn( (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) != IOMMMIO_FLAGS_WRITE_PASSTHRU 119 && (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) <= IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING, 133 static VBOXSTRICTRC iomMmioDoComplicatedWrite(PVM pVM, PVMCPU pVCpu, CTX_SUFF(PIOMMMIOENTRY) pRegEntry, RTGCPHYS GCPhys, 134 void const *pvValue, unsigned cbValue IOM_MMIO_STATS_COMMA_DECL) 135 { 136 AssertReturn( (pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) != IOMMMIO_FLAGS_WRITE_PASSTHRU 137 && (pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) <= IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING, 120 138 VERR_IOM_MMIO_IPE_1); 121 139 AssertReturn(cbValue != 0 && cbValue <= 16, VERR_IOM_MMIO_IPE_2); 122 140 RTGCPHYS const GCPhysStart = GCPhys; NOREF(GCPhysStart); 123 bool const fReadMissing = (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING 124 || (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING; 141 bool const fReadMissing = (pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING 142 || (pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING; 143 RT_NOREF_PV(pVCpu); /* ring-3 */ 125 144 126 145 /* 127 146 * Do debug stop if requested. 128 147 */ 129 intrc = VINF_SUCCESS; NOREF(pVM);148 VBOXSTRICTRC rc = VINF_SUCCESS; NOREF(pVM); 130 149 #ifdef VBOX_STRICT 131 if (pRange->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE) 150 if (!(pRegEntry->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE)) 151 { /* likely */ } 152 else 132 153 { 133 154 # ifdef IN_RING3 134 155 LogRel(("IOM: Complicated write %#x byte at %RGp to %s, initiating debugger intervention\n", cbValue, GCPhys, 135 R3STRING(pR ange->pszDesc)));156 R3STRING(pRegEntry->pszDesc))); 136 157 rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, RT_SRC_POS, 137 "Complicated write %#x byte at %RGp to %s\n", cbValue, GCPhys, R3STRING(pRange->pszDesc));158 "Complicated write %#x byte at %RGp to %s\n", cbValue, GCPhys, pRegEntry->pszDesc); 138 159 if (rc == VERR_DBGF_NOT_ATTACHED) 139 160 rc = VINF_SUCCESS; … … 144 165 #endif 145 166 167 STAM_COUNTER_INC(&pStats->ComplicatedWrites); 168 146 169 /* 147 170 * Check if we should ignore the write. 148 171 */ 149 if ((pR ange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD)172 if ((pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD) 150 173 { 151 174 Assert(cbValue != 4 || (GCPhys & 3)); 152 175 return VINF_SUCCESS; 153 176 } 154 if ((pR ange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD)177 if ((pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD) 155 178 { 156 179 Assert((cbValue != 4 && cbValue != 8) || (GCPhys & (cbValue - 1))); … … 174 197 if (fReadMissing && cbThisPart != 4) 175 198 { 176 int rc2 = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),177 GCPhys & ~(RTGCPHYS)3, &u32MissingValue, sizeof(u32MissingValue));178 switch ( rc2)199 VBOXSTRICTRC rc2 = pRegEntry->pfnReadCallback(pRegEntry->pDevIns, pRegEntry->pvUser, 200 GCPhys & ~(RTGCPHYS)3, &u32MissingValue, sizeof(u32MissingValue)); 201 switch (VBOXSTRICTRC_VAL(rc2)) 179 202 { 180 203 case VINF_SUCCESS: 181 204 break; 182 205 case VINF_IOM_MMIO_UNUSED_FF: 206 STAM_COUNTER_INC(&pStats->FFor00Reads); 183 207 u32MissingValue = UINT32_C(0xffffffff); 184 208 break; 185 209 case VINF_IOM_MMIO_UNUSED_00: 210 STAM_COUNTER_INC(&pStats->FFor00Reads); 186 211 u32MissingValue = 0; 187 212 break; … … 190 215 case VINF_IOM_R3_MMIO_READ_WRITE: 191 216 case VINF_IOM_R3_MMIO_WRITE: 192 LogFlow(("iomM MIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2));193 rc2 = VBOXSTRICTRC_TODO(iomMmioRing3WritePending(pVCpu, GCPhys, pvValue, cbValue, pRange));217 LogFlow(("iomMmioDoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2)); 218 rc2 = iomMmioRing3WritePending(pVCpu, GCPhys, pvValue, cbValue, pRegEntry->idxSelf); 194 219 if (rc == VINF_SUCCESS || rc2 < rc) 195 220 rc = rc2; … … 199 224 if (RT_FAILURE(rc2)) 200 225 { 201 Log(("iomM MIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2));226 Log(("iomMmioDoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2)); 202 227 return rc2; 203 228 } … … 248 273 * Do DWORD write to the device. 249 274 */ 250 int rc2 = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),251 GCPhys & ~(RTGCPHYS)3, &u32Value, sizeof(u32Value));252 switch ( rc2)275 VBOXSTRICTRC rc2 = pRegEntry->pfnWriteCallback(pRegEntry->pDevIns, pRegEntry->pvUser, 276 GCPhys & ~(RTGCPHYS)3, &u32Value, sizeof(u32Value)); 277 switch (VBOXSTRICTRC_VAL(rc2)) 253 278 { 254 279 case VINF_SUCCESS: … … 258 283 case VINF_IOM_R3_MMIO_READ_WRITE: 259 284 case VINF_IOM_R3_MMIO_WRITE: 260 Log3(("iomM MIODoComplicatedWrite: deferring GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2));285 Log3(("iomMmioDoComplicatedWrite: deferring GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2)); 261 286 AssertReturn(pVCpu->iom.s.PendingMmioWrite.cbValue == 0, VERR_IOM_MMIO_IPE_1); 262 287 AssertReturn(cbValue + (GCPhys & 3) <= sizeof(pVCpu->iom.s.PendingMmioWrite.abValue), VERR_IOM_MMIO_IPE_2); … … 275 300 if (RT_FAILURE(rc2)) 276 301 { 277 Log(("iomM MIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2));302 Log(("iomMmioDoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2)); 278 303 return rc2; 279 304 } … … 301 326 302 327 /** 303 * Wrapper which does the write and updates range statistics when such are enabled. 304 * @warning RT_SUCCESS(rc=VINF_IOM_R3_MMIO_WRITE) is TRUE! 305 */ 306 static VBOXSTRICTRC iomMMIODoWrite(PVM pVM, PVMCPU pVCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, 307 const void *pvData, unsigned cb) 308 { 309 #ifdef VBOX_WITH_STATISTICS 310 int rcSem = IOM_LOCK_SHARED(pVM); 311 if (rcSem == VERR_SEM_BUSY) 312 return VINF_IOM_R3_MMIO_WRITE; 313 PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhysFault, pRange); 314 if (!pStats) 315 # ifdef IN_RING3 316 return VERR_NO_MEMORY; 317 # else 318 return VINF_IOM_R3_MMIO_WRITE; 319 # endif 320 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfWrite), a); 321 #else 322 NOREF(pVCpu); 323 #endif 324 328 * Wrapper which does the write. 329 */ 330 DECLINLINE(VBOXSTRICTRC) iomMmioDoWrite(PVMCC pVM, PVMCPU pVCpu, CTX_SUFF(PIOMMMIOENTRY) pRegEntry, RTGCPHYS GCPhysFault, 331 const void *pvData, uint32_t cb IOM_MMIO_STATS_COMMA_DECL) 332 { 325 333 VBOXSTRICTRC rcStrict; 326 if (RT_LIKELY(pR ange->CTX_SUFF(pfnWriteCallback)))334 if (RT_LIKELY(pRegEntry->pfnWriteCallback)) 327 335 { 328 336 if ( (cb == 4 && !(GCPhysFault & 3)) 329 || (pR ange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_PASSTHRU330 || (cb == 8 && !(GCPhysFault & 7) && IOMMMIO_DOES_WRITE_MODE_ALLOW_QWORD(pR ange->fFlags)) )331 rcStrict = pR ange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),332 GCPhysFault, (void *)pvData, cb); /** @todo fix const!! */337 || (pRegEntry->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_PASSTHRU 338 || (cb == 8 && !(GCPhysFault & 7) && IOMMMIO_DOES_WRITE_MODE_ALLOW_QWORD(pRegEntry->fFlags)) ) 339 rcStrict = pRegEntry->pfnWriteCallback(pRegEntry->pDevIns, pRegEntry->pvUser, 340 GCPhysFault, pvData, cb); 333 341 else 334 rcStrict = iomM MIODoComplicatedWrite(pVM, pVCpu, pRange, GCPhysFault, pvData, cb);342 rcStrict = iomMmioDoComplicatedWrite(pVM, pVCpu, pRegEntry, GCPhysFault, pvData, cb IOM_MMIO_STATS_COMMA_ARG); 335 343 } 336 344 else 337 345 rcStrict = VINF_SUCCESS; 338 339 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfWrite), a);340 STAM_COUNTER_INC(&pStats->Accesses);341 346 return rcStrict; 342 347 } … … 354 359 * 355 360 * @param pVM The cross context VM structure. 356 * @param pR ange The range to read from.361 * @param pRegEntry The MMIO entry for the current context. 357 362 * @param GCPhys The physical address to start reading. 358 363 * @param pvValue Where to store the value. 359 364 * @param cbValue The size of the value to read. 360 365 */ 361 static VBOXSTRICTRC iomMMIODoComplicatedRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void *pvValue, unsigned cbValue) 362 { 363 AssertReturn( (pRange->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD 364 || (pRange->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD_QWORD, 366 static VBOXSTRICTRC iomMMIODoComplicatedRead(PVM pVM, CTX_SUFF(PIOMMMIOENTRY) pRegEntry, RTGCPHYS GCPhys, 367 void *pvValue, unsigned cbValue IOM_MMIO_STATS_COMMA_DECL) 368 { 369 AssertReturn( (pRegEntry->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD 370 || (pRegEntry->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD_QWORD, 365 371 VERR_IOM_MMIO_IPE_1); 366 372 AssertReturn(cbValue != 0 && cbValue <= 16, VERR_IOM_MMIO_IPE_2); 367 RTGCPHYS const GCPhysStart = GCPhys; NOREF(GCPhysStart); 373 #ifdef LOG_ENABLED 374 RTGCPHYS const GCPhysStart = GCPhys; 375 #endif 368 376 369 377 /* 370 378 * Do debug stop if requested. 371 379 */ 372 intrc = VINF_SUCCESS; NOREF(pVM);380 VBOXSTRICTRC rc = VINF_SUCCESS; NOREF(pVM); 373 381 #ifdef VBOX_STRICT 374 if (pR ange->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_READ)382 if (pRegEntry->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_READ) 375 383 { 376 384 # ifdef IN_RING3 377 385 rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, RT_SRC_POS, 378 "Complicated read %#x byte at %RGp to %s\n", cbValue, GCPhys, R3STRING(pR ange->pszDesc));386 "Complicated read %#x byte at %RGp to %s\n", cbValue, GCPhys, R3STRING(pRegEntry->pszDesc)); 379 387 if (rc == VERR_DBGF_NOT_ATTACHED) 380 388 rc = VINF_SUCCESS; … … 385 393 #endif 386 394 395 STAM_COUNTER_INC(&pStats->ComplicatedReads); 396 387 397 /* 388 398 * Split and conquer. … … 394 404 */ 395 405 uint32_t u32Value; 396 int rc2 = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser),397 GCPhys & ~(RTGCPHYS)3, &u32Value, sizeof(u32Value));398 switch ( rc2)406 VBOXSTRICTRC rcStrict2 = pRegEntry->pfnReadCallback(pRegEntry->pDevIns, pRegEntry->pvUser, 407 GCPhys & ~(RTGCPHYS)3, &u32Value, sizeof(u32Value)); 408 switch (VBOXSTRICTRC_VAL(rcStrict2)) 399 409 { 400 410 case VINF_SUCCESS: 401 411 break; 402 412 case VINF_IOM_MMIO_UNUSED_FF: 413 STAM_COUNTER_INC(&pStats->FFor00Reads); 403 414 u32Value = UINT32_C(0xffffffff); 404 415 break; 405 416 case VINF_IOM_MMIO_UNUSED_00: 417 STAM_COUNTER_INC(&pStats->FFor00Reads); 406 418 u32Value = 0; 407 419 break; … … 412 424 * something? Since reads can have sideeffects we could be 413 425 * kind of screwed here... */ 414 LogFlow(("iomMMIODoComplicatedRead: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc\n", GCPhys, GCPhysStart, cbValue, rc2)); 415 return rc2; 426 LogFlow(("iomMMIODoComplicatedRead: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rcStrict2=%Rrc\n", 427 GCPhys, GCPhysStart, cbValue, VBOXSTRICTRC_VAL(rcStrict2))); 428 return rcStrict2; 416 429 default: 417 if (RT_FAILURE(rc 2))430 if (RT_FAILURE(rcStrict2)) 418 431 { 419 Log(("iomMMIODoComplicatedRead: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc\n", GCPhys, GCPhysStart, cbValue, rc2)); 420 return rc2; 432 Log(("iomMMIODoComplicatedRead: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rcStrict2=%Rrc\n", 433 GCPhys, GCPhysStart, cbValue, VBOXSTRICTRC_VAL(rcStrict2))); 434 return rcStrict2; 421 435 } 422 AssertMsgReturn(rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST, ("%Rrc\n", rc2), VERR_IPE_UNEXPECTED_INFO_STATUS); 423 if (rc == VINF_SUCCESS || rc2 < rc) 424 rc = rc2; 436 AssertMsgReturn(rcStrict2 >= VINF_EM_FIRST && rcStrict2 <= VINF_EM_LAST, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)), 437 VERR_IPE_UNEXPECTED_INFO_STATUS); 438 if (rc == VINF_SUCCESS || rcStrict2 < rc) 439 rc = rcStrict2; 425 440 break; 426 441 } … … 473 488 * @param cbValue How many bytes to read. 474 489 */ 475 static int iomMMIODoReadFFs(void *pvValue, size_t cbValue )490 static int iomMMIODoReadFFs(void *pvValue, size_t cbValue IOM_MMIO_STATS_COMMA_DECL) 476 491 { 477 492 switch (cbValue) … … 489 504 } 490 505 } 506 STAM_COUNTER_INC(&pStats->FFor00Reads); 491 507 return VINF_SUCCESS; 492 508 } … … 500 516 * @param cbValue How many bytes to read. 501 517 */ 502 static int iomMMIODoRead00s(void *pvValue, size_t cbValue )518 static int iomMMIODoRead00s(void *pvValue, size_t cbValue IOM_MMIO_STATS_COMMA_DECL) 503 519 { 504 520 switch (cbValue) … … 516 532 } 517 533 } 534 STAM_COUNTER_INC(&pStats->FFor00Reads); 518 535 return VINF_SUCCESS; 519 536 } … … 521 538 522 539 /** 523 * Wrapper which does the read and updates range statistics when such are enabled. 524 */ 525 DECLINLINE(VBOXSTRICTRC) iomMMIODoRead(PVM pVM, PVMCPU pVCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, 526 void *pvValue, unsigned cbValue) 527 { 528 #ifdef VBOX_WITH_STATISTICS 529 int rcSem = IOM_LOCK_SHARED(pVM); 530 if (rcSem == VERR_SEM_BUSY) 531 return VINF_IOM_R3_MMIO_READ; 532 PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhys, pRange); 533 if (!pStats) 534 # ifdef IN_RING3 535 return VERR_NO_MEMORY; 536 # else 537 return VINF_IOM_R3_MMIO_READ; 538 # endif 539 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfRead), a); 540 #else 541 NOREF(pVCpu); 542 #endif 543 540 * Wrapper which does the read. 541 */ 542 DECLINLINE(VBOXSTRICTRC) iomMmioDoRead(PVMCC pVM, CTX_SUFF(PIOMMMIOENTRY) pRegEntry, RTGCPHYS GCPhys, 543 void *pvValue, uint32_t cbValue IOM_MMIO_STATS_COMMA_DECL) 544 { 544 545 VBOXSTRICTRC rcStrict; 545 if (RT_LIKELY(pR ange->CTX_SUFF(pfnReadCallback)))546 if (RT_LIKELY(pRegEntry->pfnReadCallback)) 546 547 { 547 548 if ( ( cbValue == 4 548 549 && !(GCPhys & 3)) 549 || (pR ange->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_PASSTHRU550 || (pRegEntry->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_PASSTHRU 550 551 || ( cbValue == 8 551 552 && !(GCPhys & 7) 552 && (pR ange->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD_QWORD ) )553 rcStrict = pR ange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys,554 553 && (pRegEntry->fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_DWORD_QWORD ) ) 554 rcStrict = pRegEntry->pfnReadCallback(pRegEntry->pDevIns, pRegEntry->pvUser, GCPhys, 555 pvValue, cbValue); 555 556 else 556 rcStrict = iomMMIODoComplicatedRead(pVM, pR ange, GCPhys, pvValue, cbValue);557 rcStrict = iomMMIODoComplicatedRead(pVM, pRegEntry, GCPhys, pvValue, cbValue IOM_MMIO_STATS_COMMA_ARG); 557 558 } 558 559 else … … 562 563 switch (VBOXSTRICTRC_VAL(rcStrict)) 563 564 { 564 case VINF_IOM_MMIO_UNUSED_FF: rcStrict = iomMMIODoReadFFs(pvValue, cbValue); break; 565 case VINF_IOM_MMIO_UNUSED_00: rcStrict = iomMMIODoRead00s(pvValue, cbValue); break; 566 } 567 } 568 569 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfRead), a); 570 STAM_COUNTER_INC(&pStats->Accesses); 565 case VINF_IOM_MMIO_UNUSED_FF: rcStrict = iomMMIODoReadFFs(pvValue, cbValue IOM_MMIO_STATS_COMMA_ARG); break; 566 case VINF_IOM_MMIO_UNUSED_00: rcStrict = iomMMIODoRead00s(pvValue, cbValue IOM_MMIO_STATS_COMMA_ARG); break; 567 } 568 } 571 569 return rcStrict; 572 570 } 571 572 #ifndef IN_RING3 573 /** 574 * Checks if we can handle an MMIO \#PF in R0/RC. 575 */ 576 DECLINLINE(bool) iomMmioCanHandlePfInRZ(PVMCC pVM, uint32_t uErrorCode, CTX_SUFF(PIOMMMIOENTRY) pRegEntry) 577 { 578 if (pRegEntry->cbRegion > 0) 579 { 580 if ( pRegEntry->pfnWriteCallback 581 && pRegEntry->pfnReadCallback) 582 return true; 583 584 PIOMMMIOENTRYR3 const pRegEntryR3 = &pVM->iomr0.s.paMmioRing3Regs[pRegEntry->idxSelf]; 585 if ( uErrorCode == UINT32_MAX 586 ? pRegEntryR3->pfnWriteCallback || pRegEntryR3->pfnReadCallback 587 : uErrorCode & X86_TRAP_PF_RW 588 ? !pRegEntry->pfnWriteCallback && pRegEntryR3->pfnWriteCallback 589 : !pRegEntry->pfnReadCallback && pRegEntryR3->pfnReadCallback) 590 return false; 591 592 return true; 593 } 594 return false; 595 } 596 #endif 573 597 574 598 /** … … 582 606 * @param pCtxCore Trap register frame. 583 607 * @param GCPhysFault The GC physical address corresponding to pvFault. 584 * @param pvUser Pointer to the MMIO ring-3 range entry. 585 */ 586 static VBOXSTRICTRC iomMmioCommonPfHandler(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore, 587 RTGCPHYS GCPhysFault, void *pvUser) 588 { 589 RT_NOREF_PV(uErrorCode); 590 int rc = IOM_LOCK_SHARED(pVM); 591 #ifndef IN_RING3 592 if (rc == VERR_SEM_BUSY) 593 return VINF_IOM_R3_MMIO_READ_WRITE; 594 #endif 595 AssertRC(rc); 596 608 * @param pRegEntry The MMIO entry for the current context. 609 */ 610 DECLINLINE(VBOXSTRICTRC) iomMmioCommonPfHandlerNew(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, 611 RTGCPHYS GCPhysFault, CTX_SUFF(PIOMMMIOENTRY) pRegEntry) 612 { 597 613 STAM_PROFILE_START(&pVM->iom.s.StatRZMMIOHandler, a); 598 Log(("iomMmioCommonPfHandler: GCPhys=%RGp uErr=%#x rip=%RGv\n", GCPhysFault, uErrorCode, (RTGCPTR)pCtxCore->rip)); 599 600 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser; 601 Assert(pRange); 602 Assert(pRange == iomMmioGetRange(pVM, pVCpu, GCPhysFault)); 603 iomMmioRetainRange(pRange); 604 #ifndef VBOX_WITH_STATISTICS 605 IOM_UNLOCK_SHARED(pVM); 606 607 #else 608 /* 609 * Locate the statistics. 610 */ 611 PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhysFault, pRange); 612 if (!pStats) 613 { 614 iomMmioReleaseRange(pVM, pRange); 615 # ifdef IN_RING3 616 return VERR_NO_MEMORY; 617 # else 618 STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a); 619 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOFailures); 620 return VINF_IOM_R3_MMIO_READ_WRITE; 621 # endif 622 } 623 #endif 614 Log(("iomMmioCommonPfHandler: GCPhysFault=%RGp uErr=%#x rip=%RGv\n", GCPhysFault, uErrorCode, CPUMGetGuestRIP(pVCpu) )); 615 RT_NOREF(GCPhysFault, uErrorCode); 616 617 VBOXSTRICTRC rcStrict; 624 618 625 619 #ifndef IN_RING3 … … 628 622 * do the simple test first and the try deal with uErrorCode being N/A. 629 623 */ 630 if (RT_UNLIKELY( ( !pRange->CTX_SUFF(pfnWriteCallback) 631 || !pRange->CTX_SUFF(pfnReadCallback)) 632 && ( uErrorCode == UINT32_MAX 633 ? pRange->pfnWriteCallbackR3 || pRange->pfnReadCallbackR3 634 : uErrorCode & X86_TRAP_PF_RW 635 ? !pRange->CTX_SUFF(pfnWriteCallback) && pRange->pfnWriteCallbackR3 636 : !pRange->CTX_SUFF(pfnReadCallback) && pRange->pfnReadCallbackR3 637 ) 638 ) 639 ) 640 { 624 PPDMDEVINS const pDevIns = pRegEntry->pDevIns; 625 if (RT_LIKELY( pDevIns 626 && iomMmioCanHandlePfInRZ(pVM, uErrorCode, pRegEntry))) 627 { 628 /* 629 * Enter the device critsect prior to engaging IOM in case of lock contention. 630 * Note! Perhaps not a good move? 631 */ 632 rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_MMIO_READ_WRITE); 633 if (rcStrict == VINF_SUCCESS) 634 { 635 #endif /* !IN_RING3 */ 636 637 /* 638 * Let IEM call us back via iomMmioHandler. 639 */ 640 rcStrict = IEMExecOne(pVCpu); 641 642 #ifndef IN_RING3 643 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 644 #endif 645 if (RT_SUCCESS(rcStrict)) 646 { /* likely */ } 647 else if ( rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED 648 || rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED) 649 { 650 Log(("IOM: Hit unsupported IEM feature!\n")); 651 rcStrict = VINF_EM_RAW_EMULATE_INSTR; 652 } 653 #ifndef IN_RING3 654 STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a); 655 return rcStrict; 656 } 657 else 658 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIODevLockContention); 659 } 660 else 661 rcStrict = VINF_IOM_R3_MMIO_READ_WRITE; 662 663 # ifdef VBOX_WITH_STATISTICS 664 if (rcStrict == VINF_IOM_R3_MMIO_READ_WRITE) 665 { 666 PIOMMMIOSTATSENTRY const pStats = iomMmioGetStats(pVM, pRegEntry); 641 667 if (uErrorCode & X86_TRAP_PF_RW) 642 STAM_COUNTER_INC(&pStats->CTX_MID_Z(Write,ToR3)); 668 { 669 STAM_COUNTER_INC(&pStats->WriteRZToR3); 670 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOWritesToR3); 671 } 643 672 else 644 STAM_COUNTER_INC(&pStats->CTX_MID_Z(Read,ToR3)); 645 646 STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a); 647 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOFailures); 648 iomMmioReleaseRange(pVM, pRange); 649 return VINF_IOM_R3_MMIO_READ_WRITE; 650 } 651 #endif /* !IN_RING3 */ 652 653 /* 654 * Retain the range and do locking. 655 */ 656 PPDMDEVINS pDevIns = pRange->CTX_SUFF(pDevIns); 657 rc = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_MMIO_READ_WRITE); 658 if (rc != VINF_SUCCESS) 659 { 660 iomMmioReleaseRange(pVM, pRange); 661 return rc; 662 } 663 664 /* 665 * Let IEM call us back via iomMmioHandler. 666 */ 667 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu); 668 669 NOREF(pCtxCore); NOREF(GCPhysFault); 673 { 674 STAM_COUNTER_INC(&pStats->ReadRZToR3); 675 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOReadsToR3); 676 } 677 } 678 # endif 679 #else /* IN_RING3 */ 680 RT_NOREF(pRegEntry); 681 #endif /* IN_RING3 */ 682 670 683 STAM_PROFILE_STOP(&pVM->iom.s.StatRZMMIOHandler, a); 671 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));672 iomMmioReleaseRange(pVM, pRange);673 if (RT_SUCCESS(rcStrict))674 return rcStrict;675 if ( rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED676 || rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED)677 {678 Log(("IOM: Hit unsupported IEM feature!\n"));679 rcStrict = VINF_EM_RAW_EMULATE_INSTR;680 }681 684 return rcStrict; 682 685 } … … 687 690 * \#PF access handler callback for MMIO pages.} 688 691 * 689 * @remarks The @a pvUser argument points to the IOMMMIORANGE.690 */ 691 DECLEXPORT(VBOXSTRICTRC) iomMmioPfHandler (PVMCC pVM, PVMCPUCC pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPTR pvFault,692 RTGCPHYS GCPhysFault, void *pvUser)692 * @remarks The @a pvUser argument is the MMIO handle. 693 */ 694 DECLEXPORT(VBOXSTRICTRC) iomMmioPfHandlerNew(PVMCC pVM, PVMCPUCC pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, 695 RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser) 693 696 { 694 697 LogFlow(("iomMmioPfHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n", 695 GCPhysFault, (uint32_t)uErrorCode, pvFault, (RTGCPTR)pCtxCore->rip)); NOREF(pvFault); 696 return iomMmioCommonPfHandler(pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pvUser); 697 } 698 699 698 GCPhysFault, (uint32_t)uErrorCode, pvFault, (RTGCPTR)pCtxCore->rip)); 699 RT_NOREF(pvFault, pCtxCore); 700 701 /* Translate the MMIO handle to a registration entry for the current context. */ 702 AssertReturn((uintptr_t)pvUser < RT_MIN(pVM->iom.s.cMmioRegs, pVM->iom.s.cMmioAlloc), VERR_IOM_INVALID_MMIO_HANDLE); 703 #ifdef IN_RING0 704 AssertReturn((uintptr_t)pvUser < pVM->iomr0.s.cMmioAlloc, VERR_IOM_INVALID_MMIO_HANDLE); 705 CTX_SUFF(PIOMMMIOENTRY) pRegEntry = &pVM->iomr0.s.paMmioRegs[(uintptr_t)pvUser]; 706 #else 707 CTX_SUFF(PIOMMMIOENTRY) pRegEntry = &pVM->iom.s.paMmioRegs[(uintptr_t)pvUser]; 708 #endif 709 710 return iomMmioCommonPfHandlerNew(pVM, pVCpu, (uint32_t)uErrorCode, GCPhysFault, pRegEntry); 711 } 712 713 714 #ifdef IN_RING0 700 715 /** 701 716 * Physical access handler for MMIO ranges. 717 * 718 * This is actually only used by VT-x for APIC page accesses. 702 719 * 703 720 * @returns VBox status code (appropriate for GC return). … … 705 722 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 706 723 * @param uErrorCode CPU Error code. 707 * @param pCtxCore Trap register frame.708 724 * @param GCPhysFault The GC physical address. 709 725 */ 710 VMM DECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVMCC pVM, PVMCPUCC pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault)726 VMM_INT_DECL(VBOXSTRICTRC) IOMMmioPhysHandler(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, RTGCPHYS GCPhysFault) 711 727 { 712 728 /* 713 729 * We don't have a range here, so look it up before calling the common function. 714 730 */ 715 int rc2 = IOM_LOCK_SHARED(pVM); NOREF(rc2); 731 VBOXSTRICTRC rcStrict = IOM_LOCK_SHARED(pVM); 732 if (RT_SUCCESS(rcStrict)) 733 { 734 uint16_t idxLastHint = UINT16_MAX; /** @todo dedicate hint for this bugger, since it will only be the APIC. */ 735 RTGCPHYS offRegion; 736 CTX_SUFF(PIOMMMIOENTRY) pRegEntry = iomMmioGetEntry(pVM, GCPhysFault, &offRegion, &idxLastHint); 737 if (RT_LIKELY(pRegEntry)) 738 { 739 IOM_UNLOCK_SHARED(pVM); 740 rcStrict = iomMmioCommonPfHandlerNew(pVM, pVCpu, (uint32_t)uErrorCode, GCPhysFault, pRegEntry); 741 } 742 else 743 { 744 /* 745 * Old style registrations. 746 */ 747 PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhysFault); 748 if (pRange) 749 { 750 iomMmioRetainRange(pRange); 751 IOM_UNLOCK_SHARED(pVM); 752 753 rcStrict = iomMmioCommonPfHandlerOld(pVM, pVCpu, (uint32_t)uErrorCode, 754 CPUMCTX2CORE(&pVCpu->cpum.GstCtx), GCPhysFault, pRange); 755 756 iomMmioReleaseRange(pVM, pRange); 757 } 758 else 759 { 760 IOM_UNLOCK_SHARED(pVM); 761 rcStrict = VERR_IOM_MMIO_RANGE_NOT_FOUND; 762 } 763 } 764 } 765 else if (rcStrict == VERR_SEM_BUSY) 766 rcStrict = VINF_IOM_R3_MMIO_READ_WRITE; 767 return rcStrict; 768 } 769 #endif /* IN_RING0 */ 770 771 772 /** 773 * @callback_method_impl{FNPGMPHYSHANDLER, MMIO page accesses} 774 * 775 * @remarks The @a pvUser argument is the MMIO handle. 776 */ 777 PGM_ALL_CB2_DECL(VBOXSTRICTRC) iomMmioHandlerNew(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysFault, void *pvPhys, void *pvBuf, 778 size_t cbBuf, PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser) 779 { 780 STAM_PROFILE_START(UnusedMacroArg, Prf); 781 STAM_COUNTER_INC(&pVM->iom.s.CTX_SUFF(StatMmioHandler)); 782 783 Assert(enmAccessType == PGMACCESSTYPE_READ || enmAccessType == PGMACCESSTYPE_WRITE); 784 AssertMsg(cbBuf >= 1, ("%zu\n", cbBuf)); 785 NOREF(pvPhys); NOREF(enmOrigin); 786 787 #ifdef IN_RING3 788 int const rcToRing3 = VERR_IOM_MMIO_IPE_3; 789 #else 790 int const rcToRing3 = enmAccessType == PGMACCESSTYPE_READ ? VINF_IOM_R3_MMIO_READ : VINF_IOM_R3_MMIO_WRITE; 791 #endif 792 793 /* 794 * Translate pvUser to an MMIO registration table entry. We can do this 795 * without any locking as the data is static after VM creation. 796 */ 797 AssertReturn((uintptr_t)pvUser < RT_MIN(pVM->iom.s.cMmioRegs, pVM->iom.s.cMmioAlloc), VERR_IOM_INVALID_MMIO_HANDLE); 798 #ifdef IN_RING0 799 AssertReturn((uintptr_t)pvUser < pVM->iomr0.s.cMmioAlloc, VERR_IOM_INVALID_MMIO_HANDLE); 800 CTX_SUFF(PIOMMMIOENTRY) const pRegEntry = &pVM->iomr0.s.paMmioRegs[(uintptr_t)pvUser]; 801 #else 802 CTX_SUFF(PIOMMMIOENTRY) const pRegEntry = &pVM->iom.s.paMmioRegs[(uintptr_t)pvUser]; 803 #endif 804 #ifdef VBOX_WITH_STATISTICS 805 PIOMMMIOSTATSENTRY const pStats = iomMmioGetStats(pVM, pRegEntry); /* (Works even without ring-0 setup.) */ 806 #endif 807 PPDMDEVINS const pDevIns = pRegEntry->pDevIns; 808 716 809 #ifndef IN_RING3 717 if (rc2 == VERR_SEM_BUSY)718 return VINF_IOM_R3_MMIO_READ_WRITE;719 #endif 720 PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhysFault);721 if (RT_UNLIKELY(!pRange))722 {723 IOM_UNLOCK_SHARED(pVM);724 return VERR_IOM_MMIO_RANGE_NOT_FOUND;725 }726 iomMmioRetainRange(pRange);810 # if defined(VBOX_STRICT) 811 /* 812 * Assert the right entry in strict builds. This may yield a false positive 813 * for SMP VMs if we're unlucky and the guest isn't well behaved. 814 */ 815 IOM_LOCK_SHARED(pVM); /** @todo Need lookup that doesn't require locking... */ 816 RTGCPHYS offIgn; 817 uint16_t idxIgn = UINT16_MAX; 818 Assert( pRegEntry == iomMmioGetEntry(pVM, GCPhysFault, &offIgn, &idxIgn) 819 || !pVM->iomr0.s.paMmioRing3Regs[(uintptr_t)pvUser].fMapped); 727 820 IOM_UNLOCK_SHARED(pVM); 728 729 VBOXSTRICTRC rcStrict = iomMmioCommonPfHandler(pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pRange); 730 731 iomMmioReleaseRange(pVM, pRange); 732 return VBOXSTRICTRC_VAL(rcStrict); 733 } 734 735 736 /** 737 * @callback_method_impl{FNPGMPHYSHANDLER, MMIO page accesses} 738 * 739 * @remarks The @a pvUser argument points to the MMIO range entry. 740 */ 741 PGM_ALL_CB2_DECL(VBOXSTRICTRC) iomMmioHandler(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysFault, void *pvPhys, void *pvBuf, 742 size_t cbBuf, PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser) 743 { 744 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser; 745 STAM_COUNTER_INC(&pVM->iom.s.StatR3MMIOHandler); 746 747 NOREF(pvPhys); NOREF(enmOrigin); 748 AssertPtr(pRange); 749 AssertMsg(cbBuf >= 1, ("%zu\n", cbBuf)); 750 751 752 #ifndef IN_RING3 821 # endif 822 753 823 /* 754 824 * If someone is doing FXSAVE, FXRSTOR, XSAVE, XRSTOR or other stuff dealing with 755 825 * large amounts of data, just go to ring-3 where we don't need to deal with partial 756 826 * successes. No chance any of these will be problematic read-modify-write stuff. 757 */ 758 if (cbBuf > sizeof(pVCpu->iom.s.PendingMmioWrite.abValue)) 759 return enmAccessType == PGMACCESSTYPE_WRITE ? VINF_IOM_R3_MMIO_WRITE : VINF_IOM_R3_MMIO_READ; 760 #endif 761 762 /* 763 * Validate the range. 764 */ 765 int rc = IOM_LOCK_SHARED(pVM); 827 * 828 * Also drop back if the ring-0 registration entry isn't actually used. 829 */ 830 if ( cbBuf <= sizeof(pVCpu->iom.s.PendingMmioWrite.abValue) 831 && pRegEntry->cbRegion != 0 832 && ( enmAccessType == PGMACCESSTYPE_READ 833 ? pRegEntry->pfnReadCallback != NULL || pVM->iomr0.s.paMmioRing3Regs[(uintptr_t)pvUser].pfnReadCallback == NULL 834 : pRegEntry->pfnWriteCallback != NULL || pVM->iomr0.s.paMmioRing3Regs[(uintptr_t)pvUser].pfnWriteCallback == NULL) 835 && pDevIns ) 836 { /* likely */ } 837 else 838 { 839 STAM_COUNTER_INC(enmAccessType == PGMACCESSTYPE_READ ? &pStats->ReadRZToR3 : &pStats->WriteRZToR3); 840 STAM_COUNTER_INC(enmAccessType == PGMACCESSTYPE_READ ? &pVM->iom.s.StatRZMMIOReadsToR3 : &pVM->iom.s.StatRZMMIOWritesToR3); 841 return rcToRing3; 842 } 843 #endif /* !IN_RING3 */ 844 845 846 /* 847 * Perform locking and the access. 848 * 849 * Writes requiring a return to ring-3 are buffered by IOM so IEM can 850 * commit the instruction. 851 * 852 * Note! We may end up locking the device even when the relevant callback is 853 * NULL. This is supposed to be an unlikely case, so not optimized yet. 854 */ 855 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), rcToRing3); 856 if (rcStrict == VINF_SUCCESS) 857 { 858 if (enmAccessType == PGMACCESSTYPE_READ) 859 { 860 rcStrict = iomMmioDoRead(pVM, pRegEntry, GCPhysFault, pvBuf, (uint32_t)cbBuf IOM_MMIO_STATS_COMMA_ARG); 861 862 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 766 863 #ifndef IN_RING3 767 if (rc == VERR_SEM_BUSY) 768 { 769 if (enmAccessType == PGMACCESSTYPE_READ) 770 return VINF_IOM_R3_MMIO_READ; 771 Assert(enmAccessType == PGMACCESSTYPE_WRITE); 772 return iomMmioRing3WritePending(pVCpu, GCPhysFault, pvBuf, cbBuf, NULL /*pRange*/); 773 } 774 #endif 775 AssertRC(rc); 776 Assert(pRange == iomMmioGetRange(pVM, pVCpu, GCPhysFault)); 777 778 /* 779 * Perform locking. 780 */ 781 iomMmioRetainRange(pRange); 782 PPDMDEVINS pDevIns = pRange->CTX_SUFF(pDevIns); 783 IOM_UNLOCK_SHARED(pVM); 784 #ifdef IN_RING3 785 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_MMIO_READ_WRITE); 786 #else 787 VBOXSTRICTRC rcStrict = pDevIns ? PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_MMIO_READ_WRITE) 788 : VINF_IOM_R3_MMIO_READ_WRITE; 789 #endif 790 if (rcStrict == VINF_SUCCESS) 791 { 792 /* 793 * Perform the access. 794 */ 795 if (enmAccessType == PGMACCESSTYPE_READ) 796 rcStrict = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, pvBuf, (unsigned)cbBuf); 864 if (rcStrict == VINF_IOM_R3_MMIO_READ) 865 { 866 STAM_COUNTER_INC(&pStats->ReadRZToR3); 867 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOReadsToR3); 868 } 869 else 870 #endif 871 STAM_COUNTER_INC(&pStats->Reads); 872 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfRead), Prf); 873 } 797 874 else 798 875 { 799 rcStrict = iomMMIODoWrite(pVM, pVCpu, pRange, GCPhysFault, pvBuf, (unsigned)cbBuf); 876 rcStrict = iomMmioDoWrite(pVM, pVCpu, pRegEntry, GCPhysFault, pvBuf, (uint32_t)cbBuf IOM_MMIO_STATS_COMMA_ARG); 877 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 800 878 #ifndef IN_RING3 801 879 if (rcStrict == VINF_IOM_R3_MMIO_WRITE) 802 rcStrict = iomMmioRing3WritePending(pVCpu, GCPhysFault, pvBuf, cbBuf, pRange); 803 #endif 804 } 805 806 /* Check the return code. */ 880 rcStrict = iomMmioRing3WritePending(pVCpu, GCPhysFault, pvBuf, cbBuf, pRegEntry->idxSelf); 881 if (rcStrict == VINF_IOM_R3_MMIO_WRITE) 882 { 883 STAM_COUNTER_INC(&pStats->WriteRZToR3); 884 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOWritesToR3); 885 } 886 else if (rcStrict == VINF_IOM_R3_MMIO_COMMIT_WRITE) 887 { 888 STAM_COUNTER_INC(&pStats->CommitRZToR3); 889 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOCommitsToR3); 890 } 891 else 892 #endif 893 STAM_COUNTER_INC(&pStats->Writes); 894 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfWrite), Prf); 895 } 896 897 /* 898 * Check the return code. 899 */ 807 900 #ifdef IN_RING3 808 901 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc - Access type %d - %RGp - %s\n", 809 VBOXSTRICTRC_VAL(rcStrict), enmAccessType, GCPhysFault, pR ange->pszDesc));902 VBOXSTRICTRC_VAL(rcStrict), enmAccessType, GCPhysFault, pRegEntry->pszDesc)); 810 903 #else 811 904 AssertMsg( rcStrict == VINF_SUCCESS 812 || rcStrict == (enmAccessType == PGMACCESSTYPE_READ ? VINF_IOM_R3_MMIO_READ : VINF_IOM_R3_MMIO_WRITE)905 || rcStrict == rcToRing3 813 906 || (rcStrict == VINF_IOM_R3_MMIO_COMMIT_WRITE && enmAccessType == PGMACCESSTYPE_WRITE) 814 || rcStrict == VINF_IOM_R3_MMIO_READ_WRITE815 907 || rcStrict == VINF_EM_DBG_STOP 816 908 || rcStrict == VINF_EM_DBG_EVENT … … 821 913 //|| rcStrict == VINF_EM_HALT /* ?? */ 822 914 //|| rcStrict == VINF_EM_NO_MEMORY /* ?? */ 823 , ("%Rrc - Access type %d - %RGp - %p\n", VBOXSTRICTRC_VAL(rcStrict), enmAccessType, GCPhysFault, pDevIns)); 824 #endif 825 826 iomMmioReleaseRange(pVM, pRange); 827 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 828 } 829 #ifdef IN_RING3 915 , ("%Rrc - Access type %d - %RGp - %s #%u\n", 916 VBOXSTRICTRC_VAL(rcStrict), enmAccessType, GCPhysFault, pDevIns->pReg->szName, pDevIns->iInstance)); 917 #endif 918 } 919 /* 920 * Deal with enter-critsect failures. 921 */ 922 #ifndef IN_RING3 923 else if (rcStrict == VINF_IOM_R3_MMIO_WRITE) 924 { 925 Assert(enmAccessType == PGMACCESSTYPE_WRITE); 926 rcStrict = iomMmioRing3WritePending(pVCpu, GCPhysFault, pvBuf, cbBuf, pRegEntry->idxSelf); 927 if (rcStrict == VINF_IOM_R3_MMIO_COMMIT_WRITE) 928 { 929 STAM_COUNTER_INC(&pStats->CommitRZToR3); 930 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOCommitsToR3); 931 } 932 else 933 { 934 STAM_COUNTER_INC(&pStats->WriteRZToR3); 935 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIOWritesToR3); 936 } 937 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIODevLockContention); 938 } 939 else if (rcStrict == VINF_IOM_R3_MMIO_READ) 940 { 941 Assert(enmAccessType == PGMACCESSTYPE_READ); 942 STAM_COUNTER_INC(&pStats->ReadRZToR3); 943 STAM_COUNTER_INC(&pVM->iom.s.StatRZMMIODevLockContention); 944 } 945 #endif 830 946 else 831 iomMmioReleaseRange(pVM, pRange); 832 #else 833 else 834 { 835 if (rcStrict == VINF_IOM_R3_MMIO_READ_WRITE) 836 { 837 if (enmAccessType == PGMACCESSTYPE_READ) 838 rcStrict = VINF_IOM_R3_MMIO_READ; 839 else 840 { 841 Assert(enmAccessType == PGMACCESSTYPE_WRITE); 842 rcStrict = iomMmioRing3WritePending(pVCpu, GCPhysFault, pvBuf, cbBuf, pRange); 843 } 844 } 845 iomMmioReleaseRange(pVM, pRange); 846 } 847 #endif 947 AssertMsg(RT_FAILURE_NP(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 848 948 return rcStrict; 849 949 } … … 853 953 * Mapping an MMIO2 page in place of an MMIO page for direct access. 854 954 * 855 * (This is a special optimization used by the VGA device.) 955 * This is a special optimization used by the VGA device. Call 956 * IOMMmioResetRegion() to undo the mapping. 856 957 * 857 958 * @returns VBox status code. This API may return VINF_SUCCESS even if no … … 859 960 * 860 961 * @param pVM The cross context VM structure. 861 * @param GCPhys The address of the MMIO page to be changed. 862 * @param GCPhysRemapped The address of the MMIO2 page. 962 * @param pDevIns The device instance @a hRegion and @a hMmio2 are 963 * associated with. 964 * @param hRegion The handle to the MMIO region. 965 * @param offRegion The offset into @a hRegion of the page to be 966 * remapped. 967 * @param hMmio2 The MMIO2 handle. 968 * @param offMmio2 Offset into @a hMmio2 of the page to be use for the 969 * mapping. 863 970 * @param fPageFlags Page flags to set. Must be (X86_PTE_RW | X86_PTE_P) 864 971 * for the time being. 865 972 */ 866 VMMDECL(int) IOMMMIOMapMMIO2Page(PVMCC pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags) 973 VMM_INT_DECL(int) IOMMmioMapMmio2Page(PVMCC pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion, 974 uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags) 867 975 { 868 976 /* Currently only called from the VGA device during MMIO. */ 869 Log(("IOMM MIOMapMMIO2Page %RGp -> %RGp flags=%RX64\n", GCPhys, GCPhysRemapped, fPageFlags));977 Log(("IOMMmioMapMmio2Page %#RX64/%RGp -> %#RX64/%RGp flags=%RX64\n", hRegion, offRegion, hMmio2, offMmio2, fPageFlags)); 870 978 AssertReturn(fPageFlags == (X86_PTE_RW | X86_PTE_P), VERR_INVALID_PARAMETER); 979 AssertReturn(pDevIns, VERR_INVALID_POINTER); 980 981 /** @todo Why is this restricted to protected mode??? Try it in all modes! */ 871 982 PVMCPUCC pVCpu = VMMGetCpu(pVM); 872 983 … … 876 987 || ( CPUMIsGuestInPagedProtectedMode(pVCpu) 877 988 && !HMIsNestedPagingActive(pVM))) 878 return VINF_SUCCESS; /* ignore */ 879 880 int rc = IOM_LOCK_SHARED(pVM); 881 if (RT_FAILURE(rc)) 882 return VINF_SUCCESS; /* better luck the next time around */ 883 884 /* 885 * Lookup the context range node the page belongs to. 886 */ 887 PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhys); 888 AssertMsgReturn(pRange, 889 ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND); 890 891 Assert((pRange->GCPhys & PAGE_OFFSET_MASK) == 0); 892 Assert((pRange->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK); 989 return VINF_SUCCESS; /* ignore */ /** @todo return some indicator if we fail here */ 990 991 /* 992 * Translate the handle into an entry and check the region offset. 993 */ 994 AssertReturn(hRegion < RT_MIN(pVM->iom.s.cMmioRegs, pVM->iom.s.cMmioAlloc), VERR_IOM_INVALID_MMIO_HANDLE); 995 #ifdef IN_RING0 996 AssertReturn(hRegion < pVM->iomr0.s.cMmioAlloc, VERR_IOM_INVALID_MMIO_HANDLE); 997 PIOMMMIOENTRYR3 const pRegEntry = &pVM->iomr0.s.paMmioRing3Regs[hRegion]; 998 AssertReturn(pRegEntry->cbRegion > 0, VERR_IOM_INVALID_MMIO_HANDLE); 999 AssertReturn(offRegion < pVM->iomr0.s.paMmioRegs[hRegion].cbRegion, VERR_OUT_OF_RANGE); 1000 AssertReturn( pVM->iomr0.s.paMmioRegs[hRegion].pDevIns == pDevIns 1001 || ( pVM->iomr0.s.paMmioRegs[hRegion].pDevIns == NULL 1002 && pRegEntry->pDevIns == pDevIns->pDevInsForR3), VERR_ACCESS_DENIED); 1003 #else 1004 PIOMMMIOENTRYR3 const pRegEntry = &pVM->iom.s.paMmioRegs[hRegion]; 1005 AssertReturn(pRegEntry->cbRegion > 0, VERR_IOM_INVALID_MMIO_HANDLE); 1006 AssertReturn(pRegEntry->pDevIns == pDevIns, VERR_ACCESS_DENIED); 1007 #endif 1008 AssertReturn(offRegion < pRegEntry->cbRegion, VERR_OUT_OF_RANGE); 1009 Assert((pRegEntry->cbRegion & PAGE_OFFSET_MASK) == 0); 1010 1011 /* 1012 * When getting and using the mapping address, we must sit on the IOM lock 1013 * to prevent remapping. Shared suffices as we change nothing. 1014 */ 1015 IOM_LOCK_SHARED(pVM); 1016 1017 RTGCPHYS const GCPhys = pRegEntry->fMapped ? pRegEntry->GCPhysMapping : NIL_RTGCPHYS; 1018 AssertReturnStmt(GCPhys != NIL_RTGCPHYS, IOM_UNLOCK_SHARED(pVM), VERR_IOM_MMIO_REGION_NOT_MAPPED); 1019 Assert(!(GCPhys & PAGE_OFFSET_MASK)); 893 1020 894 1021 /* 895 1022 * Do the aliasing; page align the addresses since PGM is picky. 896 1023 */ 897 GCPhys &= ~(RTGCPHYS)PAGE_OFFSET_MASK; 898 GCPhysRemapped &= ~(RTGCPHYS)PAGE_OFFSET_MASK; 899 900 rc = PGMHandlerPhysicalPageAlias(pVM, pRange->GCPhys, GCPhys, GCPhysRemapped); 1024 #if 0 /** @todo fix when DevVGA is converted to new model. */ 1025 int rc = PGMHandlerPhysicalPageAlias(pVM, GCPhys, GCPhys + (offRange & ~(RTGCPHYS)PAGE_OFFSET_MASK), 1026 pDevIns, hMmio2, offMmio2); 1027 #else 1028 AssertFailed(); 1029 int rc = VERR_NOT_IMPLEMENTED; 1030 RT_NOREF(offMmio2, hMmio2); 1031 #endif 901 1032 902 1033 IOM_UNLOCK_SHARED(pVM); 1034 903 1035 AssertRCReturn(rc, rc); 904 1036 1037 /** @todo either ditch this or replace it with something that works in the 1038 * nested case, since we really only care about nested paging! */ 1039 #if 0 905 1040 /* 906 1041 * Modify the shadow page table. Since it's an MMIO page it won't be present and we … … 919 1054 rc = PGMPrefetchPage(pVCpu, (RTGCPTR)GCPhys); 920 1055 Assert(rc == VINF_SUCCESS || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT); 1056 #endif 921 1057 return VINF_SUCCESS; 922 1058 } 923 1059 924 1060 1061 #ifdef IN_RING0 /* VT-x ring-0 only, move to IOMR0Mmio.cpp later. */ 925 1062 /** 926 1063 * Mapping a HC page in place of an MMIO page for direct access. 927 1064 * 928 * (This is a special optimization used by the APIC in the VT-x case.) 1065 * This is a special optimization used by the APIC in the VT-x case. This VT-x 1066 * code uses PGMHandlerPhysicalReset rather than IOMMmioResetRegion() to undo 1067 * the effects here. 1068 * 1069 * @todo Make VT-x usage more consistent. 929 1070 * 930 1071 * @returns VBox status code. … … 937 1078 * for the time being. 938 1079 */ 939 VMM DECL(int) IOMMMIOMapMMIOHCPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags)1080 VMM_INT_DECL(int) IOMR0MmioMapMmioHCPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags) 940 1081 { 941 1082 /* Currently only called from VT-x code during a page fault. */ 942 Log(("IOM MMIOMapMMIOHCPage %RGp -> %RGp flags=%RX64\n", GCPhys, HCPhys, fPageFlags));1083 Log(("IOMR0MmioMapMmioHCPage %RGp -> %RGp flags=%RX64\n", GCPhys, HCPhys, fPageFlags)); 943 1084 944 1085 AssertReturn(fPageFlags == (X86_PTE_RW | X86_PTE_P), VERR_INVALID_PARAMETER); 945 /** @todo NEM: MMIO page aliasing .*/1086 /** @todo NEM: MMIO page aliasing?? */ 946 1087 Assert(HMIsEnabled(pVM)); 947 1088 948 /*949 * Lookup the context range node the page belongs to.950 */951 1089 # ifdef VBOX_STRICT 952 /* Can't lock IOM here due to potential deadlocks in the VGA device; not safe to access. */ 953 PIOMMMIORANGE pRange = iomMMIOGetRangeUnsafe(pVM, pVCpu, GCPhys); 954 AssertMsgReturn(pRange, 955 ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND); 956 Assert((pRange->GCPhys & PAGE_OFFSET_MASK) == 0); 957 Assert((pRange->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK); 1090 /* 1091 * Check input address (it's HM calling, not the device, so no region handle). 1092 */ 1093 IOM_LOCK_SHARED(pVM); 1094 RTGCPHYS offIgn; 1095 uint16_t idxIgn = UINT16_MAX; 1096 PIOMMMIOENTRYR0 pRegEntry = iomMmioGetEntry(pVM, GCPhys, &offIgn, &idxIgn); 1097 IOM_UNLOCK_SHARED(pVM); 1098 Assert(pRegEntry); 1099 Assert(pRegEntry && !(pRegEntry->cbRegion & PAGE_OFFSET_MASK)); 958 1100 # endif 959 1101 … … 966 1108 int rc = PGMHandlerPhysicalPageAliasHC(pVM, GCPhys, GCPhys, HCPhys); 967 1109 AssertRCReturn(rc, rc); 1110 1111 /** @todo either ditch this or replace it with something that works in the 1112 * nested case, since we really only care about nested paging! */ 968 1113 969 1114 /* … … 977 1122 return VINF_SUCCESS; 978 1123 } 1124 #endif 979 1125 980 1126 … … 982 1128 * Reset a previously modified MMIO region; restore the access flags. 983 1129 * 1130 * This undoes the effects of IOMMmioMapMmio2Page() and is currently only 1131 * intended for some ancient VGA hack. However, it would be great to extend it 1132 * beyond VT-x and/or nested-paging. 1133 * 984 1134 * @returns VBox status code. 985 1135 * 986 1136 * @param pVM The cross context VM structure. 987 * @param GCPhys Physical address that's part of the MMIO region to be reset. 988 */ 989 VMMDECL(int) IOMMMIOResetRegion(PVMCC pVM, RTGCPHYS GCPhys) 990 { 991 Log(("IOMMMIOResetRegion %RGp\n", GCPhys)); 992 1137 * @param pDevIns The device instance @a hRegion is associated with. 1138 * @param hRegion The handle to the MMIO region. 1139 */ 1140 VMM_INT_DECL(int) IOMMmioResetRegion(PVMCC pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion) 1141 { 1142 Log(("IOMMMIOResetRegion %#RX64\n", hRegion)); 1143 AssertReturn(pDevIns, VERR_INVALID_POINTER); 1144 1145 /** @todo Get rid of this this real/protected or nested paging restriction, 1146 * it probably shouldn't be here and would be nasty when the CPU 1147 * changes mode while we have the hack enabled... */ 993 1148 PVMCPUCC pVCpu = VMMGetCpu(pVM); 994 1149 995 1150 /* This currently only works in real mode, protected mode without paging or with nested paging. */ 996 1151 /** @todo NEM: MMIO page aliasing. */ 997 if ( 998 || 999 1152 if ( !HMIsEnabled(pVM) /* useless without VT-x/AMD-V */ 1153 || ( CPUMIsGuestInPagedProtectedMode(pVCpu) 1154 && !HMIsNestedPagingActive(pVM))) 1000 1155 return VINF_SUCCESS; /* ignore */ 1001 1156 1002 1157 /* 1003 * Lookup the context range node the page belongs to. 1004 */ 1005 # ifdef VBOX_STRICT 1006 /* Can't lock IOM here due to potential deadlocks in the VGA device; not safe to access. */ 1007 PIOMMMIORANGE pRange = iomMMIOGetRangeUnsafe(pVM, pVCpu, GCPhys); 1008 AssertMsgReturn(pRange, 1009 ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND); 1010 Assert((pRange->GCPhys & PAGE_OFFSET_MASK) == 0); 1011 Assert((pRange->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK); 1012 # endif 1158 * Translate the handle into an entry and mapping address for PGM. 1159 * We have to take the lock to safely access the mapping address here. 1160 */ 1161 AssertReturn(hRegion < RT_MIN(pVM->iom.s.cMmioRegs, pVM->iom.s.cMmioAlloc), VERR_IOM_INVALID_MMIO_HANDLE); 1162 #ifdef IN_RING0 1163 AssertReturn(hRegion < pVM->iomr0.s.cMmioAlloc, VERR_IOM_INVALID_MMIO_HANDLE); 1164 PIOMMMIOENTRYR3 const pRegEntry = &pVM->iomr0.s.paMmioRing3Regs[hRegion]; 1165 AssertReturn(pRegEntry->cbRegion > 0, VERR_IOM_INVALID_MMIO_HANDLE); 1166 AssertReturn( pVM->iomr0.s.paMmioRegs[hRegion].pDevIns == pDevIns 1167 || ( pVM->iomr0.s.paMmioRegs[hRegion].pDevIns == NULL 1168 && pRegEntry->pDevIns == pDevIns->pDevInsForR3), VERR_ACCESS_DENIED); 1169 #else 1170 PIOMMMIOENTRYR3 const pRegEntry = &pVM->iom.s.paMmioRegs[hRegion]; 1171 AssertReturn(pRegEntry->cbRegion > 0, VERR_IOM_INVALID_MMIO_HANDLE); 1172 AssertReturn(pRegEntry->pDevIns == pDevIns, VERR_ACCESS_DENIED); 1173 #endif 1174 Assert((pRegEntry->cbRegion & PAGE_OFFSET_MASK) == 0); 1175 1176 IOM_LOCK_SHARED(pVM); 1177 RTGCPHYS GCPhys = pRegEntry->fMapped ? pRegEntry->GCPhysMapping : NIL_RTGCPHYS; 1178 IOM_UNLOCK_SHARED(pVM); 1179 1180 Assert(!(GCPhys & PAGE_OFFSET_MASK)); 1181 Assert(!(pRegEntry->cbRegion & PAGE_OFFSET_MASK)); 1013 1182 1014 1183 /* 1015 1184 * Call PGM to do the job work. 1016 1185 * 1017 * After the call, all the pages should be non-present ...unless there is1186 * After the call, all the pages should be non-present, unless there is 1018 1187 * a page pool flush pending (unlikely). 1019 1188 */ … … 1024 1193 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3)) 1025 1194 { 1026 uint32_t cb = pRange->cb; 1027 GCPhys = pRange->GCPhys; 1195 RTGCPHYS cb = pRegEntry->cbRegion; 1028 1196 while (cb) 1029 1197 { -
trunk/src/VBox/VMM/VMMR0/IOMR0IoPort.cpp
r81197 r81333 271 271 AssertReturn(pGVM->iom.s.cIoPortStatsAllocation == cOldEntries, VERR_IOM_IOPORT_IPE_1); 272 272 AssertReturn(pGVM->iom.s.cIoPortStats <= cOldEntries, VERR_IOM_IOPORT_IPE_2); 273 AssertReturn(!pGVM->iomr0.s.fIoPortStatsFrozen, VERR_WRONG_ORDER); 273 274 274 275 /* … … 329 330 } 330 331 332 /** 333 * Called after all devices has been instantiated to copy over the statistics 334 * indices to the ring-0 I/O port registration table. 335 * 336 * This simplifies keeping statistics for I/O port ranges that are ring-3 only. 337 * 338 * After this call, IOMR0IoPortGrowStatisticsTable() will stop working. 339 * 340 * @returns VBox status code. 341 * @param pGVM The global (ring-0) VM structure. 342 * @thread EMT(0) 343 * @note Only callable at VM creation time. 344 */ 345 VMMR0_INT_DECL(int) IOMR0IoPortSyncStatisticsIndices(PGVM pGVM) 346 { 347 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT); 348 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE); 349 350 #ifdef VBOX_WITH_STATISTICS 351 /* 352 * First, freeze the statistics array: 353 */ 354 pGVM->iomr0.s.fIoPortStatsFrozen = true; 355 356 /* 357 * Second, synchronize the indices: 358 */ 359 uint32_t const cRegs = RT_MIN(pGVM->iom.s.cIoPortRegs, pGVM->iomr0.s.cIoPortAlloc); 360 uint32_t const cStatsAlloc = pGVM->iomr0.s.cIoPortStatsAllocation; 361 PIOMIOPORTENTRYR0 paIoPortRegs = pGVM->iomr0.s.paIoPortRegs; 362 IOMIOPORTENTRYR3 const *paIoPortRegsR3 = pGVM->iomr0.s.paIoPortRing3Regs; 363 AssertReturn((paIoPortRegs && paIoPortRegsR3) || cRegs == 0, VERR_IOM_IOPORT_IPE_3); 364 365 for (uint32_t i = 0 ; i < cRegs; i++) 366 { 367 uint16_t idxStats = paIoPortRegsR3[i].idxStats; 368 paIoPortRegs[i].idxStats = idxStats < cStatsAlloc ? idxStats : UINT16_MAX; 369 } 370 371 #else 372 RT_NOREF(pGVM); 373 #endif 374 return VINF_SUCCESS; 375 } 376 -
trunk/src/VBox/VMM/VMMR0/IOMR0Mmio.cpp
r81197 r81333 268 268 AssertReturn(pGVM->iom.s.cMmioStatsAllocation == cOldEntries, VERR_IOM_MMIO_IPE_1); 269 269 AssertReturn(pGVM->iom.s.cMmioStats <= cOldEntries, VERR_IOM_MMIO_IPE_2); 270 AssertReturn(!pGVM->iomr0.s.fMmioStatsFrozen, VERR_WRONG_ORDER); 270 271 271 272 /* … … 326 327 } 327 328 329 330 /** 331 * Called after all devices has been instantiated to copy over the statistics 332 * indices to the ring-0 MMIO registration table. 333 * 334 * This simplifies keeping statistics for MMIO ranges that are ring-3 only. 335 * 336 * @returns VBox status code. 337 * @param pGVM The global (ring-0) VM structure. 338 * @thread EMT(0) 339 * @note Only callable at VM creation time. 340 */ 341 VMMR0_INT_DECL(int) IOMR0MmioSyncStatisticsIndices(PGVM pGVM) 342 { 343 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT); 344 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE); 345 346 #ifdef VBOX_WITH_STATISTICS 347 /* 348 * First, freeze the statistics array: 349 */ 350 pGVM->iomr0.s.fMmioStatsFrozen = true; 351 352 /* 353 * Second, synchronize the indices: 354 */ 355 uint32_t const cRegs = RT_MIN(pGVM->iom.s.cMmioRegs, pGVM->iomr0.s.cMmioAlloc); 356 uint32_t const cStatsAlloc = pGVM->iomr0.s.cMmioStatsAllocation; 357 PIOMMMIOENTRYR0 paMmioRegs = pGVM->iomr0.s.paMmioRegs; 358 IOMMMIOENTRYR3 const *paMmioRegsR3 = pGVM->iomr0.s.paMmioRing3Regs; 359 AssertReturn((paMmioRegs && paMmioRegsR3) || cRegs == 0, VERR_IOM_MMIO_IPE_3); 360 361 for (uint32_t i = 0 ; i < cRegs; i++) 362 { 363 uint16_t idxStats = paMmioRegsR3[i].idxStats; 364 paMmioRegs[i].idxStats = idxStats < cStatsAlloc ? idxStats : UINT16_MAX; 365 } 366 367 #else 368 RT_NOREF(pGVM); 369 #endif 370 return VINF_SUCCESS; 371 } 372 -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r81197 r81333 2217 2217 } 2218 2218 2219 case VMMR0_DO_IOM_SYNC_STATS_INDICES: 2220 { 2221 if (pReqHdr || idCpu != 0) 2222 return VERR_INVALID_PARAMETER; 2223 rc = IOMR0IoPortSyncStatisticsIndices(pGVM); 2224 if (RT_SUCCESS(rc)) 2225 rc = IOMR0MmioSyncStatisticsIndices(pGVM); 2226 VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING); 2227 break; 2228 } 2229 2219 2230 /* 2220 2231 * For profiling. -
trunk/src/VBox/VMM/VMMR3/IOM.cpp
r81167 r81333 138 138 static DECLCALLBACK(int) iomR3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser); 139 139 #endif 140 static DECLCALLBACK(void) iomR3MMIOInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);141 140 static FNIOMIOPORTIN iomR3IOPortDummyIn; 142 141 static FNIOMIOPORTOUT iomR3IOPortDummyOut; … … 180 179 */ 181 180 rc = MMHyperAlloc(pVM, sizeof(*pVM->iom.s.pTreesR3), 0, MM_TAG_IOM, (void **)&pVM->iom.s.pTreesR3); 182 if (RT_SUCCESS(rc)) 183 { 184 pVM->iom.s.pTreesR0 = MMHyperR3ToR0(pVM, pVM->iom.s.pTreesR3); 185 186 /* 187 * Register the MMIO access handler type. 188 */ 189 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_MMIO, 190 iomMmioHandler, 191 NULL, "iomMmioHandler", "iomMmioPfHandler", 192 NULL, "iomMmioHandler", "iomMmioPfHandler", 193 "MMIO", &pVM->iom.s.hMmioHandlerType); 194 AssertRC(rc); 195 if (RT_SUCCESS(rc)) 196 { 197 198 /* 199 * Info. 200 */ 201 DBGFR3InfoRegisterInternal(pVM, "ioport", "Dumps all IOPort ranges. No arguments.", &iomR3IoPortInfo); 202 DBGFR3InfoRegisterInternal(pVM, "mmio", "Dumps all MMIO ranges. No arguments.", &iomR3MMIOInfo); 203 204 /* 205 * Statistics. 206 */ 207 STAM_REG(pVM, &pVM->iom.s.StatRZMMIOHandler, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler", STAMUNIT_TICKS_PER_CALL, "Profiling of the iomMmioPfHandler() body, only success calls."); 208 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO1Byte, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access1", STAMUNIT_OCCURENCES, "MMIO access by 1 byte counter."); 209 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO2Bytes, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access2", STAMUNIT_OCCURENCES, "MMIO access by 2 bytes counter."); 210 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO4Bytes, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access4", STAMUNIT_OCCURENCES, "MMIO access by 4 bytes counter."); 211 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO8Bytes, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access8", STAMUNIT_OCCURENCES, "MMIO access by 8 bytes counter."); 212 STAM_REG(pVM, &pVM->iom.s.StatRZMMIOFailures, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/MMIOFailures", STAMUNIT_OCCURENCES, "Number of times iomMmioPfHandler() didn't service the request."); 213 STAM_REG(pVM, &pVM->iom.s.StatRZInstMov, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/MOV", STAMUNIT_TICKS_PER_CALL, "Profiling of the MOV instruction emulation."); 214 STAM_REG(pVM, &pVM->iom.s.StatRZInstCmp, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/CMP", STAMUNIT_TICKS_PER_CALL, "Profiling of the CMP instruction emulation."); 215 STAM_REG(pVM, &pVM->iom.s.StatRZInstAnd, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/AND", STAMUNIT_TICKS_PER_CALL, "Profiling of the AND instruction emulation."); 216 STAM_REG(pVM, &pVM->iom.s.StatRZInstOr, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/OR", STAMUNIT_TICKS_PER_CALL, "Profiling of the OR instruction emulation."); 217 STAM_REG(pVM, &pVM->iom.s.StatRZInstXor, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/XOR", STAMUNIT_TICKS_PER_CALL, "Profiling of the XOR instruction emulation."); 218 STAM_REG(pVM, &pVM->iom.s.StatRZInstBt, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/BT", STAMUNIT_TICKS_PER_CALL, "Profiling of the BT instruction emulation."); 219 STAM_REG(pVM, &pVM->iom.s.StatRZInstTest, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/TEST", STAMUNIT_TICKS_PER_CALL, "Profiling of the TEST instruction emulation."); 220 STAM_REG(pVM, &pVM->iom.s.StatRZInstXchg, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/XCHG", STAMUNIT_TICKS_PER_CALL, "Profiling of the XCHG instruction emulation."); 221 STAM_REG(pVM, &pVM->iom.s.StatRZInstStos, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/STOS", STAMUNIT_TICKS_PER_CALL, "Profiling of the STOS instruction emulation."); 222 STAM_REG(pVM, &pVM->iom.s.StatRZInstLods, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/LODS", STAMUNIT_TICKS_PER_CALL, "Profiling of the LODS instruction emulation."); 223 #ifdef IOM_WITH_MOVS_SUPPORT 224 STAM_REG(pVM, &pVM->iom.s.StatRZInstMovs, STAMTYPE_PROFILE_ADV, "/IOM/RZ-MMIOHandler/Inst/MOVS", STAMUNIT_TICKS_PER_CALL, "Profiling of the MOVS instruction emulation."); 225 STAM_REG(pVM, &pVM->iom.s.StatRZInstMovsToMMIO, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/MOVS/ToMMIO", STAMUNIT_TICKS_PER_CALL, "Profiling of the MOVS instruction emulation - Mem2MMIO."); 226 STAM_REG(pVM, &pVM->iom.s.StatRZInstMovsFromMMIO, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/MOVS/FromMMIO", STAMUNIT_TICKS_PER_CALL, "Profiling of the MOVS instruction emulation - MMIO2Mem."); 227 STAM_REG(pVM, &pVM->iom.s.StatRZInstMovsMMIO, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler/Inst/MOVS/MMIO2MMIO", STAMUNIT_TICKS_PER_CALL, "Profiling of the MOVS instruction emulation - MMIO2MMIO."); 181 AssertRCReturn(rc, rc); 182 pVM->iom.s.pTreesR0 = MMHyperR3ToR0(pVM, pVM->iom.s.pTreesR3); 183 184 /* 185 * Register the MMIO access handler type. 186 */ 187 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_MMIO, 188 iomMmioHandler, 189 NULL, "iomMmioHandler", "iomMmioPfHandler", 190 NULL, "iomMmioHandler", "iomMmioPfHandler", 191 "MMIO", &pVM->iom.s.hMmioHandlerType); 192 AssertRCReturn(rc, rc); 193 194 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_MMIO, 195 iomMmioHandlerNew, 196 NULL, "iomMmioHandlerNew", "iomMmioPfHandlerNew", 197 NULL, "iomMmioHandlerNew", "iomMmioPfHandlerNew", 198 "MMIO", &pVM->iom.s.hNewMmioHandlerType); 199 AssertRCReturn(rc, rc); 200 201 /* 202 * Info. 203 */ 204 DBGFR3InfoRegisterInternal(pVM, "ioport", "Dumps all IOPort ranges. No arguments.", &iomR3IoPortInfo); 205 DBGFR3InfoRegisterInternal(pVM, "mmio", "Dumps all MMIO ranges. No arguments.", &iomR3MmioInfo); 206 207 /* 208 * Statistics. 209 */ 210 STAM_REG(pVM, &pVM->iom.s.StatRZMMIOHandler, STAMTYPE_PROFILE, "/IOM/RZ-MMIOHandler", STAMUNIT_TICKS_PER_CALL, "Profiling of the iomMmioPfHandler() body, only success calls."); 211 #if 0 212 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO1Byte, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access1", STAMUNIT_OCCURENCES, "MMIO access by 1 byte counter."); 213 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO2Bytes, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access2", STAMUNIT_OCCURENCES, "MMIO access by 2 bytes counter."); 214 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO4Bytes, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access4", STAMUNIT_OCCURENCES, "MMIO access by 4 bytes counter."); 215 STAM_REG(pVM, &pVM->iom.s.StatRZMMIO8Bytes, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Access8", STAMUNIT_OCCURENCES, "MMIO access by 8 bytes counter."); 228 216 #endif 229 STAM_REG(pVM, &pVM->iom.s.StatRZInstOther, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Inst/Other", STAMUNIT_OCCURENCES, "Other instructions counter."); 230 STAM_REG(pVM, &pVM->iom.s.StatR3MMIOHandler, STAMTYPE_COUNTER, "/IOM/R3-MMIOHandler", STAMUNIT_OCCURENCES, "Number of calls to iomR3MmioHandler."); 231 #if 0 /* unused */ 232 STAM_REG(pVM, &pVM->iom.s.StatInstIn, STAMTYPE_COUNTER, "/IOM/IOWork/In", STAMUNIT_OCCURENCES, "Counter of any IN instructions."); 233 STAM_REG(pVM, &pVM->iom.s.StatInstOut, STAMTYPE_COUNTER, "/IOM/IOWork/Out", STAMUNIT_OCCURENCES, "Counter of any OUT instructions."); 234 STAM_REG(pVM, &pVM->iom.s.StatInstIns, STAMTYPE_COUNTER, "/IOM/IOWork/Ins", STAMUNIT_OCCURENCES, "Counter of any INS instructions."); 235 STAM_REG(pVM, &pVM->iom.s.StatInstOuts, STAMTYPE_COUNTER, "/IOM/IOWork/Outs", STAMUNIT_OCCURENCES, "Counter of any OUTS instructions."); 236 #endif 237 } 238 } 217 STAM_REG(pVM, &pVM->iom.s.StatRZMMIOReadsToR3, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/ReadsToR3", STAMUNIT_OCCURENCES, "Number of read deferred to ring-3."); 218 STAM_REG(pVM, &pVM->iom.s.StatRZMMIOWritesToR3, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/WritesToR3", STAMUNIT_OCCURENCES, "Number of writes deferred to ring-3."); 219 STAM_REG(pVM, &pVM->iom.s.StatRZMMIOCommitsToR3, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/CommitsToR3", STAMUNIT_OCCURENCES, "Number of commits deferred to ring-3."); 220 STAM_REG(pVM, &pVM->iom.s.StatRZMMIODevLockContention, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/DevLockContention", STAMUNIT_OCCURENCES, "Number of device lock contention force return to ring-3."); 221 STAM_REG(pVM, &pVM->iom.s.StatR3MMIOHandler, STAMTYPE_COUNTER, "/IOM/R3-MMIOHandler", STAMUNIT_OCCURENCES, "Number of calls to iomMmioHandler."); 222 223 STAM_REG(pVM, &pVM->iom.s.StatMmioHandlerR3, STAMTYPE_COUNTER, "/IOM/MmioHandlerR3", STAMUNIT_OCCURENCES, "Number of calls to iomMmioHandlerNew from ring-3."); 224 STAM_REG(pVM, &pVM->iom.s.StatMmioHandlerR0, STAMTYPE_COUNTER, "/IOM/MmioHandlerR0", STAMUNIT_OCCURENCES, "Number of calls to iomMmioHandlerNew from ring-0."); 239 225 240 226 /* Redundant, but just in case we change something in the future */ 241 227 iomR3FlushCache(pVM); 242 228 243 LogFlow(("IOMR3Init: returns %Rrc\n", rc));244 return rc;229 LogFlow(("IOMR3Init: returns VINF_SUCCESS\n")); 230 return VINF_SUCCESS; 245 231 } 246 232 … … 258 244 if (enmWhat == VMINITCOMPLETED_RING3) 259 245 { 246 /* 247 * Synchronize the ring-3 I/O port and MMIO statistics indices into the 248 * ring-0 tables to simplify ring-0 code. This also make sure that any 249 * later calls to grow the statistics tables will fail. 250 */ 251 int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_SYNC_STATS_INDICES, 0, NULL); 252 AssertLogRelRCReturn(rc, rc); 253 254 /* 255 * Register I/O port and MMIO stats now that we're done registering MMIO 256 * regions and won't grow the table again. 257 */ 260 258 for (uint32_t i = 0; i < pVM->iom.s.cIoPortRegs; i++) 261 259 { … … 264 262 && pRegEntry->idxStats != UINT16_MAX) 265 263 iomR3IoPortRegStats(pVM, pRegEntry); 264 } 265 266 for (uint32_t i = 0; i < pVM->iom.s.cMmioRegs; i++) 267 { 268 PIOMMMIOENTRYR3 pRegEntry = &pVM->iom.s.paMmioRegs[i]; 269 if ( pRegEntry->fMapped 270 && pRegEntry->idxStats != UINT16_MAX) 271 iomR3MmioRegStats(pVM, pRegEntry); 266 272 } 267 273 } … … 1305 1311 AssertMsgReturn(GCPhysStart + (cbRange - 1) >= GCPhysStart,("Wrapped! %RGp LB %RGp\n", GCPhysStart, cbRange), 1306 1312 VERR_IOM_INVALID_MMIO_RANGE); 1307 AssertMsgReturn( !(fFlags & ~ IOMMMIO_FLAGS_VALID_MASK)1313 AssertMsgReturn( !(fFlags & ~(IOMMMIO_FLAGS_VALID_MASK & ~IOMMMIO_FLAGS_ABS)) 1308 1314 && (fFlags & IOMMMIO_FLAGS_READ_MODE) <= IOMMMIO_FLAGS_READ_DWORD_QWORD 1309 1315 && (fFlags & IOMMMIO_FLAGS_WRITE_MODE) <= IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD, … … 1952 1958 /** @todo IOM debug events. */ 1953 1959 RT_NOREF3(pVM, enmEvent, fEnabled); 1954 }1955 1956 1957 /**1958 * Display a single MMIO range.1959 *1960 * @returns 01961 * @param pNode Pointer to MMIO R3 range.1962 * @param pvUser Pointer to info output callback structure.1963 */1964 static DECLCALLBACK(int) iomR3MMIOInfoOne(PAVLROGCPHYSNODECORE pNode, void *pvUser)1965 {1966 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode;1967 PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;1968 pHlp->pfnPrintf(pHlp,1969 "%RGp-%RGp %RHv %RHv %RHv %RHv %RHv %s\n",1970 pRange->Core.Key,1971 pRange->Core.KeyLast,1972 pRange->pDevInsR3,1973 pRange->pfnReadCallbackR3,1974 pRange->pfnWriteCallbackR3,1975 pRange->pfnFillCallbackR3,1976 pRange->pvUserR3,1977 pRange->pszDesc);1978 pHlp->pfnPrintf(pHlp,1979 "%*s %RHv %RHv %RHv %RHv %RHv\n",1980 sizeof(RTGCPHYS) * 2 * 2 + 1, "R0",1981 pRange->pDevInsR0,1982 pRange->pfnReadCallbackR0,1983 pRange->pfnWriteCallbackR0,1984 pRange->pfnFillCallbackR0,1985 pRange->pvUserR0);1986 #if 01987 pHlp->pfnPrintf(pHlp,1988 "%*s %RRv %RRv %RRv %RRv %RRv\n",1989 sizeof(RTGCPHYS) * 2 * 2 + 1, "RC",1990 pRange->pDevInsRC,1991 pRange->pfnReadCallbackRC,1992 pRange->pfnWriteCallbackRC,1993 pRange->pfnFillCallbackRC,1994 pRange->pvUserRC);1995 #endif1996 return 0;1997 }1998 1999 2000 /**2001 * Display registered MMIO ranges to the log.2002 *2003 * @param pVM The cross context VM structure.2004 * @param pHlp The info helpers.2005 * @param pszArgs Arguments, ignored.2006 */2007 static DECLCALLBACK(void) iomR3MMIOInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)2008 {2009 NOREF(pszArgs);2010 pHlp->pfnPrintf(pHlp,2011 "MMIO ranges (pVM=%p)\n"2012 "%.*s %.*s %.*s %.*s %.*s %.*s %s\n",2013 pVM,2014 sizeof(RTGCPHYS) * 4 + 1, "GC Phys Range ",2015 sizeof(RTHCPTR) * 2, "pDevIns ",2016 sizeof(RTHCPTR) * 2, "Read ",2017 sizeof(RTHCPTR) * 2, "Write ",2018 sizeof(RTHCPTR) * 2, "Fill ",2019 sizeof(RTHCPTR) * 2, "pvUser ",2020 "Description");2021 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesR3->MMIOTree, true, iomR3MMIOInfoOne, (void *)pHlp);2022 1960 } 2023 1961 -
trunk/src/VBox/VMM/VMMR3/IOMR3Mmio.cpp
r81197 r81333 61 61 62 62 /* Register statistics: */ 63 int rc = STAMR3Register(pVM, &p Stats->Accesses, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc); AssertRC(rc);63 int rc = STAMR3Register(pVM, &pRegEntry->idxSelf, STAMTYPE_U16, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_NONE, pszDesc); AssertRC(rc); 64 64 RTStrFree(pszFreeDesc); 65 65 66 66 # define SET_NM_SUFFIX(a_sz) memcpy(&szName[cchPrefix], a_sz, sizeof(a_sz)) 67 SET_NM_SUFFIX("/Read-Complicated"); 68 rc = STAMR3Register(pVM, &pStats->ComplicatedReads, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 69 SET_NM_SUFFIX("/Read-FFor00"); 70 rc = STAMR3Register(pVM, &pStats->FFor00Reads, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 67 71 SET_NM_SUFFIX("/Read-R3"); 68 72 rc = STAMR3Register(pVM, &pStats->ProfReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, NULL); AssertRC(rc); 69 SET_NM_SUFFIX("/Write-R3");70 rc = STAMR3Register(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, NULL); AssertRC(rc);71 73 SET_NM_SUFFIX("/Read-RZ"); 72 74 rc = STAMR3Register(pVM, &pStats->ProfReadRZ, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, NULL); AssertRC(rc); 75 SET_NM_SUFFIX("/Read-RZtoR3"); 76 rc = STAMR3Register(pVM, &pStats->ReadRZToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 77 SET_NM_SUFFIX("/Read-Total"); 78 rc = STAMR3Register(pVM, &pStats->Reads, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 79 80 SET_NM_SUFFIX("/Write-Complicated"); 81 rc = STAMR3Register(pVM, &pStats->ComplicatedWrites, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 82 SET_NM_SUFFIX("/Write-R3"); 83 rc = STAMR3Register(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, NULL); AssertRC(rc); 73 84 SET_NM_SUFFIX("/Write-RZ"); 74 85 rc = STAMR3Register(pVM, &pStats->ProfWriteRZ, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, NULL); AssertRC(rc); 75 SET_NM_SUFFIX("/Read-RZtoR3");76 rc = STAMR3Register(pVM, &pStats->ReadRZToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc);77 86 SET_NM_SUFFIX("/Write-RZtoR3"); 78 87 rc = STAMR3Register(pVM, &pStats->WriteRZToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 88 SET_NM_SUFFIX("/Write-RZtoR3-Commit"); 89 rc = STAMR3Register(pVM, &pStats->CommitRZToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 90 SET_NM_SUFFIX("/Write-Total"); 91 rc = STAMR3Register(pVM, &pStats->Writes, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, NULL); AssertRC(rc); 79 92 } 80 93 … … 111 124 112 125 AssertMsgReturn(cbRegion > 0 && !(cbRegion & PAGE_OFFSET_MASK), ("cbRegion=%RGp\n", cbRegion), VERR_OUT_OF_RANGE); 113 AssertReturn(!(fFlags & ~IOM _MMIO_F_VALID_MASK), VERR_INVALID_FLAGS);126 AssertReturn(!(fFlags & ~IOMMMIO_FLAGS_VALID_MASK), VERR_INVALID_FLAGS); 114 127 115 128 AssertReturn(pfnWrite || pfnRead || pfnFill, VERR_INVALID_PARAMETER); … … 218 231 else 219 232 { 233 /* Register with PGM before we shuffle the array: */ 234 rc = PGMR3PhysMMIORegister(pVM, GCPhys, cbRegion, pVM->iom.s.hNewMmioHandlerType, 235 (void *)(uintptr_t)hRegion, hRegion, hRegion, pRegEntry->pszDesc); 236 AssertRCReturnStmt(rc, IOM_UNLOCK_EXCL(pVM), rc); 237 220 238 /* Insert after the entry we just considered: */ 221 239 pEntry += 1; … … 231 249 else 232 250 { 251 /* Register with PGM before we shuffle the array: */ 252 rc = PGMR3PhysMMIORegister(pVM, GCPhys, cbRegion, pVM->iom.s.hNewMmioHandlerType, 253 (void *)(uintptr_t)hRegion, hRegion, hRegion, pRegEntry->pszDesc); 254 AssertRCReturnStmt(rc, IOM_UNLOCK_EXCL(pVM), rc); 255 233 256 /* Insert at the entry we just considered: */ 234 257 if (i < cEntries) … … 366 389 pRegEntry->GCPhysMapping = NIL_RTGCPHYS; 367 390 pRegEntry->fMapped = false; 368 rc = VINF_SUCCESS; 391 rc = PGMR3PhysMMIODeregister(pVM, GCPhys, pRegEntry->cbRegion); 392 AssertRC(rc); 369 393 break; 370 394 } -
trunk/src/VBox/VMM/include/IOMInline.h
r80679 r81333 37 37 * 38 38 * @param pVM The cross context VM structure. 39 * @param uPort The I/O port lookup.40 * @param poffPort Where to the port offset relative to the start of41 * the I/O port range.39 * @param uPort The I/O port to lookup. 40 * @param poffPort Where to return the port offset relative to the 41 * start of the I/O port range. 42 42 * @param pidxLastHint Pointer to IOMCPU::idxIoPortLastRead or 43 43 * IOMCPU::idxIoPortLastWrite. … … 47 47 * for the entry. Use IOMIOPORTENTRYR0::idxSelf to get the ring-3 48 48 * entry. 49 * 50 * @note This code is almost identical to iomMmioGetEntry, so keep in sync. 49 51 */ 50 52 DECLINLINE(CTX_SUFF(PIOMIOPORTENTRY)) iomIoPortGetEntry(PVMCC pVM, RTIOPORT uPort, PRTIOPORT poffPort, uint16_t *pidxLastHint) … … 117 119 #ifdef VBOX_WITH_STATISTICS 118 120 /** 119 * Gets the I/O port statistics entry.121 * Gets the statistics entry for an I/O port. 120 122 * 121 123 * @returns Pointer to stats. Instead of NULL, a pointer to IoPortDummyStats is … … 139 141 # endif 140 142 return &pVM->iom.s.IoPortDummyStats; 143 } 144 #endif 145 146 147 /** 148 * Gets the MMIO region entry for the specified address in the current context. 149 * 150 * @returns Pointer to MMIO region entry. 151 * @returns NULL if no MMIO region registered for the given address. 152 * 153 * @param pVM The cross context VM structure. 154 * @param GCPhys The address to lookup. 155 * @param poffRegion Where to return the byte offset into the MMIO 156 * region that corresponds to @a GCPhys. 157 * @param pidxLastHint Pointer to IOMCPU::idxMmioLastRead, 158 * IOMCPU::idxMmioLastWrite, or similar. 159 * 160 * @note In ring-0 it is possible to get an uninitialized entry (pDevIns is 161 * NULL, cbRegion is 0), in which case there should be ring-3 handlers 162 * for the entry. Use IOMMMIOENTRYR0::idxSelf to get the ring-3 entry. 163 * 164 * @note This code is almost identical to iomIoPortGetEntry, so keep in sync. 165 */ 166 DECLINLINE(CTX_SUFF(PIOMMMIOENTRY)) iomMmioGetEntry(PVMCC pVM, RTGCPHYS GCPhys, PRTGCPHYS poffRegion, uint16_t *pidxLastHint) 167 { 168 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM)); 169 170 #ifdef IN_RING0 171 uint32_t iEnd = RT_MIN(pVM->iom.s.cMmioLookupEntries, pVM->iomr0.s.cMmioAlloc); 172 PCIOMMMIOLOOKUPENTRY paLookup = pVM->iomr0.s.paMmioLookup; 173 #else 174 uint32_t iEnd = pVM->iom.s.cMmioLookupEntries; 175 PCIOMMMIOLOOKUPENTRY paLookup = pVM->iom.s.paMmioLookup; 176 #endif 177 if (iEnd > 0) 178 { 179 uint32_t iFirst = 0; 180 uint32_t i = *pidxLastHint; 181 if (i < iEnd) 182 { /* likely */ } 183 else 184 i = iEnd / 2; 185 for (;;) 186 { 187 PCIOMMMIOLOOKUPENTRY pCur = &paLookup[i]; 188 if (pCur->GCPhysFirst > GCPhys) 189 { 190 if (i > iFirst) 191 iEnd = i; 192 else 193 break; 194 } 195 else if (pCur->GCPhysLast < GCPhys) 196 { 197 i += 1; 198 if (i < iEnd) 199 iFirst = i; 200 else 201 break; 202 } 203 else 204 { 205 *pidxLastHint = (uint16_t)i; 206 *poffRegion = GCPhys - pCur->GCPhysFirst; 207 208 /* 209 * Translate the 'idx' member into a pointer. 210 */ 211 size_t const idx = pCur->idx; 212 #ifdef IN_RING0 213 AssertMsg(idx < pVM->iom.s.cMmioRegs && idx < pVM->iomr0.s.cMmioAlloc, 214 ("%#zx vs %#x/%x (GCPhys=%RGp)\n", idx, pVM->iom.s.cMmioRegs, pVM->iomr0.s.cMmioMax, GCPhys)); 215 if (idx < pVM->iomr0.s.cMmioAlloc) 216 return &pVM->iomr0.s.paMmioRegs[idx]; 217 #else 218 if (idx < pVM->iom.s.cMmioRegs) 219 return &pVM->iom.s.paMmioRegs[idx]; 220 AssertMsgFailed(("%#zx vs %#x (GCPhys=%RGp)\n", idx, pVM->iom.s.cMmioRegs, GCPhys)); 221 #endif 222 break; 223 } 224 225 i = iFirst + (iEnd - iFirst) / 2; 226 } 227 } 228 *poffRegion = 0; 229 return NULL; 230 } 231 232 233 #ifdef VBOX_WITH_STATISTICS 234 /** 235 * Gets the statistics entry for an MMIO region. 236 * 237 * @returns Pointer to stats. Instead of NULL, a pointer to MmioDummyStats is 238 * returned, so the caller does not need to check for NULL. 239 * 240 * @param pVM The cross context VM structure. 241 * @param pRegEntry The I/O port entry to get stats for. 242 */ 243 DECLINLINE(PIOMMMIOSTATSENTRY) iomMmioGetStats(PVMCC pVM, CTX_SUFF(PIOMMMIOENTRY) pRegEntry) 244 { 245 size_t idxStats = pRegEntry->idxStats; 246 # ifdef IN_RING0 247 if (idxStats < pVM->iomr0.s.cMmioStatsAllocation) 248 return &pVM->iomr0.s.paMmioStats[idxStats]; 249 # else 250 if (idxStats < pVM->iom.s.cMmioStats) 251 return &pVM->iom.s.paMmioStats[idxStats]; 252 # endif 253 return &pVM->iom.s.MmioDummyStats; 141 254 } 142 255 #endif -
trunk/src/VBox/VMM/include/IOMInternal.h
r81197 r81333 307 307 /** Pointer to the fill callback function. */ 308 308 R0PTRTYPE(PFNIOMMMIONEWFILL) pfnFillCallback; 309 /** The entry of the first statistics entry, UINT16_MAX if no stats. */ 309 /** The entry of the first statistics entry, UINT16_MAX if no stats. 310 * @note For simplicity, this is always copied from ring-3 for all entries at 311 * the end of VM creation. */ 310 312 uint16_t idxStats; 311 313 /** Same as the handle index. */ … … 371 373 typedef struct IOMMMIOSTATSENTRY 372 374 { 373 /** Number of accesses (subtract ReadRZToR3 and WriteRZToR3 to get the right 374 * number). */ 375 STAMCOUNTER Accesses; 376 375 /** Counting and profiling reads in R0/RC. */ 376 STAMPROFILE ProfReadRZ; 377 /** Number of successful read accesses. */ 378 STAMCOUNTER Reads; 379 /** Number of reads to this address from R0/RC which was serviced in R3. */ 380 STAMCOUNTER ReadRZToR3; 381 /** Number of complicated reads. */ 382 STAMCOUNTER ComplicatedReads; 383 /** Number of reads of 0xff or 0x00. */ 384 STAMCOUNTER FFor00Reads; 377 385 /** Profiling read handler overhead in R3. */ 378 386 STAMPROFILE ProfReadR3; 387 388 /** Counting and profiling writes in R0/RC. */ 389 STAMPROFILE ProfWriteRZ; 390 /** Number of successful read accesses. */ 391 STAMCOUNTER Writes; 392 /** Number of writes to this address from R0/RC which was serviced in R3. */ 393 STAMCOUNTER WriteRZToR3; 394 /** Number of writes to this address from R0/RC which was committed in R3. */ 395 STAMCOUNTER CommitRZToR3; 396 /** Number of complicated writes. */ 397 STAMCOUNTER ComplicatedWrites; 379 398 /** Profiling write handler overhead in R3. */ 380 399 STAMPROFILE ProfWriteR3; 381 /** Counting and profiling reads in R0/RC. */382 STAMPROFILE ProfReadRZ;383 /** Counting and profiling writes in R0/RC. */384 STAMPROFILE ProfWriteRZ;385 386 /** Number of reads to this address from R0/RC which was serviced in R3. */387 STAMCOUNTER ReadRZToR3;388 /** Number of writes to this address from R0/RC which was serviced in R3. */389 STAMCOUNTER WriteRZToR3;390 400 } IOMMMIOSTATSENTRY; 391 401 /** Pointer to MMIO statistics entry. */ … … 602 612 /** Guest physical MMIO address. */ 603 613 RTGCPHYS GCPhys; 614 /** The number of bytes to write (0 if nothing pending). */ 615 uint32_t cbValue; 616 /** Hint. */ 617 uint32_t idxMmioRegionHint; 604 618 /** The value to write. */ 605 619 uint8_t abValue[128]; 606 /** The number of bytes to write (0 if nothing pending). */607 uint32_t cbValue;608 /** Alignment padding. */609 uint32_t uAlignmentPadding;610 620 } PendingMmioWrite; 611 621 … … 654 664 /** MMIO physical access handler type. */ 655 665 PGMPHYSHANDLERTYPE hMmioHandlerType; 656 uint32_t u32Padding; 666 /** MMIO physical access handler type, new style. */ 667 PGMPHYSHANDLERTYPE hNewMmioHandlerType; 657 668 658 669 /** @name I/O ports … … 729 740 * @{ */ 730 741 STAMPROFILE StatRZMMIOHandler; 731 STAMCOUNTER StatRZMMIOFailures; 732 733 STAMPROFILE StatRZInstMov; 734 STAMPROFILE StatRZInstCmp; 735 STAMPROFILE StatRZInstAnd; 736 STAMPROFILE StatRZInstOr; 737 STAMPROFILE StatRZInstXor; 738 STAMPROFILE StatRZInstBt; 739 STAMPROFILE StatRZInstTest; 740 STAMPROFILE StatRZInstXchg; 741 STAMPROFILE StatRZInstStos; 742 STAMPROFILE StatRZInstLods; 743 #ifdef IOM_WITH_MOVS_SUPPORT 744 STAMPROFILEADV StatRZInstMovs; 745 STAMPROFILE StatRZInstMovsToMMIO; 746 STAMPROFILE StatRZInstMovsFromMMIO; 747 STAMPROFILE StatRZInstMovsMMIO; 748 #endif 749 STAMCOUNTER StatRZInstOther; 750 742 STAMCOUNTER StatRZMMIOReadsToR3; 743 STAMCOUNTER StatRZMMIOWritesToR3; 744 STAMCOUNTER StatRZMMIOCommitsToR3; 745 STAMCOUNTER StatRZMMIODevLockContention; 746 #if 0 751 747 STAMCOUNTER StatRZMMIO1Byte; 752 748 STAMCOUNTER StatRZMMIO2Bytes; 753 749 STAMCOUNTER StatRZMMIO4Bytes; 754 750 STAMCOUNTER StatRZMMIO8Bytes; 755 751 #endif 756 752 STAMCOUNTER StatR3MMIOHandler; 753 754 STAMCOUNTER StatMmioHandlerR3; 755 STAMCOUNTER StatMmioHandlerR0; 757 756 758 757 RTUINT cMovsMaxBytes; … … 791 790 /** The size of the paIoPortStats allocation (in entries). */ 792 791 uint32_t cIoPortStatsAllocation; 792 /** Prevents paIoPortStats from growing, set by IOMR0IoPortSyncStatisticsIndices(). */ 793 bool fIoPortStatsFrozen; 793 794 /** I/O port lookup table. */ 794 795 R0PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats; … … 822 823 /** The size of the paMmioStats allocation (in entries). */ 823 824 uint32_t cMmioStatsAllocation; 825 /* Prevents paMmioStats from growing, set by IOMR0MmioSyncStatisticsIndices(). */ 826 bool fMmioStatsFrozen; 824 827 /** MMIO lookup table. */ 825 828 R0PTRTYPE(PIOMMMIOSTATSENTRY) paMmioStats; … … 841 844 DECLCALLBACK(void) iomR3IoPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 842 845 void iomR3IoPortRegStats(PVM pVM, PIOMIOPORTENTRYR3 pRegEntry); 846 DECLCALLBACK(void) iomR3MmioInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 847 void iomR3MmioRegStats(PVM pVM, PIOMMMIOENTRYR3 pRegEntry); 843 848 #endif /* IN_RING3 */ 844 849 #ifdef IN_RING0 … … 848 853 void iomR0MmioInitPerVMData(PGVM pGVM); 849 854 #endif 855 VBOXSTRICTRC iomMmioCommonPfHandlerOld(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore, 856 RTGCPHYS GCPhysFault, void *pvUser); 850 857 851 858 #ifndef IN_RING3 852 859 DECLEXPORT(FNPGMRZPHYSPFHANDLER) iomMmioPfHandler; 860 DECLEXPORT(FNPGMRZPHYSPFHANDLER) iomMmioPfHandlerNew; 853 861 #endif 854 862 PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandler; 863 PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandlerNew; 855 864 856 865 /* IOM locking helpers. */
Note:
See TracChangeset
for help on using the changeset viewer.