VirtualBox

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


Ignore:
Timestamp:
Jun 1, 2021 7:57:29 AM (3 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

    r89418 r89419  
    476476typedef struct DMARIOTLBE
    477477{
    478     RTGCPHYS    GCPhysBase;
    479     uint8_t     cShift;
    480     uint8_t     fPerm;
    481     uint16_t    idDomain;
    482     uint16_t    uPadding0;
     478    /** The system-physical base address of the translation. */
     479    RTGCPHYS            GCPhysBase;
     480    /** The page shift of the translation. */
     481    uint8_t             cShift;
     482    /** The permissions granted. */
     483    uint8_t             fPerm;
     484    /** The domain ID of the translated region. */
     485    uint16_t            idDomain;
    483486} DMARIOTLBE;
    484487/** Pointer to an IOTLB entry. */
     
    488491
    489492/**
    490  * DMA Address Remapping Information.
    491  */
    492 typedef struct DMARADDRMAP
    493 {
    494     /** The device ID (bus, device, function). */
    495     uint16_t                idDevice;
     493 * DMA Address Request.
     494 */
     495typedef struct DMARADDRREQ
     496{
     497    /** The address being accessed. */
     498    uint64_t            uDmaAddr;
     499    /** The size of the access (in bytes). */
     500    size_t              cbDma;
    496501    /** The requested permissions (DMAR_PERM_XXX). */
    497     uint8_t                 fReqPerm;
     502    uint8_t             fReqPerm;
     503    /** The source device ID (bus, device, function). */
     504    uint16_t            idDevice;
     505    /** The PASID if present (can be NIL_PCIPASID). */
     506    PCIPASID            Pasid;
     507    /* The address translation type. */
     508    PCIADDRTYPE         enmAddrType;
     509    /** The request type. */
     510    VTDREQTYPE          enmReqType;
     511} DMARADDRREQ;
     512/** Pointer to a DMA address request. */
     513typedef DMARADDRREQ *PDMARADDRREQ;
     514/** Pointer to a const DMA request. */
     515typedef DMARADDRREQ const *PCDMARADDRREQ;
     516
     517/**
     518 * DMA Address Remap Info.
     519 */
     520typedef struct DMARADDRREMAP
     521{
     522    /* The DMA address request. */
     523    DMARADDRREQ         AddrReq;
     524    /** The table translation mode (VTD_TTM_XXX). */
     525    uint8_t             fTtm;
    498526    /** The fault processing disabled (FPD) bit. */
    499     uint8_t                 fFpd;
    500     /** The PASID if present, can be NIL_PCIPASID. */
    501     PCIPASID                Pasid;
    502     /* The address type of the memory request. */
    503     PCIADDRTYPE             enmAddrType;
    504     /** The type of the translation request. */
    505     VTDREQTYPE              enmReqType;
    506     /** The table translation mode (VTD_TTM_XXX). */
    507     uint8_t                 fTtm;
    508     uint8_t                 uPadding[7];
    509     /** The DMA address being accessed. */
    510     uint64_t                uDmaAddr;
    511     /** The size of the DMA access (in bytes). */
    512     size_t                  cbDma;
    513 
    514     /** The IOTLBE for this remapping. */
    515     DMARIOTLBE              Iotlbe;
     527    uint8_t             fFpd;
     528
     529    /** The IOTLBE results for this remapping. */
     530    DMARIOTLBE          Iotlbe;
    516531    /** The size of the contiguous translated region (in bytes). */
    517     size_t                  cbContiguous;
    518 } DMARADDRMAP;
    519 /** Pointer to a DMA address remapping object. */
    520 typedef DMARADDRMAP *PDMARADDRMAP;
    521 /** Pointer to a const DMA address remapping object. */
    522 typedef DMARADDRMAP const *PCDMARADDRMAP;
     532    size_t              cbContiguous;
     533} DMARADDRREMAP;
     534/** Pointer to a DMA remap info. */
     535typedef DMARADDRREMAP *PDMARADDRREMAP;
     536/** Pointer to a const DMA remap info. */
     537typedef DMARADDRREMAP const *PCDMARADDRREMAP;
    523538
    524539
     
    14881503 * @param   pAddrRemap  The DMA address remap info.
    14891504 */
    1490 static void dmarAtFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDATFAULT enmAtFault, PCDMARADDRMAP pAddrRemap)
     1505static void dmarAtFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDATFAULT enmAtFault, PCDMARADDRREMAP pAddrRemap)
    14911506{
    14921507    /*
     
    14961511    if (!pAddrRemap->fFpd)
    14971512    {
    1498         uint8_t const fType1 = pAddrRemap->enmReqType & RT_BIT(1);
    1499         uint8_t const fType2 = pAddrRemap->enmReqType & RT_BIT(0);
    1500         uint8_t const fExec  = pAddrRemap->fReqPerm & DMAR_PERM_EXE;
    1501         uint8_t const fPriv  = pAddrRemap->fReqPerm & DMAR_PERM_PRIV;
    1502         uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID,  pAddrRemap->idDevice)
     1513        uint8_t const fType1 = pAddrRemap->AddrReq.enmReqType & RT_BIT(1);
     1514        uint8_t const fType2 = pAddrRemap->AddrReq.enmReqType & RT_BIT(0);
     1515        uint8_t const fExec  = pAddrRemap->AddrReq.fReqPerm & DMAR_PERM_EXE;
     1516        uint8_t const fPriv  = pAddrRemap->AddrReq.fReqPerm & DMAR_PERM_PRIV;
     1517        uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID,  pAddrRemap->AddrReq.idDevice)
    15031518                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T2,   fType2)
    1504                                | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PP,   PCIPASID_IS_VALID(pAddrRemap->Pasid))
     1519                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PP,   PCIPASID_IS_VALID(pAddrRemap->AddrReq.Pasid))
    15051520                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_EXE,  fExec)
    15061521                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PRIV, fPriv)
    15071522                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR,   enmAtFault)
    1508                                | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PV,   PCIPASID_VAL(pAddrRemap->Pasid))
    1509                                | RT_BF_MAKE(VTD_BF_1_FRCD_REG_AT,   pAddrRemap->enmAddrType)
     1523                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PV,   PCIPASID_VAL(pAddrRemap->AddrReq.Pasid))
     1524                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_AT,   pAddrRemap->AddrReq.enmAddrType)
    15101525                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T1,   fType1)
    15111526                               | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F,    1);
    1512         uint64_t const uFrcdLo = pAddrRemap->uDmaAddr & X86_PAGE_BASE_MASK;
     1527        uint64_t const uFrcdLo = pAddrRemap->AddrReq.uDmaAddr & X86_PAGE_BASE_MASK;
    15131528        dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo);
    15141529    }
     
    18921907 * @param   pThis               The shared DMAR device state.
    18931908 * @param   pCtxEntry           The context entry.
    1894  * @param   pcPagingLevel       Where to store the paging level.
     1909 * @param   pcPagingLevel       Where to store the paging level. Optional, can be
     1910 *                              NULL.
    18951911 */
    18961912static bool dmarDrLegacyModeIsAwValid(PCDMAR pThis, PCVTD_CONTEXT_ENTRY_T pCtxEntry, uint8_t *pcPagingLevel)
     
    19021918    Assert(!(fSagaw & ~(RT_BIT(1) | RT_BIT(2) | RT_BIT(3))));
    19031919
    1904     *pcPagingLevel = fAw + 2;
     1920    uint8_t const cPagingLevel = fAw + 2;
     1921    if (pcPagingLevel)
     1922        *pcPagingLevel = cPagingLevel;
    19051923
    19061924    /* With pass-through, the address width must be the largest AGAW supported by hardware. */
     
    19081926    {
    19091927        Assert(pThis->cMaxPagingLevel >= 3 && pThis->cMaxPagingLevel <= 5); /* Paranoia. */
    1910         return *pcPagingLevel == pThis->cMaxPagingLevel;
     1928        return cPagingLevel == pThis->cMaxPagingLevel;
    19111929    }
    19121930
     
    19801998 */
    19811999static int dmarDrSecondLevelTranslate(PPDMDEVINS pDevIns, VTD_SLP_ENTRY_T SlpEntry, uint8_t cPagingLevel, uint16_t idDomain,
    1982                                       PDMARADDRMAP pAddrRemap)
     2000                                      PDMARADDRREMAP pAddrRemap)
    19832001{
    19842002    PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PCDMAR);
     
    20042022
    20052023    /* Second-level translations restricts input address to an implementation-specific MGAW. */
    2006     uint64_t const uDmaAddr = pAddrRemap->uDmaAddr;
     2024    uint64_t const uDmaAddr = pAddrRemap->AddrReq.uDmaAddr;
    20072025    if (!(uDmaAddr & pThis->fInvMgawMask))
    20082026    { /* likely */ }
     
    20502068         * See Intel spec. 7.1.3 "Fault conditions and Remapping hardware behavior for various request".
    20512069         */
    2052         uint8_t const fReqPerm = pAddrRemap->fReqPerm & pThis->fPermValidMask;
     2070        uint8_t const fReqPerm = pAddrRemap->AddrReq.fReqPerm & pThis->fPermValidMask;
    20532071        uint8_t const fPtPerm  = uPtEntity & pThis->fPermValidMask;
    20542072        if ((fPtPerm & fReqPerm) == fReqPerm)
     
    21282146 * @param   pAddrRemap      The DMA address remap info.
    21292147 */
    2130 static int dmarDrLegacyModeRemapAddr(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, PDMARADDRMAP pAddrRemap)
     2148static int dmarDrLegacyModeRemapAddr(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, PDMARADDRREMAP pAddrRemap)
    21312149{
    21322150    Assert(pAddrRemap->fTtm == VTD_TTM_LEGACY_MODE);    /* Paranoia. */
    21332151
    21342152    /* Read the root-entry from guest memory. */
    2135     uint8_t const idxRootEntry = RT_HI_U8(pAddrRemap->idDevice);
     2153    uint8_t const idxRootEntry = RT_HI_U8(pAddrRemap->AddrReq.idDevice);
    21362154    VTD_ROOT_ENTRY_T RootEntry;
    21372155    int rc = dmarDrReadRootEntry(pDevIns, uRtaddrReg, idxRootEntry, &RootEntry);
     
    21502168                /* Read the context-entry from guest memory. */
    21512169                RTGCPHYS const GCPhysCtxTable = RT_BF_GET(uRootEntryQword0, VTD_BF_0_ROOT_ENTRY_CTP);
    2152                 uint8_t const idxCtxEntry = RT_LO_U8(pAddrRemap->idDevice);
     2170                uint8_t const idxCtxEntry = RT_LO_U8(pAddrRemap->AddrReq.idDevice);
    21532171                VTD_CONTEXT_ENTRY_T CtxEntry;
    21542172                rc = dmarDrReadCtxEntry(pDevIns, GCPhysCtxTable, idxCtxEntry, &CtxEntry);
     
    21832201                                     * through SLPTPTR. Translated requests and Translation Requests are blocked.
    21842202                                     */
    2185                                     if (pAddrRemap->enmAddrType == PCIADDRTYPE_UNTRANSLATED)
     2203                                    if (pAddrRemap->AddrReq.enmAddrType == PCIADDRTYPE_UNTRANSLATED)
    21862204                                    {
    21872205                                        /* Validate the address width and get the paging level. */
     
    22182236                                    if (pThis->fExtCapReg & VTD_BF_ECAP_REG_PT_MASK)
    22192237                                    {
    2220                                         if (pAddrRemap->enmAddrType == PCIADDRTYPE_UNTRANSLATED)
     2238                                        if (pAddrRemap->AddrReq.enmAddrType == PCIADDRTYPE_UNTRANSLATED)
    22212239                                        {
    22222240                                            /** @todo Check AW == maximum SAGAW bit? */
    2223                                             pAddrRemap->Iotlbe.GCPhysBase = pAddrRemap->uDmaAddr & X86_PAGE_4K_BASE_MASK;
     2241                                            pAddrRemap->Iotlbe.GCPhysBase = pAddrRemap->AddrReq.uDmaAddr & X86_PAGE_4K_BASE_MASK;
    22242242                                            pAddrRemap->Iotlbe.cShift     = X86_PAGE_4K_SHIFT;
    22252243                                            pAddrRemap->Iotlbe.fPerm      = DMAR_PERM_ALL;
    22262244                                            pAddrRemap->Iotlbe.idDomain   = idDomain;
    2227                                             pAddrRemap->cbContiguous      = pAddrRemap->cbDma;
     2245                                            pAddrRemap->cbContiguous      = pAddrRemap->AddrReq.cbDma;
    22282246                                            return VINF_SUCCESS;
    22292247                                        }
     
    22812299 * @param   pAddrRemap      The DMA address remap info.
    22822300 */
    2283 static int dmarDrScalableModeRemapAddr(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, PDMARADDRMAP pAddrRemap)
     2301static int dmarDrScalableModeRemapAddr(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, PDMARADDRREMAP pAddrRemap)
    22842302{
    22852303    PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     
    23672385
    23682386        uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
    2369         DMARADDRMAP AddrRemap;
     2387        DMARADDRREMAP AddrRemap;
    23702388        RT_ZERO(AddrRemap);
    2371         AddrRemap.idDevice     = idDevice;
    2372         AddrRemap.fReqPerm     = fReqPerm;
    2373         AddrRemap.Pasid        = NIL_PCIPASID;
    2374         AddrRemap.enmAddrType  = PCIADDRTYPE_UNTRANSLATED;
    2375         AddrRemap.enmReqType   = enmReqType;
    2376         AddrRemap.fTtm         = fTtm;
    2377         AddrRemap.uDmaAddr     = uIova;
    2378         AddrRemap.cbDma        = cbIova;
    2379         AddrRemap.Iotlbe.GCPhysBase = NIL_RTGCPHYS;
     2389        AddrRemap.AddrReq.uDmaAddr    = uIova;
     2390        AddrRemap.AddrReq.cbDma       = cbIova;
     2391        AddrRemap.AddrReq.fReqPerm    = fReqPerm;
     2392        AddrRemap.AddrReq.idDevice    = idDevice;
     2393        AddrRemap.AddrReq.Pasid       = NIL_PCIPASID;
     2394        AddrRemap.AddrReq.enmAddrType = PCIADDRTYPE_UNTRANSLATED;
     2395        AddrRemap.AddrReq.enmReqType  = enmReqType;
     2396        AddrRemap.fTtm                = fTtm;
     2397        AddrRemap.Iotlbe.GCPhysBase   = NIL_RTGCPHYS;
    23802398
    23812399        int rc;
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