VirtualBox

Changeset 88627 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 21, 2021 10:27:13 AM (4 years ago)
Author:
vboxsync
Message:

Intel IOMMU: bugref:9967 Queued Invalidation WIP.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp

    r88625 r88627  
    111111
    112112/** DMAR implementation's major version number (exposed to software).
    113  *  We report 6 as the major version since we support queued invalidations as
     113 *  We report 6 as the major version since we support queued-invalidations as
    114114 *  software may make assumptions based on that.
    115115 *
     
    171171    /** The MMIO handle. */
    172172    IOMMMIOHANDLE               hMmio;
    173     /** The event semaphore the queued-invalidation thread waits on. */
    174     SUPSEMEVENT                 hEvtQueuedInvThread;
    175     /** Whether the queued-invalidation thread has been signaled. */
    176     bool volatile               fQueuedInvThreadSignaled;
     173    /** The event semaphore the invalidation-queue thread waits on. */
     174    SUPSEMEVENT                 hEvtInvQueue;
     175    /** Whether the invalidation-queue thread has been signaled. */
     176    bool volatile               fInvQueueThreadSignaled;
    177177    /** Padding. */
    178178    bool                        afPadding0[3];
     
    233233    /** The IOMMU helper. */
    234234    R3PTRTYPE(PCPDMIOMMUHLPR3)  pIommuHlpR3;
    235     /** The queued-invalidation thread. */
    236     R3PTRTYPE(PPDMTHREAD)       pQueuedInvThread;
     235    /** The invalidation-queue thread. */
     236    R3PTRTYPE(PPDMTHREAD)       pInvQueueThread;
    237237} DMARR3;
    238238/** Pointer to the ring-3 DMAR device state. */
     
    851851
    852852/**
     853 * Checks whether the invalidation-queue is empty.
     854 *
     855 * @returns @c true if empty, @c false otherwise.
     856 * @param   pThis   The shared DMAR device state.
     857 */
     858static bool dmarInvQueueIsEmpty(PCDMAR pThis)
     859{
     860    uint64_t const uIqtReg      = dmarRegRead64(pThis, VTD_MMIO_OFF_IQT_REG);
     861    uint32_t const offQueueTail = VTD_IQT_REG_GET_QT(uIqtReg);
     862
     863    uint64_t const uIqhReg      = dmarRegRead64(pThis, VTD_MMIO_OFF_IQH_REG);
     864    uint32_t const offQueueHead = VTD_IQT_REG_GET_QH(uIqhReg);
     865
     866    return offQueueTail == offQueueHead;
     867}
     868
     869
     870/**
     871 * Checks whether the invalidation-queue is capable of processing requests.
     872 *
     873 * @returns @c true if the invalidation-queue can be processed, @c false otherwise.
     874 * @param   pThis   The shared DMAR device state.
     875 */
     876static bool dmarInvQueueCanProcessRequests(PCDMAR pThis)
     877{
     878    /* Check if queued-invalidation is enabled. */
     879    uint32_t const uGstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG);
     880    if (uGstsReg & VTD_BF_GSTS_REG_QIES_MASK)
     881    {
     882        /* Check if there are no IQ errors and that the queue isn't empty. */
     883        uint32_t const uFstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_FSTS_REG);
     884        if (   !(uFstsReg & VTD_BF_FSTS_REG_IQE_MASK)
     885            && !dmarInvQueueIsEmpty(pThis))
     886            return true;
     887    }
     888    return false;
     889}
     890
     891
     892/**
     893 * Wakes up the invalidation-queue thread if there are requests to be processed.
     894 *
     895 * @param   pDevIns     The IOMMU device instance.
     896 */
     897static void dmarInvQueueThreadWakeUpIfNeeded(PPDMDEVINS pDevIns)
     898{
     899    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     900    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
     901    Log4Func(("\n"));
     902
     903    DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC);
     904
     905    if (   dmarInvQueueCanProcessRequests(pThis)
     906        && !ASMAtomicXchgBool(&pThis->fInvQueueThreadSignaled, true))
     907    {
     908        Log4Func(("Signaling the invalidation-queue thread\n"));
     909        PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtInvQueue);
     910    }
     911}
     912
     913
     914/**
    853915 * Raises an interrupt in response to an event.
    854916 *
     
    10231085        if (   fDw != VTD_IQA_REG_DW_256_BIT
    10241086            || !(offQueueTail & 0x1f))
    1025         {
    1026             /* Don't bother waking the thread if an invalidation-queue error is pending. */
    1027             uint32_t const uFstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_FSTS_REG);
    1028             if (!(uFstsReg & VTD_BF_FSTS_REG_IQE_MASK))
    1029             {
    1030                 /** @todo Figure out what to do here, like waking up worker thread or
    1031                  *        something. */
    1032             }
    1033         }
     1087            dmarInvQueueThreadWakeUpIfNeeded(pDevIns);
    10341088        else
    10351089            dmarIqeFaultRecord(pDevIns, kDmarDiag_IqtReg_Qt_NotAligned, kQueueTailNotAligned);
     
    12171271#ifdef IN_RING3
    12181272/**
    1219  * The queued-invalidation thread function.
     1273 * The invalidation-queue thread.
    12201274 *
    12211275 * @returns VBox status code.
     
    12231277 * @param   pThread     The command thread.
    12241278 */
    1225 static DECLCALLBACK(int) dmarR3QueuedInvThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1279static DECLCALLBACK(int) dmarR3InvQueueThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    12261280{
    12271281    NOREF(pThread);
     
    12391293         * Sleep until we are woken up.
    12401294         */
    1241         bool const fSignaled = ASMAtomicXchgBool(&pThis->fQueuedInvThreadSignaled, false);
     1295        bool const fSignaled = ASMAtomicXchgBool(&pThis->fInvQueueThreadSignaled, false);
    12421296        if (!fSignaled)
    12431297        {
    1244             int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtQueuedInvThread, RT_INDEFINITE_WAIT);
     1298            int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtInvQueue, RT_INDEFINITE_WAIT);
    12451299            AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
    12461300            if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
    12471301                break;
    1248             ASMAtomicWriteBool(&pThis->fQueuedInvThreadSignaled, false);
     1302            ASMAtomicWriteBool(&pThis->fInvQueueThreadSignaled, false);
    12491303        }
    12501304
    12511305        /*
    1252          * Fetch and process queued-invalidation requests.
     1306         * Fetch and process invalidation requests.
    12531307         */
    12541308        DMAR_LOCK_RET(pDevIns, pThisR3, VERR_IGNORED);
     
    12621316    }
    12631317
    1264     LogFlowFunc(("Queued-invalidation thread terminating\n"));
     1318    LogFlowFunc(("Invalidation-queue thread terminating\n"));
    12651319    return VINF_SUCCESS;
    12661320}
     
    12681322
    12691323/**
    1270  * Wakes up the queued-invalidation thread so it can respond to a state change.
     1324 * Wakes up the invalidation-queue thread so it can respond to a state
     1325 * change.
    12711326 *
    12721327 * @returns VBox status code.
    12731328 * @param   pDevIns     The IOMMU device instance.
    1274  * @param   pThread     The queued-invalidation thread.
     1329 * @param   pThread     The invalidation-queue thread.
    12751330 *
    12761331 * @thread EMT.
    12771332 */
    1278 static DECLCALLBACK(int) dmarR3QueuedInvThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1333static DECLCALLBACK(int) dmarR3InvQueueThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    12791334{
    12801335    RT_NOREF(pThread);
    12811336    LogFlowFunc(("\n"));
    12821337    PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    1283     return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtQueuedInvThread);
     1338    return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtInvQueue);
    12841339}
    12851340
     
    13791434    /* ECAP_REG */
    13801435    {
    1381         uint8_t const  fQi    = 1;                              /* Queued invalidations. */
     1436        uint8_t const  fQi    = 1;                              /* Queued-invalidations. */
    13821437        uint8_t const  fIr    = !!(DMAR_ACPI_DMAR_FLAGS & ACPI_DMAR_F_INTR_REMAP);  /* Interrupt remapping support. */
    13831438        uint8_t const  fMhmv  = 0xf;                            /* Maximum handle mask value. */
     
    14611516    LogFlowFunc(("\n"));
    14621517
    1463     if (pThis->hEvtQueuedInvThread != NIL_SUPSEMEVENT)
    1464     {
    1465         PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtQueuedInvThread);
    1466         pThis->hEvtQueuedInvThread = NIL_SUPSEMEVENT;
     1518    if (pThis->hEvtInvQueue != NIL_SUPSEMEVENT)
     1519    {
     1520        PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtInvQueue);
     1521        pThis->hEvtInvQueue = NIL_SUPSEMEVENT;
    14671522    }
    14681523
     
    15951650
    15961651    /*
    1597      * Create queued-invalidation thread and semaphore.
     1652     * Create invalidation-queue thread and semaphore.
    15981653     */
    1599     char szQueuedInvThread[32];
    1600     RT_ZERO(szQueuedInvThread);
    1601     RTStrPrintf(szQueuedInvThread, sizeof(szQueuedInvThread), "IOMMU-QI-%u", iInstance);
    1602     rc = PDMDevHlpThreadCreate(pDevIns, &pThisR3->pQueuedInvThread, pThis, dmarR3QueuedInvThread, dmarR3QueuedInvThreadWakeUp,
    1603                                0 /* cbStack */, RTTHREADTYPE_IO, szQueuedInvThread);
     1654    char szInvQueueThread[32];
     1655    RT_ZERO(szInvQueueThread);
     1656    RTStrPrintf(szInvQueueThread, sizeof(szInvQueueThread), "IOMMU-QI-%u", iInstance);
     1657    rc = PDMDevHlpThreadCreate(pDevIns, &pThisR3->pInvQueueThread, pThis, dmarR3InvQueueThread, dmarR3InvQueueThreadWakeUp,
     1658                               0 /* cbStack */, RTTHREADTYPE_IO, szInvQueueThread);
    16041659    AssertLogRelRCReturn(rc, rc);
    16051660
    1606     rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtQueuedInvThread);
     1661    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtInvQueue);
    16071662    AssertLogRelRCReturn(rc, rc);
    16081663
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