VirtualBox

Changeset 90503 in vbox for trunk/src/VBox/Devices/VMMDev


Ignore:
Timestamp:
Aug 3, 2021 9:22:13 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
146107
Message:

VMMDevTesting,bs3-locking-1: Expanded the locking test port to two ports, incorporating read/write CS and a EMT hold interval. bugref:6695

Location:
trunk/src/VBox/Devices/VMMDev
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r90467 r90503  
    261261    uint32_t            StatMemBalloonChunks;
    262262
    263     /** @name Testing
    264      * @{ */
    265     /** Set if testing is enabled. */
    266     bool                fTestingEnabled;
    267     /** Set if testing the MMIO testing range is enabled. */
    268     bool                fTestingMMIO;
    269     /** Alignment padding. */
    270     bool                afPadding9[HC_ARCH_BITS == 32 ? 2 : 6];
    271 #if !defined(VBOX_WITHOUT_TESTING_FEATURES) || defined(DOXYGEN_RUNNING)
    272     /** The high timestamp value. */
    273     uint32_t            u32TestingHighTimestamp;
    274     /** The current testing command (VMMDEV_TESTING_CMD_XXX). */
    275     uint32_t            u32TestingCmd;
    276     /** The testing data offset (command specific). */
    277     uint32_t            offTestingData;
    278     /** For buffering the what comes in over the testing data port. */
    279     union
    280     {
    281         char            padding[1024];
    282 
    283         /** VMMDEV_TESTING_CMD_INIT, VMMDEV_TESTING_CMD_SUB_NEW,
    284          *  VMMDEV_TESTING_CMD_FAILED. */
    285         struct
    286         {
    287             char        sz[1024];
    288         } String, Init, SubNew, Failed;
    289 
    290         /** VMMDEV_TESTING_CMD_TERM, VMMDEV_TESTING_CMD_SUB_DONE. */
    291         struct
    292         {
    293             uint32_t    c;
    294         } Error, Term, SubDone;
    295 
    296         /** VMMDEV_TESTING_CMD_VALUE. */
    297         struct
    298         {
    299             RTUINT64U   u64Value;
    300             uint32_t    u32Unit;
    301             char        szName[1024 - 8 - 4];
    302         } Value;
    303 
    304         /** The read back register (VMMDEV_TESTING_MMIO_OFF_READBACK,
    305          *  VMMDEV_TESTING_MMIO_OFF_READBACK_R3). */
    306         uint8_t         abReadBack[VMMDEV_TESTING_READBACK_SIZE];
    307     } TestingData;
    308     /** The locking testing control dword. */
    309     union
    310     {
    311         /** Plain view. */
    312         uint32_t        u32;
    313         struct
    314         {
    315             /** Number of microseconds to hold the lock. Zero means disabled. */
    316             uint32_t    cUsHold : 14;
    317             /** Number of microseconds to wait before retaking the lock again. */
    318             uint32_t    cUsBetween : 14;
    319             /** Reserved MBZ. */
    320             uint32_t    uReserved : 2;
    321             /** Pass VINF_SUCCESS as rcBusy if set. */
    322             uint32_t    fMustSucceed : 1;
    323             /** Whether to poke EMTs before releasing it. */
    324             uint32_t    fPokeBeforeRelease : 1;
    325         } s;
    326     } TestingLockControl;
    327     /** Alignment padding.  */
    328     uint32_t            uPadding10;
    329     /** Event semaphore that the locking thread blocks. */
    330     SUPSEMEVENT         hTestingLockEvt;
    331     /** Handle for the I/O ports used by the testing component. */
    332     IOMIOPORTHANDLE     hIoPortTesting;
    333     /** Handle for the MMIO region used by the testing component. */
    334     IOMMMIOHANDLE       hMmioTesting;
    335 #endif /* !VBOX_WITHOUT_TESTING_FEATURES || DOXYGEN_RUNNING */
    336     /** @} */
    337 
    338263    /** @name Heartbeat
    339264     * @{ */
     
    354279    /** Timer for signalling a flatlined guest. */
    355280    TMTIMERHANDLE       hFlatlinedTimer;
     281    /** @} */
     282
     283    /** @name Testing
     284     * @{ */
     285    /** Set if testing is enabled. */
     286    bool                fTestingEnabled;
     287    /** Set if testing the MMIO testing range is enabled. */
     288    bool                fTestingMMIO;
     289    /** Alignment padding. */
     290    bool                afPadding9[2];
     291#if !defined(VBOX_WITHOUT_TESTING_FEATURES) || defined(DOXYGEN_RUNNING)
     292    /** The high timestamp value. */
     293    uint32_t            u32TestingHighTimestamp;
     294    /** The current testing command (VMMDEV_TESTING_CMD_XXX). */
     295    uint32_t            u32TestingCmd;
     296    /** The testing data offset (command specific). */
     297    uint32_t            offTestingData;
     298    /** For buffering the what comes in over the testing data port. */
     299    union
     300    {
     301        char            padding[1024];
     302
     303        /** VMMDEV_TESTING_CMD_INIT, VMMDEV_TESTING_CMD_SUB_NEW,
     304         *  VMMDEV_TESTING_CMD_FAILED. */
     305        struct
     306        {
     307            char        sz[1024];
     308        } String, Init, SubNew, Failed;
     309
     310        /** VMMDEV_TESTING_CMD_TERM, VMMDEV_TESTING_CMD_SUB_DONE. */
     311        struct
     312        {
     313            uint32_t    c;
     314        } Error, Term, SubDone;
     315
     316        /** VMMDEV_TESTING_CMD_VALUE. */
     317        struct
     318        {
     319            RTUINT64U   u64Value;
     320            uint32_t    u32Unit;
     321            char        szName[1024 - 8 - 4];
     322        } Value;
     323
     324        /** The read back register (VMMDEV_TESTING_MMIO_OFF_READBACK,
     325         *  VMMDEV_TESTING_MMIO_OFF_READBACK_R3). */
     326        uint8_t         abReadBack[VMMDEV_TESTING_READBACK_SIZE];
     327    } TestingData;
     328    /** The locking testing control dword. */
     329    union
     330    {
     331        /** Plain view. */
     332        uint64_t        u64;
     333        /** Plain 32-bit view. */
     334        uint32_t        au32[2];
     335        struct
     336        {
     337            /** bits 15:0: Number of microseconds to hold the lock. */
     338            uint32_t    cUsHold : 16;
     339            /** bits 31:16: Number of microseconds to wait before retaking the lock again. */
     340            uint32_t    cUsBetween : 16;
     341            /** bits 51:32: Kilo (1024) ticks the EMT should hold the lock for. */
     342            uint32_t    cKiloTicksEmtHold : 20;
     343            /** bits 57:52: Reserved MBZ. */
     344            uint32_t    uReserved : 6;
     345            /** bit 58: Thread takes lock in shared mode when set, exclusive when clear.  */
     346            uint32_t    fThreadShared : 1;
     347            /** bit 59: EMT takes lock in shared mode when set, exclusive when clear.  */
     348            uint32_t    fEmtShared : 1;
     349            /** bit 60: Use read/write critical section instead of regular.  */
     350            uint32_t    fReadWriteSection : 1;
     351            /** bit 61: EMT passes VINF_SUCCESS as rcBusy if set. */
     352            uint32_t    fMustSucceed : 1;
     353            /** bit 62: Thread pokes EMTs before releasing it when set. */
     354            uint32_t    fPokeBeforeRelease : 1;
     355            /** bit 63: Enabled/disabled. */
     356            uint32_t    fEnabled : 1;
     357        } s;
     358    } TestingLockControl;
     359    /** Event semaphore that the locking thread blocks. */
     360    SUPSEMEVENT         hTestingLockEvt;
     361# if HC_ARCH_BITS == 32
     362    uint32_t            uPadding10;
     363# endif
     364    /** Handle for the I/O ports used by the testing component. */
     365    IOMIOPORTHANDLE     hIoPortTesting;
     366    /** Handle for the MMIO region used by the testing component. */
     367    IOMMMIOHANDLE       hMmioTesting;
     368    /** Read write critical section of lock testing. */
     369    PDMCRITSECTRW       CritSectRw;
     370#endif /* !VBOX_WITHOUT_TESTING_FEATURES || DOXYGEN_RUNNING */
    356371    /** @} */
    357372
  • trunk/src/VBox/Devices/VMMDev/VMMDevTesting.cpp

    r90467 r90503  
    3838# include <VBox/vmm/vmcc.h>
    3939#endif
     40#include <VBox/AssertGuest.h>
    4041
    4142#include "VMMDevState.h"
     
    592593         * Configure the locking contention test.
    593594         */
    594         case VMMDEV_TESTING_IOPORT_LOCKED - VMMDEV_TESTING_IOPORT_BASE:
     595        case VMMDEV_TESTING_IOPORT_LOCKED_HI - VMMDEV_TESTING_IOPORT_BASE:
     596        case VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE:
    595597            switch (cb)
    596598            {
    597599                case 4:
     600                {
     601                    bool const  fReadWriteSection = pThis->TestingLockControl.s.fReadWriteSection;
     602                    int         rc;
     603#ifndef IN_RING3
     604                    if (!pThis->TestingLockControl.s.fMustSucceed)
     605                    {
     606                        if (!fReadWriteSection)
     607                            rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE);
     608                        else
     609                            rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_IOM_R3_IOPORT_WRITE);
     610                        if (rc != VINF_SUCCESS)
     611                            return rc;
     612                    }
     613                    else
     614#endif
     615                    {
     616                        if (!fReadWriteSection)
     617                            rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS);
     618                        else
     619                            rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_SUCCESS);
     620                        AssertRCReturn(rc, rc);
     621                    }
     622
     623                    if (offPort == VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE)
     624                    {
     625                        if (pThis->TestingLockControl.au32[0] != u32)
     626                        {
     627                            pThis->TestingLockControl.au32[0] = u32;
     628                            PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTestingLockEvt);
     629                        }
     630                    }
     631                    else
     632                    {
     633                        u32 &= ~VMMDEV_TESTING_LOCKED_HI_MBZ_MASK;
     634                        if (pThis->TestingLockControl.au32[1] != u32)
     635                        {
     636                            pThis->TestingLockControl.au32[1] = u32;
     637                            PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTestingLockEvt);
     638                        }
     639                    }
     640
     641                    if (!fReadWriteSection)
     642                        PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
     643                    else
     644                        PDMDevHlpCritSectRwLeaveExcl(pDevIns, &pThis->CritSectRw);
     645                    return VINF_SUCCESS;
     646                }
     647
    598648                case 2:
    599649                case 1:
    600                 {
    601 #ifndef IN_RING3
    602                     if (!pThis->TestingLockControl.s.fMustSucceed)
    603                     {
    604                         int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE);
    605                         if (rc != VINF_SUCCESS)
    606                             return rc;
    607                     }
    608                     else
    609 #endif
    610                     {
    611                         int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS);
    612                         AssertRCReturn(rc, rc);
    613                     }
    614 
    615                     u32 &= ~VMMDEV_TESTING_LOCKED_MBZ_MASK;
    616                     if (pThis->TestingLockControl.u32 != u32)
    617                     {
    618                         pThis->TestingLockControl.u32 = u32;
    619                         PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTestingLockEvt);
    620                     }
    621 
    622                     PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
    623                     return VINF_SUCCESS;
    624                 }
     650                    ASSERT_GUEST_FAILED();
     651                    break;
    625652
    626653                default:
     
    711738         * acquiring the lock of course.
    712739         */
    713         case VMMDEV_TESTING_IOPORT_LOCKED - VMMDEV_TESTING_IOPORT_BASE:
     740        case VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE:
     741        case VMMDEV_TESTING_IOPORT_LOCKED_HI - VMMDEV_TESTING_IOPORT_BASE:
    714742            switch (cb)
    715743            {
     
    718746                case 1:
    719747                {
     748                    /*
     749                     * Check configuration and enter the designation critical
     750                     * section in the specific fashion.
     751                     */
     752                    bool const  fReadWriteSection = pThis->TestingLockControl.s.fReadWriteSection;
     753                    bool const  fEmtShared        = pThis->TestingLockControl.s.fEmtShared;
     754                    int         rc;
    720755#ifndef IN_RING3
    721756                    if (!pThis->TestingLockControl.s.fMustSucceed)
    722757                    {
    723                         int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_READ);
     758                        if (!fReadWriteSection)
     759                            rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_READ);
     760                        else if (!fEmtShared)
     761                            rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_IOM_R3_IOPORT_READ);
     762                        else
     763                            rc = PDMDevHlpCritSectRwEnterShared(pDevIns, &pThis->CritSectRw, VINF_IOM_R3_IOPORT_READ);
    724764                        if (rc != VINF_SUCCESS)
    725765                            return rc;
     
    728768#endif
    729769                    {
    730                         int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS);
     770                        if (!fReadWriteSection)
     771                            rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS);
     772                        else if (!fEmtShared)
     773                            rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_SUCCESS);
     774                        else
     775                            rc = PDMDevHlpCritSectRwEnterShared(pDevIns, &pThis->CritSectRw, VINF_SUCCESS);
    731776                        AssertRCReturn(rc, rc);
    732777                    }
    733778
    734                     *pu32 = pThis->TestingLockControl.u32;
    735 
    736                     PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
     779                    /*
     780                     * Grab return value and, if requested, hold for a while.
     781                     */
     782                    *pu32 = pThis->TestingLockControl.au32[  offPort
     783                                                           - (VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE)];
     784                    uint64_t cTicks = (uint64_t)pThis->TestingLockControl.s.cKiloTicksEmtHold * _1K;
     785                    if (cTicks)
     786                    {
     787                        uint64_t const uStartTick = ASMReadTSC();
     788                        do
     789                        {
     790                            ASMNopPause();
     791                            ASMNopPause();
     792                        } while (ASMReadTSC() - uStartTick < cTicks);
     793                    }
     794
     795                    /*
     796                     * Leave.
     797                     */
     798                    if (!fReadWriteSection)
     799                        PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
     800                    else if (!fEmtShared)
     801                        PDMDevHlpCritSectRwLeaveExcl(pDevIns, &pThis->CritSectRw);
     802                    else
     803                        PDMDevHlpCritSectRwLeaveShared(pDevIns, &pThis->CritSectRw);
    737804                    return VINF_SUCCESS;
    738805                }
     
    868935    }
    869936
    870 
    871937    /*
    872938     * Register the I/O ports used for testing.
     
    875941                                     vmmdevTestingIoWrite, vmmdevTestingIoRead, "VMMDev Testing", NULL /*paExtDescs*/,
    876942                                     &pThis->hIoPortTesting);
     943    AssertRCReturn(rc, rc);
     944
     945    /*
     946     * Initialize the read/write critical section used for the locking tests.
     947     */
     948    rc = PDMDevHlpCritSectRwInit(pDevIns, &pThis->CritSectRw, RT_SRC_POS, "VMMLockRW");
    877949    AssertRCReturn(rc, rc);
    878950
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