VirtualBox

Changeset 77193 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 7, 2019 10:06:19 AM (6 years ago)
Author:
vboxsync
Message:

Devices/DevVGA-SVGA: make FIFO polling thread sleep when idle.
bugref:9376: Complete hardware cursor implementation in VMSVGA.
This change adds an access handler for VMSVGA FIFO accesses (the first page
only, which starts with lots of register-type locations before the actual
FIFO begins) which is enabled when we have not seen any activity on the FIFO
for one second or changes to the cursor location registers. This extends
the old polling on the FIFO with increasing intervals by switching to the
handler when the interval increase reaches a maximum. After a single access
intercept the handler is disabled again and the polling interval reset to
minimum. The code contains debug assertions intended to test that we really
do switch correctly in both ways at the right time.
The change also fixes two FIFO access tests to also check the cursor
registers. Testing was done with DEBUG_FIFO_ACCESS enabled as well, which
also creates a FIFO access handler, to ensure that the changes to not break
that mode.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp

    r77151 r77193  
    143143# include <iprt/ctype.h>
    144144# include <iprt/mem.h>
     145// # ifdef DEBUG
     146#  include <iprt/time.h>
     147// # endif
    145148#endif
    146149
     
    242245    /** Information obout screens. */
    243246    VMSVGASCREENOBJECT aScreens[64];
     247
     248// #ifdef DEBUG
     249    /** The time the access handler for the FIFO last triggered.  This should
     250     *  never happen less than a certain interval from the last access, and we
     251     *  assert this. */
     252    uint64_t                TimeLastFIFOIntercept;
     253// #endif
    244254
    245255    /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
     
    314324    STAMCOUNTER             StatFifoTodoWoken;
    315325    STAMPROFILE             StatFifoStalls;
     326    STAMCOUNTER             StatFifoAccessHandler;
    316327
    317328} VMSVGAR3STATE, *PVMSVGAR3STATE;
     
    323334*********************************************************************************************************************************/
    324335#ifdef IN_RING3
    325 # ifdef DEBUG_FIFO_ACCESS
    326336static FNPGMPHYSHANDLER vmsvgaR3FIFOAccessHandler;
    327 # endif
    328337# ifdef DEBUG_GMR_ACCESS
    329338static FNPGMPHYSHANDLER vmsvgaR3GMRAccessHandler;
     
    399408    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, hBusyDelayedEmts),
    400409#endif
     410// #ifdef DEBUG
     411    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, TimeLastFIFOIntercept),
     412// #endif
    401413    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatBusyDelayEmts),
    402414    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentProf),
     
    468480    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoTodoWoken),
    469481    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoStalls),
     482    SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoAccessHandler),
    470483    SSMFIELD_ENTRY_TERM()
    471484};
     
    19972010}
    19982011
    1999 #ifdef DEBUG_FIFO_ACCESS
    2000 
    2001 # ifdef IN_RING3
     2012#ifdef IN_RING3
     2013
     2014# ifdef DEBUG_FIFO_ACCESS
    20022015/**
    20032016 * Handle FIFO memory access.
     
    20082021 * @param   fWriteAccess    Read or write access
    20092022 */
    2010 static int vmsvgaFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
     2023static int vmsvgaDebugFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
    20112024{
    20122025    RT_NOREF(pVM);
     
    23382351    return VINF_EM_RAW_EMULATE_INSTR;
    23392352}
     2353
     2354# endif /* DEBUG_FIFO_ACCESS */
    23402355
    23412356/**
     
    23642379    NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin);
    23652380
    2366     rc = vmsvgaFIFOAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
     2381    SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
     2382# ifdef DEBUG_FIFO_ACCESS
     2383    rc = vmsvgaDebugFIFOAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
     2384# else
     2385    NOREF(enmAccessType);
     2386// #  ifdef DEBUG
     2387    /* Invariant: the access handler should never trigger twice within a certain
     2388     * time span; calling it 500ms here for simplicity. */
     2389    uint64_t TimeNow = RTTimeMilliTS();
     2390    Assert(TimeNow - pThis->svga.pSvgaR3State->TimeLastFIFOIntercept > 500);
     2391    pThis->svga.pSvgaR3State->TimeLastFIFOIntercept = TimeNow;
     2392// #  endif
     2393    STAM_REL_COUNTER_INC(&pThis->svga.pSvgaR3State->StatFifoAccessHandler);
     2394    rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO);
     2395# endif
    23672396    if (RT_SUCCESS(rc))
    23682397        return VINF_PGM_HANDLER_DO_DEFAULT;
     
    23712400}
    23722401
    2373 # endif /* IN_RING3 */
    2374 #endif /* DEBUG_FIFO_ACCESS */
     2402#endif /* IN_RING3 */
    23752403
    23762404#ifdef DEBUG_GMR_ACCESS
     
    32143242}
    32153243
     3244static bool vmsvgaFIFOHasWork(uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO,
     3245                              uint32_t cCursorCount)
     3246{
     3247    return    pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP]
     3248           || cCursorCount != pFIFO[SVGA_FIFO_CURSOR_COUNT];
     3249}
     3250
    32163251/* The async FIFO handling thread. */
    32173252static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     
    32593294     * We wait for an a short interval if the guest has recently given us work
    32603295     * to do, but the interval increases the longer we're kept idle.  With the
    3261      * current parameters we'll be at a 64ms poll interval after 1 idle second,
    3262      * at 90ms after 2 seconds, and reach the max 250ms interval after about
    3263      * 16 seconds.
     3296     * current parameters we'll be at a 66ms poll interval after 1 idle second.
     3297     * When we reach the maximum we switch to intercepting accesses and after
     3298     * one intercept we restart polling at minimum.
    32643299     */
    32653300    RTMSINTERVAL const  cMsMinSleep = 16;
    32663301    RTMSINTERVAL const  cMsIncSleep = 2;
    3267     RTMSINTERVAL const  cMsMaxSleep = 250;
     3302    RTMSINTERVAL const  cMsMaxSleep = 66;
    32683303    RTMSINTERVAL        cMsSleep    = cMsMaxSleep;
    32693304
     
    32963331         * (See polling/sleep interval config above.)
    32973332         */
    3298         if (   fBadOrDisabledFifo
    3299             || pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
    3300         {
    3301             rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, cMsSleep);
     3333        if (fBadOrDisabledFifo || !vmsvgaFIFOHasWork(pFIFO, cCursorCount))
     3334        {
     3335            if (cMsSleep >= cMsMaxSleep && pThis->svga.GCPhysFIFO)
     3336            {
     3337                rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
     3338                AssertBreak(RT_SUCCESS(rc));
     3339                rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, RT_INDEFINITE_WAIT);
     3340            }
     3341            else
     3342                rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, cMsSleep);
    33023343            AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
    33033344            if (pThread->enmState != PDMTHREADSTATE_RUNNING)
     
    33123353        if (rc == VERR_TIMEOUT)
    33133354        {
    3314             if (   pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP]
    3315                 && cCursorCount == pFIFO[SVGA_FIFO_CURSOR_COUNT])
     3355            /* Invariant: we should never have been doing a timed wait if the
     3356             * interval is already at maximum.  Instead we should have been
     3357             * intercepting accesses. */
     3358            Assert(cMsSleep < cMsMaxSleep);
     3359            if (!vmsvgaFIFOHasWork(pFIFO, cCursorCount))
    33163360            {
    33173361                cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
     
    33223366            Log(("vmsvgaFIFOLoop: timeout\n"));
    33233367        }
    3324         else if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
     3368        else if (vmsvgaFIFOHasWork(pFIFO, cCursorCount))
    33253369            STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
    33263370        cMsSleep = cMsMinSleep;
     
    50995143            AssertRC(rc);
    51005144
    5101 # ifdef DEBUG_FIFO_ACCESS
    51025145            if (RT_SUCCESS(rc))
    51035146            {
    5104                 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress, GCPhysAddress + (pThis->svga.cbFIFO - 1),
     5147                rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress,
     5148#ifdef DEBUG_FIFO_ACCESS
     5149                                                GCPhysAddress + (pThis->svga.cbFIFO - 1),
     5150#else
     5151                                                GCPhysAddress + PAGE_SIZE - 1,
     5152#endif
    51055153                                                pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
    51065154                                                "VMSVGA FIFO");
    51075155                AssertRC(rc);
    51085156            }
    5109 # endif
    51105157            if (RT_SUCCESS(rc))
    51115158            {
     
    51175164        {
    51185165            Assert(pThis->svga.GCPhysFIFO);
    5119 # ifdef DEBUG_FIFO_ACCESS
    51205166            rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
    51215167            AssertRC(rc);
    5122 # endif
    51235168            pThis->svga.GCPhysFIFO = 0;
    51245169        }
     
    58245869    AssertRCReturn(rc, rc);
    58255870# endif
     5871    rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
    58265872# ifdef DEBUG_FIFO_ACCESS
    5827     rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_ALL,
     5873PGMPHYSHANDLERKIND_ALL,
     5874#else
     5875PGMPHYSHANDLERKIND_WRITE,
     5876#endif
    58285877                                          vmsvgaR3FIFOAccessHandler,
    58295878                                          NULL, NULL, NULL,
     
    58315880                                          "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
    58325881    AssertRCReturn(rc, rc);
    5833 #endif
    58345882
    58355883    /* Create the async IO thread. */
     
    59926040    STAM_REL_REG(pVM, &pSVGAState->StatFifoTodoWoken,   STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoTodoWoken",  STAMUNIT_OCCURENCES, "Number of times we discovered pending work after being woken up.");
    59936041    STAM_REL_REG(pVM, &pSVGAState->StatFifoStalls,      STAMTYPE_PROFILE, "/Devices/VMSVGA/FifoStalls",  STAMUNIT_TICKS_PER_CALL, "Profiling of FIFO stalls (waiting for guest to finish copying data).");
     6042    STAM_REL_REG(pVM, &pSVGAState->StatFifoAccessHandler, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoAccessHandler",  STAMUNIT_OCCURENCES, "Number of times the FIFO access handler triggered.");
    59946043
    59956044    /*
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h

    r76565 r77193  
    259259     * thread and does not want it do anything but the command. */
    260260    bool volatile               fFifoExtCommandWakeup;
    261 #if defined(DEBUG_GMR_ACCESS) || defined(DEBUG_FIFO_ACCESS)
     261// #if defined(DEBUG_GMR_ACCESS)  /* Needed for alignment. */
    262262    /** GMR debug access handler type handle. */
    263263    PGMPHYSHANDLERTYPE          hGmrAccessHandlerType;
     264// #endif
    264265    /** FIFO debug access handler type handle. */
    265266    PGMPHYSHANDLERTYPE          hFifoAccessHandlerType;
    266 #endif
    267267    /** Number of GMRs. */
    268268    uint32_t                    cGMR;
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