VirtualBox

Changeset 87526 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 2, 2021 7:20:50 AM (4 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 IOTLB cache bits.

File:
1 edited

Legend:

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

    r87525 r87526  
    109109
    110110/**
    111  * IOMMU operations (transaction) types.
     111 * IOMMU operation (transaction).
    112112 */
    113113typedef enum IOMMUOP
     
    125125} IOMMUOP;
    126126AssertCompileSize(IOMMUOP, 4);
     127/** Pointer to a IOMMU operation. */
     128typedef IOMMUOP *PIOMMUOP;
    127129
    128130/**
     
    135137    /** The number of offset bits in the system physical address. */
    136138    uint8_t         cShift;
    137     /** The I/O permissions allowed for this translation (IOMMU_IO_PERM_XXX). */
     139    /** The I/O permissions allowed for this translation, see IOMMU_IO_PERM_XXX. */
    138140    uint8_t         fPerm;
    139141    /** Padding. */
     
    482484static uint16_t const g_auDevTabSegMaxSizes[] = { 0x1ff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f };
    483485
     486/**
     487 * The IOMMU I/O permission names.
     488 */
     489static const char * const g_aszPerm[] = { "none", "read", "write" };
     490
    484491
    485492#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     
    26382645 * @param   uIova           The I/O virtual address to translate.
    26392646 * @param   uDevId          The device ID.
    2640  * @param   fAccess         The access permissions (IOMMU_IO_PERM_XXX). This is the
    2641  *                          permissions for the access being made.
     2647 * @param   fPerm           The I/O permissions for this access, see
     2648 *                          IOMMU_IO_PERM_XXX.
    26422649 * @param   pDte            The device table entry.
    26432650 * @param   enmOp           The IOMMU operation being performed.
     
    26472654 * @thread  Any.
    26482655 */
    2649 static int iommuAmdPreTranslateChecks(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t fAccess, PCDTE_T pDte,
     2656static int iommuAmdPreTranslateChecks(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t fPerm, PCDTE_T pDte,
    26502657                                      IOMMUOP enmOp, PIOWALKRESULT pWalkResult)
    26512658{
     
    26762683     */
    26772684    uint8_t const fDtePerm  = (pDte->au64[0] >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK;
    2678     if ((fAccess & fDtePerm) == fAccess)
     2685    if ((fPerm & fDtePerm) == fPerm)
    26792686    { /* likely */ }
    26802687    else
    26812688    {
    2682         LogFunc(("Permission denied by DTE (fAccess=%#x fDtePerm=%#x) -> IOPF\n", fAccess, fDtePerm));
     2689        LogFunc(("Permission denied by DTE (fPerm=%#x fDtePerm=%#x) -> IOPF\n", fPerm, fDtePerm));
    26832690        EVT_IO_PAGE_FAULT_T EvtIoPageFault;
    26842691        iommuAmdIoPageFaultEventInit(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */,
     
    26972704    else
    26982705    {
    2699         Assert((fAccess & fDtePerm) == fAccess);    /* Verify we've checked permissions. */
     2706        Assert((fPerm & fDtePerm) == fPerm);   /* Verify we've checked permissions. */
    27002707        pWalkResult->GCPhysSpa = uIova;
    27012708        pWalkResult->cShift    = 0;
     
    27372744 * @param   uIova           The I/O virtual address to translate. Must be 4K aligned.
    27382745 * @param   uDevId          The device ID.
    2739  * @param   fAccess         The access permissions (IOMMU_IO_PERM_XXX). This is the
    2740  *                          permissions for the access being made.
     2746 * @param   fPerm           The I/O permissions for this access, see
     2747 *                          IOMMU_IO_PERM_XXX.
    27412748 * @param   pDte            The device table entry.
    27422749 * @param   enmOp           The IOMMU operation being performed.
     
    27462753 * @thread  Any.
    27472754 */
    2748 static int iommuAmdIoPageTableWalk(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t fAccess, PCDTE_T pDte,
     2755static int iommuAmdIoPageTableWalk(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t fPerm, PCDTE_T pDte,
    27492756                                   IOMMUOP enmOp, PIOWALKRESULT pWalkResult)
    27502757{
     
    28062813        /* Check permission bits. */
    28072814        uint8_t const fPtePerm  = (PtEntity.u64 >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK;
    2808         if ((fAccess & fPtePerm) == fAccess)
     2815        if ((fPerm & fPtePerm) == fPerm)
    28092816        { /* likely */ }
    28102817        else
    28112818        {
    2812             LogFunc(("Page table entry access denied (uDevId=%#x fAccess=%#x fPtePerm=%#x) -> IOPF\n", uDevId, fAccess, fPtePerm));
     2819            LogFunc(("Page table entry access denied (uDevId=%#x fPerm=%#x fPtePerm=%#x) -> IOPF\n", uDevId, fPerm, fPtePerm));
    28132820            EVT_IO_PAGE_FAULT_T EvtIoPageFault;
    28142821            iommuAmdIoPageFaultEventInit(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */,
     
    29752982 * @param   uIova           The I/O virtual address to lookup.
    29762983 * @param   cbAccess        The size of the access.
    2977  * @param   fAccess         The access permissions (IOMMU_IO_PERM_XXX). This is the
    2978  *                          permissions for the access being made.
     2984 * @param   fPerm           The I/O permissions for this access, see
     2985 *                          IOMMU_IO_PERM_XXX.
    29792986 * @param   enmOp           The IOMMU operation being performed.
    29802987 * @param   pGCPhysSpa      Where to store the translated system physical address.
     
    29842991 * @thread  Any.
    29852992 */
    2986 static int iommuAmdDteLookup(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint8_t fAccess,
    2987                              IOMMUOP enmOp, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
     2993static int iommuAmdDteLookup(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint8_t fPerm, IOMMUOP enmOp,
     2994                             PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
    29882995{
    29892996    PIOMMU   pThis        = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     
    30123019                    IOWALKRESULT WalkResult;
    30133020                    RT_ZERO(WalkResult);
    3014                     rc = iommuAmdPreTranslateChecks(pDevIns, uDevId, uIova, fAccess, &Dte, enmOp, &WalkResult);
     3021                    rc = iommuAmdPreTranslateChecks(pDevIns, uDevId, uIova, fPerm, &Dte, enmOp, &WalkResult);
    30153022                    if (rc == VINF_SUCCESS)
    30163023                    {
     
    30253032                        for (;;)
    30263033                        {
    3027                             rc = iommuAmdIoPageTableWalk(pDevIns, uDevId, uIovaPage, fAccess, &Dte, enmOp, &WalkResult);
     3034                            rc = iommuAmdIoPageTableWalk(pDevIns, uDevId, uIovaPage, fPerm, &Dte, enmOp, &WalkResult);
    30283035                            if (RT_SUCCESS(rc))
    30293036                            {
     
    30863093                        Assert(WalkResult.cShift    == 0);
    30873094                        Assert(WalkResult.GCPhysSpa == uIova);
    3088                         Assert((WalkResult.fPerm & fAccess) == fAccess);
     3095                        Assert((WalkResult.fPerm & fPerm) == fPerm);
    30893096                        /** @todo IOMMU: Add to IOLTB cache. */
    30903097                    }
     
    31423149
    31433150/**
     3151 * Gets the I/O permission and IOMMU operation type for the given access flags.
     3152 *
     3153 * @param   fFlags      The PDM IOMMU flags, PDMIOMMU_MEM_F_XXX.
     3154 * @param   penmOp      Where to store the IOMMU operation.
     3155 * @param   pfPerm      Where to store the IOMMU I/O permission.
     3156 * @param   pStatRead   The stat counter to increment for a read operation.
     3157 * @param   pStatWrite  The stat counter to increment for a write operation.
     3158 */
     3159DECLINLINE(void) iommuAmdMemAccessGetPermAndOp(uint32_t fFlags, PIOMMUOP penmOp, uint8_t *pfPerm, PSTAMCOUNTER pStatRead,
     3160                                               PSTAMCOUNTER pStatWrite)
     3161{
     3162    if (fFlags & PDMIOMMU_MEM_F_WRITE)
     3163    {
     3164        *penmOp = IOMMUOP_MEM_WRITE;
     3165        *pfPerm = IOMMU_IO_PERM_WRITE;
     3166        STAM_COUNTER_INC(pStatWrite);
     3167    }
     3168    else
     3169    {
     3170        Assert(fFlags & PDMIOMMU_MEM_F_READ);
     3171        *penmOp = IOMMUOP_MEM_READ;
     3172        *pfPerm = IOMMU_IO_PERM_READ;
     3173        STAM_COUNTER_INC(pStatRead);
     3174    }
     3175}
     3176
     3177
     3178#ifdef LOG_ENABLED
     3179/**
     3180 * Gets the descriptive I/O permission name for a memory access.
     3181 *
     3182 * @returns The I/O permission name.
     3183 * @param   fPerm   The I/O permissions for the access, see IOMMU_IO_PERM_XXX.
     3184 */
     3185DECLINLINE(const char *) iommuAmdMemAccessGetPermName(uint8_t fPerm)
     3186{
     3187    /* We shouldn't construct an access with "none" or "read+write" (must be read or write) permissions. */
     3188    Assert(fPerm > 0 && fPerm < RT_ELEMENTS(g_aszPerm));
     3189    return g_aszPerm[fPerm];
     3190}
     3191#endif  /* LOG_ENABLED */
     3192
     3193
     3194/**
    31443195 * Memory access transaction from a device.
    31453196 *
     
    31563207 * @thread  Any.
    31573208 */
    3158 static DECLCALLBACK(int) iommuAmdDeviceMemAccess(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess,
    3159                                                  uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
     3209static DECLCALLBACK(int) iommuAmdMemAccess(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint32_t fFlags,
     3210                                           PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
    31603211{
    31613212    /* Validate. */
     
    31703221    {
    31713222        IOMMUOP enmOp;
    3172         uint8_t fAccess;
    3173         if (fFlags & PDMIOMMU_MEM_F_READ)
    3174         {
    3175             enmOp   = IOMMUOP_MEM_READ;
    3176             fAccess = IOMMU_IO_PERM_READ;
    3177             STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead));
    3178         }
    3179         else
    3180         {
    3181             Assert(fFlags & PDMIOMMU_MEM_F_WRITE);
    3182             enmOp   = IOMMUOP_MEM_WRITE;
    3183             fAccess = IOMMU_IO_PERM_WRITE;
    3184             STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite));
    3185         }
    3186 
    3187 #ifdef VBOX_STRICT
    3188         static const char * const s_apszAccess[] = { "none", "read", "write" };
    3189         Assert(fAccess > 0 && fAccess < RT_ELEMENTS(s_apszAccess));
    3190         const char *pszAccess = s_apszAccess[fAccess];
    3191         LogFlowFunc(("uDevId=%#x uIova=%#RX64 szAccess=%s cbAccess=%zu\n", uDevId, uIova, pszAccess, cbAccess));
    3192 #endif
     3223        uint8_t fPerm;
     3224        iommuAmdMemAccessGetPermAndOp(fFlags, &enmOp, &fPerm, &pThis->CTX_SUFF_Z(StatMemRead), &pThis->CTX_SUFF_Z(StatMemWrite));
     3225        LogFlowFunc(("%s: uDevId=%#x uIova=%#RX64 cb=%zu\n", iommuAmdMemAccessGetPermName(fPerm), uDevId, uIova, cbAccess));
    31933226
    31943227        /** @todo IOMMU: IOTLB cache lookup. */
    31953228
    31963229        /* Lookup the IOVA from the device table. */
    3197         int rc = iommuAmdDteLookup(pDevIns, uDevId, uIova, cbAccess, fAccess, enmOp, pGCPhysSpa, pcbContiguous);
     3230        int rc = iommuAmdDteLookup(pDevIns, uDevId, uIova, cbAccess, fPerm, enmOp, pGCPhysSpa, pcbContiguous);
    31983231        if (RT_SUCCESS(rc))
    31993232        { /* likely */ }
    32003233        else
    3201             LogFunc(("DTE lookup failed! uDevId=%#x uIova=%#RX64 fAccess=%u cbAccess=%zu rc=%#Rrc\n", uDevId, uIova, fAccess,
     3234            LogFunc(("DTE lookup failed! uDevId=%#x uIova=%#RX64 fPerm=%u cbAccess=%zu rc=%#Rrc\n", uDevId, uIova, fPerm,
    32023235                     cbAccess, rc));
    32033236        return rc;
     
    32243257 * @thread  Any.
    32253258 */
    3226 static DECLCALLBACK(int) iommuAmdDeviceMemBulkAccess(PPDMDEVINS pDevIns, uint16_t uDevId, size_t cIovas,
    3227                                                      uint64_t const *pauIovas, uint32_t fFlags, PRTGCPHYS paGCPhysSpa)
     3259static DECLCALLBACK(int) iommuAmdMemBulkAccess(PPDMDEVINS pDevIns, uint16_t uDevId, size_t cIovas, uint64_t const *pauIovas,
     3260                                               uint32_t fFlags, PRTGCPHYS paGCPhysSpa)
    32283261{
    32293262    /* Validate. */
     
    32393272    {
    32403273        IOMMUOP enmOp;
    3241         uint8_t fAccess;
    3242         if (fFlags & PDMIOMMU_MEM_F_READ)
    3243         {
    3244             enmOp   = IOMMUOP_MEM_READ;
    3245             fAccess = IOMMU_IO_PERM_READ;
    3246             STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemBulkRead));
    3247         }
    3248         else
    3249         {
    3250             Assert(fFlags & PDMIOMMU_MEM_F_WRITE);
    3251             enmOp   = IOMMUOP_MEM_WRITE;
    3252             fAccess = IOMMU_IO_PERM_WRITE;
    3253             STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemBulkWrite));
    3254         }
    3255 
    3256 #ifdef VBOX_STRICT
    3257         static const char * const s_apszAccess[] = { "none", "read", "write" };
    3258         Assert(fAccess > 0 && fAccess < RT_ELEMENTS(s_apszAccess));
    3259         const char *pszAccess = s_apszAccess[fAccess];
    3260         LogFlowFunc(("uDevId=%#x cIovas=%zu szAccess=%s\n", uDevId, cIovas, pszAccess));
    3261 #endif
     3274        uint8_t fPerm;
     3275        iommuAmdMemAccessGetPermAndOp(fFlags, &enmOp, &fPerm, &pThis->CTX_SUFF_Z(StatMemBulkRead),
     3276                                      &pThis->CTX_SUFF_Z(StatMemBulkWrite));
     3277        LogFlowFunc(("%s: uDevId=%#x cIovas=%zu\n", iommuAmdMemAccessGetPermName(fPerm), uDevId, cIovas));
    32623278
    32633279        /** @todo IOMMU: IOTLB cache lookup. */
     
    32673283        {
    32683284            size_t cbContig;
    3269             int rc = iommuAmdDteLookup(pDevIns, uDevId, pauIovas[i], X86_PAGE_SIZE, fAccess, enmOp, &paGCPhysSpa[i], &cbContig);
     3285            int rc = iommuAmdDteLookup(pDevIns, uDevId, pauIovas[i], X86_PAGE_SIZE, fPerm, enmOp, &paGCPhysSpa[i], &cbContig);
    32703286            if (RT_SUCCESS(rc))
    32713287            { /* likely */ }
    32723288            else
    32733289            {
    3274                 LogFunc(("Failed! uDevId=%#x uIova=%#RX64 fAccess=%u rc=%Rrc\n", uDevId, pauIovas[i], fAccess, rc));
     3290                LogFunc(("Failed! uDevId=%#x uIova=%#RX64 fPerm=%u rc=%Rrc\n", uDevId, pauIovas[i], fPerm, rc));
    32753291                return rc;
    32763292            }
     
    33813397                    pMsiOut->Data.n.u8Vector       = Irte.n.u8Vector;
    33823398                    pMsiOut->Data.n.u3DeliveryMode = Irte.n.u3IntrType;
    3383 
    33843399                    return VINF_SUCCESS;
    33853400                }
     
    35973612 * @param   pMsiOut     Where to store the remapped MSI.
    35983613 */
    3599 static DECLCALLBACK(int) iommuAmdDeviceMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
     3614static DECLCALLBACK(int) iommuAmdMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
    36003615{
    36013616    /* Validate. */
     
    50125027    RT_ZERO(IommuReg);
    50135028    IommuReg.u32Version       = PDM_IOMMUREGCC_VERSION;
    5014     IommuReg.pfnMemAccess     = iommuAmdDeviceMemAccess;
    5015     IommuReg.pfnMemBulkAccess = iommuAmdDeviceMemBulkAccess;
    5016     IommuReg.pfnMsiRemap      = iommuAmdDeviceMsiRemap;
     5029    IommuReg.pfnMemAccess     = iommuAmdMemAccess;
     5030    IommuReg.pfnMemBulkAccess = iommuAmdMemBulkAccess;
     5031    IommuReg.pfnMsiRemap      = iommuAmdMsiRemap;
    50175032    IommuReg.u32TheEnd        = PDM_IOMMUREGCC_VERSION;
    50185033    int rc = PDMDevHlpIommuRegister(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp), &pThis->idxIommu);
     
    53485363    IommuReg.u32Version       = PDM_IOMMUREGCC_VERSION;
    53495364    IommuReg.idxIommu         = pThis->idxIommu;
    5350     IommuReg.pfnMemAccess     = iommuAmdDeviceMemAccess;
    5351     IommuReg.pfnMemBulkAccess = iommuAmdDeviceMemBulkAccess;
    5352     IommuReg.pfnMsiRemap      = iommuAmdDeviceMsiRemap;
     5365    IommuReg.pfnMemAccess     = iommuAmdMemAccess;
     5366    IommuReg.pfnMemBulkAccess = iommuAmdMemBulkAccess;
     5367    IommuReg.pfnMsiRemap      = iommuAmdMsiRemap;
    53535368    IommuReg.u32TheEnd        = PDM_IOMMUREGCC_VERSION;
    53545369    rc = PDMDevHlpIommuSetUpContext(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp));
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