VirtualBox

Changeset 88872 in vbox


Ignore:
Timestamp:
May 5, 2021 6:32:22 AM (4 years ago)
Author:
vboxsync
Message:

Intel IOMMU: bugref:9967 Interrupt remapping, work-in-progress.

File:
1 edited

Legend:

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

    r88859 r88872  
    173173    kDmarDiag_Ir_Rfi_Irte_Not_Present,
    174174    kDmarDiag_Ir_Rfi_Irte_Rsvd,
     175    kDmarDiag_Ir_Rfi_Irte_Svt_Bus,
     176    kDmarDiag_Ir_Rfi_Irte_Svt_Masked,
     177    kDmarDiag_Ir_Rfi_Irte_Svt_Rsvd,
    175178    kDmarDiag_Ir_Rfi_Rsvd,
    176179    /* Member for determining array index limit. */
     
    208211    DMARDIAG_DESC(Ir_Rfi_Irte_Not_Present   ),
    209212    DMARDIAG_DESC(Ir_Rfi_Irte_Rsvd          ),
     213    DMARDIAG_DESC(Ir_Rfi_Irte_Svt_Bus       ),
     214    DMARDIAG_DESC(Ir_Rfi_Irte_Svt_Masked    ),
     215    DMARDIAG_DESC(Ir_Rfi_Irte_Svt_Rsvd      ),
    210216    DMARDIAG_DESC(Ir_Rfi_Rsvd               ),
    211217    /* kDmarDiag_End */
     
    10521058static void dmarFaultEventRaiseInterrupt(PPDMDEVINS pDevIns)
    10531059{
    1054     PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1060    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1061    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
     1062
     1063    DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC);
     1064
    10551065#ifdef RT_STRICT
    10561066    {
     
    10711081        Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEADDR_REG);
    10721082        Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEUADDR_REG);
    1073         Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEDATA_REG);
     1083        Msi.Data.u32     = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEDATA_REG);
    10741084
    10751085        /** @todo Assert Msi.Addr is in the MSR_IA32_APICBASE_ADDR range and ensure on
    10761086         *        FEADD_REG write it can't be anything else? */
    1077         PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
    10781087        pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */);
    10791088
     
    11011110    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    11021111    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
     1112
    11031113    DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC);
    11041114
    11051115    uint32_t const uIcsReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_ICS_REG);
    1106     if (uIcsReg & VTD_BF_ICS_REG_IWC_MASK)
    1107         return;
    1108 
    1109     uint32_t uIectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IECTL_REG);
    1110     if (!(uIectlReg & VTD_BF_IECTL_REG_IM_MASK))
    1111     {
    1112         /* Software has unmasked the interrupt, raise it. */
    1113         MSIMSG Msi;
    1114         Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEADDR_REG);
    1115         Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEUADDR_REG);
    1116         Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEDATA_REG);
    1117 
    1118         pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */);
    1119 
    1120         /* Clear interrupt pending bit. */
    1121         uIectlReg &= ~VTD_BF_IECTL_REG_IP_MASK;
    1122         dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg);
    1123     }
    1124     else
    1125     {
    1126         /* Interrupt is masked, set the interrupt pending bit. */
    1127         uIectlReg |= VTD_BF_IECTL_REG_IP_MASK;
    1128         dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg);
     1116    if (!(uIcsReg & VTD_BF_ICS_REG_IWC_MASK))
     1117    {
     1118        uint32_t uIectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IECTL_REG);
     1119        if (!(uIectlReg & VTD_BF_IECTL_REG_IM_MASK))
     1120        {
     1121            /* Software has unmasked the interrupt, raise it. */
     1122            MSIMSG Msi;
     1123            Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEADDR_REG);
     1124            Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEUADDR_REG);
     1125            Msi.Data.u32     = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEDATA_REG);
     1126
     1127            pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */);
     1128
     1129            /* Clear interrupt pending bit. */
     1130            uIectlReg &= ~VTD_BF_IECTL_REG_IP_MASK;
     1131            dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg);
     1132        }
     1133        else
     1134        {
     1135            /* Interrupt is masked, set the interrupt pending bit. */
     1136            uIectlReg |= VTD_BF_IECTL_REG_IP_MASK;
     1137            dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg);
     1138        }
    11291139    }
    11301140}
     
    11851195    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    11861196    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
    1187     DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC);
     1197
     1198    DMAR_LOCK(pDevIns, pThisCC);
    11881199
    11891200    /* Update the diagnostic reason. */
     
    12091220        dmarFaultEventRaiseInterrupt(pDevIns);
    12101221    }
     1222
     1223    DMAR_UNLOCK(pDevIns, pThisCC);
    12111224}
    12121225
     
    12461259    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    12471260    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
    1248     DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC);
     1261
     1262    DMAR_LOCK(pDevIns, pThisCC);
    12491263
    12501264    /* Update the diagnostic reason. */
     
    12601274
    12611275    dmarFaultEventRaiseInterrupt(pDevIns);
     1276
     1277    DMAR_UNLOCK(pDevIns, pThisCC);
    12621278}
    12631279
     
    15121528    size_t const   cbIrte     = sizeof(*pIrte);
    15131529    RTGCPHYS const GCPhysIrte = (uIrtaReg & VTD_BF_IRTA_REG_IRTA_MASK) + (idxIntr * cbIrte);
    1514     int rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysIrte, pIrte, cbIrte);
    1515     if (RT_SUCCESS(rc))
    1516         return VINF_SUCCESS;
    1517     return rc;
     1530    return PDMDevHlpPhysReadMeta(pDevIns, GCPhysIrte, pIrte, cbIrte);
    15181531}
    15191532
     
    15361549    AssertCompile(VTD_REMAPPABLE_MSI_ADDR_VALID_MASK == UINT32_MAX);
    15371550    if (!(pMsiIn->Data.u32 & ~VTD_REMAPPABLE_MSI_DATA_VALID_MASK))
    1538     { /* likely */ }
     1551    {
     1552        /* Compute the index into the interrupt remap table. */
     1553        uint16_t const uHandleHi       = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_HI);
     1554        uint16_t const uHandleLo       = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_LO);
     1555        uint16_t const uHandle         = uHandleLo | (uHandleHi << 15);
     1556        bool const     fSubHandleValid = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_SHV);
     1557        uint32_t const idxIntr         = fSubHandleValid
     1558                                       ? uHandle + RT_BF_GET(pMsiIn->Data.u32, VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE)
     1559                                       : uHandle;
     1560
     1561        /* Validate the index. */
     1562        uint32_t const cEntries = VTD_IRTA_REG_GET_ENTRIES(uIrtaReg);
     1563        if (idxIntr < cEntries)
     1564        {
     1565            /** @todo Implement and read IRTE from interrupt-entry cache here. */
     1566
     1567            /* Read the interrupt remap table entry (IRTE) at the index. */
     1568            VTD_IRTE_T Irte;
     1569            int rc = dmarIrReadIrte(pDevIns, uIrtaReg, idxIntr, &Irte);
     1570            if (RT_SUCCESS(rc))
     1571            {
     1572                /* Check if the IRTE is present (this must be done -before- checking reserved bits). */
     1573                uint64_t const uIrteQword0 = Irte.au64[0];
     1574                uint64_t const uIrteQword1 = Irte.au64[1];
     1575                bool const fPresent = RT_BF_GET(uIrteQword0, VTD_BF_0_IRTE_P);
     1576                if (fPresent)
     1577                {
     1578                    /* Validate reserved bits in the IRTE. */
     1579                    if (   !(uIrteQword0 & ~VTD_IRTE_0_VALID_MASK)
     1580                        && !(uIrteQword1 & ~VTD_IRTE_1_VALID_MASK))
     1581                    {
     1582                        /* Validate requester id (the device ID) as configured in the IRTE. */
     1583                        bool     fSrcValid;
     1584                        DMARDIAG enmIrDiag;
     1585                        uint8_t const fSvt = RT_BF_GET(uIrteQword1, VTD_BF_1_IRTE_SVT);
     1586                        switch (fSvt)
     1587                        {
     1588                            case VTD_IRTE_SVT_NONE:
     1589                            {
     1590                                fSrcValid = true;
     1591                                enmIrDiag = kDmarDiag_None;
     1592                                break;
     1593                            }
     1594
     1595                            case VTD_IRTE_SVT_VALIDATE_MASK:
     1596                            {
     1597                                static uint16_t const s_afValidMasks[] = { 0xffff, 0xfffb, 0xfff9, 0xfff8 };
     1598                                uint8_t const idxMask     = RT_BF_GET(uIrteQword1, VTD_BF_1_IRTE_SQ) & 3;
     1599                                uint16_t const fValidMask = s_afValidMasks[idxMask];
     1600                                fSrcValid = (idDevice & fValidMask) == idDevice;
     1601                                enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Masked;
     1602                                break;
     1603                            }
     1604
     1605                            case VTD_IRTE_SVT_VALIDATE_BUS_RANGE:
     1606                            {
     1607                                uint16_t const uSourceId = RT_BF_GET(uIrteQword1, VTD_BF_1_IRTE_SID);
     1608                                uint8_t const uBusFirst  = RT_HI_U8(uSourceId);
     1609                                uint8_t const uBusLast   = RT_LO_U8(uSourceId);
     1610                                uint8_t const uRequesterIdBus = idDevice >> VBOX_PCI_BUS_SHIFT;
     1611                                fSrcValid = (uRequesterIdBus >= uBusFirst && uRequesterIdBus <= uBusLast);
     1612                                enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Bus;
     1613                                break;
     1614                            }
     1615
     1616                            default:
     1617                            {
     1618                                fSrcValid = false;
     1619                                enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Bus;
     1620                                break;
     1621                            }
     1622                        }
     1623
     1624                        if (fSrcValid)
     1625                        {
     1626                            /** @todo Get the interrupt mode (must not be posted) and then remap. */
     1627                            *pMsiOut = *pMsiIn;      // This is just temporary to shut up the compiler!
     1628                            return VERR_NOT_IMPLEMENTED;
     1629                        }
     1630                        else
     1631                            dmarIrFaultRecordQualified(pDevIns, enmIrDiag, kIrf_Irte_Present_Rsvd, idDevice, idxIntr, &Irte);
     1632                    }
     1633                    else
     1634                        dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, kIrf_Irte_Present_Rsvd, idDevice,
     1635                                                   idxIntr, &Irte);
     1636                }
     1637                else
     1638                    dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, kIrf_Irte_Not_Present, idDevice,
     1639                                               idxIntr, &Irte);
     1640            }
     1641            else
     1642                dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, kIrf_Irte_Read_Failed, idDevice, idxIntr);
     1643        }
     1644        else
     1645            dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, kIrf_Intr_Index_Invalid, idDevice, idxIntr);
     1646    }
    15391647    else
    1540     {
    15411648        dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Rsvd, kIrf_Remappable_Intr_Rsvd, idDevice, 0 /* idxIntr */);
    1542         return VERR_IOMMU_INTR_REMAP_DENIED;
    1543     }
    1544 
    1545     /* Compute the index into the interrupt remap table. */
    1546     uint16_t const uHandleHi       = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_HI);
    1547     uint16_t const uHandleLo       = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_LO);
    1548     uint16_t const uHandle         = uHandleLo | (uHandleHi << 15);
    1549     bool const     fSubHandleValid = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_SHV);
    1550     uint32_t const idxIntr         = fSubHandleValid
    1551                                    ? uHandle + RT_BF_GET(pMsiIn->Data.u32, VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE)
    1552                                    : uHandle;
    1553 
    1554     /* Validate the index. */
    1555     uint32_t const cEntries = VTD_IRTA_REG_GET_ENTRIES(uIrtaReg);
    1556     if (idxIntr < cEntries)
    1557     { /* likely */ }
    1558     else
    1559     {
    1560         dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, kIrf_Intr_Index_Invalid, idDevice, idxIntr);
    1561         return VERR_IOMMU_INTR_REMAP_DENIED;
    1562     }
    1563 
    1564     /** @todo Implement and read IRTE from interrupt-entry cache here. */
    1565 
    1566     /* Read the interrupt remap table entry (IRTE). */
    1567     VTD_IRTE_T Irte;
    1568     int rc = dmarIrReadIrte(pDevIns, uIrtaReg, idxIntr, &Irte);
    1569     if (RT_SUCCESS(rc))
    1570     { /* likely */ }
    1571     else
    1572     {
    1573         dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, kIrf_Irte_Read_Failed, idDevice, idxIntr);
    1574         return VERR_IOMMU_INTR_REMAP_DENIED;
    1575     }
    1576 
    1577     /* Validate IRTE. */
    1578     uint64_t const uIrteQword0 = Irte.au64[0];
    1579     uint64_t const uIrteQword1 = Irte.au64[1];
    1580     bool const fPresent = RT_BF_GET(uIrteQword0, VTD_BF_0_IRTE_P);
    1581     if (fPresent)
    1582     { /* likely */ }
    1583     else
    1584     {
    1585         dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, kIrf_Irte_Not_Present, idDevice, idxIntr, &Irte);
    1586         return VERR_IOMMU_INTR_REMAP_DENIED;
    1587     }
    1588     if (   !(uIrteQword0 & ~VTD_IRTE_0_VALID_MASK)
    1589         && !(uIrteQword1 & ~VTD_IRTE_1_VALID_MASK))
    1590     { /* likely */ }
    1591     else
    1592     {
    1593         dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, kIrf_Irte_Present_Rsvd, idDevice, idxIntr, &Irte);
    1594         return VERR_IOMMU_INTR_REMAP_DENIED;
    1595     }
    1596 
    1597     /** @todo rest of validation using SVT and SQ. */
    1598     *pMsiOut = *pMsiIn;      // This is just temporary to shut up the compiler!
    1599     return VERR_NOT_IMPLEMENTED;
     1649    return VERR_IOMMU_INTR_REMAP_DENIED;
    16001650}
    16011651
     
    16531703    }
    16541704
    1655     /* If interrupt-remapping isn't enabled, all interrupts are pass-through.  */
     1705    /* Interrupt-remapping isn't enabled, all interrupts are pass-through.  */
    16561706    *pMsiOut = *pMsiIn;
    16571707    return VINF_SUCCESS;
     
    17731823    do \
    17741824    { \
    1775         DMAR_LOCK(pDevIns, pThisR3); \
    17761825        dmarIqeFaultRecord(pDevIns, (a_enmDiag), (a_enmIqei)); \
    1777         DMAR_UNLOCK(pDevIns, pThisR3); \
    17781826        return; \
    17791827    } while (0)
     
    19862034                        /* The requests have not wrapped around, read them in one go. */
    19872035                        cbRequests = offQueueTail - offQueueHead;
    1988                         rc = PDMDevHlpPhysRead(pDevIns, GCPhysRequests, pvRequests, cbRequests);
     2036                        rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysRequests, pvRequests, cbRequests);
    19892037                    }
    19902038                    else
     
    19922040                        /* The requests have wrapped around, read forward and wrapped-around. */
    19932041                        uint32_t const cbForward = cbQueue - offQueueHead;
    1994                         rc  = PDMDevHlpPhysRead(pDevIns, GCPhysRequests, pvRequests, cbForward);
     2042                        rc  = PDMDevHlpPhysReadMeta(pDevIns, GCPhysRequests, pvRequests, cbForward);
    19952043
    19962044                        uint32_t const cbWrapped = offQueueTail;
     
    19982046                            && cbWrapped > 0)
    19992047                        {
    2000                             rc = PDMDevHlpPhysRead(pDevIns, GCPhysRequests + cbForward,
    2001                                                    (void *)((uintptr_t)pvRequests + cbForward), cbWrapped);
     2048                            rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysRequests + cbForward,
     2049                                                       (void *)((uintptr_t)pvRequests + cbForward), cbWrapped);
    20022050                        }
    20032051                        cbRequests = cbForward + cbWrapped;
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