VirtualBox

Changeset 88625 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 21, 2021 8:09:20 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

    r88623 r88625  
    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;
     177    /** Padding. */
     178    bool                        afPadding0[3];
     179    /** Error diagnostic. */
     180    DMARDIAG                    enmDiag;
    173181
    174182    /** Registers (group 0). */
     
    182190    uint8_t                     uVerReg;
    183191    /** Alignment. */
    184     uint8_t                     abPadding[3];
    185     /** Error diagnostic. */
    186     DMARDIAG                    enmDiag;
     192    uint8_t                     abPadding[7];
    187193    /** Copy of CAP_REG. */
    188194    uint64_t                    fCap;
     
    215221/** Pointer to the const DMAR device state. */
    216222typedef DMAR const *PCDMAR;
     223AssertCompileMemberAlignment(DMAR, abRegs0, 8);
     224AssertCompileMemberAlignment(DMAR, abRegs1, 8);
    217225
    218226/**
     
    225233    /** The IOMMU helper. */
    226234    R3PTRTYPE(PCPDMIOMMUHLPR3)  pIommuHlpR3;
     235    /** The queued-invalidation thread. */
     236    R3PTRTYPE(PPDMTHREAD)       pQueuedInvThread;
    227237} DMARR3;
    228238/** Pointer to the ring-3 DMAR device state. */
     
    514524
    515525#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     526/** @todo Add IOMMU struct size/alignment verification, see
     527 *        Devices/testcase/Makefile.kmk and
     528 *        Devices/testcase/tstDeviceStructSize[RC].cpp  */
     529
    516530/**
    517531 * Gets the number of supported adjusted guest-address width (SAGAW) in bits given a
     
    10011015    if (off == VTD_MMIO_OFF_IQT_REG)
    10021016    {
    1003         /* Verify if the queue tail offset is aligned according to the descriptor width in IQA_REG. */
    10041017        PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    1005         uint16_t const offQueueTail = VTD_IQT_REG_GET_QT(uIqtReg);
     1018
     1019        /* Verify if the queue tail offset is aligned according to the descriptor width. */
     1020        uint32_t const offQueueTail = VTD_IQT_REG_GET_QT(uIqtReg);
    10061021        uint64_t const uIqaReg      = dmarRegRead64(pThis, VTD_MMIO_OFF_IQA_REG);
    10071022        uint8_t const  fDw          = RT_BF_GET(uIqaReg, VTD_BF_IQA_REG_DW);
     
    10091024            || !(offQueueTail & 0x1f))
    10101025        {
    1011             /** @todo Figure out what to do here, like waking up worker thread or
    1012              *        something. */
     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            }
    10131033        }
    10141034        else
     
    10381058        if (fDw == VTD_IQA_REG_DW_256_BIT)
    10391059        {
    1040             uint64_t const fDwMask           = VTD_BF_ECAP_REG_SMTS_MASK | VTD_BF_ECAP_REG_ADMS_MASK;
    1041             bool const     fSupports256BitDw = RT_BOOL(pThis->fExtCap & fDwMask);
     1060            bool const fSupports256BitDw = RT_BOOL(pThis->fExtCap & (VTD_BF_ECAP_REG_SMTS_MASK | VTD_BF_ECAP_REG_ADMS_MASK));
    10421061            if (fSupports256BitDw)
    10431062            { /* likely */ }
     
    11331152        switch (off)
    11341153        {
     1154            case VTD_MMIO_OFF_CCMD_REG:
     1155            case VTD_MMIO_OFF_CCMD_REG + 4:
     1156            {
     1157                rcStrict = dmarCcmdRegWrite(pDevIns, offReg, cb, uRegWritten);
     1158                break;
     1159            }
     1160
    11351161            case VTD_MMIO_OFF_IQT_REG:
    11361162            case VTD_MMIO_OFF_IQT_REG + 4:
    11371163            {
    11381164                rcStrict = dmarIqtRegWrite(pDevIns, offReg, uRegWritten);
    1139                 break;
    1140             }
    1141 
    1142             case VTD_MMIO_OFF_CCMD_REG:
    1143             case VTD_MMIO_OFF_CCMD_REG + 4:
    1144             {
    1145                 rcStrict = dmarCcmdRegWrite(pDevIns, offReg, cb, uRegWritten);
    11461165                break;
    11471166            }
     
    11971216
    11981217#ifdef IN_RING3
     1218/**
     1219 * The queued-invalidation thread function.
     1220 *
     1221 * @returns VBox status code.
     1222 * @param   pDevIns     The IOMMU device instance.
     1223 * @param   pThread     The command thread.
     1224 */
     1225static DECLCALLBACK(int) dmarR3QueuedInvThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1226{
     1227    NOREF(pThread);
     1228    LogFlowFunc(("\n"));
     1229
     1230    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     1231        return VINF_SUCCESS;
     1232
     1233    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1234    PCDMARR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARR3);
     1235
     1236    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     1237    {
     1238        /*
     1239         * Sleep until we are woken up.
     1240         */
     1241        bool const fSignaled = ASMAtomicXchgBool(&pThis->fQueuedInvThreadSignaled, false);
     1242        if (!fSignaled)
     1243        {
     1244            int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtQueuedInvThread, RT_INDEFINITE_WAIT);
     1245            AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
     1246            if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     1247                break;
     1248            ASMAtomicWriteBool(&pThis->fQueuedInvThreadSignaled, false);
     1249        }
     1250
     1251        /*
     1252         * Fetch and process queued-invalidation requests.
     1253         */
     1254        DMAR_LOCK_RET(pDevIns, pThisR3, VERR_IGNORED);
     1255        uint32_t const uGstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG);
     1256        DMAR_UNLOCK(pDevIns, pThisR3);
     1257
     1258        if (uGstsReg & VTD_BF_GSTS_REG_QIES_MASK)
     1259        {
     1260            /** @todo Read invalidation descriptors and perform invalidation. */
     1261        }
     1262    }
     1263
     1264    LogFlowFunc(("Queued-invalidation thread terminating\n"));
     1265    return VINF_SUCCESS;
     1266}
     1267
     1268
     1269/**
     1270 * Wakes up the queued-invalidation thread so it can respond to a state change.
     1271 *
     1272 * @returns VBox status code.
     1273 * @param   pDevIns     The IOMMU device instance.
     1274 * @param   pThread     The queued-invalidation thread.
     1275 *
     1276 * @thread EMT.
     1277 */
     1278static DECLCALLBACK(int) dmarR3QueuedInvThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1279{
     1280    RT_NOREF(pThread);
     1281    LogFlowFunc(("\n"));
     1282    PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1283    return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtQueuedInvThread);
     1284}
     1285
     1286
    11991287/**
    12001288 * @callback_method_impl{FNDBGFHANDLERDEV}
     
    13701458static DECLCALLBACK(int) iommuIntelR3Destruct(PPDMDEVINS pDevIns)
    13711459{
    1372     RT_NOREF(pDevIns);
     1460    PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    13731461    LogFlowFunc(("\n"));
     1462
     1463    if (pThis->hEvtQueuedInvThread != NIL_SUPSEMEVENT)
     1464    {
     1465        PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtQueuedInvThread);
     1466        pThis->hEvtQueuedInvThread = NIL_SUPSEMEVENT;
     1467    }
     1468
    13741469    return VINF_SUCCESS;
    13751470}
     
    14581553    AssertCompile(!(DMAR_MMIO_BASE_PHYSADDR & X86_PAGE_4K_OFFSET_MASK));
    14591554    rc = PDMDevHlpMmioCreateAndMap(pDevIns, DMAR_MMIO_BASE_PHYSADDR, DMAR_MMIO_SIZE, dmarMmioWrite, dmarMmioRead,
    1460                                    IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED,
    1461                                    "Intel-IOMMU", &pThis->hMmio);
    1462     AssertRCReturn(rc, rc);
     1555                                   IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED, "Intel-IOMMU",
     1556                                   &pThis->hMmio);
     1557    AssertLogRelRCReturn(rc, rc);
    14631558
    14641559    /*
    14651560     * Register debugger info items.
    14661561     */
    1467     PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", dmarR3DbgInfo);
     1562    rc = PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", dmarR3DbgInfo);
     1563    AssertLogRelRCReturn(rc, rc);
    14681564
    14691565#ifdef VBOX_WITH_STATISTICS
     
    14971593     */
    14981594    dmarR3RegsInit(pDevIns);
     1595
     1596    /*
     1597     * Create queued-invalidation thread and semaphore.
     1598     */
     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);
     1604    AssertLogRelRCReturn(rc, rc);
     1605
     1606    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtQueuedInvThread);
     1607    AssertLogRelRCReturn(rc, rc);
    14991608
    15001609    /*
     
    15061615    uint16_t const offFrcd         = RT_BF_GET(pThis->fCap, VTD_BF_CAP_REG_FRO);
    15071616    uint16_t const offIva          = RT_BF_GET(pThis->fExtCap, VTD_BF_ECAP_REG_IRO);
    1508     LogRel(("%s: VER=%u.%u CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%u bits, FRO=%#x, IRO=%#x) mapped at %#RGp\n", DMAR_LOG_PFX,
    1509             RT_BF_GET(uVerReg, VTD_BF_VER_REG_MAX), RT_BF_GET(uVerReg, VTD_BF_VER_REG_MIN),
     1617    LogRel(("%s: VER=%u.%u CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%u bits, FRO=%#x, IRO=%#x) mapped at %#RGp\n",
     1618            DMAR_LOG_PFX, RT_BF_GET(uVerReg, VTD_BF_VER_REG_MAX), RT_BF_GET(uVerReg, VTD_BF_VER_REG_MIN),
    15101619            pThis->fCap, pThis->fExtCap, cMaxGstAddrBits, cSupGstAddrBits, offFrcd, offIva, DMAR_MMIO_BASE_PHYSADDR));
     1620
    15111621    return VINF_SUCCESS;
    15121622}
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