VirtualBox

Changeset 88682 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 23, 2021 3:18:37 PM (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

    r88669 r88682  
    815815 *          register.
    816816 */
    817 static void dmarRegChange32(PDMAR pThis, uint16_t offReg, uint32_t fAndMask, uint32_t fOrMask)
    818 {
    819     uint32_t uReg = dmarRegRead32(pThis, offReg);
     817static void dmarRegChangeRaw32(PDMAR pThis, uint16_t offReg, uint32_t fAndMask, uint32_t fOrMask)
     818{
     819    uint32_t uReg = dmarRegReadRaw32(pThis, offReg);
    820820    uReg = (uReg & fAndMask) | fOrMask;
    821821    dmarRegWriteRaw32(pThis, offReg, uReg);
     
    833833 *          register.
    834834 */
    835 static void dmarRegChange64(PDMAR pThis, uint16_t offReg, uint64_t fAndMask, uint64_t fOrMask)
    836 {
    837     uint64_t uReg = dmarRegRead64(pThis, offReg);
     835static void dmarRegChangeRaw64(PDMAR pThis, uint16_t offReg, uint64_t fAndMask, uint64_t fOrMask)
     836{
     837    uint64_t uReg = dmarRegReadRaw64(pThis, offReg);
    838838    uReg = (uReg & fAndMask) | fOrMask;
    839839    dmarRegWriteRaw64(pThis, offReg, uReg);
     
    875875 * Checks whether the invalidation-queue is capable of processing requests.
    876876 *
    877  * @returns @c true if the invalidation-queue can be processed, @c false otherwise.
     877 * @returns @c true if the invalidation-queue can process requests, @c false
     878 *          otherwise.
    878879 * @param   pThis   The shared DMAR device state.
    879880 */
     
    884885    if (uGstsReg & VTD_BF_GSTS_REG_QIES_MASK)
    885886    {
    886         /* Check if there are no IQ errors and that the queue isn't empty. */
     887        /* Check if there are no invalidation-queue or timeout errors. */
    887888        uint32_t const uFstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_FSTS_REG);
    888         if (   !(uFstsReg & VTD_BF_FSTS_REG_IQE_MASK)
    889             && !dmarInvQueueIsEmpty(pThis))
     889        if (!(uFstsReg & (VTD_BF_FSTS_REG_IQE_MASK | VTD_BF_FSTS_REG_ITE_MASK)))
    890890            return true;
    891891    }
     
    908908
    909909    if (   dmarInvQueueCanProcessRequests(pThis)
     910        && !dmarInvQueueIsEmpty(pThis)
    910911        && !ASMAtomicXchgBool(&pThis->fInvQueueThreadSignaled, true))
    911912    {
     
    939940    if (!(uFectlReg & VTD_BF_FECTL_REG_IM_MASK))
    940941    {
     942        /* Software has unmasked the interrupt, raise it. */
    941943        MSIMSG Msi;
    942944        Msi.Addr.u64 = RT_MAKE_U64(dmarRegRead32(pThis, VTD_MMIO_OFF_FEADDR_REG),
     
    947949         *        FEADD_REG write it can't be anything else. */
    948950
    949         /* Software has unmasked the interrupt, raise it. */
    950951        pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */);
    951952
     
    10171018    /* Set the error bit. */
    10181019    uint32_t const fIqe = RT_BF_MAKE(VTD_BF_FSTS_REG_IQE, 1);
    1019     dmarRegChange32(pThis, VTD_MMIO_OFF_FSTS_REG, UINT32_MAX, fIqe);
     1020    dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_FSTS_REG, UINT32_MAX, fIqe);
    10201021
    10211022    /* Set the error information. */
    10221023    uint64_t const fIqei = RT_BF_MAKE(VTD_BF_IQERCD_REG_IQEI, enmIqei);
    1023     dmarRegChange64(pThis, VTD_MMIO_OFF_IQERCD_REG, UINT64_MAX, fIqei);
     1024    dmarRegChangeRaw64(pThis, VTD_MMIO_OFF_IQERCD_REG, UINT64_MAX, fIqei);
    10241025
    10251026    dmarFaultRaiseInterrupt(pDevIns);
     1027}
     1028
     1029
     1030/**
     1031 * Handles writes to GCMD_REG.
     1032 *
     1033 * @returns Strict VBox status code.
     1034 * @param   pDevIns     The IOMMU device instance.
     1035 * @param   uGcmdReg    The value written to GCMD_REG.
     1036 */
     1037static VBOXSTRICTRC dmarGcmdRegWrite(PPDMDEVINS pDevIns, uint32_t uGcmdReg)
     1038{
     1039    PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1040    uint32_t const uGstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG);
     1041    uint32_t const fChanged = uGstsReg ^ uGcmdReg;
     1042    if (pThis->fExtCap & VTD_BF_ECAP_REG_QI_MASK)
     1043    {
     1044        if (fChanged & VTD_BF_GCMD_REG_QIE_MASK)
     1045        {
     1046            if (uGcmdReg & VTD_BF_GCMD_REG_QIE_MASK)
     1047            {
     1048                /* Enable the invalidation-queue. */
     1049                dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_GSTS_REG, UINT32_MAX /* fAndMask */,
     1050                                   VTD_BF_GSTS_REG_QIES_MASK /* fOrMask */);
     1051                dmarInvQueueThreadWakeUpIfNeeded(pDevIns);
     1052            }
     1053            else
     1054            {
     1055                /* Disable the invalidation-queue and reset the queue head offset. */
     1056                dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_GSTS_REG, ~VTD_BF_GSTS_REG_QIES_MASK /* fAndMask */, 0 /* fOrMask */);
     1057                dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IQH_REG, 0);
     1058            }
     1059        }
     1060    }
     1061
     1062    /** @todo Rest of the bits? */
     1063
     1064    return VINF_SUCCESS;
    10261065}
    10271066
     
    10921131    else
    10931132    {
    1094         /* Hardware treats bit 4 as RsvdZ here, so clear it. */
    1095         dmarRegChange32(pThis, offReg, ~RT_BIT(4) /* fAndMask*/ , 0 /* fOrMask */);
     1133        /* Hardware treats bit 4 as RsvdZ in this situation, so clear it. */
     1134        dmarRegChangeRaw32(pThis, offReg, ~RT_BIT(4) /* fAndMask*/ , 0 /* fOrMask */);
    10961135        dmarIqeFaultRecord(pDevIns, kDmarDiag_IqtReg_Qt_NotAligned, kQueueTailNotAligned);
    10971136    }
     
    12171256        switch (off)
    12181257        {
     1258            case VTD_MMIO_OFF_GCMD_REG:
     1259            {
     1260                rcStrict = dmarGcmdRegWrite(pDevIns, uRegWritten);
     1261                break;
     1262            }
     1263
    12191264            case VTD_MMIO_OFF_CCMD_REG:
    12201265            case VTD_MMIO_OFF_CCMD_REG + 4:
     
    13011346        return VINF_SUCCESS;
    13021347
    1303     PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    1304     PCDMARR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARR3);
    1305 
    13061348    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    13071349    {
     1350        PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1351        PCDMARR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARR3);
     1352
    13081353        /*
    13091354         * Sleep until we are woken up.
     
    13191364        }
    13201365
    1321         /*
    1322          * Fetch and process invalidation requests.
    1323          */
    1324         DMAR_LOCK_RET(pDevIns, pThisR3, VERR_IGNORED);
    1325         /** @todo use dmarInvQueueCanProcessRequests instead? */
    1326         uint32_t const uGstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG);
     1366        DMAR_LOCK(pDevIns, pThisR3);
     1367        if (dmarInvQueueCanProcessRequests(pThis))
     1368        {
     1369            /** @todo Read IQH and IQT, descriptors from memory and perform invalidation. */
     1370        }
    13271371        DMAR_UNLOCK(pDevIns, pThisR3);
    1328 
    1329         if (uGstsReg & VTD_BF_GSTS_REG_QIES_MASK)
    1330         {
    1331             /** @todo Read invalidation descriptors and perform invalidation. */
    1332         }
    13331372    }
    13341373
     
    13851424{
    13861425    PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1426
     1427    /*
     1428     * Wipe all registers (required on reset).
     1429     */
    13871430    RT_ZERO(pThis->abRegs0);
    13881431    RT_ZERO(pThis->abRegs1);
     
    14601503
    14611504        pThis->fExtCap = RT_BF_MAKE(VTD_BF_ECAP_REG_C,      0)  /* Accesses don't snoop CPU cache. */
    1462                        | RT_BF_MAKE(VTD_BF_ECAP_REG_QI,     1)
     1505                       | RT_BF_MAKE(VTD_BF_ECAP_REG_QI,     fQi)
    14631506                       | RT_BF_MAKE(VTD_BF_ECAP_REG_DT,     0)  /* Device-TLBs not supported. */
    14641507                       | RT_BF_MAKE(VTD_BF_ECAP_REG_IR,     fQi & fIr)
     
    15391582    LogFlowFunc(("\n"));
    15401583
    1541     DMAR_LOCK_RET(pDevIns, pThisR3, VERR_IGNORED);
     1584    DMAR_LOCK(pDevIns, pThisR3);
    15421585
    15431586    if (pThis->hEvtInvQueue != NIL_SUPSEMEVENT)
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