VirtualBox

Changeset 26944 in vbox


Ignore:
Timestamp:
Mar 2, 2010 1:42:41 PM (15 years ago)
Author:
vboxsync
Message:

PDM,IOM,TM: Added an optional per-device critsect for avoiding the global IOM lock. Only port I/O and timer callbacks use it, cannot yet be used with MMIO callbacks (will assert and fail).

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pdmdev.h

    r26939 r26944  
    34463446    /** Pointer to device instance data. */
    34473447    RTRCPTR                     pvInstanceDataRC;
     3448    /** The critical section for the device, see pCritSectR3.
     3449     * This is automatically resolved by PDM when pCritSectR3 is set by the
     3450     * constructor. */
     3451    RCPTRTYPE(PPDMCRITSECT)     pCritSectRC;
     3452    /** Alignment padding.  */
     3453    RTRCPTR                     pAlignmentRC;
    34483454
    34493455    /** Pointer the R0 PDM Device API. */
     
    34513457    /** Pointer to device instance data (R0). */
    34523458    RTR0PTR                     pvInstanceDataR0;
     3459    /** The critical section for the device, see pCritSectR3.
     3460    * This is automatically resolved by PDM when pCritSectR3 is set by the
     3461    * constructor. */
     3462    R0PTRTYPE(PPDMCRITSECT)     pCritSectR0;
    34533463
    34543464    /** Pointer the HC PDM Device API. */
     
    34563466    /** Pointer to device instance data. */
    34573467    RTR3PTR                     pvInstanceDataR3;
     3468    /** The critical section for the device. (Optional)
     3469     *
     3470     * The device constructor initializes this if it has a critical section for
     3471     * the device and desires it to be taken automatically by MMIO, I/O port
     3472     * and timer callbacks to the device.  The advantages using this locking
     3473     * approach is both less code and avoiding the global IOM lock.
     3474     *
     3475     * @remarks Will not yet be taken by SSM.
     3476     */
     3477    R3PTRTYPE(PPDMCRITSECT)     pCritSectR3;
    34583478
    34593479    /** Pointer to device registration structure.  */
     
    34633483
    34643484    /** The base interface of the device.
     3485     *
    34653486     * The device constructor initializes this if it has any
    34663487     * device level interfaces to export. To obtain this interface
     
    34763497        PDMDEVINSINT            s;
    34773498#endif
    3478         uint8_t                 padding[HC_ARCH_BITS == 32 ? 64 + 16 : 112];
     3499        uint8_t                 padding[HC_ARCH_BITS == 32 ? 64 + 0 : 112 + 0x28];
    34793500    } Internal;
    34803501
     
    34853506
    34863507/** Current PDMDEVINS version number. */
    3487 #define PDM_DEVINS_VERSION                      PDM_VERSION_MAKE(0xffe4, 1, 0)
     3508#define PDM_DEVINS_VERSION                      PDM_VERSION_MAKE(0xffe4, 2, 0)
    34883509
    34893510/** Converts a pointer to the PDMDEVINS::IBase to a pointer to PDMDEVINS. */
  • trunk/include/VBox/tm.h

    r26158 r26944  
    7575/** @defgroup grp_tm_timer_flags Timer flags.
    7676 * @{ */
    77 /** Use the default critical section for the class of timers.
    78  * Only devices have one at the moment. */
     77/** Use the default critical section for the class of timers. */
    7978#define TMTIMER_FLAGS_DEFAULT_CRIT_SECT 0
    8079/** No critical section needed or a custom one is set using
  • trunk/src/VBox/VMM/IOM.cpp

    r26152 r26944  
    14191419        return VERR_IOM_INVALID_MMIO_RANGE;
    14201420    }
     1421    /** @todo implement per-device locks for MMIO access. */
     1422    AssertReturn(!pDevIns->pCritSectR3, VERR_INTERNAL_ERROR_2);
    14211423
    14221424    /*
  • trunk/src/VBox/VMM/IOMInternal.h

    r22924 r26944  
    249249    STAMCOUNTER                 InR3;
    250250    /** Profiling IN handler overhead in R3. */
    251     STAMPROFILEADV              ProfInR3;
     251    STAMPROFILE                 ProfInR3;
    252252    /** Number of OUTs to this port from R3. */
    253253    STAMCOUNTER                 OutR3;
    254254    /** Profiling OUT handler overhead in R3. */
    255     STAMPROFILEADV              ProfOutR3;
     255    STAMPROFILE                 ProfOutR3;
    256256
    257257    /** Number of INs to this port from R0/RC. */
    258258    STAMCOUNTER                 InRZ;
    259259    /** Profiling IN handler overhead in R0/RC. */
    260     STAMPROFILEADV              ProfInRZ;
     260    STAMPROFILE                 ProfInRZ;
    261261    /** Number of INs to this port from R0/RC which was serviced in R3. */
    262262    STAMCOUNTER                 InRZToR3;
     
    265265    STAMCOUNTER                 OutRZ;
    266266    /** Profiling OUT handler overhead in R0/RC. */
    267     STAMPROFILEADV              ProfOutRZ;
     267    STAMPROFILE                 ProfOutRZ;
    268268    /** Number of OUTs to this port from R0/RC which was serviced in R3. */
    269269    STAMCOUNTER                 OutRZToR3;
  • trunk/src/VBox/VMM/PDM.cpp

    r26175 r26944  
    466466        if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
    467467        {
    468             pDevIns->pHlpRC = pDevHlpRC;
    469             pDevIns->pvInstanceDataRC = MMHyperR3ToRC(pVM, pDevIns->pvInstanceDataR3);
    470             pDevIns->Internal.s.pVMRC = pVM->pVMRC;
     468            pDevIns->pHlpRC             = pDevHlpRC;
     469            pDevIns->pvInstanceDataRC   = MMHyperR3ToRC(pVM, pDevIns->pvInstanceDataR3);
     470            if (pDevIns->pCritSectR3)
     471                pDevIns->pCritSectRC    = MMHyperR3ToRC(pVM, pDevIns->pCritSectR3);
     472            pDevIns->Internal.s.pVMRC   = pVM->pVMRC;
    471473            if (pDevIns->Internal.s.pPciBusR3)
    472                 pDevIns->Internal.s.pPciBusRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
     474                pDevIns->Internal.s.pPciBusRC    = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
    473475            if (pDevIns->Internal.s.pPciDeviceR3)
    474476                pDevIns->Internal.s.pPciDeviceRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciDeviceR3);
  • trunk/src/VBox/VMM/PDMDevice.cpp

    r26172 r26944  
    336336        pDevIns->pvInstanceDataR0               = pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0
    337337                                                ? MMHyperR3ToR0(pVM, pDevIns->pvInstanceDataR3) : NIL_RTR0PTR;
     338        //pDevIns->pCritSectR3                    = NULL;
     339        //pDevIns->pCritSectR0                    = NIL_RTR0PTR;
     340        //pDevIns->pCritSectRC                    = NIL_RTRCPTR;
    338341
    339342        /*
     
    368371        Log(("PDM: Constructing device '%s' instance %d...\n", pDevIns->pReg->szName, pDevIns->iInstance));
    369372        rc = pDevIns->pReg->pfnConstruct(pDevIns, pDevIns->iInstance, pDevIns->pCfg);
     373        if (RT_SUCCESS(rc))
     374        {
     375            /*
     376             * Per-device critsect fun.
     377             */
     378            if (pDevIns->pCritSectR3)
     379            {
     380                AssertStmt(PDMCritSectIsInitialized(pDevIns->pCritSectR3), rc = VERR_INTERNAL_ERROR_4);
     381                if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
     382                {
     383                    pDevIns->pCritSectR0 = MMHyperCCToR0(pVM, pDevIns->pCritSectR3);
     384                    AssertStmt(pDevIns->pCritSectR0 != NIL_RTR0PTR, rc = VERR_INTERNAL_ERROR_3);
     385                }
     386                else
     387                    AssertStmt(pDevIns->pCritSectR0 == NIL_RTRCPTR, rc = VERR_INTERNAL_ERROR_2);
     388
     389                if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
     390                {
     391                    pDevIns->pCritSectRC = MMHyperCCToRC(pVM, pDevIns->pCritSectR3);
     392                    AssertStmt(pDevIns->pCritSectRC != NIL_RTRCPTR, rc = VERR_INTERNAL_ERROR_3);
     393                }
     394                else
     395                    AssertStmt(pDevIns->pCritSectRC == NIL_RTRCPTR, rc = VERR_INTERNAL_ERROR_2);
     396            }
     397            else
     398                AssertStmt(   pDevIns->pCritSectRC == NIL_RTRCPTR
     399                           && pDevIns->pCritSectR0 == NIL_RTR0PTR,
     400                           rc = VERR_INTERNAL_ERROR_5);
     401        }
    370402        if (RT_FAILURE(rc))
    371403        {
  • trunk/src/VBox/VMM/TM.cpp

    r26158 r26944  
    136136#include <VBox/vm.h>
    137137
     138#include <VBox/pdmdev.h>
    138139#include <VBox/param.h>
    139140#include <VBox/err.h>
     
    12851286        (*ppTimer)->pvUser          = pvUser;
    12861287        if (fFlags & TMTIMER_FLAGS_DEFAULT_CRIT_SECT)
    1287             (*ppTimer)->pCritSect   = IOMR3GetCritSect(pVM);
     1288        {
     1289            if (pDevIns->pCritSectR3)
     1290                (*ppTimer)->pCritSect = pDevIns->pCritSectR3;
     1291            else
     1292                (*ppTimer)->pCritSect = IOMR3GetCritSect(pVM);
     1293        }
    12881294        Log(("TM: Created device timer %p clock %d callback %p '%s'\n", (*ppTimer), enmClock, pfnCallback, pszDesc));
    12891295    }
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r22890 r26944  
    3232#include <VBox/selm.h>
    3333#include <VBox/trpm.h>
     34#include <VBox/pdmdev.h>
    3435#include <VBox/pgm.h>
    3536#include <VBox/cpum.h>
     
    297298    {
    298299        /*
    299          * Found a range.
    300          */
     300         * Found a range, get the data in case we leave the IOM lock.
     301         */
     302        PFNIOMIOPORTIN  pfnInCallback = pRange->pfnInCallback;
    301303#ifndef IN_RING3
    302         if (!pRange->pfnInCallback)
    303         {
    304 # ifdef VBOX_WITH_STATISTICS
     304        if (!pfnInCallback)
     305        {
     306            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     307            iomUnlock(pVM);
     308            return VINF_IOM_HC_IOPORT_READ;
     309        }
     310#endif
     311        void           *pvUser    = pRange->pvUser;
     312        PPDMDEVINS      pDevIns   = pRange->pDevIns;
     313        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     314
     315        /*
     316         * Call the device - 4 variations.
     317         */
     318        VBOXSTRICTRC    rcStrict;
     319        if (pCritSect)
     320        {
     321            iomUnlock(pVM);
     322            rcStrict = PDMCritSectEnter(pCritSect, VINF_IOM_HC_IOPORT_READ);
     323            if (rcStrict != VINF_SUCCESS)
     324            {
     325                STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     326                return rcStrict;
     327            }
     328#ifdef VBOX_WITH_STATISTICS
    305329            if (pStats)
    306                 STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
    307 # endif
    308             iomUnlock(pVM);
    309             return VINF_IOM_HC_IOPORT_READ;
    310         }
    311 #endif
    312         /* call the device. */
    313 #ifdef VBOX_WITH_STATISTICS
    314         if (pStats)
    315             STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    316 #endif
    317         VBOXSTRICTRC rcStrict = pRange->pfnInCallback(pRange->pDevIns, pRange->pvUser, Port, pu32Value, (unsigned)cbValue);
    318 #ifdef VBOX_WITH_STATISTICS
    319         if (pStats)
    320             STAM_PROFILE_ADV_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     330            {
     331                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     332                rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
     333                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     334            }
     335            else
     336#endif
     337                rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
     338            PDMCritSectLeave(pCritSect);
     339        }
     340        else
     341        {
     342#ifdef VBOX_WITH_STATISTICS
     343            if (pStats)
     344            {
     345                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     346                rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
     347                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     348            }
     349            else
     350#endif
     351                rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
     352        }
     353#ifdef VBOX_WITH_STATISTICS
    321354        if (rcStrict == VINF_SUCCESS && pStats)
    322355            STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
    323356# ifndef IN_RING3
    324357        else if (rcStrict == VINF_IOM_HC_IOPORT_READ && pStats)
    325             STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
     358            STAM_COUNTER_INC(&pStats->InRZToR3);
    326359# endif
    327360#endif
     
    337370                default:
    338371                    AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port));
    339                     iomUnlock(pVM);
     372                    if (!pCritSect)
     373                        iomUnlock(pVM);
    340374                    return VERR_IOM_INVALID_IOPORT_SIZE;
    341375            }
    342376        }
    343377        Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=%Rrc\n", Port, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));
    344         iomUnlock(pVM);
     378        if (!pCritSect)
     379            iomUnlock(pVM);
    345380        return rcStrict;
    346381    }
     
    355390# ifdef VBOX_WITH_STATISTICS
    356391        if (pStats)
    357             STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
     392            STAM_COUNTER_INC(&pStats->InRZToR3);
    358393# endif
    359394        iomUnlock(pVM);
     
    458493         * Found a range.
    459494         */
     495        PFNIOMIOPORTINSTRING pfnInStrCallback = pRange->pfnInStrCallback;
    460496#ifndef IN_RING3
    461         if (!pRange->pfnInStrCallback)
    462         {
    463 # ifdef VBOX_WITH_STATISTICS
     497        if (!pfnInStrCallback)
     498        {
     499            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     500            iomUnlock(pVM);
     501            return VINF_IOM_HC_IOPORT_READ;
     502        }
     503#endif
     504        void           *pvUser    = pRange->pvUser;
     505        PPDMDEVINS      pDevIns   = pRange->pDevIns;
     506        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     507
     508        /*
     509         * Call the device - 4 variations.
     510         */
     511        VBOXSTRICTRC    rcStrict;
     512        if (pCritSect)
     513        {
     514            iomUnlock(pVM);
     515            rcStrict = PDMCritSectEnter(pCritSect, VINF_IOM_HC_IOPORT_READ);
     516            if (rcStrict != VINF_SUCCESS)
     517            {
     518                STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });
     519                return rcStrict;
     520            }
     521#ifdef VBOX_WITH_STATISTICS
    464522            if (pStats)
    465                 STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
    466 # endif
    467             iomUnlock(pVM);
    468             return VINF_IOM_HC_IOPORT_READ;
    469         }
    470 #endif
    471         /* call the device. */
    472 #ifdef VBOX_WITH_STATISTICS
    473         if (pStats)
    474             STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    475 #endif
    476 
    477         VBOXSTRICTRC rcStrict = pRange->pfnInStrCallback(pRange->pDevIns, pRange->pvUser, Port, pGCPtrDst, pcTransfers, cb);
    478 #ifdef VBOX_WITH_STATISTICS
    479         if (pStats)
    480             STAM_PROFILE_ADV_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     523            {
     524                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     525                rcStrict = pfnInStrCallback(pDevIns, pvUser, Port, pGCPtrDst, pcTransfers, cb);
     526                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     527            }
     528            else
     529#endif
     530                rcStrict = pfnInStrCallback(pDevIns, pvUser, Port, pGCPtrDst, pcTransfers, cb);
     531            PDMCritSectLeave(pCritSect);
     532        }
     533        else
     534        {
     535#ifdef VBOX_WITH_STATISTICS
     536            if (pStats)
     537            {
     538                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     539                rcStrict = pfnInStrCallback(pDevIns, pvUser, Port, pGCPtrDst, pcTransfers, cb);
     540                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     541            }
     542            else
     543#endif
     544                rcStrict = pfnInStrCallback(pDevIns, pvUser, Port, pGCPtrDst, pcTransfers, cb);
     545        }
     546
     547#ifdef VBOX_WITH_STATISTICS
    481548        if (rcStrict == VINF_SUCCESS && pStats)
    482549            STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
    483550# ifndef IN_RING3
    484551        else if (rcStrict == VINF_IOM_HC_IOPORT_READ && pStats)
    485             STAM_COUNTER_INC(&pStats->CTX_MID_Z(In, ToR3));
     552            STAM_COUNTER_INC(&pStats->InRZToR3);
    486553# endif
    487554#endif
    488555        Log3(("IOMIOPortReadStr: Port=%RTiop pGCPtrDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",
    489556              Port, pGCPtrDst, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
    490         iomUnlock(pVM);
     557        if (!pCritSect)
     558            iomUnlock(pVM);
    491559        return rcStrict;
    492560    }
     
    501569# ifdef VBOX_WITH_STATISTICS
    502570        if (pStats)
    503             STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
     571            STAM_COUNTER_INC(&pStats->InRZToR3);
    504572# endif
    505573        iomUnlock(pVM);
     
    592660         * Found a range.
    593661         */
     662        PFNIOMIOPORTOUT pfnOutCallback = pRange->pfnOutCallback;
    594663#ifndef IN_RING3
    595         if (!pRange->pfnOutCallback)
    596         {
    597 # ifdef VBOX_WITH_STATISTICS
     664        if (!pfnOutCallback)
     665        {
     666            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     667            iomUnlock(pVM);
     668            return VINF_IOM_HC_IOPORT_WRITE;
     669        }
     670#endif
     671        void           *pvUser    =  pRange->pvUser;
     672        PPDMDEVINS      pDevIns   = pRange->pDevIns;
     673        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     674
     675        /*
     676         * Call the device - 4 variations.
     677         */
     678        VBOXSTRICTRC    rcStrict;
     679        if (pCritSect)
     680        {
     681            iomUnlock(pVM);
     682            rcStrict = PDMCritSectEnter(pCritSect, VINF_IOM_HC_IOPORT_WRITE);
     683            if (rcStrict != VINF_SUCCESS)
     684            {
     685                STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     686                return rcStrict;
     687            }
     688#ifdef VBOX_WITH_STATISTICS
    598689            if (pStats)
    599                 STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
    600 # endif
    601             iomUnlock(pVM);
    602             return VINF_IOM_HC_IOPORT_WRITE;
    603         }
    604 #endif
    605         /* call the device. */
    606 #ifdef VBOX_WITH_STATISTICS
    607         if (pStats)
    608             STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfOut), a);
    609 #endif
    610         VBOXSTRICTRC rcStrict = pRange->pfnOutCallback(pRange->pDevIns, pRange->pvUser, Port, u32Value, (unsigned)cbValue);
    611 
    612 #ifdef VBOX_WITH_STATISTICS
    613         if (pStats)
    614             STAM_PROFILE_ADV_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     690            {
     691                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     692                rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
     693                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     694            }
     695            else
     696#endif
     697                rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
     698            PDMCritSectLeave(pCritSect);
     699        }
     700        else
     701        {
     702#ifdef VBOX_WITH_STATISTICS
     703            if (pStats)
     704            {
     705                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     706                rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
     707                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     708            }
     709            else
     710#endif
     711                rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
     712        }
     713
     714#ifdef VBOX_WITH_STATISTICS
    615715        if (rcStrict == VINF_SUCCESS && pStats)
    616716            STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
    617717# ifndef IN_RING3
    618718        else if (rcStrict == VINF_IOM_HC_IOPORT_WRITE && pStats)
    619             STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out, ToR3));
     719            STAM_COUNTER_INC(&pStats->OutRZToR3);
    620720# endif
    621721#endif
    622722        Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d rc=%Rrc\n", Port, u32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));
    623         iomUnlock(pVM);
     723        if (!pCritSect)
     724            iomUnlock(pVM);
    624725        return rcStrict;
    625726    }
     
    634735# ifdef VBOX_WITH_STATISTICS
    635736        if (pStats)
    636             STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
     737            STAM_COUNTER_INC(&pStats->OutRZToR3);
    637738# endif
    638739        iomUnlock(pVM);
     
    726827         * Found a range.
    727828         */
     829        PFNIOMIOPORTOUTSTRING   pfnOutStrCallback = pRange->pfnOutStrCallback;
    728830#ifndef IN_RING3
    729         if (!pRange->pfnOutStrCallback)
    730         {
    731 # ifdef VBOX_WITH_STATISTICS
     831        if (!pfnOutStrCallback)
     832        {
     833            STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     834            iomUnlock(pVM);
     835            return VINF_IOM_HC_IOPORT_WRITE;
     836        }
     837#endif
     838        void           *pvUser    = pRange->pvUser;
     839        PPDMDEVINS      pDevIns   = pRange->pDevIns;
     840        PPDMCRITSECT    pCritSect = pDevIns->CTX_SUFF(pCritSect);
     841
     842        /*
     843         * Call the device - 4 variations.
     844         */
     845        VBOXSTRICTRC    rcStrict;
     846        if (pCritSect)
     847        {
     848            iomUnlock(pVM);
     849            rcStrict = PDMCritSectEnter(pCritSect, VINF_IOM_HC_IOPORT_WRITE);
     850            if (rcStrict != VINF_SUCCESS)
     851            {
     852                STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });
     853                return rcStrict;
     854            }
     855#ifdef VBOX_WITH_STATISTICS
    732856            if (pStats)
    733                 STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
    734 # endif
    735             iomUnlock(pVM);
    736             return VINF_IOM_HC_IOPORT_WRITE;
    737         }
    738 #endif
    739         /* call the device. */
    740 #ifdef VBOX_WITH_STATISTICS
    741         if (pStats)
    742             STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfOut), a);
    743 #endif
    744         VBOXSTRICTRC rcStrict = pRange->pfnOutStrCallback(pRange->pDevIns, pRange->pvUser, Port, pGCPtrSrc, pcTransfers, cb);
    745 #ifdef VBOX_WITH_STATISTICS
    746         if (pStats)
    747             STAM_PROFILE_ADV_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     857            {
     858                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     859                rcStrict = pfnOutStrCallback(pDevIns, pvUser, Port, pGCPtrSrc, pcTransfers, cb);
     860                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     861            }
     862            else
     863#endif
     864                rcStrict = pfnOutStrCallback(pDevIns, pvUser, Port, pGCPtrSrc, pcTransfers, cb);
     865            PDMCritSectLeave(pCritSect);
     866        }
     867        else
     868        {
     869#ifdef VBOX_WITH_STATISTICS
     870            if (pStats)
     871            {
     872                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     873                rcStrict = pfnOutStrCallback(pDevIns, pvUser, Port, pGCPtrSrc, pcTransfers, cb);
     874                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     875            }
     876            else
     877#endif
     878                rcStrict = pfnOutStrCallback(pDevIns, pvUser, Port, pGCPtrSrc, pcTransfers, cb);
     879        }
     880
     881#ifdef VBOX_WITH_STATISTICS
    748882        if (rcStrict == VINF_SUCCESS && pStats)
    749883            STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
    750884# ifndef IN_RING3
    751885        else if (rcStrict == VINF_IOM_HC_IOPORT_WRITE && pStats)
    752             STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out, ToR3));
     886            STAM_COUNTER_INC(&pStats->OutRZToR3);
    753887# endif
    754888#endif
    755889        Log3(("IOMIOPortWriteStr: Port=%RTiop pGCPtrSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n",
    756890              Port, pGCPtrSrc, pcTransfers, cTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
    757         iomUnlock(pVM);
     891        if (!pCritSect)
     892            iomUnlock(pVM);
    758893        return rcStrict;
    759894    }
     
    768903# ifdef VBOX_WITH_STATISTICS
    769904        if (pStats)
    770             STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
     905            STAM_COUNTER_INC(&pStats->OutRZToR3);
    771906# endif
    772907        iomUnlock(pVM);
  • trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp

    r26272 r26944  
    4040#include <VBox/dis.h>
    4141#include <VBox/disopcode.h>
     42#include <VBox/pdmdev.h>
    4243#include <VBox/param.h>
    4344#include <VBox/err.h>
     
    461462            &&  (pMMIODst = iomMMIOGetRange(&pVM->iom.s, PhysDst)))
    462463        {
     464            /** @todo implement per-device locks for MMIO access. */
     465            Assert(!pMMIODst->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSect));
     466
    463467            /*
    464468             * Extra: [MMIO] -> [MMIO]
     
    971975{
    972976    /* Check for read & write handlers since IOMMMIOHandler doesn't cover this. */
    973     if (    (!pRange->CTX_SUFF(pfnReadCallback) && pRange->pfnReadCallbackR3)
     977    if (    (!pRange->CTX_SUFF(pfnReadCallback)  && pRange->pfnReadCallbackR3)
    974978        ||  (!pRange->CTX_SUFF(pfnWriteCallback) && pRange->pfnWriteCallbackR3))
    975979        return VINF_IOM_HC_MMIO_READ_WRITE;
     
    10561060    Assert(pRange);
    10571061    Assert(pRange == iomMMIOGetRange(&pVM->iom.s, GCPhysFault));
     1062    /** @todo implement per-device locks for MMIO access. It can replace the IOM
     1063     *        lock for most of the code, provided that we retake the lock while
     1064     *        deregistering PIOMMMIORANGE to deal with remapping/access races
     1065     *        (unlikely, but an SMP guest shouldn't cause us to crash). */
     1066    Assert(!pRange->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSect));
    10581067
    10591068#ifdef VBOX_WITH_STATISTICS
     
    13041313    Assert(pRange);
    13051314    Assert(pRange == iomMMIOGetRange(&pVM->iom.s, GCPhysFault));
     1315    /** @todo implement per-device locks for MMIO access. It can replace the IOM
     1316     *        lock for most of the code, provided that we retake the lock while
     1317     *        deregistering PIOMMMIORANGE to deal with remapping/access races
     1318     *        (unlikely, but an SMP guest shouldn't cause us to crash). */
     1319    Assert(!pRange->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSect));
    13061320
    13071321    if (enmAccessType == PGMACCESSTYPE_READ)
     
    13461360        return VERR_INTERNAL_ERROR;
    13471361    }
     1362    /** @todo implement per-device locks for MMIO access. */
     1363    Assert(!pRange->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSect));
    13481364#ifdef VBOX_WITH_STATISTICS
    13491365    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange);
     
    14671483        return VERR_INTERNAL_ERROR;
    14681484    }
     1485    /** @todo implement per-device locks for MMIO access. */
     1486    Assert(!pRange->CTX_SUFF(pDevIns)->CTX_SUFF(pCritSect));
    14691487#ifdef VBOX_WITH_STATISTICS
    14701488    PIOMMMIOSTATS pStats = iomMMIOGetStats(&pVM->iom.s, GCPhys, pRange);
     
    18861904    PIOMMMIORANGE pRange = iomMMIOGetRange(&pVM->iom.s, GCPhys);
    18871905    AssertMsgReturn(pRange,
    1888             ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
     1906                    ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
    18891907
    18901908    Assert((pRange->GCPhys       & PAGE_OFFSET_MASK) == 0);
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