diff options
Diffstat (limited to 'src/VBox/VMM/VMMR3/IOM.cpp')
| -rw-r--r-- | src/VBox/VMM/VMMR3/IOM.cpp | 318 |
1 files changed, 140 insertions, 178 deletions
diff --git a/src/VBox/VMM/VMMR3/IOM.cpp b/src/VBox/VMM/VMMR3/IOM.cpp index 6654fda8..667ce9f7 100644 --- a/src/VBox/VMM/VMMR3/IOM.cpp +++ b/src/VBox/VMM/VMMR3/IOM.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -52,7 +52,7 @@ * execution. * * - * @section sec_iom_hwaccm Hardware Assisted Virtualization Mode + * @section sec_iom_hm Hardware Assisted Virtualization Mode * * When running in hardware assisted virtualization mode we'll be doing much the * same things as in raw-mode. The main difference is that we're running in the @@ -88,6 +88,13 @@ * */ +/** @todo MMIO - simplifying the device end. + * - Add a return status for doing DBGFSTOP on access where there are no known + * registers. + * - + * + * */ + /******************************************************************************* * Header Files * @@ -97,6 +104,7 @@ #include <VBox/vmm/cpum.h> #include <VBox/vmm/pgm.h> #include <VBox/sup.h> +#include <VBox/vmm/hm.h> #include <VBox/vmm/mm.h> #include <VBox/vmm/stam.h> #include <VBox/vmm/dbgf.h> @@ -158,7 +166,11 @@ VMMR3_INT_DECL(int) IOMR3Init(PVM pVM) /* * Initialize the REM critical section. */ +#ifdef IOM_WITH_CRIT_SECT_RW + int rc = PDMR3CritSectRwInit(pVM, &pVM->iom.s.CritSect, RT_SRC_POS, "IOM Lock"); +#else int rc = PDMR3CritSectInit(pVM, &pVM->iom.s.CritSect, RT_SRC_POS, "IOM Lock"); +#endif AssertRCReturn(rc, rc); /* @@ -226,33 +238,41 @@ VMMR3_INT_DECL(int) IOMR3Init(PVM pVM) */ static void iomR3FlushCache(PVM pVM) { - IOM_LOCK(pVM); - /* - * Caching of port and statistics (saves some time in rep outs/ins instruction emulation) + * Since all relevant (1) cache use requires at least read access to the + * critical section, we can exclude all other EMTs by grabbing exclusive + * access to the critical section and then safely update the caches of + * other EMTs. + * (1) The irrelvant access not holding the lock is in assertion code. */ - pVM->iom.s.pRangeLastReadR0 = NIL_RTR0PTR; - pVM->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR; - pVM->iom.s.pStatsLastReadR0 = NIL_RTR0PTR; - pVM->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR; - pVM->iom.s.pMMIORangeLastR0 = NIL_RTR0PTR; - pVM->iom.s.pMMIOStatsLastR0 = NIL_RTR0PTR; - - pVM->iom.s.pRangeLastReadR3 = NULL; - pVM->iom.s.pRangeLastWriteR3 = NULL; - pVM->iom.s.pStatsLastReadR3 = NULL; - pVM->iom.s.pStatsLastWriteR3 = NULL; - pVM->iom.s.pMMIORangeLastR3 = NULL; - pVM->iom.s.pMMIOStatsLastR3 = NULL; - - pVM->iom.s.pRangeLastReadRC = NIL_RTRCPTR; - pVM->iom.s.pRangeLastWriteRC = NIL_RTRCPTR; - pVM->iom.s.pStatsLastReadRC = NIL_RTRCPTR; - pVM->iom.s.pStatsLastWriteRC = NIL_RTRCPTR; - pVM->iom.s.pMMIORangeLastRC = NIL_RTRCPTR; - pVM->iom.s.pMMIOStatsLastRC = NIL_RTRCPTR; - - IOM_UNLOCK(pVM); + IOM_LOCK_EXCL(pVM); + VMCPUID iCpu = pVM->cCpus; + while (iCpu-- > 0) + { + PVMCPU pVCpu = &pVM->aCpus[iCpu]; + pVCpu->iom.s.pRangeLastReadR0 = NIL_RTR0PTR; + pVCpu->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR; + pVCpu->iom.s.pStatsLastReadR0 = NIL_RTR0PTR; + pVCpu->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR; + pVCpu->iom.s.pMMIORangeLastR0 = NIL_RTR0PTR; + pVCpu->iom.s.pMMIOStatsLastR0 = NIL_RTR0PTR; + + pVCpu->iom.s.pRangeLastReadR3 = NULL; + pVCpu->iom.s.pRangeLastWriteR3 = NULL; + pVCpu->iom.s.pStatsLastReadR3 = NULL; + pVCpu->iom.s.pStatsLastWriteR3 = NULL; + pVCpu->iom.s.pMMIORangeLastR3 = NULL; + pVCpu->iom.s.pMMIOStatsLastR3 = NULL; + + pVCpu->iom.s.pRangeLastReadRC = NIL_RTRCPTR; + pVCpu->iom.s.pRangeLastWriteRC = NIL_RTRCPTR; + pVCpu->iom.s.pStatsLastReadRC = NIL_RTRCPTR; + pVCpu->iom.s.pStatsLastWriteRC = NIL_RTRCPTR; + pVCpu->iom.s.pMMIORangeLastRC = NIL_RTRCPTR; + pVCpu->iom.s.pMMIOStatsLastRC = NIL_RTRCPTR; + } + + IOM_UNLOCK_EXCL(pVM); } @@ -288,24 +308,23 @@ VMMR3_INT_DECL(void) IOMR3Relocate(PVM pVM, RTGCINTPTR offDelta) RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeRC, true, iomR3RelocateIOPortCallback, &offDelta); RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesR3->MMIOTree, true, iomR3RelocateMMIOCallback, &offDelta); - if (pVM->iom.s.pfnMMIOHandlerRC) + if (pVM->iom.s.pfnMMIOHandlerRC != NIL_RTRCPTR) pVM->iom.s.pfnMMIOHandlerRC += offDelta; /* - * Apply relocations to the cached GC handlers + * Reset the raw-mode cache (don't bother relocating it). */ - if (pVM->iom.s.pRangeLastReadRC) - pVM->iom.s.pRangeLastReadRC += offDelta; - if (pVM->iom.s.pRangeLastWriteRC) - pVM->iom.s.pRangeLastWriteRC += offDelta; - if (pVM->iom.s.pStatsLastReadRC) - pVM->iom.s.pStatsLastReadRC += offDelta; - if (pVM->iom.s.pStatsLastWriteRC) - pVM->iom.s.pStatsLastWriteRC += offDelta; - if (pVM->iom.s.pMMIORangeLastRC) - pVM->iom.s.pMMIORangeLastRC += offDelta; - if (pVM->iom.s.pMMIOStatsLastRC) - pVM->iom.s.pMMIOStatsLastRC += offDelta; + VMCPUID iCpu = pVM->cCpus; + while (iCpu-- > 0) + { + PVMCPU pVCpu = &pVM->aCpus[iCpu]; + pVCpu->iom.s.pRangeLastReadRC = NIL_RTRCPTR; + pVCpu->iom.s.pRangeLastWriteRC = NIL_RTRCPTR; + pVCpu->iom.s.pStatsLastReadRC = NIL_RTRCPTR; + pVCpu->iom.s.pStatsLastWriteRC = NIL_RTRCPTR; + pVCpu->iom.s.pMMIORangeLastRC = NIL_RTRCPTR; + pVCpu->iom.s.pMMIOStatsLastRC = NIL_RTRCPTR; + } } @@ -396,13 +415,17 @@ VMMR3_INT_DECL(int) IOMR3Term(PVM pVM) * @param Port Port. * @param pszDesc Description. */ -PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc) +static PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc) { - Assert(IOMIsLockOwner(pVM)); + IOM_LOCK_EXCL(pVM); + /* check if it already exists. */ PIOMIOPORTSTATS pPort = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.pTreesR3->IOPortStatTree, Port); if (pPort) + { + IOM_UNLOCK_EXCL(pVM); return pPort; + } /* allocate stats node. */ int rc = MMHyperAlloc(pVM, sizeof(*pPort), 0, MM_TAG_IOM_STATS, (void **)&pPort); @@ -413,6 +436,8 @@ PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDe pPort->Core.Key = Port; if (RTAvloIOPortInsert(&pVM->iom.s.pTreesR3->IOPortStatTree, &pPort->Core)) { + IOM_UNLOCK_EXCL(pVM); + /* put a name on common ports. */ if (!pszDesc) pszDesc = iomR3IOPortGetStandardName(Port); @@ -433,9 +458,11 @@ PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDe return pPort; } + AssertMsgFailed(("what! Port=%d\n", Port)); MMHyperFree(pVM, pPort); } + IOM_UNLOCK_EXCL(pVM); return NULL; } @@ -451,14 +478,15 @@ PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDe */ PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc) { - Assert(IOMIsLockOwner(pVM)); -#ifdef DEBUG_sandervl - AssertGCPhys32(GCPhys); -#endif + IOM_LOCK_EXCL(pVM); + /* check if it already exists. */ PIOMMMIOSTATS pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pVM->iom.s.pTreesR3->MmioStatTree, GCPhys); if (pStats) + { + IOM_UNLOCK_EXCL(pVM); return pStats; + } /* allocate stats node. */ int rc = MMHyperAlloc(pVM, sizeof(*pStats), 0, MM_TAG_IOM_STATS, (void **)&pStats); @@ -469,6 +497,8 @@ PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc pStats->Core.Key = GCPhys; if (RTAvloGCPhysInsert(&pVM->iom.s.pTreesR3->MmioStatTree, &pStats->Core)) { + IOM_UNLOCK_EXCL(pVM); + rc = STAMR3RegisterF(pVM, &pStats->Accesses, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp", GCPhys); AssertRC(rc); rc = STAMR3RegisterF(pVM, &pStats->ProfReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp/Read-R3", GCPhys); AssertRC(rc); rc = STAMR3RegisterF(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp/Write-R3", GCPhys); AssertRC(rc); @@ -482,6 +512,7 @@ PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc AssertMsgFailed(("what! GCPhys=%RGp\n", GCPhys)); MMHyperFree(pVM, pStats); } + IOM_UNLOCK_EXCL(pVM); return NULL; } @@ -563,20 +594,20 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT /* * Try Insert it. */ - IOM_LOCK(pVM); + IOM_LOCK_EXCL(pVM); if (RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR3, &pRange->Core)) { #ifdef VBOX_WITH_STATISTICS for (unsigned iPort = 0; iPort < cPorts; iPort++) iomR3IOPortStatsCreate(pVM, PortStart + iPort, pszDesc); #endif - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); /* conflict. */ - DBGFR3Info(pVM, "ioport", NULL, NULL); + DBGFR3Info(pVM->pUVM, "ioport", NULL, NULL); AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); MMHyperFree(pVM, pRange); rc = VERR_IOM_IOPORT_RANGE_CONFLICT; @@ -612,6 +643,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT { LogFlow(("IOMR3IOPortRegisterRC: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RRv pfnOutCallback=%RRv pfnInCallback=%RRv pfnOutStrCallback=%RRv pfnInStrCallback=%RRv pszDesc=%s\n", pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc)); + AssertReturn(!HMIsEnabled(pVM), VERR_IOM_HM_IPE); /* * Validate input. @@ -629,7 +661,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT return VERR_INVALID_PARAMETER; } - IOM_LOCK(pVM); + IOM_LOCK_EXCL(pVM); /* * Validate that there are ring-3 ranges for the ports. @@ -641,7 +673,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT if (!pRange) { AssertMsgFailed(("No R3! Port=#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VERR_IOM_NO_R3_IOPORT_RANGE; } #ifndef IOM_NO_PDMINS_CHECKS @@ -652,7 +684,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT # endif { AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VERR_IOM_NOT_IOPORT_RANGE_OWNER; } #endif @@ -686,7 +718,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT */ if (RTAvlroIOPortInsert(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeRC, &pRange->Core)) { - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } @@ -695,7 +727,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT MMHyperFree(pVM, pRange); rc = VERR_IOM_IOPORT_RANGE_CONFLICT; } - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return rc; } @@ -744,7 +776,8 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT return VERR_INVALID_PARAMETER; } - IOM_LOCK(pVM); + IOM_LOCK_EXCL(pVM); + /* * Validate that there are ring-3 ranges for the ports. */ @@ -755,7 +788,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT if (!pRange) { AssertMsgFailed(("No R3! Port=#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VERR_IOM_NO_R3_IOPORT_RANGE; } #ifndef IOM_NO_PDMINS_CHECKS @@ -766,7 +799,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT # endif { AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VERR_IOM_NOT_IOPORT_RANGE_OWNER; } #endif @@ -800,7 +833,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT */ if (RTAvlroIOPortInsert(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR0, &pRange->Core)) { - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } @@ -809,7 +842,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT MMHyperFree(pVM, pRange); rc = VERR_IOM_IOPORT_RANGE_CONFLICT; } - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return rc; } @@ -847,7 +880,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT return VERR_IOM_INVALID_IOPORT_RANGE; } - IOM_LOCK(pVM); + IOM_LOCK_EXCL(pVM); /* Flush the IO port lookup cache */ iomR3FlushCache(pVM); @@ -868,7 +901,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT { AssertMsgFailed(("Removal of ports in range %#x-%#x rejected because not owner of %#x-%#x (%s)\n", PortStart, PortLast, pRange->Core.Key, pRange->Core.KeyLast, pRange->pszDesc)); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VERR_IOM_NOT_IOPORT_RANGE_OWNER; } #endif /* !IOM_NO_PDMINS_CHECKS */ @@ -932,7 +965,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew); if (RT_FAILURE(rc2)) { - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return rc2; } *pRangeNew = *pRange; @@ -1015,7 +1048,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew); if (RT_FAILURE(rc2)) { - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return rc2; } *pRangeNew = *pRange; @@ -1097,7 +1130,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew); if (RT_FAILURE(rc2)) { - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return rc2; } *pRangeNew = *pRange; @@ -1126,7 +1159,7 @@ VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT } /* for all ports - ring-3. */ /* done */ - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return rc; } @@ -1303,84 +1336,6 @@ static DECLCALLBACK(void) iomR3IOPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const cha sizeof(RTRCPTR) * 2, "Out ", sizeof(RTRCPTR) * 2, "pvUser "); RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeRC, true, iomR3IOPortInfoOneRC, (void *)pHlp); - - if (pVM->iom.s.pRangeLastReadRC) - { - PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)MMHyperRCToCC(pVM, pVM->iom.s.pRangeLastReadRC); - pHlp->pfnPrintf(pHlp, "RC Read Ports: %#04x-%#04x %RRv %s\n", - pRange->Port, pRange->Port + pRange->cPorts, pVM->iom.s.pRangeLastReadRC, pRange->pszDesc); - } - if (pVM->iom.s.pStatsLastReadRC) - { - PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperRCToCC(pVM, pVM->iom.s.pStatsLastReadRC); - pHlp->pfnPrintf(pHlp, "RC Read Stats: %#04x %RRv\n", - pRange->Core.Key, pVM->iom.s.pStatsLastReadRC); - } - - if (pVM->iom.s.pRangeLastWriteRC) - { - PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)MMHyperRCToCC(pVM, pVM->iom.s.pRangeLastWriteRC); - pHlp->pfnPrintf(pHlp, "RC Write Ports: %#04x-%#04x %RRv %s\n", - pRange->Port, pRange->Port + pRange->cPorts, pVM->iom.s.pRangeLastWriteRC, pRange->pszDesc); - } - if (pVM->iom.s.pStatsLastWriteRC) - { - PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperRCToCC(pVM, pVM->iom.s.pStatsLastWriteRC); - pHlp->pfnPrintf(pHlp, "RC Write Stats: %#04x %RRv\n", - pRange->Core.Key, pVM->iom.s.pStatsLastWriteRC); - } - - if (pVM->iom.s.pRangeLastReadR3) - { - PIOMIOPORTRANGER3 pRange = pVM->iom.s.pRangeLastReadR3; - pHlp->pfnPrintf(pHlp, "R3 Read Ports: %#04x-%#04x %p %s\n", - pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc); - } - if (pVM->iom.s.pStatsLastReadR3) - { - PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastReadR3; - pHlp->pfnPrintf(pHlp, "R3 Read Stats: %#04x %p\n", - pRange->Core.Key, pRange); - } - - if (pVM->iom.s.pRangeLastWriteR3) - { - PIOMIOPORTRANGER3 pRange = pVM->iom.s.pRangeLastWriteR3; - pHlp->pfnPrintf(pHlp, "R3 Write Ports: %#04x-%#04x %p %s\n", - pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc); - } - if (pVM->iom.s.pStatsLastWriteR3) - { - PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastWriteR3; - pHlp->pfnPrintf(pHlp, "R3 Write Stats: %#04x %p\n", - pRange->Core.Key, pRange); - } - - if (pVM->iom.s.pRangeLastReadR0) - { - PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastReadR0); - pHlp->pfnPrintf(pHlp, "R0 Read Ports: %#04x-%#04x %p %s\n", - pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc); - } - if (pVM->iom.s.pStatsLastReadR0) - { - PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastReadR0); - pHlp->pfnPrintf(pHlp, "R0 Read Stats: %#04x %p\n", - pRange->Core.Key, pRange); - } - - if (pVM->iom.s.pRangeLastWriteR0) - { - PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastWriteR0); - pHlp->pfnPrintf(pHlp, "R0 Write Ports: %#04x-%#04x %p %s\n", - pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc); - } - if (pVM->iom.s.pStatsLastWriteR0) - { - PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastWriteR0); - pHlp->pfnPrintf(pHlp, "R0 Write Stats: %#04x %p\n", - pRange->Core.Key, pRange); - } } @@ -1417,8 +1372,8 @@ IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t AssertMsgReturn(GCPhysStart + (cbRange - 1) >= GCPhysStart,("Wrapped! %RGp %#x bytes\n", GCPhysStart, cbRange), VERR_IOM_INVALID_MMIO_RANGE); AssertMsgReturn( !(fFlags & ~IOMMMIO_FLAGS_VALID_MASK) - || (fFlags & IOMMMIO_FLAGS_READ_MODE) == IOMMMIO_FLAGS_READ_MODE - || (fFlags & IOMMMIO_FLAGS_WRITE_MODE) > IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING, + && (fFlags & IOMMMIO_FLAGS_READ_MODE) <= IOMMMIO_FLAGS_READ_DWORD_QWORD + && (fFlags & IOMMMIO_FLAGS_WRITE_MODE) <= IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD, ("%#x\n", fFlags), VERR_INVALID_PARAMETER); @@ -1427,8 +1382,11 @@ IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t */ if (pVM->iom.s.pfnMMIOHandlerR0 == NIL_RTR0PTR) { - rc = PDMR3LdrGetSymbolRC(pVM, NULL, "IOMMMIOHandler", &pVM->iom.s.pfnMMIOHandlerRC); - AssertLogRelRCReturn(rc, rc); + if (!HMIsEnabled(pVM)) + { + rc = PDMR3LdrGetSymbolRC(pVM, NULL, "IOMMMIOHandler", &pVM->iom.s.pfnMMIOHandlerRC); + AssertLogRelRCReturn(rc, rc); + } rc = PDMR3LdrGetSymbolR0(pVM, NULL, "IOMMMIOHandler", &pVM->iom.s.pfnMMIOHandlerR0); AssertLogRelRCReturn(rc, rc); } @@ -1470,28 +1428,26 @@ IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t /* * Try register it with PGM and then insert it into the tree. */ - IOM_LOCK(pVM); - iomR3FlushCache(pVM); rc = PGMR3PhysMMIORegister(pVM, GCPhysStart, cbRange, IOMR3MMIOHandler, pRange, pVM->iom.s.pfnMMIOHandlerR0, MMHyperR3ToR0(pVM, pRange), pVM->iom.s.pfnMMIOHandlerRC, MMHyperR3ToRC(pVM, pRange), pszDesc); if (RT_SUCCESS(rc)) { + IOM_LOCK_EXCL(pVM); if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesR3->MMIOTree, &pRange->Core)) { - IOM_UNLOCK(pVM); + iomR3FlushCache(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } /* bail out */ - IOM_UNLOCK(pVM); - DBGFR3Info(pVM, "mmio", NULL, NULL); + IOM_UNLOCK_EXCL(pVM); + DBGFR3Info(pVM->pUVM, "mmio", NULL, NULL); AssertMsgFailed(("This cannot happen!\n")); rc = VERR_IOM_IOPORT_IPE_3; } - else - IOM_UNLOCK(pVM); MMHyperFree(pVM, pRange); } @@ -1518,6 +1474,7 @@ IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t * @param pfnWriteCallback Pointer to function which is gonna handle Write operations. * @param pfnReadCallback Pointer to function which is gonna handle Read operations. * @param pfnFillCallback Pointer to function which is gonna handle Fill/memset operations. + * @thread EMT */ VMMR3_INT_DECL(int) IOMR3MmioRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTGCPTR pvUser, @@ -1526,6 +1483,7 @@ IOMR3MmioRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t { LogFlow(("IOMR3MmioRegisterRC: pDevIns=%p GCPhysStart=%RGp cbRange=%#x pvUser=%RGv pfnWriteCallback=%#x pfnReadCallback=%#x pfnFillCallback=%#x\n", pDevIns, GCPhysStart, cbRange, pvUser, pfnWriteCallback, pfnReadCallback, pfnFillCallback)); + AssertReturn(!HMIsEnabled(pVM), VERR_IOM_HM_IPE); /* * Validate input. @@ -1535,23 +1493,24 @@ IOMR3MmioRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t AssertMsgFailed(("No callbacks! %RGp LB%#x %s\n", GCPhysStart, cbRange)); return VERR_INVALID_PARAMETER; } + PVMCPU pVCpu = VMMGetCpu(pVM); Assert(pVCpu); /* * Find the MMIO range and check that the input matches. */ - IOM_LOCK(pVM); - PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhysStart); - AssertReturnStmt(pRange, IOM_UNLOCK(pVM), VERR_IOM_MMIO_RANGE_NOT_FOUND); - AssertReturnStmt(pRange->pDevInsR3 == pDevIns, IOM_UNLOCK(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER); - AssertReturnStmt(pRange->GCPhys == GCPhysStart, IOM_UNLOCK(pVM), VERR_IOM_INVALID_MMIO_RANGE); - AssertReturnStmt(pRange->cb == cbRange, IOM_UNLOCK(pVM), VERR_IOM_INVALID_MMIO_RANGE); + IOM_LOCK_EXCL(pVM); + PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhysStart); + AssertReturnStmt(pRange, IOM_UNLOCK_EXCL(pVM), VERR_IOM_MMIO_RANGE_NOT_FOUND); + AssertReturnStmt(pRange->pDevInsR3 == pDevIns, IOM_UNLOCK_EXCL(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER); + AssertReturnStmt(pRange->GCPhys == GCPhysStart, IOM_UNLOCK_EXCL(pVM), VERR_IOM_INVALID_MMIO_RANGE); + AssertReturnStmt(pRange->cb == cbRange, IOM_UNLOCK_EXCL(pVM), VERR_IOM_INVALID_MMIO_RANGE); pRange->pvUserRC = pvUser; pRange->pfnReadCallbackRC = pfnReadCallback; pRange->pfnWriteCallbackRC= pfnWriteCallback; pRange->pfnFillCallbackRC = pfnFillCallback; pRange->pDevInsRC = MMHyperCCToRC(pVM, pDevIns); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } @@ -1574,6 +1533,7 @@ IOMR3MmioRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t * @param pfnWriteCallback Pointer to function which is gonna handle Write operations. * @param pfnReadCallback Pointer to function which is gonna handle Read operations. * @param pfnFillCallback Pointer to function which is gonna handle Fill/memset operations. + * @thread EMT */ VMMR3_INT_DECL(int) IOMR3MmioRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTR0PTR pvUser, @@ -1592,23 +1552,24 @@ IOMR3MmioRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t AssertMsgFailed(("No callbacks! %RGp LB%#x %s\n", GCPhysStart, cbRange)); return VERR_INVALID_PARAMETER; } + PVMCPU pVCpu = VMMGetCpu(pVM); Assert(pVCpu); /* * Find the MMIO range and check that the input matches. */ - IOM_LOCK(pVM); - PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhysStart); - AssertReturnStmt(pRange, IOM_UNLOCK(pVM), VERR_IOM_MMIO_RANGE_NOT_FOUND); - AssertReturnStmt(pRange->pDevInsR3 == pDevIns, IOM_UNLOCK(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER); - AssertReturnStmt(pRange->GCPhys == GCPhysStart, IOM_UNLOCK(pVM), VERR_IOM_INVALID_MMIO_RANGE); - AssertReturnStmt(pRange->cb == cbRange, IOM_UNLOCK(pVM), VERR_IOM_INVALID_MMIO_RANGE); + IOM_LOCK_EXCL(pVM); + PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhysStart); + AssertReturnStmt(pRange, IOM_UNLOCK_EXCL(pVM), VERR_IOM_MMIO_RANGE_NOT_FOUND); + AssertReturnStmt(pRange->pDevInsR3 == pDevIns, IOM_UNLOCK_EXCL(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER); + AssertReturnStmt(pRange->GCPhys == GCPhysStart, IOM_UNLOCK_EXCL(pVM), VERR_IOM_INVALID_MMIO_RANGE); + AssertReturnStmt(pRange->cb == cbRange, IOM_UNLOCK_EXCL(pVM), VERR_IOM_INVALID_MMIO_RANGE); pRange->pvUserR0 = pvUser; pRange->pfnReadCallbackR0 = pfnReadCallback; pRange->pfnWriteCallbackR0= pfnWriteCallback; pRange->pfnFillCallbackR0 = pfnFillCallback; pRange->pDevInsR0 = MMHyperCCToR0(pVM, pDevIns); - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } @@ -1642,8 +1603,9 @@ VMMR3_INT_DECL(int) IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GC AssertMsgFailed(("Wrapped! %#x LB%#x\n", GCPhysStart, cbRange)); return VERR_IOM_INVALID_MMIO_RANGE; } + PVMCPU pVCpu = VMMGetCpu(pVM); Assert(pVCpu); - IOM_LOCK(pVM); + IOM_LOCK_EXCL(pVM); /* * Check ownership and such for the entire area. @@ -1651,19 +1613,19 @@ VMMR3_INT_DECL(int) IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GC RTGCPHYS GCPhys = GCPhysStart; while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) { - PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhys); + PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhys); if (!pRange) { - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VERR_IOM_MMIO_RANGE_NOT_FOUND; } AssertMsgReturnStmt(pRange->pDevInsR3 == pDevIns, ("Not owner! GCPhys=%RGp %RGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc), - IOM_UNLOCK(pVM), + IOM_UNLOCK_EXCL(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER); AssertMsgReturnStmt(pRange->Core.KeyLast <= GCPhysLast, ("Incomplete R3 range! GCPhys=%RGp %RGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc), - IOM_UNLOCK(pVM), + IOM_UNLOCK_EXCL(pVM), VERR_IOM_INCOMPLETE_MMIO_RANGE); /* next */ @@ -1682,13 +1644,13 @@ VMMR3_INT_DECL(int) IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GC PIOMMMIORANGE pRange = (PIOMMMIORANGE)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesR3->MMIOTree, GCPhys); Assert(pRange); Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast); - IOM_UNLOCK(pVM); /** @todo r=bird: Why are we leaving the lock here? We don't leave it when registering the range above... */ + IOM_UNLOCK_EXCL(pVM); /* Lock order fun. */ /* remove it from PGM */ int rc = PGMR3PhysMMIODeregister(pVM, GCPhys, pRange->cb); AssertRC(rc); - IOM_LOCK(pVM); + IOM_LOCK_EXCL(pVM); /* advance and free. */ GCPhys = pRange->Core.KeyLast + 1; @@ -1700,7 +1662,7 @@ VMMR3_INT_DECL(int) IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GC iomMmioReleaseRange(pVM, pRange); } - IOM_UNLOCK(pVM); + IOM_UNLOCK_EXCL(pVM); return VINF_SUCCESS; } |
