VirtualBox

Changeset 56415 in vbox


Ignore:
Timestamp:
Jun 14, 2015 12:08:29 PM (10 years ago)
Author:
vboxsync
Message:

IOM: Do the single I/O fallback in the string APIs instead of having the caller do it in a non-optimal manner.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/iom.h

    r56413 r56415  
    275275VMMDECL(VBOXSTRICTRC)   IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
    276276VMMDECL(VBOXSTRICTRC)   IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
    277 VMMDECL(VBOXSTRICTRC)  IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, void *pvDst,
    278                                             uint32_t *pcTransfers, unsigned cb);
    279 VMMDECL(VBOXSTRICTRC)  IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
    280                                              uint32_t *pcTransfers, unsigned cb);
     277VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, void *pvDst,
     278                                               uint32_t *pcTransfers, unsigned cb);
     279VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
     280                                                uint32_t *pcTransfers, unsigned cb);
    281281VMMDECL(VBOXSTRICTRC)   IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
    282282VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r56413 r56415  
    123123        PFNIOMIOPORTIN  pfnInCallback = pRange->pfnInCallback;
    124124#ifndef IN_RING3
    125         if (!pfnInCallback)
     125        if (pfnInCallback)
     126        { /* likely */ }
     127        else
    126128        {
    127129            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     
    138140         */
    139141        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);
    140         if (rcStrict != VINF_SUCCESS)
     142        if (rcStrict == VINF_SUCCESS)
     143        { /* likely */ }
     144        else
    141145        {
    142146            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     
    240244 * @param   cb          Size of the transfer unit (1, 2 or 4 bytes).
    241245 */
    242 VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort,
    243                                           void *pvDst, uint32_t *pcTransfers, unsigned cb)
     246VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort,
     247                                               void *pvDst, uint32_t *pcTransfers, unsigned cb)
    244248{
    245249    /* Take the IOM lock before performing any device I/O. */
     
    254258#endif
    255259
    256 #ifdef LOG_ENABLED
    257     const uint32_t cTransfers = *pcTransfers;
    258 #endif
     260    const uint32_t cRequestedTransfers = *pcTransfers;
     261    Assert(cRequestedTransfers > 0);
     262
    259263#ifdef VBOX_WITH_STATISTICS
    260264    /*
     
    288292         */
    289293        PFNIOMIOPORTINSTRING pfnInStrCallback = pRange->pfnInStrCallback;
    290 #ifndef IN_RING3
    291         if (!pfnInStrCallback)
    292         {
    293             STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     294        PFNIOMIOPORTIN       pfnInCallback    = pRange->pfnInCallback;
     295#ifndef IN_RING3
     296        if (pfnInStrCallback || pfnInCallback)
     297        { /* likely */ }
     298        else
     299        {
     300            STAM_STATS({ if (pStats)
     301                    STAM_COUNTER_INC(&pStats->InRZToR3); });
    294302            IOM_UNLOCK_SHARED(pVM);
    295303            return VINF_SUCCESS;
     
    304312         */
    305313        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);
    306         if (rcStrict != VINF_SUCCESS)
     314        if (rcStrict == VINF_SUCCESS)
     315        { /* likely */ }
     316        else
    307317        {
    308318            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
    309319            return rcStrict;
    310320        }
    311 #ifdef VBOX_WITH_STATISTICS
    312         if (pStats)
    313         {
    314             STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    315             rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
    316             STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
    317         }
    318         else
    319 #endif
    320             rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
     321
     322        /*
     323         * First using the string I/O callback.
     324         */
     325        if (pfnInStrCallback)
     326        {
     327#ifdef VBOX_WITH_STATISTICS
     328            if (pStats)
     329            {
     330                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     331                rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
     332                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     333            }
     334            else
     335#endif
     336                rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
     337        }
     338
     339        /*
     340         * Then doing the single I/O fallback.
     341         */
     342        if (   *pcTransfers > 0
     343            && rcStrict == VINF_SUCCESS)
     344        {
     345            pvDst = (uint8_t *)pvDst + (cRequestedTransfers - *pcTransfers) * cb;
     346            do
     347            {
     348                uint32_t u32Value = 0;
     349#ifdef VBOX_WITH_STATISTICS
     350                if (pStats)
     351                {
     352                    STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     353                    rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);
     354                    STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     355                }
     356                else
     357#endif
     358                    rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);
     359                if (rcStrict == VERR_IOM_IOPORT_UNUSED)
     360                {
     361                    u32Value = UINT32_MAX;
     362                    rcStrict = VINF_SUCCESS;
     363                }
     364                if (IOM_SUCCESS(rcStrict))
     365                {
     366                    switch (cb)
     367                    {
     368                        case 4: *(uint32_t *)pvDst =           u32Value; pvDst = (uint8_t *)pvDst + 4; break;
     369                        case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break;
     370                        case 1: *(uint8_t  *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break;
     371                        default: AssertFailed();
     372                    }
     373                    *pcTransfers -= 1;
     374                }
     375            } while (   *pcTransfers > 0
     376                     && rcStrict == VINF_SUCCESS);
     377        }
    321378        PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
    322379
     
    330387#endif
    331388        Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",
    332               uPort, pvDst, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
     389              uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
    333390        return rcStrict;
    334391    }
     
    359416
    360417    Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",
    361           uPort, pvDst, pcTransfers, cTransfers, *pcTransfers, cb));
     418          uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb));
    362419    IOM_UNLOCK_SHARED(pVM);
    363420    return VINF_SUCCESS;
     
    428485        PFNIOMIOPORTOUT pfnOutCallback = pRange->pfnOutCallback;
    429486#ifndef IN_RING3
    430         if (!pfnOutCallback)
     487        if (pfnOutCallback)
     488        { /* likely */ }
     489        else
    431490        {
    432491            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     
    443502         */
    444503        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);
    445         if (rcStrict != VINF_SUCCESS)
     504        if (rcStrict == VINF_SUCCESS)
     505        { /* likely */ }
     506        else
    446507        {
    447508            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     
    521582 * @param   cb          Size of the transfer unit (1, 2 or 4 bytes).
    522583 */
    523 VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
    524                                            uint32_t *pcTransfers, unsigned cb)
     584VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
     585                                                uint32_t *pcTransfers, unsigned cb)
    525586{
    526587    Assert(cb == 1 || cb == 2 || cb == 4);
     
    537598#endif
    538599
    539 #ifdef LOG_ENABLED
    540     const uint32_t cTransfers = *pcTransfers;
    541 #endif
     600    const uint32_t cRequestedTransfers = *pcTransfers;
     601    Assert(cRequestedTransfers > 0);
     602
    542603#ifdef VBOX_WITH_STATISTICS
    543604    /*
     
    571632         */
    572633        PFNIOMIOPORTOUTSTRING   pfnOutStrCallback = pRange->pfnOutStrCallback;
    573 #ifndef IN_RING3
    574         if (!pfnOutStrCallback)
     634        PFNIOMIOPORTOUT         pfnOutCallback    = pRange->pfnOutCallback;
     635#ifndef IN_RING3
     636        if (pfnOutStrCallback || pfnOutCallback)
     637        { /* likely */ }
     638        else
    575639        {
    576640            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     
    587651         */
    588652        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);
    589         if (rcStrict != VINF_SUCCESS)
     653        if (rcStrict == VINF_SUCCESS)
     654        { /* likely */ }
     655        else
    590656        {
    591657            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
    592658            return rcStrict;
    593659        }
    594 #ifdef VBOX_WITH_STATISTICS
    595         if (pStats)
    596         {
    597             STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
    598             rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
    599             STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
    600         }
    601         else
    602 #endif
    603             rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
     660
     661        /*
     662         * First using string I/O if possible.
     663         */
     664        if (pfnOutStrCallback)
     665        {
     666#ifdef VBOX_WITH_STATISTICS
     667            if (pStats)
     668            {
     669                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     670                rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
     671                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     672            }
     673            else
     674#endif
     675                rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
     676        }
     677
     678        /*
     679         * Then doing the single I/O fallback.
     680         */
     681        if (   *pcTransfers > 0
     682            && rcStrict == VINF_SUCCESS)
     683        {
     684            pvSrc = (uint8_t *)pvSrc + (cRequestedTransfers - *pcTransfers) * cb;
     685            do
     686            {
     687                uint32_t u32Value;
     688                switch (cb)
     689                {
     690                    case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break;
     691                    case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break;
     692                    case 1: u32Value = *(uint8_t  *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 1; break;
     693                    default: AssertFailed(); u32Value = UINT32_MAX;
     694                }
     695#ifdef VBOX_WITH_STATISTICS
     696                if (pStats)
     697                {
     698                    STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     699                    rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);
     700                    STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     701                }
     702                else
     703#endif
     704                    rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);
     705                if (IOM_SUCCESS(rcStrict))
     706                    *pcTransfers -= 1;
     707            } while (   *pcTransfers > 0
     708                     && rcStrict == VINF_SUCCESS);
     709        }
     710
    604711        PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
    605712
     
    613720#endif
    614721        Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n",
    615               uPort, pvSrc, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
     722              uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
    616723        return rcStrict;
    617724    }
     
    642749
    643750    Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",
    644           uPort, pvSrc, pcTransfers, cTransfers, *pcTransfers, cb));
     751          uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb));
    645752    IOM_UNLOCK_SHARED(pVM);
    646753    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp

    r56413 r56415  
    23612361                Assert(cThisTime <= cMaxThisTime); /* cThisTime is now how many transfers we have left. */
    23622362
    2363                 /* If not supported do IOMIOPortRead. */
    2364 /** @todo this code should move to IOMIOPortReadString! */
    2365                 if (   cThisTime > 0
    2366                     && rcStrict == VINF_SUCCESS)
    2367                 {
    2368                     pvDst = (uint8_t *)pvDst + (cMaxThisTime - cThisTime) * cbTransfer;
    2369                     do
    2370                     {
    2371                         uint32_t u32Value = 0;
    2372                         rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Value, cbTransfer);
    2373                         if (IOM_SUCCESS(rcStrict))
    2374                         {
    2375                             switch (cbTransfer)
    2376                             {
    2377                                 case 4: *(uint32_t *)pvDst =           u32Value; pvDst = (uint8_t *)pvDst + 4; break;
    2378                                 case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break;
    2379                                 case 1: *(uint8_t  *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break;
    2380                                 default: AssertFailedReturn(VERR_IOM_IOPORT_IPE_3);
    2381                             }
    2382                             cThisTime--;
    2383                         }
    2384                     } while (   cThisTime > 0
    2385                              && rcStrict == VINF_SUCCESS);
    2386                 }
    2387 
    23882363                PGMPhysReleasePageMappingLock(pVM, &Lock);
    23892364
     
    25452520                AssertRC(VBOXSTRICTRC_VAL(rcStrict));
    25462521                Assert(cThisTime <= cMaxThisTime); /* cThisTime is now how many transfers we have left. */
    2547 
    2548                 /* If not supported do IOMIOPortWrite. */
    2549 /** @todo this code should move to IOMIOPortReadString! */
    2550                 if (   cThisTime > 0
    2551                     && rcStrict == VINF_SUCCESS)
    2552                 {
    2553                     pvSrc = (uint8_t const *)pvSrc + (cMaxThisTime - cThisTime) * cbTransfer;
    2554                     do
    2555                     {
    2556                         uint32_t u32Value;
    2557                         switch (cbTransfer)
    2558                         {
    2559                             case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break;
    2560                             case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break;
    2561                             case 1: u32Value = *(uint8_t *)pvSrc;  pvSrc = (uint8_t const *)pvSrc + 1; break;
    2562                             default: AssertFailedReturn(VERR_IOM_IOPORT_IPE_3);
    2563                         }
    2564                         rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u32Value, cbTransfer);
    2565                         if (IOM_SUCCESS(rcStrict))
    2566                             cThisTime--;
    2567                     } while (   cThisTime > 0
    2568                              && rcStrict == VINF_SUCCESS);
    2569                 }
    25702522
    25712523                PGMPhysReleasePageMappingLock(pVM, &Lock);
Note: See TracChangeset for help on using the changeset viewer.

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