VirtualBox

Changeset 7751 in vbox for trunk/src


Ignore:
Timestamp:
Apr 4, 2008 5:10:17 PM (17 years ago)
Author:
vboxsync
Message:

Simplified and cleaned up the MMIO code.

  • The R0 and GC MMIO range records have been merged into the R3 one.
  • Added caching of the last MMIO range and stats record like we're doing for the I/O port ranges.

TODO:

  • Drop the pszDesc parameter of the GC/R0 registration functions.
  • Do the same cleanup to the I/O port code.
Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/IOM.cpp

    r7749 r7751  
    165165     * Caching of port and statistics (saves some time in rep outs/ins instruction emulation)
    166166     */
    167     pVM->iom.s.pRangeLastReadGC  = 0;
    168     pVM->iom.s.pRangeLastWriteGC = 0;
    169     pVM->iom.s.pStatsLastReadGC  = 0;
    170     pVM->iom.s.pStatsLastWriteGC = 0;
    171 
    172     pVM->iom.s.pRangeLastReadR3  = 0;
    173     pVM->iom.s.pRangeLastWriteR3 = 0;
    174     pVM->iom.s.pStatsLastReadR3  = 0;
    175     pVM->iom.s.pStatsLastWriteR3 = 0;
    176 
    177     pVM->iom.s.pRangeLastReadR0  = 0;
    178     pVM->iom.s.pRangeLastWriteR0 = 0;
    179     pVM->iom.s.pStatsLastReadR0  = 0;
    180     pVM->iom.s.pStatsLastWriteR0 = 0;
     167    pVM->iom.s.pRangeLastReadR0  = NIL_RTR0PTR;
     168    pVM->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR;
     169    pVM->iom.s.pStatsLastReadR0  = NIL_RTR0PTR;
     170    pVM->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR;
     171    pVM->iom.s.pMMIORangeLastR0  = NIL_RTR0PTR;
     172    pVM->iom.s.pMMIOStatsLastR0  = NIL_RTR0PTR;
     173
     174    pVM->iom.s.pRangeLastReadR3  = NULL;
     175    pVM->iom.s.pRangeLastWriteR3 = NULL;
     176    pVM->iom.s.pStatsLastReadR3  = NULL;
     177    pVM->iom.s.pStatsLastWriteR3 = NULL;
     178    pVM->iom.s.pMMIORangeLastR3  = NULL;
     179    pVM->iom.s.pMMIOStatsLastR3  = NULL;
     180
     181    pVM->iom.s.pRangeLastReadGC  = NIL_RTGCPTR;
     182    pVM->iom.s.pRangeLastWriteGC = NIL_RTGCPTR;
     183    pVM->iom.s.pStatsLastReadGC  = NIL_RTGCPTR;
     184    pVM->iom.s.pStatsLastWriteGC = NIL_RTGCPTR;
     185    pVM->iom.s.pMMIORangeLastGC  = NIL_RTGCPTR;
     186    pVM->iom.s.pMMIOStatsLastGC  = NIL_RTGCPTR;
    181187}
    182188
     
    212218    pVM->iom.s.pTreesGC = MMHyperHC2GC(pVM, pVM->iom.s.pTreesHC);
    213219    RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesHC->IOPortTreeGC, true, iomr3RelocateIOPortCallback, &offDelta);
    214     RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeGC, true, iomr3RelocateMMIOCallback, &offDelta);
     220    RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTree, true, iomr3RelocateMMIOCallback, &offDelta);
    215221
    216222    if (pVM->iom.s.pfnMMIOHandlerGC)
     
    228234    if (pVM->iom.s.pStatsLastWriteGC)
    229235        pVM->iom.s.pStatsLastWriteGC += offDelta;
     236    if (pVM->iom.s.pMMIORangeLastGC)
     237        pVM->iom.s.pMMIORangeLastGC  += offDelta;
     238    if (pVM->iom.s.pMMIOStatsLastGC)
     239        pVM->iom.s.pMMIOStatsLastGC  += offDelta;
    230240}
    231241
     
    245255
    246256    Assert(pRange->pDevIns);
    247     pRange->pDevIns         += offDelta;
     257    pRange->pDevIns                 += offDelta;
    248258    if (pRange->pfnOutCallback)
    249         pRange->pfnOutCallback  += offDelta;
     259        pRange->pfnOutCallback      += offDelta;
    250260    if (pRange->pfnInCallback)
    251         pRange->pfnInCallback   += offDelta;
     261        pRange->pfnInCallback       += offDelta;
    252262    if (pRange->pfnOutStrCallback)
    253         pRange->pfnOutStrCallback  += offDelta;
     263        pRange->pfnOutStrCallback   += offDelta;
    254264    if (pRange->pfnInStrCallback)
    255         pRange->pfnInStrCallback   += offDelta;
    256     /** @todo IOMIOPORTRANGEGC::pvUser hack - relocate if 64KB or higher. This hack should be removed! */
     265        pRange->pfnInStrCallback    += offDelta;
    257266    if (pRange->pvUser > _64K)
    258         pRange->pvUser          += offDelta;
     267        pRange->pvUser              += offDelta;
    259268    return 0;
    260269}
     
    265274 *
    266275 * @returns 0 (continue enum)
    267  * @param   pNode       Pointer to a IOMMMIORANGEGC node.
     276 * @param   pNode       Pointer to a IOMMMIORANGE node.
    268277 * @param   pvUser      Pointer to the offDelta. This is a pointer to the delta since we're
    269278 *                      not certain the delta will fit in a void pointer for all possible configs.
     
    271280static DECLCALLBACK(int) iomr3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser)
    272281{
    273     PIOMMMIORANGEGC pRange = (PIOMMMIORANGEGC)pNode;
     282    PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode;
    274283    RTGCINTPTR    offDelta = *(PRTGCINTPTR)pvUser;
    275284
    276     Assert(pRange->pDevIns);
    277     pRange->pDevIns         += offDelta;
    278 
    279     if (pRange->pfnWriteCallback)
    280         pRange->pfnWriteCallback += offDelta;
    281     if (pRange->pfnReadCallback)
    282         pRange->pfnReadCallback  += offDelta;
    283     if (pRange->pfnFillCallback)
    284         pRange->pfnFillCallback  += offDelta;
    285     /** @todo IOMMMIORANGEGC::pvUser hack - relocate if 64KB or higher. This hack should be removed! */
    286     if (pRange->pvUser > _64K)
    287         pRange->pvUser           += offDelta;
     285    if (pRange->pDevInsGC)
     286        pRange->pDevInsGC           += offDelta;
     287    if (pRange->pfnWriteCallbackGC)
     288        pRange->pfnWriteCallbackGC  += offDelta;
     289    if (pRange->pfnReadCallbackGC)
     290        pRange->pfnReadCallbackGC   += offDelta;
     291    if (pRange->pfnFillCallbackGC)
     292        pRange->pfnFillCallbackGC   += offDelta;
     293    if (pRange->pvUserGC > _64K)
     294        pRange->pvUserGC            += offDelta;
     295
    288296    return 0;
    289297}
     
    433441    if (pStats)
    434442        return pStats;
    435 #if 1
     443
    436444    /* allocate stats node. */
    437445    int rc = MMHyperAlloc(pVM, sizeof(*pStats), 0, MM_TAG_IOM_STATS, (void **)&pStats);
     
    444452        {
    445453            /* register the statistics counters. */
    446             char szName[64];
    447             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R3", GCPhys);
    448             rc = STAMR3Register(pVM, &pStats->ReadR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    449             AssertRC(rc);
    450 
    451             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R3", GCPhys);
    452             rc = STAMR3Register(pVM, &pStats->WriteR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    453             AssertRC(rc);
    454 
    455             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-GC", GCPhys);
    456             rc = STAMR3Register(pVM, &pStats->ReadGC, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    457             AssertRC(rc);
    458 
    459             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-GC", GCPhys);
    460             rc = STAMR3Register(pVM, &pStats->WriteGC, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    461             AssertRC(rc);
    462 
    463             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-GC-2-R3", GCPhys);
    464             rc = STAMR3Register(pVM, &pStats->ReadGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    465             AssertRC(rc);
    466 
    467             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-GC-2-R3", GCPhys);
    468             rc = STAMR3Register(pVM, &pStats->WriteGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    469             AssertRC(rc);
    470 
    471             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R0", GCPhys);
    472             rc = STAMR3Register(pVM, &pStats->ReadR0, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    473             AssertRC(rc);
    474 
    475             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R0", GCPhys);
    476             rc = STAMR3Register(pVM, &pStats->WriteR0, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    477             AssertRC(rc);
    478 
    479             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R0-2-R3", GCPhys);
    480             rc = STAMR3Register(pVM, &pStats->ReadR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
    481             AssertRC(rc);
    482 
    483             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R0-2-R3", GCPhys);
    484             rc = STAMR3Register(pVM, &pStats->WriteR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, pszDesc);
     454            rc = STAMR3RegisterF(pVM, &pStats->ReadR3,      STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-R3", GCPhys);
     455            AssertRC(rc);
     456            rc = STAMR3RegisterF(pVM, &pStats->WriteR3,     STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-R3", GCPhys);
     457            AssertRC(rc);
     458            rc = STAMR3RegisterF(pVM, &pStats->ReadGC,      STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-GC", GCPhys);
     459            AssertRC(rc);
     460            rc = STAMR3RegisterF(pVM, &pStats->WriteGC,     STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-GC", GCPhys);
     461            AssertRC(rc);
     462            rc = STAMR3RegisterF(pVM, &pStats->ReadGCToR3,  STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-GC-2-R3", GCPhys);
     463            AssertRC(rc);
     464            rc = STAMR3RegisterF(pVM, &pStats->WriteGCToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-GC-2-R3", GCPhys);
     465            AssertRC(rc);
     466            rc = STAMR3RegisterF(pVM, &pStats->ReadR0,      STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-R0", GCPhys);
     467            AssertRC(rc);
     468            rc = STAMR3RegisterF(pVM, &pStats->WriteR0,     STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-R0", GCPhys);
     469            AssertRC(rc);
     470            rc = STAMR3RegisterF(pVM, &pStats->ReadR0ToR3,  STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Read-R0-2-R3", GCPhys);
     471            AssertRC(rc);
     472            rc = STAMR3RegisterF(pVM, &pStats->WriteR0ToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/MMIO/%RGp-Write-R0-2-R3", GCPhys);
    485473            AssertRC(rc);
    486474
    487475            /* Profiling */
    488             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R3/Prof", GCPhys);
    489             rc = STAMR3Register(pVM, &pStats->ProfReadR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc);
    490             AssertRC(rc);
    491 
    492             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R3/Prof", GCPhys);
    493             rc = STAMR3Register(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc);
    494             AssertRC(rc);
    495 
    496             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-GC/Prof", GCPhys);
    497             rc = STAMR3Register(pVM, &pStats->ProfReadGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc);
    498             AssertRC(rc);
    499 
    500             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-GC/Prof", GCPhys);
    501             rc = STAMR3Register(pVM, &pStats->ProfWriteGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc);
    502             AssertRC(rc);
    503 
    504             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Read-R0/Prof", GCPhys);
    505             rc = STAMR3Register(pVM, &pStats->ProfReadR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc);
    506             AssertRC(rc);
    507 
    508             RTStrPrintf(szName, sizeof(szName), "/IOM/MMIO/%RGp-Write-R0/Prof", GCPhys);
    509             rc = STAMR3Register(pVM, &pStats->ProfWriteR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szName, STAMUNIT_TICKS_PER_CALL, pszDesc);
     476            rc = STAMR3RegisterF(pVM, &pStats->ProfReadR3,  STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Read-R3/Prof", GCPhys);
     477            AssertRC(rc);
     478            rc = STAMR3RegisterF(pVM, &pStats->ProfWriteR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Write-R3/Prof", GCPhys);
     479            AssertRC(rc);
     480            rc = STAMR3RegisterF(pVM, &pStats->ProfReadGC,  STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Read-GC/Prof", GCPhys);
     481            AssertRC(rc);
     482            rc = STAMR3RegisterF(pVM, &pStats->ProfWriteGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Write-GC/Prof", GCPhys);
     483            AssertRC(rc);
     484            rc = STAMR3RegisterF(pVM, &pStats->ProfReadR0,  STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Read-R0/Prof", GCPhys);
     485            AssertRC(rc);
     486            rc = STAMR3RegisterF(pVM, &pStats->ProfWriteR0, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc, "/IOM/MMIO/%RGp-Write-R0/Prof", GCPhys);
    510487            AssertRC(rc);
    511488
     
    515492        MMHyperFree(pVM, pStats);
    516493    }
    517 #endif
    518494    return NULL;
    519495}
     
    13681344    if (pVM->iom.s.pRangeLastReadR0)
    13691345    {
    1370         PIOMIOPORTRANGER0 pRange = pVM->iom.s.pRangeLastReadR0;
     1346        PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastReadR0);
    13711347        pHlp->pfnPrintf(pHlp, "R0 Read  Ports: %#04x-%#04x %VGv %s\n",
    13721348                        pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc);
     
    13741350    if (pVM->iom.s.pStatsLastReadR0)
    13751351    {
    1376         PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastReadR0;
     1352        PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastReadR0);
    13771353        pHlp->pfnPrintf(pHlp, "R0 Read  Stats: %#04x %VGv\n",
    13781354                        pRange->Core.Key, pRange);
     
    13811357    if (pVM->iom.s.pRangeLastWriteR0)
    13821358    {
    1383         PIOMIOPORTRANGER0 pRange = pVM->iom.s.pRangeLastWriteR0;
     1359        PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastWriteR0);
    13841360        pHlp->pfnPrintf(pHlp, "R0 Write Ports: %#04x-%#04x %VGv %s\n",
    13851361                        pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc);
     
    13871363    if (pVM->iom.s.pStatsLastWriteR0)
    13881364    {
    1389         PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastWriteR0;
     1365        PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastWriteR0);
    13901366        pHlp->pfnPrintf(pHlp, "R0 Write Stats: %#04x %VGv\n",
    13911367                        pRange->Core.Key, pRange);
     
    14431419     * Allocate new range record and initialize it.
    14441420     */
    1445     PIOMMMIORANGER3 pRange;
     1421    PIOMMMIORANGE pRange;
    14461422    rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);
    14471423    if (VBOX_SUCCESS(rc))
    14481424    {
    1449         pRange->Core.Key        = GCPhysStart;
    1450         pRange->Core.KeyLast    = GCPhysStart + (cbRange - 1);
    1451         pRange->GCPhys          = GCPhysStart;
    1452         pRange->cb              = cbRange;
    1453         pRange->pvUser          = pvUser;
    1454         pRange->pDevIns         = pDevIns;
    1455         pRange->pfnReadCallback = pfnReadCallback;
    1456         pRange->pfnWriteCallback= pfnWriteCallback;
    1457         pRange->pfnFillCallback = pfnFillCallback;
    1458         pRange->pszDesc         = pszDesc;
     1425        pRange->Core.Key            = GCPhysStart;
     1426        pRange->Core.KeyLast        = GCPhysStart + (cbRange - 1);
     1427        pRange->GCPhys              = GCPhysStart;
     1428        pRange->cb                  = cbRange;
     1429        pRange->pszDesc             = pszDesc;
     1430
     1431        pRange->pvUserR3            = pvUser;
     1432        pRange->pDevInsR3           = pDevIns;
     1433        pRange->pfnReadCallbackR3   = pfnReadCallback;
     1434        pRange->pfnWriteCallbackR3  = pfnWriteCallback;
     1435        pRange->pfnFillCallbackR3   = pfnFillCallback;
     1436
     1437        //pRange->pvUserR0            = NIL_RTR0PTR;
     1438        //pRange->pDevInsR0           = NIL_RTR0PTR;
     1439        //pRange->pfnReadCallbackR0   = NIL_RTR0PTR;
     1440        //pRange->pfnWriteCallbackR0  = NIL_RTR0PTR;
     1441        //pRange->pfnFillCallbackR0   = NIL_RTR0PTR;
     1442
     1443        //pRange->pvUserGC            = NIL_RTGCPTR;
     1444        //pRange->pDevInsGC           = NIL_RTGCPTR;
     1445        //pRange->pfnReadCallbackGC   = NIL_RTGCPTR;
     1446        //pRange->pfnWriteCallbackGC  = NIL_RTGCPTR;
     1447        //pRange->pfnFillCallbackGC   = NIL_RTGCPTR;
    14591448
    14601449        /*
     
    14671456        if (RT_SUCCESS(rc))
    14681457        {
    1469             if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesHC->MMIOTreeR3, &pRange->Core))
     1458            if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesHC->MMIOTree, &pRange->Core))
    14701459                return VINF_SUCCESS;
    14711460
     
    15151504        return VERR_INVALID_PARAMETER;
    15161505    }
    1517     RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1);
    1518     if (GCPhysLast < GCPhysStart)
    1519     {
    1520         AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));
    1521         return VERR_IOM_INVALID_MMIO_RANGE;
    1522     }
    1523 
    1524     /*
    1525      * Check that a ring-3 MMIO range exists.
    1526      */
    1527     RTGCPHYS GCPhys = GCPhysStart;
    1528     while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
    1529     {
    1530         PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);
    1531         if (!pRange)
    1532         {
    1533             AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc));
    1534             return VERR_IOM_NO_HC_MMIO_RANGE;
    1535         }
    1536 #ifndef IOM_NO_PDMINS_CHECKS
    1537 # ifndef IN_GC
    1538         if (pRange->pDevIns != pDevIns)
    1539 # else
    1540         if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))
    1541 # endif
    1542         {
    1543             AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc,
    1544                              pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc)));
    1545             return VERR_IOM_NOT_MMIO_RANGE_OWNER;
    1546         }
    1547 #endif /* !IOM_NO_PDMINS_CHECKS */
    1548         /* next */
    1549         Assert(GCPhys <= pRange->Core.KeyLast);
    1550         GCPhys = pRange->Core.KeyLast + 1;
    1551     }
    1552 
    1553 
    1554     /*
    1555      * Allocate new range record and initialize it.
    1556      */
    1557     PIOMMMIORANGEGC pRange;
    1558     int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);
    1559     if (VBOX_SUCCESS(rc))
    1560     {
    1561         pRange->Core.Key        = GCPhysStart;
    1562         pRange->Core.KeyLast    = GCPhysStart + (cbRange - 1);
    1563         pRange->GCPhys          = GCPhysStart;
    1564         pRange->cb              = cbRange;
    1565         pRange->pvUser          = pvUser;
    1566         pRange->pfnReadCallback = pfnReadCallback;
    1567         pRange->pfnWriteCallback= pfnWriteCallback;
    1568         pRange->pfnFillCallback = pfnFillCallback;
    1569 #ifdef IN_GC
    1570         pRange->pDevIns         = pDevIns;
    1571         pRange->pszDesc         = MMHyperGC2HC(pVM, (void *)pszDesc);
    1572 #else
    1573         pRange->pDevIns         = MMHyperHC2GC(pVM, pDevIns);
    1574         pRange->pszDesc         = pszDesc;
    1575 #endif
    1576 
    1577         /*
    1578          * Try insert it.
    1579          */
    1580         if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeGC, &pRange->Core))
    1581             return VINF_SUCCESS;
    1582 
    1583         AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));
    1584         MMHyperFree(pVM, pRange);
    1585         rc = VERR_IOM_MMIO_RANGE_CONFLICT;
    1586     }
    1587 
    1588     return rc;
     1506
     1507    /*
     1508     * Find the MMIO range and check that the input matches.
     1509     */
     1510    PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhysStart);
     1511    AssertReturn(pRange, VERR_IOM_MMIO_RANGE_NOT_FOUND);
     1512    AssertReturn(pRange->pDevInsR3 == pDevIns, VERR_IOM_NOT_MMIO_RANGE_OWNER);
     1513    AssertReturn(pRange->GCPhys == GCPhysStart, VERR_IOM_INVALID_MMIO_RANGE);
     1514    AssertReturn(pRange->cb == cbRange, VERR_IOM_INVALID_MMIO_RANGE);
     1515
     1516    pRange->pvUserGC          = pvUser;
     1517    pRange->pfnReadCallbackGC = pfnReadCallback;
     1518    pRange->pfnWriteCallbackGC= pfnWriteCallback;
     1519    pRange->pfnFillCallbackGC = pfnFillCallback;
     1520    pRange->pDevInsGC         = MMHyperCCToGC(pVM, pDevIns);
     1521
     1522    return VINF_SUCCESS;
    15891523}
    15901524
     
    16241558        return VERR_INVALID_PARAMETER;
    16251559    }
    1626     RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1);
    1627     if (GCPhysLast < GCPhysStart)
    1628     {
    1629         AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));
    1630         return VERR_IOM_INVALID_MMIO_RANGE;
    1631     }
    1632 
    1633     /*
    1634      * Check that a ring-3 MMIO range exists.
    1635      */
    1636     RTGCPHYS GCPhys = GCPhysStart;
    1637     while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
    1638     {
    1639         PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);
    1640         if (!pRange)
    1641         {
    1642             AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc));
    1643             return VERR_IOM_NO_HC_MMIO_RANGE;
    1644         }
    1645 #ifndef IOM_NO_PDMINS_CHECKS
    1646 # ifndef IN_GC
    1647         if (pRange->pDevIns != pDevIns)
    1648 # else
    1649         if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))
    1650 # endif
    1651         {
    1652             AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc,
    1653                              pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc)));
    1654             return VERR_IOM_NOT_MMIO_RANGE_OWNER;
    1655         }
    1656 #endif /* !IOM_NO_PDMINS_CHECKS */
    1657         /* next */
    1658         Assert(GCPhys <= pRange->Core.KeyLast);
    1659         GCPhys = pRange->Core.KeyLast + 1;
    1660     }
    1661 
    1662 
    1663     /*
    1664      * Allocate new range record and initialize it.
    1665      */
    1666     PIOMMMIORANGER0 pRange;
    1667     int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);
    1668     if (VBOX_SUCCESS(rc))
    1669     {
    1670         pRange->Core.Key        = GCPhysStart;
    1671         pRange->Core.KeyLast    = GCPhysStart + (cbRange - 1);
    1672         pRange->GCPhys          = GCPhysStart;
    1673         pRange->cb              = cbRange;
    1674         pRange->pvUser          = pvUser;
    1675         pRange->pfnReadCallback = pfnReadCallback;
    1676         pRange->pfnWriteCallback= pfnWriteCallback;
    1677         pRange->pfnFillCallback = pfnFillCallback;
    1678 #ifdef IN_GC
    1679         pRange->pDevIns         = MMHyperGCToR0(pVM, pDevIns);
    1680         pRange->pszDesc         = MMHyperGCToR3(pVM, (void *)pszDesc);
    1681 #elif defined(IN_RING3)
    1682         pRange->pDevIns         = MMHyperR3ToR0(pVM, pDevIns);
    1683         pRange->pszDesc         = pszDesc;
    1684 #else
    1685         pRange->pDevIns         = pDevIns;
    1686         pRange->pszDesc         = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc);
    1687 #endif
    1688 
    1689         /*
    1690          * Try insert it.
    1691          */
    1692         if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR0, &pRange->Core))
    1693             return VINF_SUCCESS;
    1694 
    1695         AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));
    1696         MMHyperFree(pVM, pRange);
    1697         rc = VERR_IOM_MMIO_RANGE_CONFLICT;
    1698     }
    1699 
    1700     return rc;
     1560
     1561    /*
     1562     * Find the MMIO range and check that the input matches.
     1563     */
     1564    PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhysStart);
     1565    AssertReturn(pRange, VERR_IOM_MMIO_RANGE_NOT_FOUND);
     1566    AssertReturn(pRange->pDevInsR3 == pDevIns, VERR_IOM_NOT_MMIO_RANGE_OWNER);
     1567    AssertReturn(pRange->GCPhys == GCPhysStart, VERR_IOM_INVALID_MMIO_RANGE);
     1568    AssertReturn(pRange->cb == cbRange, VERR_IOM_INVALID_MMIO_RANGE);
     1569
     1570    pRange->pvUserR0          = pvUser;
     1571    pRange->pfnReadCallbackR0 = pfnReadCallback;
     1572    pRange->pfnWriteCallbackR0= pfnWriteCallback;
     1573    pRange->pfnFillCallbackR0 = pfnFillCallback;
     1574    pRange->pDevInsR0         = MMHyperCCToR0(pVM, pDevIns);
     1575
     1576    return VINF_SUCCESS;
    17011577}
    17021578
     
    17321608
    17331609    /*
    1734      * Check ownership and such.
     1610     * Check ownership and such for the entire area.
    17351611     */
    17361612    RTGCPHYS GCPhys = GCPhysStart;
    17371613    while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
    17381614    {
    1739         PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysGet(&pVM->iom.s.pTreesHC->MMIOTreeR3, GCPhys);
     1615        PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
    17401616        if (!pRange)
    17411617            return VERR_IOM_MMIO_RANGE_NOT_FOUND;
    1742 #ifndef IOM_NO_PDMINS_CHECKS
    1743         if (pRange->pDevIns != pDevIns)
    1744         {
    1745             AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc));
    1746             return VERR_IOM_NOT_MMIO_RANGE_OWNER;
    1747         }
    1748 #endif /* !IOM_NO_PDMINS_CHECKS */
    1749         if (pRange->Core.KeyLast > GCPhysLast)
    1750         {
    1751             AssertMsgFailed(("Incomplete R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc));
    1752             return VERR_IOM_INCOMPLETE_MMIO_RANGE;
    1753         }
     1618        AssertMsgReturn(pRange->pDevInsR3 == pDevIns,
     1619                        ("Not owner! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc),
     1620                        VERR_IOM_NOT_MMIO_RANGE_OWNER);
     1621        AssertMsgReturn(pRange->Core.KeyLast <= GCPhysLast,
     1622                        ("Incomplete R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pRange->pszDesc),
     1623                        VERR_IOM_INCOMPLETE_MMIO_RANGE);
     1624
    17541625        /* next */
    17551626        Assert(GCPhys <= pRange->Core.KeyLast);
     
    17581629
    17591630    /*
    1760      * Remove GC ranges.
     1631     * Do the actual removing of the MMIO ranges.
    17611632     */
    17621633    GCPhys = GCPhysStart;
    17631634    while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
    17641635    {
    1765         PIOMMMIORANGEGC pRange = (PIOMMMIORANGEGC)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTreeGC, GCPhys);
    1766         if (pRange)
    1767         {
    1768             Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast);
    1769 
    1770             /* next and delete. */
    1771             GCPhys = pRange->Core.KeyLast + 1;
    1772             MMHyperFree(pVM, pRange);
    1773         }
    1774         else /* next - this'll be damned slow! */
    1775             GCPhys++;
    1776     }
    1777 
    1778     /*
    1779      * Remove R0 ranges.
    1780      */
    1781     GCPhys = GCPhysStart;
    1782     while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
    1783     {
    1784         PIOMMMIORANGER0 pRange = (PIOMMMIORANGER0)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTreeR0, GCPhys);
    1785         if (pRange)
    1786         {
    1787             Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast);
    1788 
    1789             /* next and delete. */
    1790             GCPhys = pRange->Core.KeyLast + 1;
    1791             MMHyperFree(pVM, pRange);
    1792         }
    1793         else /* next - this'll be damned slow! */
    1794             GCPhys++;
    1795     }
    1796 
    1797     /*
    1798      * Remove R3 ranges.
    1799      */
    1800     GCPhys = GCPhysStart;
    1801     while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
    1802     {
    1803         PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTreeR3, GCPhys);
     1636        PIOMMMIORANGE pRange = (PIOMMMIORANGE)RTAvlroGCPhysRemove(&pVM->iom.s.pTreesHC->MMIOTree, GCPhys);
    18041637        Assert(pRange);
    18051638        Assert(pRange->Core.Key == GCPhys && pRange->Core.KeyLast <= GCPhysLast);
     
    18091642        AssertRC(rc);
    18101643
    1811         /* next and delete. */
     1644        /* advance and free. */
    18121645        GCPhys = pRange->Core.KeyLast + 1;
    18131646        MMHyperFree(pVM, pRange);
    18141647    }
    18151648
     1649    iomR3FlushCache(pVM);
    18161650    return VINF_SUCCESS;
    18171651}
     
    18191653
    18201654/**
    1821  * Display a single MMIO R3 range.
     1655 * Display a single MMIO range.
    18221656 *
    18231657 * @returns 0
     
    18251659 * @param   pvUser  Pointer to info output callback structure.
    18261660 */
    1827 static DECLCALLBACK(int) iomR3MMIOInfoOneR3(PAVLROGCPHYSNODECORE pNode, void *pvUser)
    1828 {
    1829     PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)pNode;
     1661static DECLCALLBACK(int) iomR3MMIOInfoOne(PAVLROGCPHYSNODECORE pNode, void *pvUser)
     1662{
     1663    PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode;
    18301664    PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;
    18311665    pHlp->pfnPrintf(pHlp,
     
    18331667                    pRange->Core.Key,
    18341668                    pRange->Core.KeyLast,
    1835                     pRange->pDevIns,
    1836                     pRange->pfnReadCallback,
    1837                     pRange->pfnWriteCallback,
    1838                     pRange->pfnFillCallback,
    1839                     pRange->pvUser,
     1669                    pRange->pDevInsR3,
     1670                    pRange->pfnReadCallbackR3,
     1671                    pRange->pfnWriteCallbackR3,
     1672                    pRange->pfnFillCallbackR3,
     1673                    pRange->pvUserR3,
    18401674                    pRange->pszDesc);
    1841     return 0;
    1842 }
    1843 
    1844 
    1845 /**
    1846  * Display a single MMIO GC range.
    1847  *
    1848  * @returns 0
    1849  * @param   pNode   Pointer to MMIO GC range.
    1850  * @param   pvUser  Pointer to info output callback structure.
    1851  */
    1852 static DECLCALLBACK(int) iomR3MMIOInfoOneGC(PAVLROGCPHYSNODECORE pNode, void *pvUser)
    1853 {
    1854     PIOMMMIORANGEGC pRange = (PIOMMMIORANGEGC)pNode;
    1855     PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;
    18561675    pHlp->pfnPrintf(pHlp,
    1857                     "%VGp-%VGp %VGv %VGv %VGv %VGv %VGv %s\n",
    1858                     pRange->Core.Key,
    1859                     pRange->Core.KeyLast,
    1860                     pRange->pDevIns,
    1861                     pRange->pfnReadCallback,
    1862                     pRange->pfnWriteCallback,
    1863                     pRange->pfnFillCallback,
    1864                     pRange->pvUser,
    1865                     pRange->pszDesc);
     1676                    "%*s %VHv %VHv %VHv %VHv %VHv\n",
     1677                    sizeof(RTGCPHYS) * 2 * 2 + 1, "R0",
     1678                    pRange->pDevInsR0,
     1679                    pRange->pfnReadCallbackR0,
     1680                    pRange->pfnWriteCallbackR0,
     1681                    pRange->pfnFillCallbackR0,
     1682                    pRange->pvUserR0);
     1683    pHlp->pfnPrintf(pHlp,
     1684                    "%*s %VGv %VGv %VGv %VGv %VGv\n",
     1685                    sizeof(RTGCPHYS) * 2 * 2 + 1, "GC",
     1686                    pRange->pDevInsGC,
     1687                    pRange->pfnReadCallbackGC,
     1688                    pRange->pfnWriteCallbackGC,
     1689                    pRange->pfnFillCallbackGC,
     1690                    pRange->pvUserGC);
    18661691    return 0;
    18671692}
     
    18791704    NOREF(pszArgs);
    18801705    pHlp->pfnPrintf(pHlp,
    1881                     "MMIO R3 ranges (pVM=%p)\n"
     1706                    "MMIO ranges (pVM=%p)\n"
    18821707                    "%.*s %.*s %.*s %.*s %.*s %.*s %s\n",
    18831708                    pVM,
     
    18881713                    sizeof(RTHCPTR) * 2,      "Fill            ",
    18891714                    sizeof(RTHCPTR) * 2,      "pvUser          ",
    1890                                                 "Description");
    1891     RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeR3, true, iomR3MMIOInfoOneR3, (void *)pHlp);
    1892 
    1893     pHlp->pfnPrintf(pHlp,
    1894                     "MMIO R0 ranges (pVM=%p)\n"
    1895                     "%.*s %.*s %.*s %.*s %.*s %.*s %s\n",
    1896                     pVM,
    1897                     sizeof(RTGCPHYS) * 4 + 1, "GC Phys Range                    ",
    1898                     sizeof(RTGCPTR) * 2,      "pDevIns         ",
    1899                     sizeof(RTGCPTR) * 2,      "Read            ",
    1900                     sizeof(RTGCPTR) * 2,      "Write           ",
    1901                     sizeof(RTGCPTR) * 2,      "Fill            ",
    1902                     sizeof(RTGCPTR) * 2,      "pvUser          ",
    1903                                                 "Description");
    1904     RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeR0, true, iomR3MMIOInfoOneR3, (void *)pHlp);
    1905 
    1906     pHlp->pfnPrintf(pHlp,
    1907                     "MMIO GC ranges (pVM=%p)\n"
    1908                     "%.*s %.*s %.*s %.*s %.*s %.*s %s\n",
    1909                     pVM,
    1910                     sizeof(RTGCPHYS) * 4 + 1, "GC Phys Range                    ",
    1911                     sizeof(RTGCPTR) * 2,      "pDevIns         ",
    1912                     sizeof(RTGCPTR) * 2,      "Read            ",
    1913                     sizeof(RTGCPTR) * 2,      "Write           ",
    1914                     sizeof(RTGCPTR) * 2,      "Fill            ",
    1915                     sizeof(RTGCPTR) * 2,      "pvUser          ",
    1916                                                 "Description");
    1917     RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTreeGC, true, iomR3MMIOInfoOneGC, (void *)pHlp);
     1715                                              "Description");
     1716    RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesHC->MMIOTree, true, iomR3MMIOInfoOne, (void *)pHlp);
    19181717}
    19191718
  • trunk/src/VBox/VMM/IOMInternal.h

    r7731 r7751  
    2424#include <VBox/stam.h>
    2525#include <VBox/pgm.h>
     26#include <VBox/param.h>
    2627#include <iprt/avl.h>
    2728
     
    3839
    3940/**
    40  * MMIO range descriptor, R3 version.
    41  */
    42 typedef struct IOMMMIORANGER3
    43 {
    44     /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
    45     AVLROGCPHYSNODECORE         Core;
    46 #if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32 && !defined(RT_OS_WINDOWS)
    47     uint32_t                    u32Alignment; /**< The sizeof(Core) differs. */
    48 #endif
    49     /** Start physical address. */
    50     RTGCPHYS                    GCPhys;
    51     /** Size of the range. */
    52     RTUINT                      cb;
    53     /** Pointer to user argument. */
    54     RTR3PTR                     pvUser;
    55     /** Pointer to device instance. */
    56     R3PTRTYPE(PPDMDEVINS)       pDevIns;
    57     /** Pointer to write callback function. */
    58     R3PTRTYPE(PFNIOMMMIOWRITE)  pfnWriteCallback;
    59     /** Pointer to read callback function. */
    60     R3PTRTYPE(PFNIOMMMIOREAD)   pfnReadCallback;
    61     /** Pointer to fill (memset) callback function. */
    62     R3PTRTYPE(PFNIOMMMIOFILL)   pfnFillCallback;
    63     /** Description / Name. For easing debugging. */
    64     R3PTRTYPE(const char *)     pszDesc;
    65 } IOMMMIORANGER3;
    66 /** Pointer to a MMIO range descriptor, R3 version. */
    67 typedef struct IOMMMIORANGER3 *PIOMMMIORANGER3;
    68 
    69 /**
    70  * MMIO range descriptor, R0 version.
    71  */
    72 typedef struct IOMMMIORANGER0
    73 {
    74     /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
    75     AVLROGCPHYSNODECORE         Core;
    76     /** Start physical address. */
    77     RTGCPHYS                    GCPhys;
    78 #if HC_ARCH_BITS == 64
    79     uint32_t                    u32Alignment;
    80 #endif
    81     /** Size of the range. */
    82     RTUINT                      cb;
    83     /** Pointer to user argument. */
    84     RTR0PTR                     pvUser;
    85     /** Pointer to device instance. */
    86     R0PTRTYPE(PPDMDEVINS)       pDevIns;
    87     /** Pointer to write callback function. */
    88     R0PTRTYPE(PFNIOMMMIOWRITE)  pfnWriteCallback;
    89     /** Pointer to read callback function. */
    90     R0PTRTYPE(PFNIOMMMIOREAD)   pfnReadCallback;
    91     /** Pointer to fill (memset) callback function. */
    92     R0PTRTYPE(PFNIOMMMIOFILL)   pfnFillCallback;
    93     /** Description / Name. For easing debugging. */
    94     R3PTRTYPE(const char *)     pszDesc;
    95 } IOMMMIORANGER0;
    96 /** Pointer to a MMIO range descriptor, R0 version. */
    97 typedef struct IOMMMIORANGER0 *PIOMMMIORANGER0;
    98 
    99 /**
    100  * MMIO range descriptor, GC version.
    101  */
    102 typedef struct IOMMMIORANGEGC
     41 * MMIO range descriptor.
     42 */
     43typedef struct IOMMMIORANGE
    10344{
    10445    /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
     
    10748    RTGCPHYS                    GCPhys;
    10849    /** Size of the range. */
    109     RTUINT                      cb;
    110 #if HC_ARCH_BITS == 64
    111     uint32_t                    u32Alignment;
    112 #endif
     50    uint32_t                    cb;
     51    uint32_t                    u32Alignment; /**< Alignment padding. */
     52
    11353    /** Pointer to user argument. */
    114     RTGCPTR                     pvUser;
     54    RTR3PTR                     pvUserR3;
    11555    /** Pointer to device instance. */
    116     GCPTRTYPE(PPDMDEVINS)       pDevIns;
     56    PPDMDEVINSR3                pDevInsR3;
    11757    /** Pointer to write callback function. */
    118     GCPTRTYPE(PFNIOMMMIOWRITE)  pfnWriteCallback;
     58    R3PTRTYPE(PFNIOMMMIOWRITE)  pfnWriteCallbackR3;
    11959    /** Pointer to read callback function. */
    120     GCPTRTYPE(PFNIOMMMIOREAD)   pfnReadCallback;
     60    R3PTRTYPE(PFNIOMMMIOREAD)   pfnReadCallbackR3;
    12161    /** Pointer to fill (memset) callback function. */
    122     GCPTRTYPE(PFNIOMMMIOFILL)   pfnFillCallback;
    123 #if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
    124     RTGCPTR                     GCPtrAlignment; /**< pszDesc is 8 byte aligned. */
    125 #endif
     62    R3PTRTYPE(PFNIOMMMIOFILL)   pfnFillCallbackR3;
     63
     64    /** Pointer to user argument. */
     65    RTR0PTR                     pvUserR0;
     66    /** Pointer to device instance. */
     67    PPDMDEVINSR0                pDevInsR0;
     68    /** Pointer to write callback function. */
     69    R0PTRTYPE(PFNIOMMMIOWRITE)  pfnWriteCallbackR0;
     70    /** Pointer to read callback function. */
     71    R0PTRTYPE(PFNIOMMMIOREAD)   pfnReadCallbackR0;
     72    /** Pointer to fill (memset) callback function. */
     73    R0PTRTYPE(PFNIOMMMIOFILL)   pfnFillCallbackR0;
     74
     75    /** Pointer to user argument. */
     76    RTGCPTR                     pvUserGC;
     77    /** Pointer to device instance. */
     78    PPDMDEVINSGC                pDevInsGC;
     79    /** Pointer to write callback function. */
     80    GCPTRTYPE(PFNIOMMMIOWRITE)  pfnWriteCallbackGC;
     81    /** Pointer to read callback function. */
     82    GCPTRTYPE(PFNIOMMMIOREAD)   pfnReadCallbackGC;
     83    /** Pointer to fill (memset) callback function. */
     84    GCPTRTYPE(PFNIOMMMIOFILL)   pfnFillCallbackGC;
     85    RTGCPTR                     GCPtrAlignment; /**< Alignment padding */
     86
    12687    /** Description / Name. For easing debugging. */
    12788    R3PTRTYPE(const char *)     pszDesc;
    128 } IOMMMIORANGEGC;
    129 /** Pointer to a MMIO range descriptor, GC version. */
    130 typedef struct IOMMMIORANGEGC *PIOMMMIORANGEGC;
     89} IOMMMIORANGE;
     90/** Pointer to a MMIO range descriptor, R3 version. */
     91typedef struct IOMMMIORANGE *PIOMMMIORANGE;
    13192
    13293
     
    340301    AVLROIOPORTTREE         IOPortTreeGC;
    341302
    342     /** Tree containing MMIO range descriptors registered for HC (IOMMMIORANGEHC). */
    343     AVLROGCPHYSTREE         MMIOTreeR3;
    344     /** Tree containing MMIO range descriptors registered for R0 (IOMMMIORANGER0). */
    345     AVLROGCPHYSTREE         MMIOTreeR0;
    346     /** Tree containing MMIO range descriptors registered for GC (IOMMMIORANGEGC). */
    347     AVLROGCPHYSTREE         MMIOTreeGC;
     303    /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */
     304    AVLROGCPHYSTREE         MMIOTree;
    348305
    349306    /** Tree containing I/O port statistics (IOMIOPORTSTATS). */
     
    382339    RTGCPTR                         Alignment;
    383340
    384     /** @name Caching of I/O Port ranges and statistics.
     341    /** @name Caching of I/O Port and MMIO ranges and statistics.
    385342     * (Saves quite some time in rep outs/ins instruction emulation.)
    386343     * @{ */
     
    389346    R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR3;
    390347    R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR3;
    391 
    392     R3R0PTRTYPE(PIOMIOPORTRANGER0)  pRangeLastReadR0;
    393     R3R0PTRTYPE(PIOMIOPORTRANGER0)  pRangeLastWriteR0;
    394     R3R0PTRTYPE(PIOMIOPORTSTATS)    pStatsLastReadR0;
    395     R3R0PTRTYPE(PIOMIOPORTSTATS)    pStatsLastWriteR0;
     348    R3PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR3;
     349    R3PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR3;
     350
     351    R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastReadR0;
     352    R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastWriteR0;
     353    R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR0;
     354    R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR0;
     355    R0PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR0;
     356    R0PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR0;
    396357
    397358    GCPTRTYPE(PIOMIOPORTRANGEGC)    pRangeLastReadGC;
     
    399360    GCPTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadGC;
    400361    GCPTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteGC;
     362    GCPTRTYPE(PIOMMMIORANGE)        pMMIORangeLastGC;
     363    GCPTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastGC;
    401364    /** @} */
    402365
     
    472435 * @param   Port    Port to lookup.
    473436 */
    474 inline CTXALLSUFF(PIOMIOPORTRANGE) iomIOPortGetRange(PIOM pIOM, RTIOPORT Port)
     437DECLINLINE(CTXALLSUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PIOM pIOM, RTIOPORT Port)
    475438{
    476439    CTXALLSUFF(PIOMIOPORTRANGE) pRange = (CTXALLSUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(IOPortTree), Port);
     
    487450 * @param   Port    Port to lookup.
    488451 */
    489 inline PIOMIOPORTRANGER3 iomIOPortGetRangeHC(PIOM pIOM, RTIOPORT Port)
     452DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeHC(PIOM pIOM, RTIOPORT Port)
    490453{
    491454    PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->IOPortTreeR3, Port);
     
    503466 * @param   GCPhys  Physical address to lookup.
    504467 */
    505 inline CTXALLSUFF(PIOMMMIORANGE) iomMMIOGetRange(PIOM pIOM, RTGCPHYS GCPhys)
    506 {
    507     CTXALLSUFF(PIOMMMIORANGE) pRange = (CTXALLSUFF(PIOMMMIORANGE))RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(MMIOTree), GCPhys);
     468DECLINLINE(PIOMMMIORANGE) iomMMIOGetRange(PIOM pIOM, RTGCPHYS GCPhys)
     469{
     470    PIOMMMIORANGE pRange = CTXALLSUFF(pIOM->pMMIORangeLast);
     471    if (    !pRange
     472        ||  GCPhys - pRange->GCPhys >= pRange->cb)
     473        CTXALLSUFF(pIOM->pMMIORangeLast) = pRange = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->MMIOTree, GCPhys);
    508474    return pRange;
    509475}
    510476
    511477
    512 /**
    513  * Gets the MMIO range for the specified physical address in the current context.
    514  *
    515  * @returns Pointer to MMIO range.
    516  * @returns NULL if address not in a MMIO range.
    517  *
    518  * @param   pIOM    IOM instance data.
    519  * @param   GCPhys  Physical address to lookup.
    520  */
    521 inline PIOMMMIORANGER3 iomMMIOGetRangeHC(PIOM pIOM, RTGCPHYS GCPhys)
    522 {
    523     PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);
    524     return pRange;
    525 }
    526 
    527478#ifdef VBOX_WITH_STATISTICS
    528479/**
    529480 * Gets the MMIO statistics record.
     481 *
     482 * In ring-3 this will lazily create missing records, while in GC/R0 the caller has to
     483 * return the appropriate status to defer the operation to ring-3.
     484 *
    530485 * @returns Pointer to MMIO stats.
    531  * @returns NULL if not found.
    532  *
    533  * @param   pIOM    IOM instance data.
    534  * @param   GCPhys  Physical address to lookup.
    535  */
    536 inline PIOMMMIOSTATS iomMMIOGetStats(PIOM pIOM, RTGCPHYS GCPhys)
    537 {
    538     PIOMMMIOSTATS pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pIOM->CTXSUFF(pTrees)->MMIOStatTree, GCPhys);
     486 * @returns NULL if not found (R0/GC), or out of memory (R3).
     487 *
     488 * @param   pIOM        IOM instance data.
     489 * @param   GCPhys      Physical address to lookup.
     490 * @param   pRange      The MMIO range.
     491 */
     492DECLINLINE(PIOMMMIOSTATS) iomMMIOGetStats(PIOM pIOM, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
     493{
     494    /* For large ranges, we'll put everything on the first byte. */
     495    if (pRange->cb > PAGE_SIZE)
     496        GCPhys = pRange->GCPhys;
     497
     498    PIOMMMIOSTATS pStats = CTXALLSUFF(pIOM->pMMIOStatsLast);
     499    if (    !pStats
     500        ||  pStats->Core.Key != GCPhys)
     501    {
     502        pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pIOM->CTXSUFF(pTrees)->MMIOStatTree, GCPhys);
     503# ifdef IN_RING3
     504        if (!pStats)
     505            pStats = iomR3MMIOStatsCreate(IOM2VM(pIOM), GCPhys, pRange->pszDesc);
     506# endif
     507    }
    539508    return pStats;
    540509}
  • trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp

    r7731 r7751  
    159159 * @warning VBOX_SUCCESS(rc=VINF_IOM_HC_MMIO_WRITE) is TRUE!
    160160 */
    161 DECLINLINE(int) iomMMIODoWrite(PVM pVM, CTXALLSUFF(PIOMMMIORANGE) pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
     161DECLINLINE(int) iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
    162162{
    163163#ifdef VBOX_WITH_STATISTICS
    164     if (pRange->cb <= PAGE_SIZE)
    165     {
    166         PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault);
    167         if (!pStats)
    168             return VINF_IOM_HC_MMIO_WRITE;
    169 
    170         int rc = pRange->pfnWriteCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */
    171         if (rc != VINF_IOM_HC_MMIO_WRITE)
    172             STAM_COUNTER_INC(&pStats->WriteGC);
    173         return rc;
    174     }
    175 #endif
    176     return pRange->pfnWriteCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, (void *)pvData, cb);
     164    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange);
     165    Assert(pStats);
     166#endif
     167
     168    int rc;
     169    if (RT_LIKELY(pRange->CTXALLSUFF(pfnWriteCallback)))
     170        rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, (void *)pvData, cb); /* @todo fix const!! */
     171    else
     172        rc = VINF_SUCCESS;
     173    if (rc != VINF_IOM_HC_MMIO_WRITE)
     174        STAM_COUNTER_INC(&pStats->CTXALLSUFF(Write));
     175    return rc;
    177176}
    178177
     
    180179 * Wrapper which does the read and updates range statistics when such are enabled.
    181180 */
    182 DECLINLINE(int) iomMMIODoRead(PVM pVM, CTXALLSUFF(PIOMMMIORANGE) pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb)
     181DECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, void *pvData, unsigned cb)
    183182{
    184183#ifdef VBOX_WITH_STATISTICS
    185     if (pRange->cb <= PAGE_SIZE)
    186     {
    187         PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault);
    188         if (!pStats)
    189             return VINF_IOM_HC_MMIO_READ;
    190 
    191         int rc = pRange->pfnReadCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, pvData, cb);
    192         if (rc != VINF_IOM_HC_MMIO_READ)
    193             STAM_COUNTER_INC(&pStats->ReadGC);
    194         return rc;
    195     }
    196 #endif
    197     return pRange->pfnReadCallback(pRange->pDevIns, pRange->pvUser, GCPhysFault, pvData, cb);
     184    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange);
     185    Assert(pStats);
     186#endif
     187
     188    int rc;
     189    if (RT_LIKELY(pRange->CTXALLSUFF(pfnReadCallback)))
     190        rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhysFault, pvData, cb);
     191    else
     192    {
     193        switch (cb)
     194        {
     195            case 1: *(uint8_t  *)pvData = 0; break;
     196            case 2: *(uint16_t *)pvData = 0; break;
     197            case 4: *(uint32_t *)pvData = 0; break;
     198            case 8: *(uint64_t *)pvData = 0; break;
     199            default:
     200                memset(pvData, 0, cb);
     201                break;
     202        }
     203        rc = VINF_SUCCESS;
     204    }
     205    if (rc != VINF_IOM_HC_MMIO_READ)
     206        STAM_COUNTER_INC(&pStats->CTXALLSUFF(Read));
     207    return rc;
    198208}
    199209
     
    323333 * Internal - statistics only.
    324334 */
    325 inline void iomMMIOStatLength(PVM pVM, unsigned cb)
     335DECLINLINE(void) iomMMIOStatLength(PVM pVM, unsigned cb)
    326336{
    327337#ifdef VBOX_WITH_STATISTICS
     
    361371 * @param   GCPhysFault The GC physical address corresponding to pvFault.
    362372 */
    363 static int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange, RTGCPHYS GCPhysFault)
    364 {
    365     /*
    366      * If no read handler then go to ring-3 and handle it there.
    367      */
    368     if (!pRange->pfnReadCallback)
    369         return VINF_IOM_HC_MMIO_READ;
     373static int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
     374{
     375    Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
    370376
    371377    /*
     
    424430 * @param   GCPhysFault The GC physical address corresponding to pvFault.
    425431 */
    426 static int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange, RTGCPHYS GCPhysFault)
    427 {
    428     /*
    429      * If no write handler then go to ring-3 and handle it there.
    430      */
    431     if (!pRange->pfnWriteCallback)
    432         return VINF_IOM_HC_MMIO_WRITE;
     432static int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
     433{
     434    Assert(pRange->CTXALLSUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3);
    433435
    434436    /*
     
    448450
    449451
    450 /** @todo All the string MMIO stuff can do terrible things since physical contiguous mappings are
    451  * assumed all over the place! This must be addressed in a general way, like for example let EM do
    452  * all the interpretation and checking of selectors and addresses.
    453  *
    454  * -> I don't see the problem here. MMIO ranges are by definition linear ranges. The virtual source or destination is read/written properly.
    455  */
    456 
    457 
     452/** Wrapper for reading virtual memory. */
    458453DECLINLINE(int) iomRamRead(PVM pVM, void *pDest, RTGCPTR GCSrc, uint32_t cb)
    459454{
     
    465460}
    466461
     462
     463/** Wrapper for writing virtual memory. */
    467464DECLINLINE(int) iomRamWrite(PVM pVM, RTGCPTR GCDest, void *pSrc, uint32_t cb)
    468465{
     
    474471}
    475472
     473
     474#ifdef iom_MOVS_SUPPORT
    476475/**
    477476 * [REP] MOVSB
     
    491490 * @param   pRange      Pointer MMIO range.
    492491 */
    493 #ifdef iom_MOVS_SUPPORT
    494 static int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    495 {
    496     STAM_PROFILE_START(&pVM->iom.s.StatGCInstMovs, a);
    497 
     492static int iomInterpretMOVS(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     493{
    498494    /*
    499495     * We do not support segment prefixes or REPNE.
    500496     */
    501497    if (pCpu->prefix & (PREFIX_SEG | PREFIX_REPNE))
    502         return VINF_IOM_HC_MMIO_READ_WRITE;
     498        return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> interpret whatever. */
    503499
    504500
     
    531527        pVM->iom.s.cMovsMaxBytes = cTransfers << SIZE_2_SHIFT(cb);
    532528#endif
     529
     530/** @todo re-evaluate on page boundraries. */
    533531
    534532    RTGCPHYS Phys = GCPhysFault;
     
    543541
    544542        /* Check callback. */
    545         if (!pRange->pfnWriteCallback)
     543        if (!pRange->CTXALLSUFF(pfnWriteCallback))
    546544        {
    547545            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovsToMMIO, a2);
     
    552550        RTGCUINTPTR pu8Virt;
    553551        rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
    554                                 SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
    555                                 (PRTGCPTR)&pu8Virt, NULL);
     552                          SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
     553                          (PRTGCPTR)&pu8Virt, NULL);
    556554        if (VBOX_SUCCESS(rc))
    557555        {
     
    617615
    618616        /* Check if destination address is MMIO. */
     617        PIOMMMIORANGE pMMIODst;
    619618        RTGCPHYS PhysDst;
    620619        rc = PGMGstGetPage(pVM, (RTGCPTR)pu8Virt, NULL, &PhysDst);
     620        PhysDst |= (RTGCUINTPTR)pu8Virt & PAGE_OFFSET_MASK;
    621621        if (    VBOX_SUCCESS(rc)
    622             &&  iomMMIOGetRangeHC(&pVM->iom.s, PhysDst))
     622            &&  (pMMIODst = iomMMIOGetRange(&pVM->iom.s, PhysDst)))
    623623        {
    624624            /*
     
    628628            STAM_PROFILE_START(&pVM->iom.s.StatGCInstMovsFromMMIO, c);
    629629
    630             PhysDst |= (RTGCUINTPTR)pu8Virt & PAGE_OFFSET_MASK;
    631             CTXALLSUFF(PIOMMMIORANGE) pMMIODst = iomMMIOGetRange(&pVM->iom.s, PhysDst);
    632             if (    !pMMIODst
    633                 ||  !pMMIODst->pfnWriteCallback)
     630            if (!pMMIODst->CTXALLSUFF(pfnWriteCallback) && pMMIODst->pfnWriteCallbackR3)
    634631            {
    635632                STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovsMMIO, d);
     
    711708    if (rc == VINF_SUCCESS)
    712709    {
    713         STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovs, a);
    714710        iomMMIOStatLength(pVM, cb);
    715711    }
     
    736732 * @param   pRange      Pointer MMIO range.
    737733 */
    738 static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    739 {
    740     STAM_PROFILE_START(&pVM->iom.s.StatGCInstStos, a);
    741 
     734static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     735{
    742736    /*
    743737     * We do not support segment prefixes or REPNE..
    744738     */
    745739    if (pCpu->prefix & (PREFIX_SEG | PREFIX_REPNE))
    746         return VINF_IOM_HC_MMIO_READ_WRITE;
     740        return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> REM instead of HC */
    747741
    748742    /*
     
    776770    uint32_t    u32Data = pRegFrame->eax;
    777771    int rc;
    778     if (pRange->pfnFillCallback)
     772    if (pRange->CTXALLSUFF(pfnFillCallback))
    779773    {
    780774        /*
     
    785779        {
    786780            /* addr++ variant. */
    787             rc = pRange->pfnFillCallback(pRange->pDevIns, pRange->pvUser, Phys, u32Data, cb, cTransfers);
     781            rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), Phys, u32Data, cb, cTransfers);
    788782            if (rc == VINF_SUCCESS)
    789783            {
     
    797791        {
    798792            /* addr-- variant. */
    799             rc = pRange->pfnFillCallback(pRange->pDevIns, pRange->pvUser, (Phys - (cTransfers - 1)) << SIZE_2_SHIFT(cb), u32Data, cb, cTransfers);
     793            rc = pRange->CTXALLSUFF(pfnFillCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), (Phys - (cTransfers - 1)) << SIZE_2_SHIFT(cb), u32Data, cb, cTransfers);
    800794            if (rc == VINF_SUCCESS)
    801795            {
     
    812806         * Use the write callback.
    813807         */
    814         /* Check write callback. */
    815         if (!pRange->pfnWriteCallback)
    816             return VINF_IOM_HC_MMIO_WRITE;
     808        Assert(pRange->CTXALLSUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3);
    817809
    818810        /* fill loop. */
     
    837829     */
    838830    if (rc == VINF_SUCCESS)
    839     {
    840         STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstStos, a);
    841831        iomMMIOStatLength(pVM, cb);
    842     }
    843832    return rc;
    844833}
     
    861850 * @param   pRange      Pointer MMIO range.
    862851 */
    863 static int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    864 {
    865     STAM_PROFILE_START(&pVM->iom.s.StatGCInstLods, a1);
     852static int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     853{
     854    Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
    866855
    867856    /*
     
    869858     */
    870859    if (pCpu->prefix & (PREFIX_SEG | PREFIX_REP | PREFIX_REPNE))
    871         return VINF_IOM_HC_MMIO_READ_WRITE;
    872 
    873     /* Check that we can handle it. */
    874     if (!pRange->pfnReadCallback)
    875         return VINF_IOM_HC_MMIO_READ;
     860        return VINF_IOM_HC_MMIO_READ_WRITE; /** @todo -> REM instead of HC */
    876861
    877862    /*
     
    893878     */
    894879    if (rc == VINF_SUCCESS)
    895     {
    896         STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstLods, a1);
    897880        iomMMIOStatLength(pVM, cb);
    898     }
    899881    return rc;
    900882}
     
    916898 * @param   pRange      Pointer MMIO range.
    917899 */
    918 static int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    919 {
    920     STAM_PROFILE_START(&pVM->iom.s.StatGCInstCmp, a1);
    921 
    922     /* Check read callback. */
    923     if (!pRange->pfnReadCallback)
    924         return VINF_EM_RAW_GUEST_TRAP;
     900static int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     901{
     902    Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
    925903
    926904    /*
     
    949927        pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    950928                              | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    951 
    952         STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstCmp, a1);
    953929        iomMMIOStatLength(pVM, cb);
    954930    }
     
    973949 * @param   pRange      Pointer MMIO range.
    974950 */
    975 static int iomInterpretAND(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    976 {
    977     STAM_PROFILE_START(&pVM->iom.s.StatGCInstAnd, a1);
    978 
    979     /* Check read callback. */
    980 
     951static int iomInterpretAND(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     952{
    981953    unsigned    cb = 0;
    982954    uint32_t    uData1;
     
    987959    {
    988960        /* and reg, [MMIO]. */
     961        Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
    989962        fAndWrite = false;
    990         if (pRange->pfnReadCallback)
    991             rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
    992         else
    993             rc = VINF_IOM_HC_MMIO_READ;
     963        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
    994964    }
    995965    else if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb))
     
    997967        /* and [MMIO], reg|imm. */
    998968        fAndWrite = true;
    999         if (pRange->pfnReadCallback && pRange->pfnWriteCallback)
     969        if (    (pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3)
     970            &&  (pRange->CTXALLSUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3))
    1000971            rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
    1001972        else
     
    1026997            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    1027998                                  | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    1028             STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstAnd, a1);
    1029999            iomMMIOStatLength(pVM, cb);
    10301000        }
     
    10511021 * @param   pRange      Pointer MMIO range.
    10521022 */
    1053 static int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    1054 {
    1055     STAM_PROFILE_START(&pVM->iom.s.StatGCInstTest, a1);
    1056 
    1057     /* Check read callback. */
     1023static int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     1024{
     1025    Assert(pRange->CTXALLSUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
    10581026
    10591027    unsigned    cb = 0;
     
    10651033    {
    10661034        /* and test, [MMIO]. */
    1067         if (pRange->pfnReadCallback)
    1068             rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
    1069         else
    1070             rc = VINF_IOM_HC_MMIO_READ;
     1035        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
    10711036    }
    10721037    else if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb))
    10731038    {
    10741039        /* test [MMIO], reg|imm. */
    1075         if (pRange->pfnReadCallback)
    1076             rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
    1077         else
    1078             rc = VINF_IOM_HC_MMIO_READ;
     1040        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
    10791041    }
    10801042    else
     
    10901052        pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    10911053                              | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    1092         STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstTest, a1);
    10931054        iomMMIOStatLength(pVM, cb);
    10941055    }
     
    11121073 * @param   pRange      Pointer MMIO range.
    11131074 */
    1114 static int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, CTXALLSUFF(PIOMMMIORANGE) pRange)
    1115 {
    1116     STAM_PROFILE_START(&pVM->iom.s.StatGCInstTest, a1);
    1117 
    1118     /* Check read callback. */
     1075static int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
     1076{
     1077    /* Check for read & write handlers since IOMMMIOHandler doesn't cover this. */
     1078    if (    (!pRange->CTXALLSUFF(pfnReadCallback) && pRange->pfnReadCallbackR3)
     1079        ||  (!pRange->CTXALLSUFF(pfnWriteCallback) && pRange->pfnWriteCallbackR3))
     1080        return VINF_IOM_HC_MMIO_READ_WRITE;
     1081
     1082    int         rc;
    11191083    unsigned    cb = 0;
    11201084    uint32_t    uData1;
    11211085    uint32_t    uData2;
    1122     int         rc;
    1123 
    1124     if (!pRange->pfnReadCallback || !pRange->pfnWriteCallback)
    1125     {
    1126         rc = VINF_IOM_HC_MMIO_READ;
    1127         goto end;
    1128     }
    1129 
    11301086    if (iomGetRegImmData(pCpu, &pCpu->param1, pRegFrame, &uData1, &cb))
    11311087    {
     
    11491105            Assert(rc == VINF_IOM_HC_MMIO_READ || rc == VINF_PATM_HC_MMIO_PATCH_READ);
    11501106    }
    1151     else
    1152     if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb))
     1107    else if (iomGetRegImmData(pCpu, &pCpu->param2, pRegFrame, &uData2, &cb))
    11531108    {
    11541109        /* xchg [MMIO], reg. */
     
    11581113            /* Store result to MMIO. */
    11591114            rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &uData2, cb);
    1160 
    11611115            if (rc == VINF_SUCCESS)
    11621116            {
     
    11751129        AssertMsgFailed(("Disassember XCHG problem..\n"));
    11761130        rc = VERR_IOM_MMIO_HANDLER_DISASM_ERROR;
    1177         goto end;
    1178     }
    1179 
    1180 end:
    1181     STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstTest, a1);
     1131    }
    11821132    return rc;
    11831133}
    11841134
    1185 
    1186 #ifdef IN_RING0
    1187 
    1188 /**
    1189  * Read callback for disassembly function; supports reading bytes that cross a page boundary
    1190  *
    1191  * @returns VBox status code.
    1192  * @param   pSrc        GC source pointer
    1193  * @param   pDest       HC destination pointer
    1194  * @param   size        Number of bytes to read
    1195  * @param   pvUserdata  Callback specific user data (pCpu)
    1196  *
    1197  */
    1198 DECLCALLBACK(int) iomReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata)
    1199 {
    1200     DISCPUSTATE  *pCpu     = (DISCPUSTATE *)pvUserdata;
    1201     PVM           pVM      = (PVM)pCpu->apvUserData[0];
    1202 
    1203     int rc = PGMPhysReadGCPtr(pVM, pDest, pSrc, size);
    1204     AssertRC(rc);
    1205     return rc;
    1206 }
    1207 
    1208 inline bool iomDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    1209 {
    1210     return VBOX_SUCCESS(DISCoreOneEx(InstrGC, pCpu->mode, iomReadBytes, pVM, pCpu, pOpsize));
    1211 }
    1212 #else
    1213 inline bool iomDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    1214 {
    1215     return VBOX_SUCCESS(DISCoreOne(pCpu, InstrGC, pOpsize));
    1216 }
    1217 
    1218 #endif
    12191135
    12201136/**
     
    12251141 * @param   pVM         VM Handle.
    12261142 * @param   uErrorCode  CPU Error code.
    1227  * @param   pRegFrame   Trap register frame.
     1143 * @param   pCtxCore    Trap register frame.
    12281144 * @param   pvFault     The fault address (cr2).
    12291145 * @param   GCPhysFault The GC physical address corresponding to pvFault.
    12301146 * @param   pvUser      Pointer to the MMIO ring-3 range entry.
    12311147 */
    1232 IOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
     1148IOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
    12331149{
    12341150    STAM_PROFILE_START(&pVM->iom.s.StatGCMMIOHandler, a);
    1235     NOREF(pvUser); /** @todo implement pvUser usage! */
    12361151    Log3(("IOMMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%p eip=%RGv\n",
    1237           GCPhysFault, uErrorCode, pvFault, pRegFrame->eip));
    1238 
    1239     /*
    1240      * Find the corresponding MMIO range.
    1241      */
    1242     CTXALLSUFF(PIOMMMIORANGE) pRange = iomMMIOGetRange(&pVM->iom.s, GCPhysFault);
    1243     if (!pRange)
    1244     {
     1152          GCPhysFault, uErrorCode, pvFault, pCtxCore->eip));
     1153
     1154    PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser;
     1155    Assert(pRange);
     1156    Assert(pRange == iomMMIOGetRange(&pVM->iom.s, GCPhysFault));
     1157
    12451158#ifdef VBOX_WITH_STATISTICS
    1246         PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault);
    1247         if (pStats)
     1159    /*
     1160     * Locate the statistics, if > PAGE_SIZE we'll use the first byte for everything.
     1161     */
     1162    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault, pRange);
     1163    if (!pStats)
     1164    {
     1165# ifdef IN_RING3
     1166        return VERR_NO_MEMORY;
     1167# else
     1168        STAM_PROFILE_STOP(&pVM->iom.s.StatGCMMIOHandler, a);
     1169        STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures);
     1170        return uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
     1171# endif
     1172    }
     1173#endif
     1174
     1175#ifndef IN_RING3
     1176    /*
     1177     * Should we defer the request right away?
     1178     */
     1179    if (uErrorCode & X86_TRAP_PF_RW
     1180        ? !pRange->CTXALLSUFF(pfnWriteCallback) && !pRange->pfnWriteCallbackR3
     1181        : !pRange->CTXALLSUFF(pfnReadCallback)  && !pRange->pfnReadCallbackR3)
     1182    {
     1183# ifdef VBOX_WITH_STATISTICS
     1184        if (uErrorCode & X86_TRAP_PF_RW)
     1185            STAM_COUNTER_INC(&pStats->CTXALLMID(Write,ToR3));
     1186        else
     1187            STAM_COUNTER_INC(&pStats->CTXALLMID(Read,ToR3));
     1188# endif
     1189
     1190        STAM_PROFILE_STOP(&pVM->iom.s.StatGCMMIOHandler, a);
     1191        STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures);
     1192        return uErrorCode & X86_TRAP_PF_RW ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
     1193    }
     1194#endif /* !IN_RING3 */
     1195
     1196    /*
     1197     * Disassemble the instruction and interprete it.
     1198     */
     1199    DISCPUSTATE Cpu;
     1200    unsigned cbOp;
     1201    int rc = EMInterpretDisasOne(pVM, pCtxCore, &Cpu, &cbOp);
     1202    AssertRCReturn(rc, rc);
     1203    switch (Cpu.pCurInstr->opcode)
     1204    {
     1205        case OP_MOV:
     1206        case OP_MOVZX:
     1207        case OP_MOVSX:
    12481208        {
     1209            STAM_PROFILE_START(&pVM->iom.s.StatGCInstMov, b);
    12491210            if (uErrorCode & X86_TRAP_PF_RW)
    1250                 STAM_COUNTER_INC(&pStats->WriteGCToR3);
     1211                rc = iomInterpretMOVxXWrite(pVM, pCtxCore, &Cpu, pRange, GCPhysFault);
    12511212            else
    1252                 STAM_COUNTER_INC(&pStats->ReadGCToR3);
     1213                rc = iomInterpretMOVxXRead(pVM, pCtxCore, &Cpu, pRange, GCPhysFault);
     1214            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMov, b);
     1215            break;
    12531216        }
    1254 #endif
    1255         PIOMMMIORANGER3 pRangeR3 = iomMMIOGetRangeHC(&pVM->iom.s, GCPhysFault);
    1256         if (pRangeR3)
    1257         {
    1258             STAM_PROFILE_START(&pVM->iom.s.StatGCMMIOHandler, a);
    1259             STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures);
    1260             return (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
    1261         }
     1217
     1218
     1219#ifdef iom_MOVS_SUPPORT
     1220        case OP_MOVSB:
     1221        case OP_MOVSWD:
     1222            STAM_PROFILE_START(&pVM->iom.s.StatGCInstMovs, c);
     1223            rc = iomInterpretMOVS(pVM, uErrorCode, pCtxCore, GCPhysFault, &Cpu, pRange);
     1224            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMovs, c);
     1225            break;
     1226#endif
     1227
     1228        case OP_STOSB:
     1229        case OP_STOSWD:
     1230            Assert(uErrorCode & X86_TRAP_PF_RW);
     1231            STAM_PROFILE_START(&pVM->iom.s.StatGCInstStos, d);
     1232            rc = iomInterpretSTOS(pVM, pCtxCore, GCPhysFault, &Cpu, pRange);
     1233            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstStos, d);
     1234            break;
     1235
     1236        case OP_LODSB:
     1237        case OP_LODSWD:
     1238            Assert(!(uErrorCode & X86_TRAP_PF_RW));
     1239            STAM_PROFILE_START(&pVM->iom.s.StatGCInstLods, e);
     1240            rc = iomInterpretLODS(pVM, pCtxCore, GCPhysFault, &Cpu, pRange);
     1241            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstLods, e);
     1242            break;
     1243
     1244        case OP_CMP:
     1245            Assert(!(uErrorCode & X86_TRAP_PF_RW));
     1246            STAM_PROFILE_START(&pVM->iom.s.StatGCInstCmp, f);
     1247            rc = iomInterpretCMP(pVM, pCtxCore, GCPhysFault, &Cpu, pRange);
     1248            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstCmp, f);
     1249            break;
     1250
     1251        case OP_AND:
     1252            STAM_PROFILE_START(&pVM->iom.s.StatGCInstAnd, g);
     1253            rc = iomInterpretAND(pVM, pCtxCore, GCPhysFault, &Cpu, pRange);
     1254            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstAnd, g);
     1255            break;
     1256
     1257        case OP_TEST:
     1258            Assert(!(uErrorCode & X86_TRAP_PF_RW));
     1259            STAM_PROFILE_START(&pVM->iom.s.StatGCInstTest, h);
     1260            rc = iomInterpretTEST(pVM, pCtxCore, GCPhysFault, &Cpu, pRange);
     1261            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstTest, h);
     1262            break;
     1263
     1264        case OP_XCHG:
     1265            STAM_PROFILE_START(&pVM->iom.s.StatGCInstXchg, i);
     1266            rc = iomInterpretXCHG(pVM, pCtxCore, GCPhysFault, &Cpu, pRange);
     1267            STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstXchg, i);
     1268            break;
     1269
    12621270
    12631271        /*
    1264          * Now, why are we here...
     1272         * The instruction isn't supported. Hand it on to ring-3.
    12651273         */
    1266         AssertMsgFailed(("Internal error! GCPhysFault=%x\n", GCPhysFault));
    1267         return VERR_IOM_MMIO_HANDLER_BOGUS_CALL;
    1268     }
    1269 
    1270     /*
    1271      * Convert CS:EIP to linear address and initialize the disassembler.
    1272      */
    1273     DISCPUSTATE cpu;
    1274     cpu.mode = SELMIsSelector32Bit(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) ? CPUMODE_32BIT : CPUMODE_16BIT;
    1275 
    1276     RTGCPTR pvCode;
    1277     int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)(cpu.mode == CPUMODE_32BIT ? pRegFrame->eip : pRegFrame->eip & 0xffff), &pvCode);
    1278     if (VBOX_FAILURE(rc))
    1279     {
    1280         AssertMsgFailed(("Internal error! cs:eip=%04x:%08x rc=%Vrc\n", pRegFrame->cs, pRegFrame->eip, rc));
    1281         return VERR_IOM_MMIO_HANDLER_BOGUS_CALL;
    1282     }
    1283 
    1284     /*
    1285      * Disassemble the instruction and interprete it.
    1286      */
    1287     unsigned cbOp;
    1288     if (iomDisCoreOne(pVM, &cpu, (RTGCUINTPTR)pvCode, &cbOp))
    1289     {
    1290         switch (cpu.pCurInstr->opcode)
    1291         {
    1292             case OP_MOV:
    1293             case OP_MOVZX:
    1294             case OP_MOVSX:
    1295             {
    1296                 STAM_PROFILE_START(&pVM->iom.s.StatGCInstMov, b);
    1297                 if (uErrorCode & X86_TRAP_PF_RW)
    1298                     rc = iomInterpretMOVxXWrite(pVM, pRegFrame, &cpu, pRange, GCPhysFault);
    1299                 else
    1300                     rc = iomInterpretMOVxXRead(pVM, pRegFrame, &cpu, pRange, GCPhysFault);
    1301                 if (rc == VINF_SUCCESS)
    1302                     STAM_PROFILE_STOP(&pVM->iom.s.StatGCInstMov, b);
    1303                 break;
    1304             }
    1305 
    1306 
    1307 #ifdef iom_MOVS_SUPPORT
    1308             case OP_MOVSB:
    1309             case OP_MOVSWD:
    1310                 rc = iomInterpretMOVS(pVM, uErrorCode, pRegFrame, GCPhysFault, &cpu, pRange);
    1311                 break;
    1312 #endif
    1313 
    1314             case OP_STOSB:
    1315             case OP_STOSWD:
    1316                 Assert(uErrorCode & X86_TRAP_PF_RW);
    1317                 rc = iomInterpretSTOS(pVM, pRegFrame, GCPhysFault, &cpu, pRange);
    1318                 break;
    1319 
    1320             case OP_LODSB:
    1321             case OP_LODSWD:
    1322                 Assert(!(uErrorCode & X86_TRAP_PF_RW));
    1323                 rc = iomInterpretLODS(pVM, pRegFrame, GCPhysFault, &cpu, pRange);
    1324                 break;
    1325 
    1326 
    1327             case OP_CMP:
    1328                 Assert(!(uErrorCode & X86_TRAP_PF_RW));
    1329                 rc = iomInterpretCMP(pVM, pRegFrame, GCPhysFault, &cpu, pRange);
    1330                 break;
    1331 
    1332             case OP_AND:
    1333                 rc = iomInterpretAND(pVM, pRegFrame, GCPhysFault, &cpu, pRange);
    1334                 break;
    1335 
    1336             case OP_TEST:
    1337                 Assert(!(uErrorCode & X86_TRAP_PF_RW));
    1338                 rc = iomInterpretTEST(pVM, pRegFrame, GCPhysFault, &cpu, pRange);
    1339                 break;
    1340 
    1341             case OP_XCHG:
    1342                 rc = iomInterpretXCHG(pVM, pRegFrame, GCPhysFault, &cpu, pRange);
    1343                 break;
    1344 
    1345 
    1346             /*
    1347              * The instruction isn't supported. Hand it on to ring-3.
    1348              */
    1349             default:
    1350                 STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOther);
    1351                 rc = (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
    1352                 break;
    1353         }
    1354     }
     1274        default:
     1275            STAM_COUNTER_INC(&pVM->iom.s.StatGCInstOther);
     1276            rc = (uErrorCode & X86_TRAP_PF_RW) ? VINF_IOM_HC_MMIO_WRITE : VINF_IOM_HC_MMIO_READ;
     1277            break;
     1278    }
     1279
     1280    /*
     1281     * On success advance EIP.
     1282     */
     1283    if (rc == VINF_SUCCESS)
     1284        pCtxCore->eip += cbOp;
    13551285    else
    13561286    {
    1357         AssertMsgFailed(("Disassembler freaked out!\n"));
    1358         rc = VERR_IOM_MMIO_HANDLER_DISASM_ERROR;
    1359     }
    1360 
    1361     /*
    1362      * On success advance EIP.
    1363      */
    1364     if (rc == VINF_SUCCESS)
    1365         pRegFrame->eip += cbOp;
    1366     else
    1367     {
    13681287        STAM_COUNTER_INC(&pVM->iom.s.StatGCMMIOFailures);
    1369 #ifdef VBOX_WITH_STATISTICS
     1288#if defined(VBOX_WITH_STATISTICS) && !defined(IN_RING3)
    13701289        switch (rc)
    13711290        {
    13721291            case VINF_IOM_HC_MMIO_READ:
     1292            case VINF_IOM_HC_MMIO_READ_WRITE:
     1293                STAM_COUNTER_INC(&pStats->CTXALLMID(Read,ToR3));
     1294                break;
    13731295            case VINF_IOM_HC_MMIO_WRITE:
    1374             case VINF_IOM_HC_MMIO_READ_WRITE:
    1375             {
    1376                 PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhysFault);
    1377                 if (pStats)
    1378                 {
    1379                     if (uErrorCode & X86_TRAP_PF_RW)
    1380                         STAM_COUNTER_INC(&pStats->WriteGCToR3);
    1381                     else
    1382                         STAM_COUNTER_INC(&pStats->ReadGCToR3);
    1383                 }
    1384             }
    1385             break;
     1296                STAM_COUNTER_INC(&pStats->CTXALLMID(Write,ToR3));
     1297                break;
    13861298        }
    13871299#endif
    13881300    }
     1301
    13891302    STAM_PROFILE_STOP(&pVM->iom.s.StatGCMMIOHandler, a);
    13901303    return rc;
     
    14041317IOMDECL(int) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue)
    14051318{
    1406 /** @todo add return to ring-3 statistics when this function is used in GC! */
    1407 
    14081319    /*
    14091320     * Lookup the current context range node and statistics.
    14101321     */
    1411     CTXALLSUFF(PIOMMMIORANGE) pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
     1322    PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
     1323    AssertMsgReturn(pRange,
     1324                    ("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue),
     1325                    VERR_INTERNAL_ERROR);
    14121326#ifdef VBOX_WITH_STATISTICS
    1413     PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys);
    1414     if (!pStats && (!pRange || pRange->cb <= PAGE_SIZE))
     1327    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange);
     1328    if (!pStats)
    14151329# ifdef IN_RING3
    1416         pStats = iomR3MMIOStatsCreate(pVM, GCPhys, pRange ? pRange->pszDesc : NULL);
     1330        return VERR_NO_MEMORY;
    14171331# else
    14181332        return VINF_IOM_HC_MMIO_READ;
    14191333# endif
    14201334#endif /* VBOX_WITH_STATISTICS */
    1421 #ifdef IN_RING3
    1422     if (pRange)
    1423 #else /* !IN_RING3 */
    1424     if (pRange && pRange->pfnReadCallback)
    1425 #endif /* !IN_RING3 */
     1335    if (pRange->CTXALLSUFF(pfnReadCallback))
    14261336    {
    14271337        /*
     
    14321342            STAM_PROFILE_ADV_START(&pStats->CTXALLSUFF(ProfRead), a);
    14331343#endif
    1434         int rc = pRange->pfnReadCallback(pRange->pDevIns, pRange->pvUser, GCPhys, pu32Value, cbValue);
     1344        int rc = pRange->CTXALLSUFF(pfnReadCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, pu32Value, cbValue);
    14351345#ifdef VBOX_WITH_STATISTICS
    14361346        if (pStats)
     
    14691379        }
    14701380    }
    1471 
    14721381#ifndef IN_RING3
     1382    if (pRange->pfnReadCallbackR3)
     1383    {
     1384        STAM_COUNTER_INC(&pStats->CTXALLMID(Read,ToR3));
     1385        return VINF_IOM_HC_MMIO_READ;
     1386    }
     1387#endif
     1388
    14731389    /*
    14741390     * Lookup the ring-3 range.
    14751391     */
    1476     PIOMMMIORANGER3 pRangeR3 = iomMMIOGetRangeHC(&pVM->iom.s, GCPhys);
    1477     if (pRangeR3)
    1478     {
    1479         if (pRangeR3->pfnReadCallback)
    1480             return VINF_IOM_HC_MMIO_READ;
    1481 # ifdef VBOX_WITH_STATISTICS
    1482         if (pStats)
    1483             STAM_COUNTER_INC(&pStats->CTXALLSUFF(Read));
    1484 # endif
    1485         *pu32Value = 0;
    1486         Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
    1487         return VINF_SUCCESS;
    1488     }
    1489 #endif
    1490 
    1491     AssertMsgFailed(("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue));
    1492     return VERR_INTERNAL_ERROR;
     1392#ifdef VBOX_WITH_STATISTICS
     1393    if (pStats)
     1394        STAM_COUNTER_INC(&pStats->CTXALLSUFF(Read));
     1395#endif
     1396    *pu32Value = 0;
     1397    Log4(("IOMMMIORead: GCPhys=%RGp *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", GCPhys, *pu32Value, cbValue));
     1398    return VINF_SUCCESS;
    14931399}
    14941400
     
    15061412IOMDECL(int) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
    15071413{
    1508 /** @todo add return to ring-3 statistics when this function is used in GC! */
    15091414    /*
    15101415     * Lookup the current context range node.
    15111416     */
    1512     CTXALLSUFF(PIOMMMIORANGE) pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
     1417    PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
     1418    AssertMsgReturn(pRange,
     1419                    ("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue),
     1420                    VERR_INTERNAL_ERROR);
    15131421#ifdef VBOX_WITH_STATISTICS
    1514     PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys);
    1515     if (!pStats && (!pRange || pRange->cb <= PAGE_SIZE))
     1422    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange);
     1423    if (!pStats)
    15161424# ifdef IN_RING3
    1517         pStats = iomR3MMIOStatsCreate(pVM, GCPhys, pRange ? pRange->pszDesc : NULL);
     1425        return VERR_NO_MEMORY;
    15181426# else
    15191427        return VINF_IOM_HC_MMIO_WRITE;
     
    15221430
    15231431    /*
    1524      * Perform the write if we found a range.
    1525      */
    1526 #ifdef IN_RING3
    1527     if (pRange)
    1528 #else /* !IN_RING3 */
    1529     if (pRange && pRange->pfnWriteCallback)
    1530 #endif /* !IN_RING3 */
     1432     * Perform the write if there's a write handler. R0/GC may have
     1433     * to defer it to ring-3.
     1434     */
     1435    if (pRange->CTXALLSUFF(pfnWriteCallback))
    15311436    {
    15321437#ifdef VBOX_WITH_STATISTICS
     
    15341439            STAM_PROFILE_ADV_START(&pStats->CTXALLSUFF(ProfWrite), a);
    15351440#endif
    1536         int rc = pRange->pfnWriteCallback(pRange->pDevIns, pRange->pvUser, GCPhys, &u32Value, cbValue);
     1441        int rc = pRange->CTXALLSUFF(pfnWriteCallback)(pRange->CTXALLSUFF(pDevIns), pRange->CTXALLSUFF(pvUser), GCPhys, &u32Value, cbValue);
    15371442#ifdef VBOX_WITH_STATISTICS
    15381443        if (pStats)
     
    15441449        return rc;
    15451450    }
    1546 
    15471451#ifndef IN_RING3
    1548     /*
    1549      * Lookup the ring-3 range.
    1550      */
    1551     PIOMMMIORANGER3 pRangeR3 = iomMMIOGetRangeHC(&pVM->iom.s, GCPhys);
    1552     if (pRangeR3)
    1553     {
    1554         if (pRangeR3->pfnWriteCallback)
    1555             return VINF_IOM_HC_MMIO_WRITE;
    1556 # ifdef VBOX_WITH_STATISTICS
    1557         if (pStats)
    1558             STAM_COUNTER_INC(&pStats->CTXALLSUFF(Write));
    1559 # endif
    1560         Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, u32Value, cbValue));
    1561         return VINF_SUCCESS;
    1562     }
    1563 #endif
    1564 
    1565     AssertMsgFailed(("Handlers and page tables are out of sync or something! GCPhys=%VGp cbValue=%d\n", GCPhys, cbValue));
    1566     return VERR_INTERNAL_ERROR;
     1452    if (pRange->pfnWriteCallbackR3)
     1453    {
     1454        STAM_COUNTER_INC(&pStats->CTXALLMID(Write,ToR3));
     1455        return VINF_IOM_HC_MMIO_WRITE;
     1456    }
     1457#endif
     1458
     1459    /*
     1460     * No write handler, nothing to do.
     1461     */
     1462#ifdef VBOX_WITH_STATISTICS
     1463    if (pStats)
     1464        STAM_COUNTER_INC(&pStats->CTXALLSUFF(Write));
     1465#endif
     1466    Log4(("IOMMMIOWrite: GCPhys=%RGp u32=%08RX32 cb=%d rc=%Vrc\n", GCPhys, u32Value, cbValue, VINF_SUCCESS));
     1467    return VINF_SUCCESS;
    15671468}
    15681469
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r7731 r7751  
    122122
    123123    GEN_CHECK_SIZE(IOM);
    124 
    125     GEN_CHECK_SIZE(IOMMMIORANGER0);
    126     GEN_CHECK_OFF(IOMMMIORANGER0, GCPhys);
    127     GEN_CHECK_OFF(IOMMMIORANGER0, cb);
    128     GEN_CHECK_OFF(IOMMMIORANGER0, pvUser);
    129     GEN_CHECK_OFF(IOMMMIORANGER0, pDevIns);
    130     GEN_CHECK_OFF(IOMMMIORANGER0, pfnWriteCallback);
    131     GEN_CHECK_OFF(IOMMMIORANGER0, pszDesc);
    132 
    133     GEN_CHECK_SIZE(IOMMMIORANGEGC);
    134     GEN_CHECK_OFF(IOMMMIORANGEGC, GCPhys);
    135     GEN_CHECK_OFF(IOMMMIORANGEGC, cb);
    136     GEN_CHECK_OFF(IOMMMIORANGEGC, pvUser);
    137     GEN_CHECK_OFF(IOMMMIORANGEGC, pDevIns);
    138     GEN_CHECK_OFF(IOMMMIORANGEGC, pfnWriteCallback);
    139     GEN_CHECK_OFF(IOMMMIORANGEGC, pszDesc);
     124    GEN_CHECK_OFF(IOM, pMMIORangeLastR3);
     125    GEN_CHECK_OFF(IOM, pMMIOStatsLastR3);
     126    GEN_CHECK_OFF(IOM, pMMIORangeLastR0);
     127    GEN_CHECK_OFF(IOM, pMMIOStatsLastR0);
     128    GEN_CHECK_OFF(IOM, pMMIORangeLastGC);
     129    GEN_CHECK_OFF(IOM, pMMIOStatsLastGC);
     130    GEN_CHECK_OFF(IOM, pRangeLastReadR0);
     131    GEN_CHECK_OFF(IOM, pRangeLastReadGC);
     132
     133    GEN_CHECK_SIZE(IOMMMIORANGE);
     134    GEN_CHECK_OFF(IOMMMIORANGE, GCPhys);
     135    GEN_CHECK_OFF(IOMMMIORANGE, cb);
     136    GEN_CHECK_OFF(IOMMMIORANGE, pszDesc);
     137    GEN_CHECK_OFF(IOMMMIORANGE, pvUserR3);
     138    GEN_CHECK_OFF(IOMMMIORANGE, pDevInsR3);
     139    GEN_CHECK_OFF(IOMMMIORANGE, pfnWriteCallbackR3);
     140    GEN_CHECK_OFF(IOMMMIORANGE, pfnReadCallbackR3);
     141    GEN_CHECK_OFF(IOMMMIORANGE, pfnFillCallbackR3);
     142    GEN_CHECK_OFF(IOMMMIORANGE, pvUserR0);
     143    GEN_CHECK_OFF(IOMMMIORANGE, pDevInsR0);
     144    GEN_CHECK_OFF(IOMMMIORANGE, pfnWriteCallbackR0);
     145    GEN_CHECK_OFF(IOMMMIORANGE, pfnReadCallbackR0);
     146    GEN_CHECK_OFF(IOMMMIORANGE, pfnFillCallbackR0);
     147    GEN_CHECK_OFF(IOMMMIORANGE, pvUserGC);
     148    GEN_CHECK_OFF(IOMMMIORANGE, pDevInsGC);
     149    GEN_CHECK_OFF(IOMMMIORANGE, pfnWriteCallbackGC);
     150    GEN_CHECK_OFF(IOMMMIORANGE, pfnReadCallbackGC);
     151    GEN_CHECK_OFF(IOMMMIORANGE, pfnFillCallbackGC);
    140152
    141153    GEN_CHECK_SIZE(IOMMMIOSTATS);
     
    163175    GEN_CHECK_OFF(IOMTREES, IOPortTreeR0);
    164176    GEN_CHECK_OFF(IOMTREES, IOPortTreeGC);
    165     GEN_CHECK_OFF(IOMTREES, MMIOTreeR3);
    166     GEN_CHECK_OFF(IOMTREES, MMIOTreeR0);
    167     GEN_CHECK_OFF(IOMTREES, MMIOTreeGC);
     177    GEN_CHECK_OFF(IOMTREES, MMIOTree);
    168178    GEN_CHECK_OFF(IOMTREES, IOPortStatTree);
    169179    GEN_CHECK_OFF(IOMTREES, MMIOStatTree);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette