VirtualBox

Changeset 82311 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Dec 1, 2019 1:45:02 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
135135
Message:

IOM,PDMDevHlp: Kicked out the old I/O port code. bugref:9218

Location:
trunk/src/VBox/VMM
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r81383 r82311  
    142142
    143143    /*
    144      * Old code
    145      * Old code
    146      * Old code
    147      */
    148 
    149 #ifdef VBOX_WITH_STATISTICS
    150     /*
    151      * Get the statistics record.
    152      */
    153     PIOMIOPORTSTATS  pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead);
    154     if (!pStats || pStats->Core.Key != Port)
    155     {
    156         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);
    157         if (pStats)
    158             pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats;
    159     }
    160 #endif
    161 
    162     /*
    163      * Get handler for current context.
    164      */
    165     CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead);
    166     if (    !pRange
    167         ||   (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
    168     {
    169         pRange = iomIOPortGetRange(pVM, Port);
    170         if (pRange)
    171             pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange;
    172     }
    173     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
    174     if (pRange)
    175     {
    176         /*
    177          * Found a range, get the data in case we leave the IOM lock.
    178          */
    179         PFNIOMIOPORTIN  pfnInCallback = pRange->pfnInCallback;
    180 #ifndef IN_RING3
    181         if (pfnInCallback)
    182         { /* likely */ }
    183         else
    184         {
    185             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
    186             IOM_UNLOCK_SHARED(pVM);
    187             return VINF_IOM_R3_IOPORT_READ;
    188         }
    189 #endif
    190         void           *pvUser    = pRange->pvUser;
    191         PPDMDEVINS      pDevIns   = pRange->pDevIns;
    192         IOM_UNLOCK_SHARED(pVM);
    193 
    194         /*
    195          * Call the device.
    196          */
    197         VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);
    198         if (rcStrict == VINF_SUCCESS)
    199         { /* likely */ }
    200         else
    201         {
    202             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
    203             return rcStrict;
    204         }
    205 #ifdef VBOX_WITH_STATISTICS
    206         if (pStats)
    207         {
    208             STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    209             rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
    210             STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
    211         }
    212         else
    213 #endif
    214             rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
    215         PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
    216 
    217 #ifdef VBOX_WITH_STATISTICS
    218         if (rcStrict == VINF_SUCCESS && pStats)
    219             STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
    220 # ifndef IN_RING3
    221         else if (rcStrict == VINF_IOM_R3_IOPORT_READ && pStats)
    222             STAM_COUNTER_INC(&pStats->InRZToR3);
    223 # endif
    224 #endif
    225         if (rcStrict == VERR_IOM_IOPORT_UNUSED)
    226         {
    227             /* make return value */
    228             rcStrict = VINF_SUCCESS;
    229             switch (cbValue)
    230             {
    231                 case 1: *(uint8_t  *)pu32Value = 0xff; break;
    232                 case 2: *(uint16_t *)pu32Value = 0xffff; break;
    233                 case 4: *(uint32_t *)pu32Value = UINT32_C(0xffffffff); break;
    234                 default:
    235                     AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port));
    236                     return VERR_IOM_INVALID_IOPORT_SIZE;
    237             }
    238         }
    239         Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=%Rrc\n", Port, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));
    240         return rcStrict;
    241     }
    242 
    243 #ifndef IN_RING3
    244     /*
    245      * Handler in ring-3?
    246      */
    247     PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, Port);
    248     if (pRangeR3)
    249     {
    250 # ifdef VBOX_WITH_STATISTICS
    251         if (pStats)
    252             STAM_COUNTER_INC(&pStats->InRZToR3);
    253 # endif
    254         IOM_UNLOCK_SHARED(pVM);
    255         return VINF_IOM_R3_IOPORT_READ;
    256     }
    257 #endif
    258 
    259     /*
    260144     * Ok, no handler for this port.
    261145     */
    262 #ifdef VBOX_WITH_STATISTICS
    263     if (pStats)
    264         STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
    265 #endif
    266 
    267     /* make return value */
     146    IOM_UNLOCK_SHARED(pVM);
    268147    switch (cbValue)
    269148    {
     
    272151        case 4: *(uint32_t *)pu32Value = UINT32_C(0xffffffff); break;
    273152        default:
    274             AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port));
    275             IOM_UNLOCK_SHARED(pVM);
    276             return VERR_IOM_INVALID_IOPORT_SIZE;
     153            AssertMsgFailedReturn(("Invalid I/O port size %d. Port=%d\n", cbValue, Port), VERR_IOM_INVALID_IOPORT_SIZE);
    277154    }
    278155    Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", Port, *pu32Value, cbValue));
    279     IOM_UNLOCK_SHARED(pVM);
    280156    return VINF_SUCCESS;
    281157}
     
    421297
    422298    /*
    423      * Old code
    424      * Old code
    425      * Old code
    426      */
    427 
    428 #ifdef VBOX_WITH_STATISTICS
    429     /*
    430      * Get the statistics record.
    431      */
    432     PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead);
    433     if (!pStats || pStats->Core.Key != uPort)
    434     {
    435         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, uPort);
    436         if (pStats)
    437             pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats;
    438     }
    439 #endif
    440 
    441     /*
    442      * Get handler for current context.
    443      */
    444     CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead);
    445     if (    !pRange
    446         ||   (unsigned)uPort - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
    447     {
    448         pRange = iomIOPortGetRange(pVM, uPort);
    449         if (pRange)
    450             pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange;
    451     }
    452     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
    453     if (pRange)
    454     {
    455         /*
    456          * Found a range.
    457          */
    458         PFNIOMIOPORTINSTRING pfnInStrCallback = pRange->pfnInStrCallback;
    459         PFNIOMIOPORTIN       pfnInCallback    = pRange->pfnInCallback;
    460 #ifndef IN_RING3
    461         if (pfnInStrCallback || pfnInCallback)
    462         { /* likely */ }
    463         else
    464         {
    465             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
    466             IOM_UNLOCK_SHARED(pVM);
    467             return VINF_IOM_R3_IOPORT_READ;
    468         }
    469 #endif
    470         void           *pvUser    = pRange->pvUser;
    471         PPDMDEVINS      pDevIns   = pRange->pDevIns;
    472         IOM_UNLOCK_SHARED(pVM);
    473 
    474         /*
    475          * Call the device.
    476          */
    477         VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);
    478         if (rcStrict == VINF_SUCCESS)
    479         { /* likely */ }
    480         else
    481         {
    482             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
    483             return rcStrict;
    484         }
    485 
    486         /*
    487          * First using the string I/O callback.
    488          */
    489         if (pfnInStrCallback)
    490         {
    491 #ifdef VBOX_WITH_STATISTICS
    492             if (pStats)
    493             {
    494                 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    495                 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
    496                 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
    497             }
    498             else
    499 #endif
    500                 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
    501         }
    502 
    503         /*
    504          * Then doing the single I/O fallback.
    505          */
    506         if (   *pcTransfers > 0
    507             && rcStrict == VINF_SUCCESS)
    508         {
    509             pvDst = (uint8_t *)pvDst + (cRequestedTransfers - *pcTransfers) * cb;
    510             do
    511             {
    512                 uint32_t u32Value = 0;
    513 #ifdef VBOX_WITH_STATISTICS
    514                 if (pStats)
    515                 {
    516                     STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    517                     rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);
    518                     STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
    519                 }
    520                 else
    521 #endif
    522                     rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);
    523                 if (rcStrict == VERR_IOM_IOPORT_UNUSED)
    524                 {
    525                     u32Value = UINT32_MAX;
    526                     rcStrict = VINF_SUCCESS;
    527                 }
    528                 if (IOM_SUCCESS(rcStrict))
    529                 {
    530                     switch (cb)
    531                     {
    532                         case 4: *(uint32_t *)pvDst =           u32Value; pvDst = (uint8_t *)pvDst + 4; break;
    533                         case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break;
    534                         case 1: *(uint8_t  *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break;
    535                         default: AssertFailed();
    536                     }
    537                     *pcTransfers -= 1;
    538                 }
    539             } while (   *pcTransfers > 0
    540                      && rcStrict == VINF_SUCCESS);
    541         }
    542         PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
    543 
    544 #ifdef VBOX_WITH_STATISTICS
    545         if (rcStrict == VINF_SUCCESS && pStats)
    546             STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
    547 # ifndef IN_RING3
    548         else if (rcStrict == VINF_IOM_R3_IOPORT_READ && pStats)
    549             STAM_COUNTER_INC(&pStats->InRZToR3);
    550 # endif
    551 #endif
    552         Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",
    553               uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
    554         return rcStrict;
    555     }
    556 
    557 #ifndef IN_RING3
    558     /*
    559      * Handler in ring-3?
    560      */
    561     PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, uPort);
    562     if (pRangeR3)
    563     {
    564 # ifdef VBOX_WITH_STATISTICS
    565         if (pStats)
    566             STAM_COUNTER_INC(&pStats->InRZToR3);
    567 # endif
    568         IOM_UNLOCK_SHARED(pVM);
    569         return VINF_IOM_R3_IOPORT_READ;
    570     }
    571 #endif
    572 
    573     /*
    574299     * Ok, no handler for this port.
    575300     */
     301    IOM_UNLOCK_SHARED(pVM);
    576302    *pcTransfers = 0;
    577303    memset(pvDst, 0xff, cRequestedTransfers * cb);
    578 #ifdef VBOX_WITH_STATISTICS
    579     if (pStats)
    580         STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
    581 #endif
    582304    Log3(("IOMIOPortReadStr: uPort=%RTiop (unused) pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",
    583305          uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb));
    584     IOM_UNLOCK_SHARED(pVM);
    585306    return VINF_SUCCESS;
    586307}
     
    703424
    704425    /*
    705      * Old code
    706      * Old code
    707      * Old code
    708      */
    709 
    710 #ifdef VBOX_WITH_STATISTICS
    711     /*
    712      * Find the statistics record.
    713      */
    714     PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite);
    715     if (!pStats || pStats->Core.Key != Port)
    716     {
    717         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);
    718         if (pStats)
    719             pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;
    720     }
    721 #endif
    722 
    723     /*
    724      * Get handler for current context.
    725      */
    726     CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite);
    727     if (    !pRange
    728         ||   (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
    729     {
    730         pRange = iomIOPortGetRange(pVM, Port);
    731         if (pRange)
    732             pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;
    733     }
    734     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
    735     if (pRange)
    736     {
    737         /*
    738          * Found a range.
    739          */
    740         PFNIOMIOPORTOUT pfnOutCallback = pRange->pfnOutCallback;
    741 #ifndef IN_RING3
    742         if (pfnOutCallback)
    743         { /* likely */ }
    744         else
    745         {
    746             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
    747             IOM_UNLOCK_SHARED(pVM);
    748             return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);
    749         }
    750 #endif
    751         void           *pvUser    = pRange->pvUser;
    752         PPDMDEVINS      pDevIns   = pRange->pDevIns;
    753         IOM_UNLOCK_SHARED(pVM);
    754 
    755         /*
    756          * Call the device.
    757          */
    758         VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);
    759         if (rcStrict == VINF_SUCCESS)
    760         { /* likely */ }
    761         else
    762         {
    763             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
    764 #ifndef IN_RING3
    765             if (RT_LIKELY(rcStrict == VINF_IOM_R3_IOPORT_WRITE))
    766                 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);
    767 #endif
    768             return rcStrict;
    769         }
    770 #ifdef VBOX_WITH_STATISTICS
    771         if (pStats)
    772         {
    773             STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
    774             rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
    775             STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
    776         }
    777         else
    778 #endif
    779             rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
    780         PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
    781 
    782 #ifdef VBOX_WITH_STATISTICS
    783         if (rcStrict == VINF_SUCCESS && pStats)
    784             STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
    785 # ifndef IN_RING3
    786         else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE && pStats)
    787             STAM_COUNTER_INC(&pStats->OutRZToR3);
    788 # endif
    789 #endif
    790         Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d rc=%Rrc\n", Port, u32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));
    791 #ifndef IN_RING3
    792         if (rcStrict == VINF_IOM_R3_IOPORT_WRITE)
    793             return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);
    794 #endif
    795         return rcStrict;
    796     }
    797 
    798 #ifndef IN_RING3
    799     /*
    800      * Handler in ring-3?
    801      */
    802     PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, Port);
    803     if (pRangeR3)
    804     {
    805 # ifdef VBOX_WITH_STATISTICS
    806         if (pStats)
    807             STAM_COUNTER_INC(&pStats->OutRZToR3);
    808 # endif
    809         IOM_UNLOCK_SHARED(pVM);
    810         return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);
    811     }
    812 #endif
    813 
    814     /*
    815426     * Ok, no handler for that port.
    816427     */
    817 #ifdef VBOX_WITH_STATISTICS
    818     /* statistics. */
    819     if (pStats)
    820         STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
    821 #endif
     428    IOM_UNLOCK_SHARED(pVM);
    822429    Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d nop\n", Port, u32Value, cbValue));
    823     IOM_UNLOCK_SHARED(pVM);
    824430    return VINF_SUCCESS;
    825431}
     
    961567
    962568    /*
    963      * Old code.
    964      * Old code.
    965      * Old code.
    966      */
    967 
    968 #ifdef VBOX_WITH_STATISTICS
    969     /*
    970      * Get the statistics record.
    971      */
    972     PIOMIOPORTSTATS     pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite);
    973     if (!pStats || pStats->Core.Key != uPort)
    974     {
    975         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, uPort);
    976         if (pStats)
    977             pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;
    978     }
    979 #endif
    980 
    981     /*
    982      * Get handler for current context.
    983      */
    984     CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite);
    985     if (    !pRange
    986         ||   (unsigned)uPort - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
    987     {
    988         pRange = iomIOPortGetRange(pVM, uPort);
    989         if (pRange)
    990             pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;
    991     }
    992     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
    993     if (pRange)
    994     {
    995         /*
    996          * Found a range.
    997          */
    998         PFNIOMIOPORTOUTSTRING   pfnOutStrCallback = pRange->pfnOutStrCallback;
    999         PFNIOMIOPORTOUT         pfnOutCallback    = pRange->pfnOutCallback;
    1000 #ifndef IN_RING3
    1001         if (pfnOutStrCallback || pfnOutCallback)
    1002         { /* likely */ }
    1003         else
    1004         {
    1005             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
    1006             IOM_UNLOCK_SHARED(pVM);
    1007             return VINF_IOM_R3_IOPORT_WRITE;
    1008         }
    1009 #endif
    1010         void           *pvUser    = pRange->pvUser;
    1011         PPDMDEVINS      pDevIns   = pRange->pDevIns;
    1012         IOM_UNLOCK_SHARED(pVM);
    1013 
    1014         /*
    1015          * Call the device.
    1016          */
    1017         VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);
    1018         if (rcStrict == VINF_SUCCESS)
    1019         { /* likely */ }
    1020         else
    1021         {
    1022             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
    1023             return rcStrict;
    1024         }
    1025 
    1026         /*
    1027          * First using string I/O if possible.
    1028          */
    1029         if (pfnOutStrCallback)
    1030         {
    1031 #ifdef VBOX_WITH_STATISTICS
    1032             if (pStats)
    1033             {
    1034                 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
    1035                 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
    1036                 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
    1037             }
    1038             else
    1039 #endif
    1040                 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
    1041         }
    1042 
    1043         /*
    1044          * Then doing the single I/O fallback.
    1045          */
    1046         if (   *pcTransfers > 0
    1047             && rcStrict == VINF_SUCCESS)
    1048         {
    1049             pvSrc = (uint8_t *)pvSrc + (cRequestedTransfers - *pcTransfers) * cb;
    1050             do
    1051             {
    1052                 uint32_t u32Value;
    1053                 switch (cb)
    1054                 {
    1055                     case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break;
    1056                     case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break;
    1057                     case 1: u32Value = *(uint8_t  *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 1; break;
    1058                     default: AssertFailed(); u32Value = UINT32_MAX;
    1059                 }
    1060 #ifdef VBOX_WITH_STATISTICS
    1061                 if (pStats)
    1062                 {
    1063                     STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
    1064                     rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);
    1065                     STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
    1066                 }
    1067                 else
    1068 #endif
    1069                     rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);
    1070                 if (IOM_SUCCESS(rcStrict))
    1071                     *pcTransfers -= 1;
    1072             } while (   *pcTransfers > 0
    1073                      && rcStrict == VINF_SUCCESS);
    1074         }
    1075 
    1076         PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
    1077 
    1078 #ifdef VBOX_WITH_STATISTICS
    1079         if (rcStrict == VINF_SUCCESS && pStats)
    1080             STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
    1081 # ifndef IN_RING3
    1082         else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE && pStats)
    1083             STAM_COUNTER_INC(&pStats->OutRZToR3);
    1084 # endif
    1085 #endif
    1086         Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n",
    1087               uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
    1088         return rcStrict;
    1089     }
    1090 
    1091 #ifndef IN_RING3
    1092     /*
    1093      * Handler in ring-3?
    1094      */
    1095     PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, uPort);
    1096     if (pRangeR3)
    1097     {
    1098 # ifdef VBOX_WITH_STATISTICS
    1099         if (pStats)
    1100             STAM_COUNTER_INC(&pStats->OutRZToR3);
    1101 # endif
    1102         IOM_UNLOCK_SHARED(pVM);
    1103         return VINF_IOM_R3_IOPORT_WRITE;
    1104     }
    1105 #endif
    1106 
    1107     /*
    1108569     * Ok, no handler for this port.
    1109570     */
     571    IOM_UNLOCK_SHARED(pVM);
    1110572    *pcTransfers = 0;
    1111 #ifdef VBOX_WITH_STATISTICS
    1112     if (pStats)
    1113         STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
    1114 #endif
    1115573    Log3(("IOMIOPortWriteStr: uPort=%RTiop (unused) pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",
    1116574          uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb));
    1117     IOM_UNLOCK_SHARED(pVM);
    1118575    return VINF_SUCCESS;
    1119576}
  • trunk/src/VBox/VMM/VMMR3/IOM.cpp

    r81983 r82311  
    134134*********************************************************************************************************************************/
    135135static void iomR3FlushCache(PVM pVM);
    136 #if 0
    137 static DECLCALLBACK(int) iomR3RelocateIOPortCallback(PAVLROIOPORTNODECORE pNode, void *pvUser);
    138 static DECLCALLBACK(int) iomR3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser);
    139 #endif
    140 static FNIOMIOPORTIN        iomR3IOPortDummyIn;
    141 static FNIOMIOPORTOUT       iomR3IOPortDummyOut;
    142 static FNIOMIOPORTINSTRING  iomR3IOPortDummyInStr;
    143 static FNIOMIOPORTOUTSTRING iomR3IOPortDummyOutStr;
    144136
    145137#ifdef VBOX_WITH_STATISTICS
     
    302294    {
    303295        PVMCPU pVCpu = pVM->apCpusR3[idCpu];
    304         pVCpu->iom.s.pRangeLastReadR0  = NIL_RTR0PTR;
    305         pVCpu->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR;
    306         pVCpu->iom.s.pStatsLastReadR0  = NIL_RTR0PTR;
    307         pVCpu->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR;
    308296        pVCpu->iom.s.pMMIORangeLastR0  = NIL_RTR0PTR;
    309297        pVCpu->iom.s.pMMIOStatsLastR0  = NIL_RTR0PTR;
    310298
    311         pVCpu->iom.s.pRangeLastReadR3  = NULL;
    312         pVCpu->iom.s.pRangeLastWriteR3 = NULL;
    313         pVCpu->iom.s.pStatsLastReadR3  = NULL;
    314         pVCpu->iom.s.pStatsLastWriteR3 = NULL;
    315299        pVCpu->iom.s.pMMIORangeLastR3  = NULL;
    316300        pVCpu->iom.s.pMMIOStatsLastR3  = NULL;
     
    344328VMMR3_INT_DECL(void) IOMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
    345329{
    346 #if 0
    347     LogFlow(("IOMR3Relocate: offDelta=%d\n", offDelta));
    348 
    349     /*
    350      * Apply relocations to the GC callbacks.
    351      */
    352     pVM->iom.s.pTreesRC = MMHyperR3ToRC(pVM, pVM->iom.s.pTreesR3);
    353     RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeRC, true, iomR3RelocateIOPortCallback, &offDelta);
    354     RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesR3->MMIOTree,     true, iomR3RelocateMMIOCallback,   &offDelta);
    355 
    356     /*
    357      * Reset the raw-mode cache (don't bother relocating it).
    358      */
    359     VMCPUID idCpu = pVM->cCpus;
    360     while (idCpu-- > 0)
    361     {
    362         PVMCPU pVCpu = pVM->apCpusR3[idCpu];
    363         pVCpu->iom.s.pRangeLastReadRC  = NIL_RTRCPTR;
    364         pVCpu->iom.s.pRangeLastWriteRC = NIL_RTRCPTR;
    365         pVCpu->iom.s.pStatsLastReadRC  = NIL_RTRCPTR;
    366         pVCpu->iom.s.pStatsLastWriteRC = NIL_RTRCPTR;
    367         pVCpu->iom.s.pMMIORangeLastRC  = NIL_RTRCPTR;
    368         pVCpu->iom.s.pMMIOStatsLastRC  = NIL_RTRCPTR;
    369     }
    370 #else
    371330    RT_NOREF(pVM, offDelta);
    372 #endif
    373 }
    374 
    375 #if 0
    376 
    377 /**
    378  * Callback function for relocating a I/O port range.
    379  *
    380  * @returns 0 (continue enum)
    381  * @param   pNode       Pointer to a IOMIOPORTRANGERC node.
    382  * @param   pvUser      Pointer to the offDelta. This is a pointer to the delta since we're
    383  *                      not certain the delta will fit in a void pointer for all possible configs.
    384  */
    385 static DECLCALLBACK(int) iomR3RelocateIOPortCallback(PAVLROIOPORTNODECORE pNode, void *pvUser)
    386 {
    387     PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)pNode;
    388     RTGCINTPTR      offDelta = *(PRTGCINTPTR)pvUser;
    389 
    390     Assert(pRange->pDevIns);
    391     pRange->pDevIns                 += offDelta;
    392     if (pRange->pfnOutCallback)
    393         pRange->pfnOutCallback      += offDelta;
    394     if (pRange->pfnInCallback)
    395         pRange->pfnInCallback       += offDelta;
    396     if (pRange->pfnOutStrCallback)
    397         pRange->pfnOutStrCallback   += offDelta;
    398     if (pRange->pfnInStrCallback)
    399         pRange->pfnInStrCallback    += offDelta;
    400     if (pRange->pvUser > _64K)
    401         pRange->pvUser              += offDelta;
    402     return 0;
    403 }
    404 
    405 
    406 /**
    407  * Callback function for relocating a MMIO range.
    408  *
    409  * @returns 0 (continue enum)
    410  * @param   pNode       Pointer to a IOMMMIORANGE node.
    411  * @param   pvUser      Pointer to the offDelta. This is a pointer to the delta since we're
    412  *                      not certain the delta will fit in a void pointer for all possible configs.
    413  */
    414 static DECLCALLBACK(int) iomR3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser)
    415 {
    416     PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode;
    417     RTGCINTPTR    offDelta = *(PRTGCINTPTR)pvUser;
    418 
    419     if (pRange->pDevInsRC)
    420         pRange->pDevInsRC           += offDelta;
    421     if (pRange->pfnWriteCallbackRC)
    422         pRange->pfnWriteCallbackRC  += offDelta;
    423     if (pRange->pfnReadCallbackRC)
    424         pRange->pfnReadCallbackRC   += offDelta;
    425     if (pRange->pfnFillCallbackRC)
    426         pRange->pfnFillCallbackRC   += offDelta;
    427     if (pRange->pvUserRC > _64K)
    428         pRange->pvUserRC            += offDelta;
    429 
    430     return 0;
    431 }
    432 
    433 #endif
     331}
    434332
    435333/**
     
    454352
    455353#ifdef VBOX_WITH_STATISTICS
    456 
    457 /**
    458  * Create the statistics node for an I/O port.
    459  *
    460  * @returns Pointer to new stats node.
    461  *
    462  * @param   pVM         The cross context VM structure.
    463  * @param   Port        Port.
    464  * @param   pszDesc     Description.
    465  */
    466 static PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc)
    467 {
    468     IOM_LOCK_EXCL(pVM);
    469 
    470     /* check if it already exists. */
    471     PIOMIOPORTSTATS pPort = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.pTreesR3->IOPortStatTree, Port);
    472     if (pPort)
    473     {
    474         IOM_UNLOCK_EXCL(pVM);
    475         return pPort;
    476     }
    477 
    478     /* allocate stats node. */
    479     int rc = MMHyperAlloc(pVM, sizeof(*pPort), 0, MM_TAG_IOM_STATS, (void **)&pPort);
    480     AssertRC(rc);
    481     if (RT_SUCCESS(rc))
    482     {
    483         /* insert into the tree. */
    484         pPort->Core.Key = Port;
    485         if (RTAvloIOPortInsert(&pVM->iom.s.pTreesR3->IOPortStatTree, &pPort->Core))
    486         {
    487             IOM_UNLOCK_EXCL(pVM);
    488 
    489             /* put a name on common ports. */
    490             if (!pszDesc)
    491                 pszDesc = iomR3IOPortGetStandardName(Port);
    492 
    493             /* register the statistics counters. */
    494             rc = STAMR3RegisterF(pVM, &pPort->InR3,     STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc,    "/IOM/Ports/%04x-In-R3", Port); AssertRC(rc);
    495             rc = STAMR3RegisterF(pVM, &pPort->OutR3,    STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc,    "/IOM/Ports/%04x-Out-R3", Port); AssertRC(rc);
    496             rc = STAMR3RegisterF(pVM, &pPort->InRZ,     STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc,    "/IOM/Ports/%04x-In-RZ", Port); AssertRC(rc);
    497             rc = STAMR3RegisterF(pVM, &pPort->OutRZ,    STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc,    "/IOM/Ports/%04x-Out-RZ", Port); AssertRC(rc);
    498             rc = STAMR3RegisterF(pVM, &pPort->InRZToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc,    "/IOM/Ports/%04x-In-RZtoR3", Port); AssertRC(rc);
    499             rc = STAMR3RegisterF(pVM, &pPort->OutRZToR3,STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc,    "/IOM/Ports/%04x-Out-RZtoR3", Port); AssertRC(rc);
    500 
    501             /* Profiling */
    502             rc = STAMR3RegisterF(pVM, &pPort->ProfInR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-In-R3/Prof", Port); AssertRC(rc);
    503             rc = STAMR3RegisterF(pVM, &pPort->ProfOutR3,STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-Out-R3/Prof", Port); AssertRC(rc);
    504             rc = STAMR3RegisterF(pVM, &pPort->ProfInRZ, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-In-RZ/Prof", Port); AssertRC(rc);
    505             rc = STAMR3RegisterF(pVM, &pPort->ProfOutRZ,STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-Out-RZ/Prof", Port); AssertRC(rc);
    506 
    507             return pPort;
    508         }
    509 
    510         AssertMsgFailed(("what! Port=%d\n", Port));
    511         MMHyperFree(pVM, pPort);
    512     }
    513     IOM_UNLOCK_EXCL(pVM);
    514     return NULL;
    515 }
    516 
    517354
    518355/**
     
    566403
    567404#endif /* VBOX_WITH_STATISTICS */
    568 
    569 /**
    570  * Registers a I/O port ring-3 handler.
    571  *
    572  * This API is called by PDM on behalf of a device. Devices must first register
    573  * ring-3 ranges before any GC and R0 ranges can be registered using IOMR3IOPortRegisterRC()
    574  * and IOMR3IOPortRegisterR0().
    575  *
    576  *
    577  * @returns VBox status code.
    578  *
    579  * @param   pVM                 The cross context VM structure.
    580  * @param   pDevIns             PDM device instance owning the port range.
    581  * @param   PortStart           First port number in the range.
    582  * @param   cPorts              Number of ports to register.
    583  * @param   pvUser              User argument for the callbacks.
    584  * @param   pfnOutCallback      Pointer to function which is gonna handle OUT operations in R3.
    585  * @param   pfnInCallback       Pointer to function which is gonna handle IN operations in R3.
    586  * @param   pfnOutStrCallback   Pointer to function which is gonna handle string OUT operations in R3.
    587  * @param   pfnInStrCallback    Pointer to function which is gonna handle string IN operations in R3.
    588  * @param   pszDesc             Pointer to description string. This must not be freed.
    589  */
    590 VMMR3_INT_DECL(int) IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTHCPTR pvUser,
    591                                           R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
    592                                           R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, const char *pszDesc)
    593 {
    594     LogFlow(("IOMR3IOPortRegisterR3: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RHv pfnOutCallback=%#x pfnInCallback=%#x pfnOutStrCallback=%#x pfnInStrCallback=%#x pszDesc=%s\n",
    595              pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));
    596 
    597     /*
    598      * Validate input.
    599      */
    600     if (    (RTUINT)PortStart + cPorts <= (RTUINT)PortStart
    601         ||  (RTUINT)PortStart + cPorts > 0x10000)
    602     {
    603         AssertMsgFailed(("Invalid port range %#x-%#x (inclusive)! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));
    604         return VERR_IOM_INVALID_IOPORT_RANGE;
    605     }
    606     if (!pfnOutCallback && !pfnInCallback)
    607     {
    608         AssertMsgFailed(("no handlers specfied for %#x-%#x (inclusive)! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));
    609         return VERR_INVALID_PARAMETER;
    610     }
    611     if (!pfnOutCallback)
    612         pfnOutCallback = iomR3IOPortDummyOut;
    613     if (!pfnInCallback)
    614         pfnInCallback = iomR3IOPortDummyIn;
    615     if (!pfnOutStrCallback)
    616         pfnOutStrCallback = iomR3IOPortDummyOutStr;
    617     if (!pfnInStrCallback)
    618         pfnInStrCallback = iomR3IOPortDummyInStr;
    619 
    620     /* Flush the IO port lookup cache */
    621     iomR3FlushCache(pVM);
    622 
    623     /*
    624      * Allocate new range record and initialize it.
    625      */
    626     PIOMIOPORTRANGER3 pRange;
    627     int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);
    628     if (RT_SUCCESS(rc))
    629     {
    630         pRange->Core.Key        = PortStart;
    631         pRange->Core.KeyLast    = PortStart + (cPorts - 1);
    632         pRange->Port            = PortStart;
    633         pRange->cPorts          = cPorts;
    634         pRange->pvUser          = pvUser;
    635         pRange->pDevIns         = pDevIns;
    636         pRange->pfnOutCallback  = pfnOutCallback;
    637         pRange->pfnInCallback   = pfnInCallback;
    638         pRange->pfnOutStrCallback = pfnOutStrCallback;
    639         pRange->pfnInStrCallback = pfnInStrCallback;
    640         pRange->pszDesc         = pszDesc;
    641 
    642         /*
    643          * Try Insert it.
    644          */
    645         IOM_LOCK_EXCL(pVM);
    646         if (RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR3, &pRange->Core))
    647         {
    648 #ifdef VBOX_WITH_STATISTICS
    649             for (unsigned iPort = 0; iPort < cPorts; iPort++)
    650                 iomR3IOPortStatsCreate(pVM, PortStart + iPort, pszDesc);
    651 #endif
    652             IOM_UNLOCK_EXCL(pVM);
    653             return VINF_SUCCESS;
    654         }
    655         IOM_UNLOCK_EXCL(pVM);
    656 
    657         /* conflict. */
    658         DBGFR3Info(pVM->pUVM, "ioport", NULL, NULL);
    659         AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    660         MMHyperFree(pVM, pRange);
    661         rc = VERR_IOM_IOPORT_RANGE_CONFLICT;
    662     }
    663 
    664     return rc;
    665 }
    666 
    667 
    668 #if 0
    669 /**
    670  * Registers a I/O port RC handler.
    671  *
    672  * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges
    673  * using IOMIOPortRegisterR3() before calling this function.
    674  *
    675  *
    676  * @returns VBox status code.
    677  *
    678  * @param   pVM                 The cross context VM structure.
    679  * @param   pDevIns             PDM device instance owning the port range.
    680  * @param   PortStart           First port number in the range.
    681  * @param   cPorts              Number of ports to register.
    682  * @param   pvUser              User argument for the callbacks.
    683  * @param   pfnOutCallback      Pointer to function which is gonna handle OUT operations in GC.
    684  * @param   pfnInCallback       Pointer to function which is gonna handle IN operations in GC.
    685  * @param   pfnOutStrCallback   Pointer to function which is gonna handle string OUT operations in GC.
    686  * @param   pfnInStrCallback    Pointer to function which is gonna handle string IN operations in GC.
    687  * @param   pszDesc             Pointer to description string. This must not be freed.
    688  */
    689 VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTRCPTR pvUser,
    690                                           RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
    691                                           RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, const char *pszDesc)
    692 {
    693     LogFlow(("IOMR3IOPortRegisterRC: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RRv pfnOutCallback=%RRv pfnInCallback=%RRv pfnOutStrCallback=%RRv pfnInStrCallback=%RRv pszDesc=%s\n",
    694              pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));
    695     AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_IOM_HM_IPE);
    696 
    697     /*
    698      * Validate input.
    699      */
    700     if (    (RTUINT)PortStart + cPorts <= (RTUINT)PortStart
    701         ||  (RTUINT)PortStart + cPorts > 0x10000)
    702     {
    703         AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));
    704         return VERR_IOM_INVALID_IOPORT_RANGE;
    705     }
    706     RTIOPORT PortLast = PortStart + (cPorts - 1);
    707     if (!pfnOutCallback && !pfnInCallback)
    708     {
    709         AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc));
    710         return VERR_INVALID_PARAMETER;
    711     }
    712 
    713     IOM_LOCK_EXCL(pVM);
    714 
    715     /*
    716      * Validate that there are ring-3 ranges for the ports.
    717      */
    718     RTIOPORT Port = PortStart;
    719     while (Port <= PortLast && Port >= PortStart)
    720     {
    721         PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);
    722         if (!pRange)
    723         {
    724             AssertMsgFailed(("No R3! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    725             IOM_UNLOCK_EXCL(pVM);
    726             return VERR_IOM_NO_R3_IOPORT_RANGE;
    727         }
    728 #ifndef IOM_NO_PDMINS_CHECKS
    729         if (pRange->pDevIns != pDevIns)
    730         {
    731             AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    732             IOM_UNLOCK_EXCL(pVM);
    733             return VERR_IOM_NOT_IOPORT_RANGE_OWNER;
    734         }
    735 #endif
    736         Port = pRange->Core.KeyLast + 1;
    737     }
    738 
    739     /* Flush the IO port lookup cache */
    740     iomR3FlushCache(pVM);
    741 
    742     /*
    743      * Allocate new range record and initialize it.
    744      */
    745     PIOMIOPORTRANGERC pRange;
    746     int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);
    747     if (RT_SUCCESS(rc))
    748     {
    749         pRange->Core.Key        = PortStart;
    750         pRange->Core.KeyLast    = PortLast;
    751         pRange->Port            = PortStart;
    752         pRange->cPorts          = cPorts;
    753         pRange->pvUser          = pvUser;
    754         pRange->pfnOutCallback  = pfnOutCallback;
    755         pRange->pfnInCallback   = pfnInCallback;
    756         pRange->pfnOutStrCallback = pfnOutStrCallback;
    757         pRange->pfnInStrCallback = pfnInStrCallback;
    758         pRange->pDevIns         = pDevIns->pDevInsForRC;
    759         pRange->pszDesc         = pszDesc;
    760 
    761         /*
    762          * Insert it.
    763          */
    764         if (RTAvlroIOPortInsert(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeRC, &pRange->Core))
    765         {
    766             IOM_UNLOCK_EXCL(pVM);
    767             return VINF_SUCCESS;
    768         }
    769 
    770         /* conflict. */
    771         AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    772         MMHyperFree(pVM, pRange);
    773         rc = VERR_IOM_IOPORT_RANGE_CONFLICT;
    774     }
    775     IOM_UNLOCK_EXCL(pVM);
    776     return rc;
    777 }
    778 #endif
    779 
    780 
    781 /**
    782  * Registers a Port IO R0 handler.
    783  *
    784  * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges
    785  * using IOMR3IOPortRegisterR3() before calling this function.
    786  *
    787  *
    788  * @returns VBox status code.
    789  *
    790  * @param   pVM                 The cross context VM structure.
    791  * @param   pDevIns             PDM device instance owning the port range.
    792  * @param   PortStart           First port number in the range.
    793  * @param   cPorts              Number of ports to register.
    794  * @param   pvUser              User argument for the callbacks.
    795  * @param   pfnOutCallback      Pointer to function which is gonna handle OUT operations in GC.
    796  * @param   pfnInCallback       Pointer to function which is gonna handle IN operations in GC.
    797  * @param   pfnOutStrCallback   Pointer to function which is gonna handle OUT operations in GC.
    798  * @param   pfnInStrCallback    Pointer to function which is gonna handle IN operations in GC.
    799  * @param   pszDesc             Pointer to description string. This must not be freed.
    800  */
    801 VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser,
    802                                           R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
    803                                           R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,
    804                                           const char *pszDesc)
    805 {
    806     LogFlow(("IOMR3IOPortRegisterR0: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RHv pfnOutCallback=%RHv pfnInCallback=%RHv pfnOutStrCallback=%RHv  pfnInStrCallback=%RHv pszDesc=%s\n",
    807              pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));
    808 
    809     /*
    810      * Validate input.
    811      */
    812     if (    (RTUINT)PortStart + cPorts <= (RTUINT)PortStart
    813         ||  (RTUINT)PortStart + cPorts > 0x10000)
    814     {
    815         AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));
    816         return VERR_IOM_INVALID_IOPORT_RANGE;
    817     }
    818     RTIOPORT PortLast = PortStart + (cPorts - 1);
    819     if (!pfnOutCallback && !pfnInCallback)
    820     {
    821         AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc));
    822         return VERR_INVALID_PARAMETER;
    823     }
    824 
    825     IOM_LOCK_EXCL(pVM);
    826 
    827     /*
    828      * Validate that there are ring-3 ranges for the ports.
    829      */
    830     RTIOPORT Port = PortStart;
    831     while (Port <= PortLast && Port >= PortStart)
    832     {
    833         PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);
    834         if (!pRange)
    835         {
    836             AssertMsgFailed(("No R3! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    837             IOM_UNLOCK_EXCL(pVM);
    838             return VERR_IOM_NO_R3_IOPORT_RANGE;
    839         }
    840 #ifndef IOM_NO_PDMINS_CHECKS
    841         if (pRange->pDevIns != pDevIns)
    842         {
    843             AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    844             IOM_UNLOCK_EXCL(pVM);
    845             return VERR_IOM_NOT_IOPORT_RANGE_OWNER;
    846         }
    847 #endif
    848         Port = pRange->Core.KeyLast + 1;
    849     }
    850 
    851     /* Flush the IO port lookup cache */
    852     iomR3FlushCache(pVM);
    853 
    854     /*
    855      * Allocate new range record and initialize it.
    856      */
    857     PIOMIOPORTRANGER0 pRange;
    858     int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);
    859     if (RT_SUCCESS(rc))
    860     {
    861         pRange->Core.Key        = PortStart;
    862         pRange->Core.KeyLast    = PortLast;
    863         pRange->Port            = PortStart;
    864         pRange->cPorts          = cPorts;
    865         pRange->pvUser          = pvUser;
    866         pRange->pfnOutCallback  = pfnOutCallback;
    867         pRange->pfnInCallback   = pfnInCallback;
    868         pRange->pfnOutStrCallback = pfnOutStrCallback;
    869         pRange->pfnInStrCallback = pfnInStrCallback;
    870         pRange->pDevIns         = PDMDEVINS_2_R0PTR(pDevIns);
    871         pRange->pszDesc         = pszDesc;
    872 
    873         /*
    874          * Insert it.
    875          */
    876         if (RTAvlroIOPortInsert(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR0, &pRange->Core))
    877         {
    878             IOM_UNLOCK_EXCL(pVM);
    879             return VINF_SUCCESS;
    880         }
    881 
    882         /* conflict. */
    883         AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));
    884         MMHyperFree(pVM, pRange);
    885         rc = VERR_IOM_IOPORT_RANGE_CONFLICT;
    886     }
    887     IOM_UNLOCK_EXCL(pVM);
    888     return rc;
    889 }
    890 
    891 
    892 /**
    893  * Deregisters a I/O Port range.
    894  *
    895  * The specified range must be registered using IOMR3IOPortRegister previous to
    896  * this call. The range does can be a smaller part of the range specified to
    897  * IOMR3IOPortRegister, but it can never be larger.
    898  *
    899  * This function will remove GC, R0 and R3 context port handlers for this range.
    900  *
    901  * @returns VBox status code.
    902  *
    903  * @param   pVM                 The cross context VM structure.
    904  * @param   pDevIns             The device instance associated with the range.
    905  * @param   PortStart           First port number in the range.
    906  * @param   cPorts              Number of ports to remove starting at PortStart.
    907  *
    908  * @remark  This function mainly for PCI PnP Config and will not do
    909  *          all the checks you might expect it to do.
    910  */
    911 VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts)
    912 {
    913     LogFlow(("IOMR3IOPortDeregister: pDevIns=%p PortStart=%#x cPorts=%#x\n", pDevIns, PortStart, cPorts));
    914 
    915     /*
    916      * Validate input.
    917      */
    918     if (    (RTUINT)PortStart + cPorts < (RTUINT)PortStart
    919         ||  (RTUINT)PortStart + cPorts > 0x10000)
    920     {
    921         AssertMsgFailed(("Invalid port range %#x-%#x!\n", PortStart, (unsigned)PortStart + cPorts - 1));
    922         return VERR_IOM_INVALID_IOPORT_RANGE;
    923     }
    924 
    925     IOM_LOCK_EXCL(pVM);
    926 
    927     /* Flush the IO port lookup cache */
    928     iomR3FlushCache(pVM);
    929 
    930     /*
    931      * Check ownership.
    932      */
    933     RTIOPORT PortLast = PortStart + (cPorts - 1);
    934     RTIOPORT Port = PortStart;
    935     while (Port <= PortLast && Port >= PortStart)
    936     {
    937         PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeR3, Port);
    938         if (pRange)
    939         {
    940             Assert(Port <= pRange->Core.KeyLast);
    941 #ifndef IOM_NO_PDMINS_CHECKS
    942             if (pRange->pDevIns != pDevIns)
    943             {
    944                 AssertMsgFailed(("Removal of ports in range %#x-%#x rejected because not owner of %#x-%#x (%s)\n",
    945                                  PortStart, PortLast, pRange->Core.Key, pRange->Core.KeyLast, pRange->pszDesc));
    946                 IOM_UNLOCK_EXCL(pVM);
    947                 return VERR_IOM_NOT_IOPORT_RANGE_OWNER;
    948             }
    949 #else  /* IOM_NO_PDMINS_CHECKS */
    950             RT_NOREF_PV(pDevIns);
    951 #endif /* IOM_NO_PDMINS_CHECKS */
    952             Port = pRange->Core.KeyLast;
    953         }
    954         Port++;
    955     }
    956 
    957 #if 0
    958     /*
    959      * Remove any RC ranges first.
    960      */
    961     int     rc = VINF_SUCCESS;
    962     Port = PortStart;
    963     while (Port <= PortLast && Port >= PortStart)
    964     {
    965         /*
    966          * Try find range.
    967          */
    968         PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeRC, Port);
    969         if (pRange)
    970         {
    971             if (   pRange->Core.Key     == Port
    972                 && pRange->Core.KeyLast <= PortLast)
    973             {
    974                 /*
    975                  * Kick out the entire range.
    976                  */
    977                 void *pv = RTAvlroIOPortRemove(&pVM->iom.s.pTreesR3->IOPortTreeRC, Port);
    978                 Assert(pv == (void *)pRange); NOREF(pv);
    979                 Port += pRange->cPorts;
    980                 MMHyperFree(pVM, pRange);
    981             }
    982             else if (pRange->Core.Key == Port)
    983             {
    984                 /*
    985                  * Cut of the head of the range, done.
    986                  */
    987                 pRange->cPorts  -= Port - pRange->Port;
    988                 pRange->Core.Key = Port;
    989                 pRange->Port     = Port;
    990                 break;
    991             }
    992             else if (pRange->Core.KeyLast <= PortLast)
    993             {
    994                 /*
    995                  * Just cut of the tail.
    996                  */
    997                 unsigned c = pRange->Core.KeyLast - Port + 1;
    998                 pRange->Core.KeyLast -= c;
    999                 pRange->cPorts -= c;
    1000                 Port += c;
    1001             }
    1002             else
    1003             {
    1004                 /*
    1005                  * Split the range, done.
    1006                  */
    1007                 Assert(pRange->Core.KeyLast > PortLast && pRange->Core.Key < Port);
    1008                 /* create tail. */
    1009                 PIOMIOPORTRANGERC pRangeNew;
    1010                 int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew);
    1011                 if (RT_FAILURE(rc2))
    1012                 {
    1013                     IOM_UNLOCK_EXCL(pVM);
    1014                     return rc2;
    1015                 }
    1016                 *pRangeNew = *pRange;
    1017                 pRangeNew->Core.Key     = PortLast;
    1018                 pRangeNew->Port         = PortLast;
    1019                 pRangeNew->cPorts       = pRangeNew->Core.KeyLast - PortLast + 1;
    1020 
    1021                 LogFlow(("IOMR3IOPortDeregister (rc): split the range; new %x\n", pRangeNew->Core.Key));
    1022 
    1023                 /* adjust head */
    1024                 pRange->Core.KeyLast  = Port - 1;
    1025                 pRange->cPorts        = Port - pRange->Port;
    1026 
    1027                 /* insert */
    1028                 if (!RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeRC, &pRangeNew->Core))
    1029                 {
    1030                     AssertMsgFailed(("This cannot happen!\n"));
    1031                     MMHyperFree(pVM, pRangeNew);
    1032                     rc = VERR_IOM_IOPORT_IPE_1;
    1033                 }
    1034                 break;
    1035             }
    1036         }
    1037         else /* next port */
    1038             Port++;
    1039     } /* for all ports - RC. */
    1040 #else
    1041     int rc = VINF_SUCCESS;
    1042 #endif
    1043 
    1044     /*
    1045      * Remove any R0 ranges.
    1046      */
    1047     Port = PortStart;
    1048     while (Port <= PortLast && Port >= PortStart)
    1049     {
    1050         /*
    1051          * Try find range.
    1052          */
    1053         PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeR0, Port);
    1054         if (pRange)
    1055         {
    1056             if (   pRange->Core.Key     == Port
    1057                 && pRange->Core.KeyLast <= PortLast)
    1058             {
    1059                 /*
    1060                  * Kick out the entire range.
    1061                  */
    1062                 void *pv = RTAvlroIOPortRemove(&pVM->iom.s.pTreesR3->IOPortTreeR0, Port);
    1063                 Assert(pv == (void *)pRange); NOREF(pv);
    1064                 Port += pRange->cPorts;
    1065                 MMHyperFree(pVM, pRange);
    1066             }
    1067             else if (pRange->Core.Key == Port)
    1068             {
    1069                 /*
    1070                  * Cut of the head of the range, done.
    1071                  */
    1072                 pRange->cPorts  -= Port - pRange->Port;
    1073                 pRange->Core.Key = Port;
    1074                 pRange->Port     = Port;
    1075                 break;
    1076             }
    1077             else if (pRange->Core.KeyLast <= PortLast)
    1078             {
    1079                 /*
    1080                  * Just cut of the tail.
    1081                  */
    1082                 unsigned c = pRange->Core.KeyLast - Port + 1;
    1083                 pRange->Core.KeyLast -= c;
    1084                 pRange->cPorts -= c;
    1085                 Port += c;
    1086             }
    1087             else
    1088             {
    1089                 /*
    1090                  * Split the range, done.
    1091                  */
    1092                 Assert(pRange->Core.KeyLast > PortLast && pRange->Core.Key < Port);
    1093                 /* create tail. */
    1094                 PIOMIOPORTRANGER0 pRangeNew;
    1095                 int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew);
    1096                 if (RT_FAILURE(rc2))
    1097                 {
    1098                     IOM_UNLOCK_EXCL(pVM);
    1099                     return rc2;
    1100                 }
    1101                 *pRangeNew = *pRange;
    1102                 pRangeNew->Core.Key     = PortLast;
    1103                 pRangeNew->Port         = PortLast;
    1104                 pRangeNew->cPorts       = pRangeNew->Core.KeyLast - PortLast + 1;
    1105 
    1106                 LogFlow(("IOMR3IOPortDeregister (r0): split the range; new %x\n", pRangeNew->Core.Key));
    1107 
    1108                 /* adjust head */
    1109                 pRange->Core.KeyLast  = Port - 1;
    1110                 pRange->cPorts        = Port - pRange->Port;
    1111 
    1112                 /* insert */
    1113                 if (!RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR0, &pRangeNew->Core))
    1114                 {
    1115                     AssertMsgFailed(("This cannot happen!\n"));
    1116                     MMHyperFree(pVM, pRangeNew);
    1117                     rc = VERR_IOM_IOPORT_IPE_1;
    1118                 }
    1119                 break;
    1120             }
    1121         }
    1122         else /* next port */
    1123             Port++;
    1124     } /* for all ports - R0. */
    1125 
    1126     /*
    1127      * And the same procedure for ring-3 ranges.
    1128      */
    1129     Port = PortStart;
    1130     while (Port <= PortLast && Port >= PortStart)
    1131     {
    1132         /*
    1133          * Try find range.
    1134          */
    1135         PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeR3, Port);
    1136         if (pRange)
    1137         {
    1138             if (   pRange->Core.Key     == Port
    1139                 && pRange->Core.KeyLast <= PortLast)
    1140             {
    1141                 /*
    1142                  * Kick out the entire range.
    1143                  */
    1144                 void *pv = RTAvlroIOPortRemove(&pVM->iom.s.pTreesR3->IOPortTreeR3, Port);
    1145                 Assert(pv == (void *)pRange); NOREF(pv);
    1146                 Port += pRange->cPorts;
    1147                 MMHyperFree(pVM, pRange);
    1148             }
    1149             else if (pRange->Core.Key == Port)
    1150             {
    1151                 /*
    1152                  * Cut of the head of the range, done.
    1153                  */
    1154                 pRange->cPorts  -= Port - pRange->Port;
    1155                 pRange->Core.Key = Port;
    1156                 pRange->Port     = Port;
    1157                 break;
    1158             }
    1159             else if (pRange->Core.KeyLast <= PortLast)
    1160             {
    1161                 /*
    1162                  * Just cut of the tail.
    1163                  */
    1164                 unsigned c = pRange->Core.KeyLast - Port + 1;
    1165                 pRange->Core.KeyLast -= c;
    1166                 pRange->cPorts -= c;
    1167                 Port += c;
    1168             }
    1169             else
    1170             {
    1171                 /*
    1172                  * Split the range, done.
    1173                  */
    1174                 Assert(pRange->Core.KeyLast > PortLast && pRange->Core.Key < Port);
    1175                 /* create tail. */
    1176                 PIOMIOPORTRANGER3 pRangeNew;
    1177                 int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew);
    1178                 if (RT_FAILURE(rc2))
    1179                 {
    1180                     IOM_UNLOCK_EXCL(pVM);
    1181                     return rc2;
    1182                 }
    1183                 *pRangeNew = *pRange;
    1184                 pRangeNew->Core.Key     = PortLast;
    1185                 pRangeNew->Port         = PortLast;
    1186                 pRangeNew->cPorts       = pRangeNew->Core.KeyLast - PortLast + 1;
    1187 
    1188                 LogFlow(("IOMR3IOPortDeregister (r3): split the range; new %x\n", pRangeNew->Core.Key));
    1189 
    1190                 /* adjust head */
    1191                 pRange->Core.KeyLast  = Port - 1;
    1192                 pRange->cPorts        = Port - pRange->Port;
    1193 
    1194                 /* insert */
    1195                 if (!RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR3, &pRangeNew->Core))
    1196                 {
    1197                     AssertMsgFailed(("This cannot happen!\n"));
    1198                     MMHyperFree(pVM, pRangeNew);
    1199                     rc = VERR_IOM_IOPORT_IPE_1;
    1200                 }
    1201                 break;
    1202             }
    1203         }
    1204         else /* next port */
    1205             Port++;
    1206     } /* for all ports - ring-3. */
    1207 
    1208     /* done */
    1209     IOM_UNLOCK_EXCL(pVM);
    1210     return rc;
    1211 }
    1212 
    1213 
    1214 /**
    1215  * Dummy Port I/O Handler for IN operations.
    1216  *
    1217  * @returns VBox status code.
    1218  *
    1219  * @param   pDevIns     The device instance.
    1220  * @param   pvUser      User argument.
    1221  * @param   Port        Port number used for the IN operation.
    1222  * @param   pu32        Where to store the result.
    1223  * @param   cb          Number of bytes read.
    1224  */
    1225 static DECLCALLBACK(int) iomR3IOPortDummyIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
    1226 {
    1227     NOREF(pDevIns); NOREF(pvUser); NOREF(Port);
    1228     switch (cb)
    1229     {
    1230         case 1: *pu32 = 0xff; break;
    1231         case 2: *pu32 = 0xffff; break;
    1232         case 4: *pu32 = UINT32_C(0xffffffff); break;
    1233         default:
    1234             AssertReleaseMsgFailed(("cb=%d\n", cb));
    1235             return VERR_IOM_IOPORT_IPE_2;
    1236     }
    1237     return VINF_SUCCESS;
    1238 }
    1239 
    1240 
    1241 /**
    1242  * @callback_method_impl{FNIOMIOPORTINSTRING,
    1243  *      Dummy Port I/O Handler for string IN operations.}
    1244  */
    1245 static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t *pbDst,
    1246                                                uint32_t *pcTransfer, unsigned cb)
    1247 {
    1248     NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pbDst); NOREF(pcTransfer); NOREF(cb);
    1249     return VINF_SUCCESS;
    1250 }
    1251 
    1252 
    1253 /**
    1254  * Dummy Port I/O Handler for OUT operations.
    1255  *
    1256  * @returns VBox status code.
    1257  *
    1258  * @param   pDevIns     The device instance.
    1259  * @param   pvUser      User argument.
    1260  * @param   Port        Port number used for the OUT operation.
    1261  * @param   u32         The value to output.
    1262  * @param   cb          The value size in bytes.
    1263  */
    1264 static DECLCALLBACK(int) iomR3IOPortDummyOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
    1265 {
    1266     NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(u32); NOREF(cb);
    1267     return VINF_SUCCESS;
    1268 }
    1269 
    1270 
    1271 /**
    1272  * @callback_method_impl{FNIOMIOPORTOUTSTRING,
    1273  *      Dummy Port I/O Handler for string OUT operations.}
    1274  */
    1275 static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t const *pbSrc,
    1276                                                 uint32_t *pcTransfer, unsigned cb)
    1277 {
    1278     NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pbSrc); NOREF(pcTransfer); NOREF(cb);
    1279     return VINF_SUCCESS;
    1280 }
    1281 
    1282 
    1283405
    1284406/**
  • trunk/src/VBox/VMM/VMMR3/IOMR3IoPort.cpp

    r82277 r82311  
    592592
    593593/**
    594  * Display a single I/O port ring-3 range.
    595  *
    596  * @returns 0
    597  * @param   pNode   Pointer to I/O port HC range.
    598  * @param   pvUser  Pointer to info output callback structure.
    599  */
    600 static DECLCALLBACK(int) iomR3IOPortInfoOneR3(PAVLROIOPORTNODECORE pNode, void *pvUser)
    601 {
    602     PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)pNode;
    603     PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;
    604     pHlp->pfnPrintf(pHlp,
    605                     "%04x-%04x %p %p %p %p %s\n",
    606                     pRange->Core.Key,
    607                     pRange->Core.KeyLast,
    608                     pRange->pDevIns,
    609                     pRange->pfnInCallback,
    610                     pRange->pfnOutCallback,
    611                     pRange->pvUser,
    612                     pRange->pszDesc);
    613     return 0;
    614 }
    615 
    616 
    617 /**
    618594 * Display all registered I/O port ranges.
    619595 *
     
    624600DECLCALLBACK(void) iomR3IoPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
    625601{
     602    RT_NOREF(pszArgs);
     603
    626604    /* No locking needed here as registerations are only happening during VMSTATE_CREATING. */
    627605    pHlp->pfnPrintf(pHlp,
     
    648626                            paRegs[i].idxSelf, pszRing, paRegs[i].cPorts, paRegs[i].pszDesc);
    649627    }
    650 
    651     /* Legacy registration: */
    652     NOREF(pszArgs);
    653     pHlp->pfnPrintf(pHlp,
    654                     "I/O Port R3 ranges (pVM=%p)\n"
    655                     "Range     %.*s %.*s %.*s %.*s Description\n",
    656                     pVM,
    657                     sizeof(RTHCPTR) * 2,      "pDevIns         ",
    658                     sizeof(RTHCPTR) * 2,      "In              ",
    659                     sizeof(RTHCPTR) * 2,      "Out             ",
    660                     sizeof(RTHCPTR) * 2,      "pvUser          ");
    661     IOM_LOCK_SHARED(pVM);
    662     RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeR3, true, iomR3IOPortInfoOneR3, (void *)pHlp);
    663     IOM_UNLOCK_SHARED(pVM);
    664 
    665     pHlp->pfnPrintf(pHlp,
    666                     "I/O Port R0 ranges (pVM=%p)\n"
    667                     "Range     %.*s %.*s %.*s %.*s Description\n",
    668                     pVM,
    669                     sizeof(RTHCPTR) * 2,      "pDevIns         ",
    670                     sizeof(RTHCPTR) * 2,      "In              ",
    671                     sizeof(RTHCPTR) * 2,      "Out             ",
    672                     sizeof(RTHCPTR) * 2,      "pvUser          ");
    673     IOM_LOCK_SHARED(pVM);
    674     RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeR0, true, iomR3IOPortInfoOneR3, (void *)pHlp);
    675     IOM_UNLOCK_SHARED(pVM);
    676 }
    677 
     628}
     629
  • trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp

    r82224 r82311  
    139139    LogFlow(("pdmR3DevHlp_IoPortGetMappingAddress: caller='%s'/%d: returns %#RX32\n", pDevIns->pReg->szName, pDevIns->iInstance, uAddress));
    140140    return uAddress;
    141 }
    142 
    143 
    144 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegister} */
    145 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
    146                                                     PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
    147 {
    148     PDMDEV_ASSERT_DEVINS(pDevIns);
    149     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,
    150              Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
    151     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    152 
    153 #if 0 /** @todo needs a real string cache for this */
    154     if (pDevIns->iInstance > 0)
    155     {
    156          char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
    157          if (pszDesc2)
    158              pszDesc = pszDesc2;
    159     }
    160 #endif
    161 
    162     int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser,
    163                                    pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
    164 
    165     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    166     return rc;
    167 }
    168 
    169 
    170 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegisterRC} */
    171 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterRC(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTRCPTR pvUser,
    172                                                       const char *pszOut, const char *pszIn,
    173                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    174 {
    175     PDMDEV_ASSERT_DEVINS(pDevIns);
    176     Assert(pDevIns->pReg->pszRCMod[0]);
    177     Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);
    178     LogFlow(("pdmR3DevHlp_IOPortRegisterRC: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,
    179              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    180 
    181 #if 0
    182     /*
    183      * Resolve the functions (one of the can be NULL).
    184      */
    185     PVM pVM = pDevIns->Internal.s.pVMR3;
    186     VM_ASSERT_EMT(pVM);
    187     int rc = VINF_SUCCESS;
    188     if (   pDevIns->pReg->pszRCMod[0]
    189         && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
    190         && VM_IS_RAW_MODE_ENABLED(pVM))
    191     {
    192         RTRCPTR RCPtrIn = NIL_RTRCPTR;
    193         if (pszIn)
    194         {
    195             rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszIn, &RCPtrIn);
    196             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pReg->pszRCMod, pszIn));
    197         }
    198         RTRCPTR RCPtrOut = NIL_RTRCPTR;
    199         if (pszOut && RT_SUCCESS(rc))
    200         {
    201             rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszOut, &RCPtrOut);
    202             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pReg->pszRCMod, pszOut));
    203         }
    204         RTRCPTR RCPtrInStr = NIL_RTRCPTR;
    205         if (pszInStr && RT_SUCCESS(rc))
    206         {
    207             rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszInStr, &RCPtrInStr);
    208             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pReg->pszRCMod, pszInStr));
    209         }
    210         RTRCPTR RCPtrOutStr = NIL_RTRCPTR;
    211         if (pszOutStr && RT_SUCCESS(rc))
    212         {
    213             rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszOutStr, &RCPtrOutStr);
    214             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pReg->pszRCMod, pszOutStr));
    215         }
    216 
    217         if (RT_SUCCESS(rc))
    218         {
    219 #if 0 /** @todo needs a real string cache for this */
    220             if (pDevIns->iInstance > 0)
    221             {
    222                  char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
    223                  if (pszDesc2)
    224                      pszDesc = pszDesc2;
    225             }
    226 #endif
    227 
    228             rc = IOMR3IOPortRegisterRC(pVM, pDevIns, Port, cPorts, pvUser, RCPtrOut, RCPtrIn, RCPtrOutStr, RCPtrInStr, pszDesc);
    229         }
    230     }
    231     else if (VM_IS_RAW_MODE_ENABLED(pVM))
    232     {
    233         AssertMsgFailed(("No RC module for this driver!\n"));
    234         rc = VERR_INVALID_PARAMETER;
    235     }
    236 #else
    237     RT_NOREF(pDevIns, Port, cPorts, pvUser, pszOut, pszIn, pszOutStr, pszInStr, pszDesc);
    238     int rc = VINF_SUCCESS;
    239 #endif
    240 
    241     LogFlow(("pdmR3DevHlp_IOPortRegisterRC: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    242     return rc;
    243 }
    244 
    245 
    246 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegisterR0} */
    247 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTR0PTR pvUser,
    248                                                       const char *pszOut, const char *pszIn,
    249                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    250 {
    251     PDMDEV_ASSERT_DEVINS(pDevIns);
    252     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    253     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,
    254              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    255 
    256     /*
    257      * Resolve the functions (one of the can be NULL).
    258      */
    259     int rc = VINF_SUCCESS;
    260     if (    pDevIns->pReg->pszR0Mod[0]
    261         &&  (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
    262     {
    263         R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
    264         if (pszIn)
    265         {
    266             rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszIn, &pfnR0PtrIn);
    267             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pReg->pszR0Mod, pszIn));
    268         }
    269         R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
    270         if (pszOut && RT_SUCCESS(rc))
    271         {
    272             rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszOut, &pfnR0PtrOut);
    273             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pReg->pszR0Mod, pszOut));
    274         }
    275         R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
    276         if (pszInStr && RT_SUCCESS(rc))
    277         {
    278             rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszInStr, &pfnR0PtrInStr);
    279             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pReg->pszR0Mod, pszInStr));
    280         }
    281         R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
    282         if (pszOutStr && RT_SUCCESS(rc))
    283         {
    284             rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszOutStr, &pfnR0PtrOutStr);
    285             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pReg->pszR0Mod, pszOutStr));
    286         }
    287 
    288         if (RT_SUCCESS(rc))
    289         {
    290 #if 0 /** @todo needs a real string cache for this */
    291             if (pDevIns->iInstance > 0)
    292             {
    293                  char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
    294                  if (pszDesc2)
    295                      pszDesc = pszDesc2;
    296             }
    297 #endif
    298 
    299             rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
    300         }
    301     }
    302     else
    303     {
    304         AssertMsgFailed(("No R0 module for this driver!\n"));
    305         rc = VERR_INVALID_PARAMETER;
    306     }
    307 
    308     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    309     return rc;
    310 }
    311 
    312 
    313 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortDeregister} */
    314 static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts)
    315 {
    316     PDMDEV_ASSERT_DEVINS(pDevIns);
    317     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    318     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance,
    319              Port, cPorts));
    320 
    321     int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);
    322 
    323     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    324     return rc;
    325141}
    326142
     
    697513
    698514    LogFlow(("pdmR3DevHlp_Mmio2ChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    699     return rc;
    700 }
    701 
    702 
    703 /**
    704  * @copydoc PDMDEVHLPR3::pfnMMIO2Register
    705  */
    706 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cb,
    707                                                    uint32_t fFlags, void **ppv, const char *pszDesc)
    708 {
    709     PDMDEV_ASSERT_DEVINS(pDevIns);
    710     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    711     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: pPciDev=%p (%#x) iRegion=%#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
    712              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion,
    713              cb, fFlags, ppv, pszDesc, pszDesc));
    714     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
    715 
    716 /** @todo PGMR3PhysMMIO2Register mangles the description, move it here and
    717  *        use a real string cache. */
    718     int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,
    719                                     cb, fFlags, pszDesc, ppv, NULL);
    720 
    721     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    722     return rc;
    723 }
    724 
    725 
    726 /**
    727  * @copydoc PDMDEVHLPR3::pfnMMIOExDeregister
    728  */
    729 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExDeregister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion)
    730 {
    731     PDMDEV_ASSERT_DEVINS(pDevIns);
    732     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    733     LogFlow(("pdmR3DevHlp_MMIOExDeregister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x\n",
    734              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion));
    735 
    736     AssertReturn(iRegion <= UINT8_MAX || iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
    737     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
    738 
    739     int rc = PGMR3PhysMMIOExDeregister(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254,
    740                                        iRegion, NIL_PGMMMIO2HANDLE);
    741 
    742     LogFlow(("pdmR3DevHlp_MMIOExDeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    743     return rc;
    744 }
    745 
    746 
    747 /**
    748  * @copydoc PDMDEVHLPR3::pfnMMIOExMap
    749  */
    750 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS GCPhys)
    751 {
    752     PDMDEV_ASSERT_DEVINS(pDevIns);
    753     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    754     LogFlow(("pdmR3DevHlp_MMIOExMap: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x GCPhys=%#RGp\n",
    755              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, GCPhys));
    756     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);
    757 
    758     int rc = PGMR3PhysMMIOExMap(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,
    759                                 NIL_PGMMMIO2HANDLE, GCPhys);
    760 
    761     LogFlow(("pdmR3DevHlp_MMIOExMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    762     return rc;
    763 }
    764 
    765 
    766 /**
    767  * @copydoc PDMDEVHLPR3::pfnMMIOExUnmap
    768  */
    769 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS GCPhys)
    770 {
    771     PDMDEV_ASSERT_DEVINS(pDevIns);
    772     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    773     LogFlow(("pdmR3DevHlp_MMIOExUnmap: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x GCPhys=%#RGp\n",
    774              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, GCPhys));
    775     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);
    776 
    777     int rc = PGMR3PhysMMIOExUnmap(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,
    778                                   NIL_PGMMMIO2HANDLE, GCPhys);
    779 
    780     LogFlow(("pdmR3DevHlp_MMIOExUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    781     return rc;
    782 }
    783 
    784 
    785 /**
    786  * @copydoc PDMDEVHLPR3::pfnMMIOExReduce
    787  */
    788 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExReduce(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion)
    789 {
    790     PDMDEV_ASSERT_DEVINS(pDevIns);
    791     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    792     LogFlow(("pdmR3DevHlp_MMIOExReduce: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x cbRegion=%RGp\n",
    793              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, cbRegion));
    794     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);
    795 
    796     int rc = PGMR3PhysMMIOExReduce(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,
    797                                    NIL_PGMMMIO2HANDLE, cbRegion);
    798 
    799     LogFlow(("pdmR3DevHlp_MMIOExReduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    800     return rc;
    801 }
    802 
    803 
    804 /**
    805  * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
    806  */
    807 static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS off,
    808                                                      RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)
    809 {
    810     PDMDEV_ASSERT_DEVINS(pDevIns);
    811 #ifndef PGM_WITHOUT_MAPPINGS
    812     PVM pVM = pDevIns->Internal.s.pVMR3;
    813     VM_ASSERT_EMT(pVM);
    814     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",
    815              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));
    816     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
    817 
    818     if (pDevIns->iInstance > 0)
    819     {
    820          char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
    821          if (pszDesc2)
    822              pszDesc = pszDesc2;
    823     }
    824 
    825     int rc = MMR3HyperMapMMIO2(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, off, cb, pszDesc, pRCPtr);
    826 
    827 #else
    828     RT_NOREF(pDevIns, pPciDev, iRegion, off, cb, pszDesc, pRCPtr);
    829     AssertFailed();
    830     int rc = VERR_RAW_MODE_NOT_SUPPORTED;
    831 #endif
    832     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pRCPtr));
    833     return rc;
    834 }
    835 
    836 
    837 /**
    838  * @copydoc PDMDEVHLPR3::pfnMMIO2MapKernel
    839  */
    840 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2MapKernel(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS off,
    841                                                     RTGCPHYS cb,const char *pszDesc, PRTR0PTR pR0Ptr)
    842 {
    843     PDMDEV_ASSERT_DEVINS(pDevIns);
    844     PVM pVM = pDevIns->Internal.s.pVMR3;
    845     VM_ASSERT_EMT(pVM);
    846     LogFlow(("pdmR3DevHlp_MMIO2MapKernel: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x off=%RGp cb=%RGp pszDesc=%p:{%s} pR0Ptr=%p\n",
    847              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, off, cb, pszDesc, pszDesc, pR0Ptr));
    848     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
    849 
    850     if (pDevIns->iInstance > 0)
    851     {
    852          char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
    853          if (pszDesc2)
    854              pszDesc = pszDesc2;
    855     }
    856 
    857     int rc = PGMR3PhysMMIO2MapKernel(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, off, cb, pszDesc, pR0Ptr);
    858 
    859     LogFlow(("pdmR3DevHlp_MMIO2MapKernel: caller='%s'/%d: returns %Rrc *pR0Ptr=%RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pR0Ptr));
    860     return rc;
    861 }
    862 
    863 
    864 /**
    865  * @copydoc PDMDEVHLPR3::pfnMMIOExChangeRegionNo
    866  */
    867 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExChangeRegionNo(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    868                                                           uint32_t iNewRegion)
    869 {
    870     PDMDEV_ASSERT_DEVINS(pDevIns);
    871     PVM pVM = pDevIns->Internal.s.pVMR3;
    872     VM_ASSERT_EMT(pVM);
    873     LogFlow(("pdmR3DevHlp_MMIOExChangeRegionNo: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x iNewRegion=%#x\n",
    874              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, iNewRegion));
    875     AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
    876 
    877     int rc = PGMR3PhysMMIOExChangeRegionNo(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,
    878                                            NIL_PGMMMIO2HANDLE, iNewRegion);
    879 
    880     LogFlow(("pdmR3DevHlp_MMIOExChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
    881515    return rc;
    882516}
     
    20961730    }
    20971731
     1732    /* This flag is required now. */
     1733    AssertLogRelMsgReturn(fFlags & PDMPCIDEV_IORGN_F_NEW_STYLE,
     1734                          ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
     1735                          VERR_INVALID_FLAGS);
     1736
    20981737    /*
    20991738     * We're currently restricted to page aligned MMIO regions.
     
    43453984    pdmR3DevHlp_IoPortUnmap,
    43463985    pdmR3DevHlp_IoPortGetMappingAddress,
    4347     pdmR3DevHlp_IOPortRegister,
    4348     pdmR3DevHlp_IOPortRegisterRC,
    4349     pdmR3DevHlp_IOPortRegisterR0,
    4350     pdmR3DevHlp_IOPortDeregister,
    43513986    pdmR3DevHlp_MmioCreateEx,
    43523987    pdmR3DevHlp_MmioMap,
     
    43654000    pdmR3DevHlp_Mmio2GetMappingAddress,
    43664001    pdmR3DevHlp_Mmio2ChangeRegionNo,
    4367     pdmR3DevHlp_MMIO2Register,
    4368     pdmR3DevHlp_MMIOExDeregister,
    4369     pdmR3DevHlp_MMIOExMap,
    4370     pdmR3DevHlp_MMIOExUnmap,
    4371     pdmR3DevHlp_MMIOExReduce,
    4372     pdmR3DevHlp_MMHyperMapMMIO2,
    4373     pdmR3DevHlp_MMIO2MapKernel,
    43744002    pdmR3DevHlp_ROMRegister,
    43754003    pdmR3DevHlp_ROMProtectShadow,
     
    46584286    pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
    46594287    pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
    4660     pdmR3DevHlp_MMIOExChangeRegionNo,
    46614288    0,
    46624289    0,
     
    48434470    pdmR3DevHlp_IoPortUnmap,
    48444471    pdmR3DevHlp_IoPortGetMappingAddress,
    4845     pdmR3DevHlp_IOPortRegister,
    4846     pdmR3DevHlp_IOPortRegisterRC,
    4847     pdmR3DevHlp_IOPortRegisterR0,
    4848     pdmR3DevHlp_IOPortDeregister,
    48494472    pdmR3DevHlp_MmioCreateEx,
    48504473    pdmR3DevHlp_MmioMap,
     
    48634486    pdmR3DevHlp_Mmio2GetMappingAddress,
    48644487    pdmR3DevHlp_Mmio2ChangeRegionNo,
    4865     pdmR3DevHlp_MMIO2Register,
    4866     pdmR3DevHlp_MMIOExDeregister,
    4867     pdmR3DevHlp_MMIOExMap,
    4868     pdmR3DevHlp_MMIOExUnmap,
    4869     pdmR3DevHlp_MMIOExReduce,
    4870     pdmR3DevHlp_MMHyperMapMMIO2,
    4871     pdmR3DevHlp_MMIO2MapKernel,
    48724488    pdmR3DevHlp_ROMRegister,
    48734489    pdmR3DevHlp_ROMProtectShadow,
     
    51564772    pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
    51574773    pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
    5158     pdmR3DevHlp_MMIOExChangeRegionNo,
    51594774    0,
    51604775    0,
  • trunk/src/VBox/VMM/include/IOMInline.h

    r81333 r82311  
    257257
    258258/**
    259  * Gets the I/O port range for the specified I/O port in the current context.
    260  *
    261  * @returns Pointer to I/O port range.
    262  * @returns NULL if no port registered.
    263  *
    264  * @param   pVM     The cross context VM structure.
    265  * @param   Port    The I/O port lookup.
    266  */
    267 DECLINLINE(CTX_SUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PVM pVM, RTIOPORT Port)
    268 {
    269     Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
    270     return (CTX_SUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->CTX_SUFF(IOPortTree), Port);
    271 }
    272 
    273 
    274 /**
    275  * Gets the I/O port range for the specified I/O port in the HC.
    276  *
    277  * @returns Pointer to I/O port range.
    278  * @returns NULL if no port registered.
    279  *
    280  * @param   pVM     The cross context VM structure.
    281  * @param   Port    The I/O port to lookup.
    282  */
    283 DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeR3(PVM pVM, RTIOPORT Port)
    284 {
    285     Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
    286     return (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);
    287 }
    288 
    289 
    290 /**
    291259 * Gets the MMIO range for the specified physical address in the current context.
    292260 *
  • trunk/src/VBox/VMM/include/IOMInternal.h

    r81463 r82311  
    407407
    408408/**
    409  * I/O port range descriptor, R3 version.
    410  */
    411 typedef struct IOMIOPORTRANGER3
    412 {
    413     /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
    414     AVLROIOPORTNODECORE         Core;
    415 #if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
    416     uint32_t                    u32Alignment; /**< The sizeof(Core) differs. */
    417 #endif
    418     /** Start I/O port address. */
    419     RTIOPORT                    Port;
    420     /** Size of the range. */
    421     uint16_t                    cPorts;
    422     /** Pointer to user argument. */
    423     RTR3PTR                     pvUser;
    424     /** Pointer to the associated device instance. */
    425     R3PTRTYPE(PPDMDEVINS)       pDevIns;
    426     /** Pointer to OUT callback function. */
    427     R3PTRTYPE(PFNIOMIOPORTOUT)  pfnOutCallback;
    428     /** Pointer to IN callback function. */
    429     R3PTRTYPE(PFNIOMIOPORTIN)   pfnInCallback;
    430     /** Pointer to string OUT callback function. */
    431     R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
    432     /** Pointer to string IN callback function. */
    433     R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
    434     /** Description / Name. For easing debugging. */
    435     R3PTRTYPE(const char *)     pszDesc;
    436 } IOMIOPORTRANGER3;
    437 /** Pointer to I/O port range descriptor, R3 version. */
    438 typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;
    439 
    440 /**
    441  * I/O port range descriptor, R0 version.
    442  */
    443 typedef struct IOMIOPORTRANGER0
    444 {
    445     /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
    446     AVLROIOPORTNODECORE         Core;
    447 #if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
    448     uint32_t                    u32Alignment; /**< The sizeof(Core) differs. */
    449 #endif
    450     /** Start I/O port address. */
    451     RTIOPORT                    Port;
    452     /** Size of the range. */
    453     uint16_t                    cPorts;
    454     /** Pointer to user argument. */
    455     RTR0PTR                     pvUser;
    456     /** Pointer to the associated device instance. */
    457     R0PTRTYPE(PPDMDEVINS)       pDevIns;
    458     /** Pointer to OUT callback function. */
    459     R0PTRTYPE(PFNIOMIOPORTOUT)  pfnOutCallback;
    460     /** Pointer to IN callback function. */
    461     R0PTRTYPE(PFNIOMIOPORTIN)   pfnInCallback;
    462     /** Pointer to string OUT callback function. */
    463     R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
    464     /** Pointer to string IN callback function. */
    465     R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
    466     /** Description / Name. For easing debugging. */
    467     R3PTRTYPE(const char *)     pszDesc;
    468 } IOMIOPORTRANGER0;
    469 /** Pointer to I/O port range descriptor, R0 version. */
    470 typedef IOMIOPORTRANGER0 *PIOMIOPORTRANGER0;
    471 
    472 /**
    473  * I/O port range descriptor, RC version.
    474  */
    475 typedef struct IOMIOPORTRANGERC
    476 {
    477     /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
    478     AVLROIOPORTNODECORE         Core;
    479     /** Start I/O port address. */
    480     RTIOPORT                    Port;
    481     /** Size of the range. */
    482     uint16_t                    cPorts;
    483     /** Pointer to user argument. */
    484     RTRCPTR                     pvUser;
    485     /** Pointer to the associated device instance. */
    486     RCPTRTYPE(PPDMDEVINS)       pDevIns;
    487     /** Pointer to OUT callback function. */
    488     RCPTRTYPE(PFNIOMIOPORTOUT)  pfnOutCallback;
    489     /** Pointer to IN callback function. */
    490     RCPTRTYPE(PFNIOMIOPORTIN)   pfnInCallback;
    491     /** Pointer to string OUT callback function. */
    492     RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
    493     /** Pointer to string IN callback function. */
    494     RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
    495 #if HC_ARCH_BITS == 64
    496     RTRCPTR                     RCPtrAlignment; /**< pszDesc is 8 byte aligned. */
    497 #endif
    498     /** Description / Name. For easing debugging. */
    499     R3PTRTYPE(const char *)     pszDesc;
    500 } IOMIOPORTRANGERC;
    501 /** Pointer to I/O port range descriptor, RC version. */
    502 typedef IOMIOPORTRANGERC *PIOMIOPORTRANGERC;
    503 
    504 
    505 /**
    506  * I/O port statistics. (one I/O port)
    507  *
    508  * This is a simple way of making on demand statistics, however it's a
    509  * bit free with the hypervisor heap memory.
    510  */
    511 typedef struct IOMIOPORTSTATS
    512 {
    513     /** Avl node core with the port as Key. */
    514     AVLOIOPORTNODECORE          Core;
    515 #if HC_ARCH_BITS != 64 || !defined(RT_OS_WINDOWS)
    516     uint32_t                    u32Alignment; /**< The sizeof(Core) differs. */
    517 #endif
    518     /** Number of INs to this port from R3. */
    519     STAMCOUNTER                 InR3;
    520     /** Profiling IN handler overhead in R3. */
    521     STAMPROFILE                 ProfInR3;
    522     /** Number of OUTs to this port from R3. */
    523     STAMCOUNTER                 OutR3;
    524     /** Profiling OUT handler overhead in R3. */
    525     STAMPROFILE                 ProfOutR3;
    526 
    527     /** Number of INs to this port from R0/RC. */
    528     STAMCOUNTER                 InRZ;
    529     /** Profiling IN handler overhead in R0/RC. */
    530     STAMPROFILE                 ProfInRZ;
    531     /** Number of INs to this port from R0/RC which was serviced in R3. */
    532     STAMCOUNTER                 InRZToR3;
    533 
    534     /** Number of OUTs to this port from R0/RC. */
    535     STAMCOUNTER                 OutRZ;
    536     /** Profiling OUT handler overhead in R0/RC. */
    537     STAMPROFILE                 ProfOutRZ;
    538     /** Number of OUTs to this port from R0/RC which was serviced in R3. */
    539     STAMCOUNTER                 OutRZToR3;
    540 } IOMIOPORTSTATS;
    541 AssertCompileMemberAlignment(IOMIOPORTSTATS, InR3, 8);
    542 /** Pointer to I/O port statistics. */
    543 typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;
    544 
    545 
    546 /**
    547409 * The IOM trees.
    548410 *
     
    553415typedef struct IOMTREES
    554416{
    555     /** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */
    556     AVLROIOPORTTREE         IOPortTreeR3;
    557     /** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */
    558     AVLROIOPORTTREE         IOPortTreeR0;
    559 #if 0
    560     /** Tree containing I/O port range descriptors registered for RC (IOMIOPORTRANGERC). */
    561     AVLROIOPORTTREE         IOPortTreeRC;
    562 #endif
    563 
    564417    /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */
    565418    AVLROGCPHYSTREE         MMIOTree;
    566 
    567     /** Tree containing I/O port statistics (IOMIOPORTSTATS). */
    568     AVLOIOPORTTREE          IOPortStatTree;
    569419    /** Tree containing MMIO statistics (IOMMMIOSTATS). */
    570420    AVLOGCPHYSTREE          MmioStatTree;
     
    639489    uint16_t                            u16Padding;
    640490
    641     R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastReadR3;
    642     R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastWriteR3;
    643     R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR3;
    644     R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR3;
    645491    R3PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR3;
    646492    R3PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR3;
    647493
    648     R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastReadR0;
    649     R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastWriteR0;
    650     R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR0;
    651     R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR0;
    652494    R0PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR0;
    653495    R0PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR0;
Note: See TracChangeset for help on using the changeset viewer.

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