VirtualBox

Changeset 89524 in vbox for trunk/src/VBox/Devices/Bus


Ignore:
Timestamp:
Jun 5, 2021 7:34:32 AM (3 years ago)
Author:
vboxsync
Message:

Intel IOMMU: bugref:9967 Address translation and interrupt remapping fault handling cleanup.

File:
1 edited

Legend:

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

    r89523 r89524  
    15031503 * @param   pDevIns     The IOMMU device instance.
    15041504 * @param   enmDiag     The diagnostic reason.
    1505  * @param   enmIrFault  The interrupt fault reason.
    15061505 * @param   idDevice    The device ID (bus, device, function).
    15071506 * @param   idxIntr     The interrupt index.
    1508  */
    1509 static void dmarIrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDIRFAULT enmIrFault, uint16_t idDevice, uint16_t idxIntr)
    1510 {
    1511     /* Update the diagnostic reason. */
    1512     PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    1513     pThis->enmDiag = enmDiag;
    1514 
    1515     uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, idDevice)
    1516                            | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR,  enmIrFault)
    1517                            | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F,   1);
    1518     uint64_t const uFrcdLo = (uint64_t)idxIntr << 48;
    1519     dmarPrimaryFaultRecord(pDevIns, uFrcdHi, uFrcdLo);
    1520 }
    1521 
    1522 
    1523 /**
    1524  * Records a qualified interrupt request fault.
    1525  *
    1526  * Qualified faults are those that can be suppressed by software using the FPD bit
    1527  * in the IRTE.
    1528  *
    1529  * @param   pDevIns     The IOMMU device instance.
    1530  * @param   enmDiag     The diagnostic reason.
    1531  * @param   enmIrFault  The interrupt fault reason.
    1532  * @param   idDevice    The device ID (bus, device, function).
    1533  * @param   idxIntr     The interrupt index.
    1534  * @param   pIrte       The IRTE that caused this fault.
    1535  */
    1536 static void dmarIrFaultRecordQualified(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDIRFAULT enmIrFault, uint16_t idDevice,
    1537                                        uint16_t idxIntr, PCVTD_IRTE_T pIrte)
    1538 {
    1539     Assert(vtdIrFaultIsQualified(enmIrFault));
    1540     Assert(pIrte);
    1541     if (!(pIrte->au64[0] & VTD_BF_0_IRTE_FPD_MASK))
    1542         return dmarIrFaultRecord(pDevIns, enmDiag, enmIrFault, idDevice, idxIntr);
    1543 
    1544     /* Update the diagnostic reason (even if software wants to supress faults). */
    1545     PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    1546     pThis->enmDiag = enmDiag;
    1547 }
    1548 
    1549 
    1550 /**
    1551  * Records an address translation fault.
    1552  *
    1553  * @param   pDevIns         The IOMMU device instance.
    1554  * @param   enmDiag         The diagnostic reason.
    1555  * @param   pMemReqIn       The DMA memory request input.
    1556  * @param   pMemReqAux      The DMA memory request auxiliary info.
    1557  */
    1558 static void dmarAtFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, PCDMARMEMREQIN pMemReqIn, PCDMARMEMREQAUX pMemReqAux)
     1507 * @param   pIrte       The IRTE that caused this fault. Can be NULL if the fault is
     1508 *                      not qualified.
     1509 */
     1510static void dmarIrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, uint16_t idDevice, uint16_t idxIntr, PCVTD_IRTE_T pIrte)
    15591511{
    15601512    /*
     
    15651517
    15661518    /*
     1519     * Figure out the fault reason to report to software from our diagnostic code.
     1520     * The case labels below are sorted alphabetically for convenience.
     1521     */
     1522    VTDIRFAULT enmIrFault;
     1523    switch (enmDiag)
     1524    {
     1525        case kDmarDiag_Ir_Cfi_Blocked:            enmIrFault = VTDIRFAULT_CFI_BLOCKED;          break;
     1526        case kDmarDiag_Ir_Rfi_Intr_Index_Invalid: enmIrFault = VTDIRFAULT_INTR_INDEX_INVALID;   break;
     1527        case kDmarDiag_Ir_Rfi_Irte_Mode_Invalid:  enmIrFault = VTDIRFAULT_IRTE_PRESENT_RSVD;    break;
     1528        case kDmarDiag_Ir_Rfi_Irte_Not_Present:   enmIrFault = VTDIRFAULT_IRTE_NOT_PRESENT;     break;
     1529        case kDmarDiag_Ir_Rfi_Irte_Read_Failed:   enmIrFault = VTDIRFAULT_IRTE_READ_FAILED;     break;
     1530        case kDmarDiag_Ir_Rfi_Irte_Rsvd:
     1531        case kDmarDiag_Ir_Rfi_Irte_Svt_Bus:
     1532        case kDmarDiag_Ir_Rfi_Irte_Svt_Masked:
     1533        case kDmarDiag_Ir_Rfi_Irte_Svt_Rsvd:      enmIrFault = VTDIRFAULT_IRTE_PRESENT_RSVD;    break;
     1534        case kDmarDiag_Ir_Rfi_Rsvd:               enmIrFault = VTDIRFAULT_REMAPPABLE_INTR_RSVD; break;
     1535
     1536        /* Shouldn't ever happen. */
     1537        default:
     1538        {
     1539            AssertLogRelMsgFailedReturnVoid(("%s: Invalid interrupt remapping fault diagnostic code %#x\n", DMAR_LOG_PFX,
     1540                                             enmDiag));
     1541        }
     1542    }
     1543
     1544    /*
    15671545     * Qualified faults are those that can be suppressed by software using the FPD bit
    1568      * in the contex entry, scalable-mode context entry etc.
     1546     * in the interrupt-remapping table entry.
     1547     */
     1548    bool fFpd;
     1549    bool const fQualifiedFault = vtdIrFaultIsQualified(enmIrFault);
     1550    if (fQualifiedFault)
     1551    {
     1552        AssertReturnVoid(pIrte);
     1553        fFpd = RT_BOOL(pIrte->au64[0] & VTD_BF_0_IRTE_FPD_MASK);
     1554    }
     1555    else
     1556        fFpd = false;
     1557
     1558    if (!fFpd)
     1559    {
     1560        /* Construct and record the error. */
     1561        uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, idDevice)
     1562                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR,  enmIrFault)
     1563                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F,   1);
     1564        uint64_t const uFrcdLo = (uint64_t)idxIntr << 48;
     1565        dmarPrimaryFaultRecord(pDevIns, uFrcdHi, uFrcdLo);
     1566    }
     1567}
     1568
     1569
     1570/**
     1571 * Records an address translation fault.
     1572 *
     1573 * @param   pDevIns         The IOMMU device instance.
     1574 * @param   enmDiag         The diagnostic reason.
     1575 * @param   pMemReqIn       The DMA memory request input.
     1576 * @param   pMemReqAux      The DMA memory request auxiliary info.
     1577 */
     1578static void dmarAtFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, PCDMARMEMREQIN pMemReqIn, PCDMARMEMREQAUX pMemReqAux)
     1579{
     1580    /*
     1581     * Update the diagnostic reason (even if software wants to supress faults).
     1582     */
     1583    PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1584    pThis->enmDiag = enmDiag;
     1585
     1586    /*
     1587     * Qualified faults are those that can be suppressed by software using the FPD bit
     1588     * in the context entry, scalable-mode context entry etc.
    15691589     */
    15701590    if (!pMemReqAux->fFpd)
     
    21942214        {
    21952215            dmarAtFaultRecord(pDevIns, kDmarDiag_At_Xm_Perm_Denied, pMemReqIn, pMemReqAux);
    2196             return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2216            break;
    21972217        }
    21982218
     
    22052225        {
    22062226            dmarAtFaultRecord(pDevIns, kDmarDiag_At_Xm_Pte_Rsvd, pMemReqIn, pMemReqAux);
    2207             return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2227            break;
    22082228        }
    22092229
     
    22312251
    22322252            dmarAtFaultRecord(pDevIns, kDmarDiag_At_Xm_Pte_Sllps_Invalid, pMemReqIn, pMemReqAux);
    2233             return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2253            break;
    22342254        }
    22352255
     
    22622282            {
    22632283                dmarAtFaultRecord(pDevIns, kDmarDiag_At_Xm_Read_Pte_Failed, pMemReqIn, pMemReqAux);
    2264                 return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2284                break;
    22652285            }
    22662286        }
    22672287    }
     2288
     2289    return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
    22682290}
    22692291
     
    28442866                            {
    28452867                                fSrcValid = false;
    2846                                 enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Bus;
     2868                                enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Rsvd;
    28472869                                break;
    28482870                            }
     
    28572879                                return VINF_SUCCESS;
    28582880                            }
    2859                             dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Mode_Invalid,
    2860                                                          VTDIRFAULT_IRTE_PRESENT_RSVD, idDevice, idxIntr, &Irte);
     2881                            dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Mode_Invalid, idDevice, idxIntr, &Irte);
    28612882                        }
    28622883                        else
    2863                             dmarIrFaultRecordQualified(pDevIns, enmIrDiag, VTDIRFAULT_IRTE_PRESENT_RSVD, idDevice, idxIntr,
    2864                                                          &Irte);
     2884                            dmarIrFaultRecord(pDevIns, enmIrDiag, idDevice, idxIntr, &Irte);
    28652885                    }
    28662886                    else
    2867                         dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, VTDIRFAULT_IRTE_PRESENT_RSVD,
    2868                                                      idDevice, idxIntr, &Irte);
     2887                        dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, idDevice, idxIntr, &Irte);
    28692888                }
    28702889                else
    2871                     dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, VTDIRFAULT_IRTE_NOT_PRESENT,
    2872                                                  idDevice, idxIntr, &Irte);
     2890                    dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, idDevice, idxIntr, &Irte);
    28732891            }
    28742892            else
    2875                 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, VTDIRFAULT_IRTE_READ_FAILED, idDevice, idxIntr);
     2893                dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, idDevice, idxIntr, NULL /* pIrte */);
    28762894        }
    28772895        else
    2878             dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, VTDIRFAULT_INTR_INDEX_INVALID, idDevice, idxIntr);
     2896            dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, idDevice, idxIntr, NULL /* pIrte */);
    28792897    }
    28802898    else
    2881         dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Rsvd, VTDIRFAULT_REMAPPABLE_INTR_RSVD, idDevice, 0 /* idxIntr */);
     2899        dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Rsvd, idDevice, 0 /* idxIntr */, NULL /* pIrte */);
    28822900    return VERR_IOMMU_INTR_REMAP_DENIED;
    28832901}
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