VirtualBox

Changeset 89418 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 1, 2021 6:52:41 AM (4 years ago)
Author:
vboxsync
Message:

Intel IOMMU: bugref:9967 Address translation, WIP.

File:
1 edited

Legend:

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

    r89407 r89418  
    151151/** DMA request permission: Write. */
    152152#define DMAR_PERM_WRITE                             RT_BIT(1)
    153 /** DMA request permission: Execute. */
     153/** DMA request permission: Execute (ER). */
    154154#define DMAR_PERM_EXE                               RT_BIT(2)
    155 /** DMA request permission: Supervisor privilege. */
     155/** DMA request permission: Supervisor privilege (PR). */
    156156#define DMAR_PERM_PRIV                              RT_BIT(3)
    157157/** DMA request permissions: All. */
     
    189189    kDmarDiag_Atf_Lct_4_3,
    190190    kDmarDiag_Atf_Lct_5,
     191    kDmarDiag_Atf_Lgn_1_1,
     192    kDmarDiag_Atf_Lgn_1_2,
     193    kDmarDiag_Atf_Lgn_1_3,
    191194    kDmarDiag_Atf_Lrt_1,
    192195    kDmarDiag_Atf_Lrt_2,
     
    198201    kDmarDiag_Atf_Rta_1_2,
    199202    kDmarDiag_Atf_Rta_1_3,
     203    kDmarDiag_Atf_Sgn_5,
    200204    kDmarDiag_Atf_Ssl_1,
    201205    kDmarDiag_Atf_Ssl_2,
     
    262266    DMARDIAG_DESC(Atf_Lct_4_3               ),
    263267    DMARDIAG_DESC(Atf_Lct_5                 ),
     268    DMARDIAG_DESC(Atf_Lgn_1_1               ),
     269    DMARDIAG_DESC(Atf_Lgn_1_2               ),
     270    DMARDIAG_DESC(Atf_Lgn_1_3               ),
    264271    DMARDIAG_DESC(Atf_Lrt_1                 ),
    265272    DMARDIAG_DESC(Atf_Lrt_2                 ),
     
    271278    DMARDIAG_DESC(Atf_Rta_1_2               ),
    272279    DMARDIAG_DESC(Atf_Rta_1_3               ),
     280    DMARDIAG_DESC(Atf_Sgn_5                 ),
    273281    DMARDIAG_DESC(Atf_Ssl_1                 ),
    274282    DMARDIAG_DESC(Atf_Ssl_2                 ),
     
    344352    /** Host-address width (HAW) base address mask. */
    345353    uint64_t                    fHawBaseMask;
    346     /** Maximum guest-address width (MGAW) base address mask. */
    347     uint64_t                    fMgawBaseMask;
     354    /** Maximum guest-address width (MGAW) invalid address mask. */
     355    uint64_t                    fInvMgawMask;
    348356    /** Maximum supported paging level (3, 4 or 5). */
    349     uint8_t                     uMaxPagingLevel;
     357    uint8_t                     cMaxPagingLevel;
    350358    /** DMA request valid permissions mask. */
    351359    uint8_t                     fPermValidMask;
     
    18841892 * @param   pThis               The shared DMAR device state.
    18851893 * @param   pCtxEntry           The context entry.
    1886  * @param   puPagingLevel       Where to store the paging level.
    1887  */
    1888 static bool dmarDrLegacyModeIsAwValid(PCDMAR pThis, PCVTD_CONTEXT_ENTRY_T pCtxEntry, uint8_t *puPagingLevel)
     1894 * @param   pcPagingLevel       Where to store the paging level.
     1895 */
     1896static bool dmarDrLegacyModeIsAwValid(PCDMAR pThis, PCVTD_CONTEXT_ENTRY_T pCtxEntry, uint8_t *pcPagingLevel)
    18891897{
    18901898    uint8_t const fTt     = RT_BF_GET(pCtxEntry->au64[0], VTD_BF_0_CONTEXT_ENTRY_TT);
     
    18941902    Assert(!(fSagaw & ~(RT_BIT(1) | RT_BIT(2) | RT_BIT(3))));
    18951903
    1896     *puPagingLevel = fAw + 2;
     1904    *pcPagingLevel = fAw + 2;
    18971905
    18981906    /* With pass-through, the address width must be the largest AGAW supported by hardware. */
    18991907    if (fTt == VTD_TT_UNTRANSLATED_PT)
    19001908    {
    1901         Assert(pThis->uMaxPagingLevel >= 3 && pThis->uMaxPagingLevel <= 5); /* Paranoia. */
    1902         return *puPagingLevel == pThis->uMaxPagingLevel;
     1909        Assert(pThis->cMaxPagingLevel >= 3 && pThis->cMaxPagingLevel <= 5); /* Paranoia. */
     1910        return *pcPagingLevel == pThis->cMaxPagingLevel;
    19031911    }
    19041912
     
    19671975 * @param   pDevIns         The IOMMU device instance.
    19681976 * @param   SlpEntry        The second-level paging entry.
    1969  * @param   uPagingLevel    The paging level.
     1977 * @param   cPagingLevel    The paging level.
    19701978 * @param   idDomain        The domain ID for the translation.
    19711979 * @param   pAddrRemap      The DMA address remap info.
    19721980 */
    1973 static int dmarDrSecondLevelTranslate(PPDMDEVINS pDevIns, VTD_SLP_ENTRY_T SlpEntry, uint8_t uPagingLevel, uint16_t idDomain,
     1981static int dmarDrSecondLevelTranslate(PPDMDEVINS pDevIns, VTD_SLP_ENTRY_T SlpEntry, uint8_t cPagingLevel, uint16_t idDomain,
    19741982                                      PDMARADDRMAP pAddrRemap)
    19751983{
     
    19831991                                                 VTD_SL_PML5E_VALID_MASK };
    19841992
    1985     /* Mask of valid large-page paging entry bits. */
     1993    /* Mask of valid large-page (1GB, 2MB) paging entries. */
    19861994    static uint64_t const s_auLargePageRsvd[] = { 0,
    19871995                                                  VTD_SL_PDE2M_VALID_MASK,
     
    19911999
    19922000    /* Paranoia. */
    1993     Assert(uPagingLevel >= 3 && uPagingLevel <= 5);
     2001    Assert(cPagingLevel >= 3 && cPagingLevel <= 5);
    19942002    AssertCompile(RT_ELEMENTS(s_auPtEntityRsvd) == RT_ELEMENTS(s_auLargePageRsvd));
    19952003    AssertCompile(RT_ELEMENTS(s_auPtEntityRsvd) == 5);
     2004
     2005    /* Second-level translations restricts input address to an implementation-specific MGAW. */
     2006    uint64_t const uDmaAddr = pAddrRemap->uDmaAddr;
     2007    if (!(uDmaAddr & pThis->fInvMgawMask))
     2008    { /* likely */ }
     2009    else
     2010    {
     2011        if (pAddrRemap->fTtm == VTD_TTM_LEGACY_MODE)
     2012            dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Lgn_1_1, VTDATFAULT_LGN_1_1, pAddrRemap);
     2013        else
     2014            dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Sgn_5, VTDATFAULT_SGN_5, pAddrRemap);
     2015        return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2016    }
    19962017
    19972018    /*
     
    19992020     * Unlike AMD IOMMU paging, here there is no feature for "skipping" levels.
    20002021     */
    2001     uint64_t       uPtEntity    = SlpEntry;
    2002     uint64_t const uDmaAddr     = pAddrRemap->uDmaAddr & pThis->fMgawBaseMask;
    2003     uint64_t const fHawBaseMask = pThis->fHawBaseMask;
    2004     for (int8_t iLevel = uPagingLevel - 1; iLevel >= 0; iLevel--)
     2022    uint64_t uPtEntity = SlpEntry;
     2023    for (int8_t iLevel = cPagingLevel - 1; iLevel >= 0; iLevel--)
    20052024    {
    20062025        /*
     
    20112030            uint16_t const idxPte         = (uDmaAddr >> cLevelShift) & UINT64_C(0x1ff);
    20122031            uint64_t const offPte         = idxPte << 3;
    2013             /** @todo if we validate 63:HAW (since hardware treats it as reserved and we should fault if that's the case, we might not need to & fHawbaseMask here. */
    2014             RTGCPHYS const GCPhysPtEntity = (uPtEntity & fHawBaseMask) | offPte;
     2032            RTGCPHYS const GCPhysPtEntity = uPtEntity | offPte;
    20152033            int const rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysPtEntity, &uPtEntity, sizeof(uPtEntity));
    20162034            if (RT_SUCCESS(rc))
     
    21682186                                    {
    21692187                                        /* Validate the address width and get the paging level. */
    2170                                         uint8_t uPagingLevel;
    2171                                         if (dmarDrLegacyModeIsAwValid(pThis, &CtxEntry, &uPagingLevel))
     2188                                        uint8_t cPagingLevel;
     2189                                        if (dmarDrLegacyModeIsAwValid(pThis, &CtxEntry, &cPagingLevel))
    21722190                                        {
    21732191                                            /* Read the SLPTPTR from guest memory. */
     
    21782196                                            {
    21792197                                                /* Finally... perform second-level translation. */
    2180                                                 return dmarDrSecondLevelTranslate(pDevIns, SlpEntry, uPagingLevel, idDomain,
     2198                                                return dmarDrSecondLevelTranslate(pDevIns, SlpEntry, cPagingLevel, idDomain,
    21812199                                                                                  pAddrRemap);
    21822200                                            }
     
    34613479        dmarRegWriteRaw64(pThis, VTD_MMIO_OFF_CAP_REG, pThis->fCapReg);
    34623480
    3463         pThis->fHawBaseMask    = ~(UINT64_MAX << cGstPhysAddrBits) & X86_PAGE_4K_BASE_MASK;
    3464         pThis->fMgawBaseMask   = pThis->fHawBaseMask;
    3465         pThis->uMaxPagingLevel = vtdCapRegGetMaxPagingLevel(fSagaw);
     3481        pThis->fHawBaseMask = ~(UINT64_MAX << cGstPhysAddrBits) & X86_PAGE_4K_BASE_MASK;
     3482        pThis->fInvMgawMask = UINT64_MAX << cGstPhysAddrBits;
     3483        pThis->cMaxPagingLevel = vtdCapRegGetMaxPagingLevel(fSagaw);
    34663484    }
    34673485
     
    37303748    uint16_t const offFrcd   = RT_BF_GET(pThis->fCapReg, VTD_BF_CAP_REG_FRO);
    37313749    uint16_t const offIva    = RT_BF_GET(pThis->fExtCapReg, VTD_BF_ECAP_REG_IRO);
    3732     LogRel(("%s: VER=%u.%u CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%#x HAW=%#RX64 MGAW=%#RX64 FRO=%#x IRO=%#x) mapped at %#RGp\n",
     3750    LogRel(("%s: VER=%u.%u CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%#x HAW_Base=%#RX64 MGAW_Inv=%#RX64 FRO=%#x IRO=%#x) mapped at %#RGp\n",
    37333751            DMAR_LOG_PFX, RT_BF_GET(uVerReg, VTD_BF_VER_REG_MAX), RT_BF_GET(uVerReg, VTD_BF_VER_REG_MIN),
    3734             pThis->fCapReg, pThis->fExtCapReg, cMgawBits, fSagaw, pThis->fHawBaseMask, pThis->fMgawBaseMask, offFrcd, offIva,
     3752            pThis->fCapReg, pThis->fExtCapReg, cMgawBits, fSagaw, pThis->fHawBaseMask, pThis->fInvMgawMask, offFrcd, offIva,
    37353753            DMAR_MMIO_BASE_PHYSADDR));
    37363754
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