VirtualBox

Changeset 89235 in vbox


Ignore:
Timestamp:
May 24, 2021 7:31:02 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144578
Message:

Intel IOMMU: bugref:9967 Address translation, WIP.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/iommu-intel.h

    r89223 r89235  
    13411341
    13421342/**
    1343  * VT-d FRCD type requests (FRCD_REG::T2).
     1343 * VT-d faulted request types (FRCD_REG::T2).
    13441344 * In accordance with the Intel spec.
    13451345 */
    13461346typedef enum VTDREQTYPE
    13471347{
    1348     VTDREQTYPE_WRITE = 0,
    1349     VTDREQTYPE_PAGE,
    1350     VTDREQTYPE_READ,
    1351     VTDREQTYPE_ATOMIC_OP
     1348    VTDREQTYPE_WRITE = 0,   /**< Memory access write request. */
     1349    VTDREQTYPE_PAGE,        /**< Page translation request. */
     1350    VTDREQTYPE_READ,        /**< Memory access read request. */
     1351    VTDREQTYPE_ATOMIC_OP    /**< Memory access atomic operation. */
    13521352} VTDREQTYPE;
     1353
     1354
     1355/** @name VT-d faulted request attributes (FRCD_REG::EXE, FRCD_REG::PRIV).
     1356 * In accordance with the Intel spec.
     1357 * @{
     1358 */
     1359/** Supervisory privilege was requested. */
     1360#define VTD_REQ_ATTR_PRIV                                       RT_BIT(0)
     1361/** Execute permission was requested. */
     1362#define VTD_REQ_ATTR_EXE                                        RT_BIT(1)
     1363/** @} */
    13531364
    13541365
  • trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp

    r89216 r89235  
    154154typedef enum
    155155{
     156    /* No error, this must be zero! */
    156157    kDmarDiag_None = 0,
     158
     159    /* Address Translation Faults. */
     160    kDmarDiag_Atf_Rta_1_1,
     161    kDmarDiag_Atf_Rta_1_2,
     162    kDmarDiag_Atf_Rta_1_3,
     163
     164    /* CCMD_REG faults. */
    157165    kDmarDiag_CcmdReg_NotSupported,
    158166    kDmarDiag_CcmdReg_Qi_Enabled,
    159167    kDmarDiag_CcmdReg_Ttm_Invalid,
     168
     169    /* IQA_REG faults. */
    160170    kDmarDiag_IqaReg_Dsc_Fetch_Error,
    161171    kDmarDiag_IqaReg_Dw_128_Invalid,
    162172    kDmarDiag_IqaReg_Dw_256_Invalid,
     173
     174    /* Invalidation Queue Error Info. */
    163175    kDmarDiag_Iqei_Dsc_Type_Invalid,
    164176    kDmarDiag_Iqei_Inv_Wait_Dsc_0_1_Rsvd,
     
    166178    kDmarDiag_Iqei_Inv_Wait_Dsc_Invalid,
    167179    kDmarDiag_Iqei_Ttm_Rsvd,
     180
     181    /* IQT_REG faults. */
    168182    kDmarDiag_IqtReg_Qt_Invalid,
    169183    kDmarDiag_IqtReg_Qt_NotAligned,
     184
     185    /* Compatibility Format Interrupt Faults. */
    170186    kDmarDiag_Ir_Cfi_Blocked,
     187
     188    /* Remappable Format Interrupt Faults. */
    171189    kDmarDiag_Ir_Rfi_Intr_Index_Invalid,
    172190    kDmarDiag_Ir_Rfi_Irte_Mode_Invalid,
     
    178196    kDmarDiag_Ir_Rfi_Irte_Svt_Rsvd,
    179197    kDmarDiag_Ir_Rfi_Rsvd,
     198
    180199    /* Member for determining array index limit. */
    181200    kDmarDiag_End,
    182     /* Type size hack. */
     201
     202    /* Usual 32-bit type size hack. */
    183203    kDmarDiag_32Bit_Hack = 0x7fffffff
    184204} DMARDIAG;
     
    194214{
    195215    DMARDIAG_DESC(None                      ),
     216    DMARDIAG_DESC(Atf_Rta_1_1               ),
     217    DMARDIAG_DESC(Atf_Rta_1_2               ),
     218    DMARDIAG_DESC(Atf_Rta_1_3               ),
    196219    DMARDIAG_DESC(CcmdReg_NotSupported      ),
    197220    DMARDIAG_DESC(CcmdReg_Qi_Enabled        ),
     
    13181341
    13191342/**
    1320  * Records an address translation fault.
     1343 * Records an address translation fault (extensive version).
    13211344 *
    13221345 * @param   pDevIns         The IOMMU device instance.
     
    13301353 * @param   fHasPasid       Whether the faulted request has a PASID TLP prefix.
    13311354 * @param   uPasid          The PASID value when a PASID TLP prefix is present.
    1332  * @param   fExec           Execute permission was requested by the faulted request.
    1333  * @param   fPriv           Supervisor privilege permission was requested by the
    1334  *                          faulted request.
    1335  */
    1336 static void dmarAddrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice,
    1337                                 uint64_t uFaultAddr, VTDREQTYPE enmReqType, uint8_t uAddrType, bool fHasPasid, uint32_t uPasid,
    1338                                 bool fExec, bool fPriv)
     1355 * @param   fReqAttr        The attributes of the faulted requested
     1356 *                          (VTD_REQ_ATTR_XXX).
     1357 */
     1358static void dmarAddrFaultRecordEx(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice,
     1359                                  uint64_t uFaultAddr, VTDREQTYPE enmReqType, uint8_t uAddrType, bool fHasPasid, uint32_t uPasid,
     1360                                  uint8_t fReqAttr)
    13391361{
    13401362    uint8_t const fType1 = enmReqType & RT_BIT(1);
    13411363    uint8_t const fType2 = enmReqType & RT_BIT(0);
     1364    uint8_t const fExec = fReqAttr & VTD_REQ_ATTR_EXE;
     1365    uint8_t const fPriv = fReqAttr & VTD_REQ_ATTR_PRIV;
    13421366    uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID,  idDevice)
    13431367                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T2,   fType2)
     
    13521376    uint64_t const uFrcdLo = uFaultAddr & X86_PAGE_BASE_MASK;
    13531377    dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo);
     1378}
     1379
     1380
     1381/**
     1382 * Records an address translation fault.
     1383 *
     1384 * This is to be used when Device-TLB, and PASIDs are not supported or for requests
     1385 * where the device-TLB and PASID is not relevant/present.
     1386 *
     1387 * @param   pDevIns         The IOMMU device instance.
     1388 * @param   enmDiag         The diagnostic reason.
     1389 * @param   enmAddrFault    The address translation fault reason.
     1390 * @param   idDevice        The device ID (bus, device, function).
     1391 * @param   uFaultAddr      The page address of the faulted request.
     1392 * @param   enmReqType      The type of the faulted request.
     1393 */
     1394static void dmarAddrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice,
     1395                                  uint64_t uFaultAddr, VTDREQTYPE enmReqType)
     1396{
     1397    dmarAddrFaultRecordEx(pDevIns, enmDiag, enmAddrFault, idDevice, uFaultAddr, enmReqType, 0 /* uAddrType */,
     1398                          false /* fHasPasid */, 0 /* uPasid */, 0 /* fReqAttr */);
    13541399}
    13551400
     
    17091754
    17101755/**
     1756 * Performs a PCI target abort for a DMA operation.
     1757 *
     1758 * @param   pDevIns     The IOMMU device instance.
     1759 */
     1760static void dmarDmaTargetAbort(PPDMDEVINS pDevIns)
     1761{
     1762    /** @todo r=ramshankar: I don't know for sure if a PCI target abort is caused or not
     1763     *        as the Intel VT-d spec. is vague. Wording seems to suggest it does, but
     1764     *        who knows. */
     1765    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     1766    uint16_t const u16Status = PDMPciDevGetStatus(pPciDev) | VBOX_PCI_STATUS_SIG_TARGET_ABORT;
     1767    PDMPciDevSetStatus(pPciDev, u16Status);
     1768}
     1769
     1770
     1771/**
     1772 * Validates the table translation mode for a DMA request.
     1773 *
     1774 * @returns @c true if the TTM is valid, @c false otherwise.
     1775 * @param   pDevIns         The IOMMU device instance.
     1776 * @param   uRtaddrReg      The current RTADDR_REG value.
     1777 * @param   idDevice        The device ID (bus, device, function).
     1778 * @param   uIova           The I/O virtual address being accessed.
     1779 * @param   enmReqType      The type of the request (for fault recording).
     1780 */
     1781static bool dmarDmaIsTtmValid(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, uint16_t idDevice, uint64_t uIova, VTDREQTYPE enmReqType)
     1782{
     1783    bool fValid = true;
     1784    PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PCDMAR);
     1785    uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
     1786    switch (fTtm)
     1787    {
     1788        case VTD_TTM_LEGACY_MODE:
     1789            break;
     1790
     1791        case VTD_TTM_SCALABLE_MODE:
     1792        {
     1793            if (pThis->fExtCapReg & VTD_BF_ECAP_REG_SMTS_MASK)
     1794                break;
     1795            dmarAddrFaultRecord(pDevIns, kDmarDiag_Atf_Rta_1_3, VTDADDRFAULT_RTA_1_3, idDevice, uIova, enmReqType);
     1796            fValid = false;
     1797            break;
     1798        }
     1799
     1800        case VTD_TTM_ABORT_DMA_MODE:
     1801        {
     1802            if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK)
     1803                dmarDmaTargetAbort(pDevIns);
     1804            else
     1805                dmarAddrFaultRecord(pDevIns, kDmarDiag_Atf_Rta_1_1, VTDADDRFAULT_RTA_1_1, idDevice, uIova, enmReqType);
     1806            fValid = false;
     1807            break;
     1808        }
     1809
     1810        default:
     1811        {
     1812            dmarAddrFaultRecord(pDevIns, kDmarDiag_Atf_Rta_1_2, VTDADDRFAULT_RTA_1_2, idDevice, uIova, enmReqType);
     1813            fValid = false;
     1814            break;
     1815        }
     1816    }
     1817    return fValid;
     1818}
     1819
     1820
     1821/**
    17111822 * Memory access bulk (one or more 4K pages) request from a device.
    17121823 *
     
    17471858                                             uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
    17481859{
    1749     RT_NOREF6(idDevice, uIova, cbIova, fFlags, pGCPhysSpa, pcbContiguous);
     1860    /* Validate. */
     1861    AssertPtr(pDevIns);
     1862    AssertPtr(pGCPhysSpa);
     1863    AssertPtr(pcbContiguous);
     1864    Assert(cbIova > 0);         /** @todo Are we going to support ZLR (zero-length reads to write-only pages)? */
     1865    Assert(!(fFlags & ~PDMIOMMU_MEM_F_VALID_MASK));
    17501866
    17511867    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     
    17621878        if (fFlags & PDMIOMMU_MEM_F_READ)
    17631879        {
     1880            enmReqType = VTDREQTYPE_READ;
    17641881            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead));
    1765             enmReqType = VTDREQTYPE_READ;
    17661882        }
    17671883        else
    17681884        {
     1885            enmReqType = VTDREQTYPE_WRITE;
    17691886            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite));
    1770             enmReqType = VTDREQTYPE_WRITE;
    17711887        }
    17721888
    1773         uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
    1774         switch (fTtm)
    1775         {
    1776             case VTD_TTM_LEGACY_MODE:
    1777             case VTD_TTM_ABORT_DMA_MODE:
    1778             {
    1779                 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK)
    1780                 {
    1781                 }
    1782             }
    1783         }
     1889        bool fTtmValid = dmarDmaIsTtmValid(pDevIns, uRtaddrReg, idDevice, uIova, enmReqType);
     1890        if (!fTtmValid)
     1891            return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
    17841892
    17851893        return VERR_NOT_IMPLEMENTED;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette