Changeset 87526 in vbox for trunk/src/VBox
- Timestamp:
- Feb 2, 2021 7:20:50 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r87525 r87526 109 109 110 110 /** 111 * IOMMU operation s (transaction) types.111 * IOMMU operation (transaction). 112 112 */ 113 113 typedef enum IOMMUOP … … 125 125 } IOMMUOP; 126 126 AssertCompileSize(IOMMUOP, 4); 127 /** Pointer to a IOMMU operation. */ 128 typedef IOMMUOP *PIOMMUOP; 127 129 128 130 /** … … 135 137 /** The number of offset bits in the system physical address. */ 136 138 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. */ 138 140 uint8_t fPerm; 139 141 /** Padding. */ … … 482 484 static uint16_t const g_auDevTabSegMaxSizes[] = { 0x1ff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f }; 483 485 486 /** 487 * The IOMMU I/O permission names. 488 */ 489 static const char * const g_aszPerm[] = { "none", "read", "write" }; 490 484 491 485 492 #ifndef VBOX_DEVICE_STRUCT_TESTCASE … … 2638 2645 * @param uIova The I/O virtual address to translate. 2639 2646 * @param uDevId The device ID. 2640 * @param f Access The access permissions (IOMMU_IO_PERM_XXX). This is the2641 * permissions for the access being made.2647 * @param fPerm The I/O permissions for this access, see 2648 * IOMMU_IO_PERM_XXX. 2642 2649 * @param pDte The device table entry. 2643 2650 * @param enmOp The IOMMU operation being performed. … … 2647 2654 * @thread Any. 2648 2655 */ 2649 static int iommuAmdPreTranslateChecks(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t f Access, PCDTE_T pDte,2656 static int iommuAmdPreTranslateChecks(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t fPerm, PCDTE_T pDte, 2650 2657 IOMMUOP enmOp, PIOWALKRESULT pWalkResult) 2651 2658 { … … 2676 2683 */ 2677 2684 uint8_t const fDtePerm = (pDte->au64[0] >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK; 2678 if ((f Access & fDtePerm) == fAccess)2685 if ((fPerm & fDtePerm) == fPerm) 2679 2686 { /* likely */ } 2680 2687 else 2681 2688 { 2682 LogFunc(("Permission denied by DTE (f Access=%#x fDtePerm=%#x) -> IOPF\n", fAccess, fDtePerm));2689 LogFunc(("Permission denied by DTE (fPerm=%#x fDtePerm=%#x) -> IOPF\n", fPerm, fDtePerm)); 2683 2690 EVT_IO_PAGE_FAULT_T EvtIoPageFault; 2684 2691 iommuAmdIoPageFaultEventInit(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */, … … 2697 2704 else 2698 2705 { 2699 Assert((f Access & fDtePerm) == fAccess);/* Verify we've checked permissions. */2706 Assert((fPerm & fDtePerm) == fPerm); /* Verify we've checked permissions. */ 2700 2707 pWalkResult->GCPhysSpa = uIova; 2701 2708 pWalkResult->cShift = 0; … … 2737 2744 * @param uIova The I/O virtual address to translate. Must be 4K aligned. 2738 2745 * @param uDevId The device ID. 2739 * @param f Access The access permissions (IOMMU_IO_PERM_XXX). This is the2740 * permissions for the access being made.2746 * @param fPerm The I/O permissions for this access, see 2747 * IOMMU_IO_PERM_XXX. 2741 2748 * @param pDte The device table entry. 2742 2749 * @param enmOp The IOMMU operation being performed. … … 2746 2753 * @thread Any. 2747 2754 */ 2748 static int iommuAmdIoPageTableWalk(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t f Access, PCDTE_T pDte,2755 static int iommuAmdIoPageTableWalk(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, uint8_t fPerm, PCDTE_T pDte, 2749 2756 IOMMUOP enmOp, PIOWALKRESULT pWalkResult) 2750 2757 { … … 2806 2813 /* Check permission bits. */ 2807 2814 uint8_t const fPtePerm = (PtEntity.u64 >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK; 2808 if ((f Access & fPtePerm) == fAccess)2815 if ((fPerm & fPtePerm) == fPerm) 2809 2816 { /* likely */ } 2810 2817 else 2811 2818 { 2812 LogFunc(("Page table entry access denied (uDevId=%#x f Access=%#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)); 2813 2820 EVT_IO_PAGE_FAULT_T EvtIoPageFault; 2814 2821 iommuAmdIoPageFaultEventInit(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */, … … 2975 2982 * @param uIova The I/O virtual address to lookup. 2976 2983 * @param cbAccess The size of the access. 2977 * @param f Access The access permissions (IOMMU_IO_PERM_XXX). This is the2978 * permissions for the access being made.2984 * @param fPerm The I/O permissions for this access, see 2985 * IOMMU_IO_PERM_XXX. 2979 2986 * @param enmOp The IOMMU operation being performed. 2980 2987 * @param pGCPhysSpa Where to store the translated system physical address. … … 2984 2991 * @thread Any. 2985 2992 */ 2986 static int iommuAmdDteLookup(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint8_t f Access,2987 IOMMUOP enmOp,PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)2993 static int iommuAmdDteLookup(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint8_t fPerm, IOMMUOP enmOp, 2994 PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous) 2988 2995 { 2989 2996 PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU); … … 3012 3019 IOWALKRESULT WalkResult; 3013 3020 RT_ZERO(WalkResult); 3014 rc = iommuAmdPreTranslateChecks(pDevIns, uDevId, uIova, f Access, &Dte, enmOp, &WalkResult);3021 rc = iommuAmdPreTranslateChecks(pDevIns, uDevId, uIova, fPerm, &Dte, enmOp, &WalkResult); 3015 3022 if (rc == VINF_SUCCESS) 3016 3023 { … … 3025 3032 for (;;) 3026 3033 { 3027 rc = iommuAmdIoPageTableWalk(pDevIns, uDevId, uIovaPage, f Access, &Dte, enmOp, &WalkResult);3034 rc = iommuAmdIoPageTableWalk(pDevIns, uDevId, uIovaPage, fPerm, &Dte, enmOp, &WalkResult); 3028 3035 if (RT_SUCCESS(rc)) 3029 3036 { … … 3086 3093 Assert(WalkResult.cShift == 0); 3087 3094 Assert(WalkResult.GCPhysSpa == uIova); 3088 Assert((WalkResult.fPerm & f Access) == fAccess);3095 Assert((WalkResult.fPerm & fPerm) == fPerm); 3089 3096 /** @todo IOMMU: Add to IOLTB cache. */ 3090 3097 } … … 3142 3149 3143 3150 /** 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 */ 3159 DECLINLINE(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 */ 3185 DECLINLINE(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 /** 3144 3195 * Memory access transaction from a device. 3145 3196 * … … 3156 3207 * @thread Any. 3157 3208 */ 3158 static DECLCALLBACK(int) iommuAmd DeviceMemAccess(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess,3159 uint32_t fFlags,PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)3209 static DECLCALLBACK(int) iommuAmdMemAccess(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint32_t fFlags, 3210 PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous) 3160 3211 { 3161 3212 /* Validate. */ … … 3170 3221 { 3171 3222 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)); 3193 3226 3194 3227 /** @todo IOMMU: IOTLB cache lookup. */ 3195 3228 3196 3229 /* Lookup the IOVA from the device table. */ 3197 int rc = iommuAmdDteLookup(pDevIns, uDevId, uIova, cbAccess, f Access, enmOp, pGCPhysSpa, pcbContiguous);3230 int rc = iommuAmdDteLookup(pDevIns, uDevId, uIova, cbAccess, fPerm, enmOp, pGCPhysSpa, pcbContiguous); 3198 3231 if (RT_SUCCESS(rc)) 3199 3232 { /* likely */ } 3200 3233 else 3201 LogFunc(("DTE lookup failed! uDevId=%#x uIova=%#RX64 f Access=%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, 3202 3235 cbAccess, rc)); 3203 3236 return rc; … … 3224 3257 * @thread Any. 3225 3258 */ 3226 static DECLCALLBACK(int) iommuAmd DeviceMemBulkAccess(PPDMDEVINS pDevIns, uint16_t uDevId, size_t cIovas,3227 uint64_t const *pauIovas,uint32_t fFlags, PRTGCPHYS paGCPhysSpa)3259 static DECLCALLBACK(int) iommuAmdMemBulkAccess(PPDMDEVINS pDevIns, uint16_t uDevId, size_t cIovas, uint64_t const *pauIovas, 3260 uint32_t fFlags, PRTGCPHYS paGCPhysSpa) 3228 3261 { 3229 3262 /* Validate. */ … … 3239 3272 { 3240 3273 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)); 3262 3278 3263 3279 /** @todo IOMMU: IOTLB cache lookup. */ … … 3267 3283 { 3268 3284 size_t cbContig; 3269 int rc = iommuAmdDteLookup(pDevIns, uDevId, pauIovas[i], X86_PAGE_SIZE, f Access, enmOp, &paGCPhysSpa[i], &cbContig);3285 int rc = iommuAmdDteLookup(pDevIns, uDevId, pauIovas[i], X86_PAGE_SIZE, fPerm, enmOp, &paGCPhysSpa[i], &cbContig); 3270 3286 if (RT_SUCCESS(rc)) 3271 3287 { /* likely */ } 3272 3288 else 3273 3289 { 3274 LogFunc(("Failed! uDevId=%#x uIova=%#RX64 f Access=%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)); 3275 3291 return rc; 3276 3292 } … … 3381 3397 pMsiOut->Data.n.u8Vector = Irte.n.u8Vector; 3382 3398 pMsiOut->Data.n.u3DeliveryMode = Irte.n.u3IntrType; 3383 3384 3399 return VINF_SUCCESS; 3385 3400 } … … 3597 3612 * @param pMsiOut Where to store the remapped MSI. 3598 3613 */ 3599 static DECLCALLBACK(int) iommuAmd DeviceMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)3614 static DECLCALLBACK(int) iommuAmdMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut) 3600 3615 { 3601 3616 /* Validate. */ … … 5012 5027 RT_ZERO(IommuReg); 5013 5028 IommuReg.u32Version = PDM_IOMMUREGCC_VERSION; 5014 IommuReg.pfnMemAccess = iommuAmd DeviceMemAccess;5015 IommuReg.pfnMemBulkAccess = iommuAmd DeviceMemBulkAccess;5016 IommuReg.pfnMsiRemap = iommuAmd DeviceMsiRemap;5029 IommuReg.pfnMemAccess = iommuAmdMemAccess; 5030 IommuReg.pfnMemBulkAccess = iommuAmdMemBulkAccess; 5031 IommuReg.pfnMsiRemap = iommuAmdMsiRemap; 5017 5032 IommuReg.u32TheEnd = PDM_IOMMUREGCC_VERSION; 5018 5033 int rc = PDMDevHlpIommuRegister(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp), &pThis->idxIommu); … … 5348 5363 IommuReg.u32Version = PDM_IOMMUREGCC_VERSION; 5349 5364 IommuReg.idxIommu = pThis->idxIommu; 5350 IommuReg.pfnMemAccess = iommuAmd DeviceMemAccess;5351 IommuReg.pfnMemBulkAccess = iommuAmd DeviceMemBulkAccess;5352 IommuReg.pfnMsiRemap = iommuAmd DeviceMsiRemap;5365 IommuReg.pfnMemAccess = iommuAmdMemAccess; 5366 IommuReg.pfnMemBulkAccess = iommuAmdMemBulkAccess; 5367 IommuReg.pfnMsiRemap = iommuAmdMsiRemap; 5353 5368 IommuReg.u32TheEnd = PDM_IOMMUREGCC_VERSION; 5354 5369 rc = PDMDevHlpIommuSetUpContext(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp));
Note:
See TracChangeset
for help on using the changeset viewer.