Changeset 87506 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Feb 1, 2021 3:18:35 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142530
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r87499 r87506 2912 2912 2913 2913 /** 2914 * Checks whether two I/O walk results are physically contiguous. 2915 * 2916 * @returns @c true if they are physically contiguous, @c false otherwise. 2917 * @param pWalkResultPrev The I/O walk result of the previous page. 2918 * @param pWalkResult The I/O walk result of the current page. 2919 */ 2920 DECL_FORCE_INLINE(bool) iommuAmdDteLookupIsAddrPhysContig(PCIOWALKRESULT pWalkResultPrev, PCIOWALKRESULT pWalkResult) 2921 { 2922 size_t const cbPrev = RT_BIT_64(pWalkResultPrev->cShift); 2923 RTGCPHYS const GCPhysPrev = pWalkResultPrev->GCPhysSpa; 2924 RTGCPHYS const GCPhys = pWalkResult->GCPhysSpa; 2925 uint64_t const offMaskPrev = ~(UINT64_C(0xffffffffffffffff) << pWalkResultPrev->cShift); 2926 uint64_t const offMask = ~(UINT64_C(0xffffffffffffffff) << pWalkResult->cShift); 2927 2928 /* Paranoia: Ensure offset bits are 0. */ 2929 Assert(!(GCPhysPrev & offMaskPrev)); 2930 Assert(!(GCPhys & offMask)); 2931 2932 if ((GCPhysPrev & ~offMaskPrev) + cbPrev == (GCPhys & ~offMask)) 2933 return true; 2934 return false; 2935 } 2936 2937 2938 /** 2939 * Checks whether two I/O walk results form a "contiguous" access. 2940 * 2941 * When IOTLB caching is used, in addition to the translated system-physical 2942 * addresses being physically contiguous, this function also verifies that the two 2943 * pages are identical in terms of their page size and permissions. 2944 * 2945 * This is required to simplify IOTLB lookups for for large accesses (e.g. ATA 2946 * device doing 65k transfers on Ubuntu 18.04 guests). 2947 * 2948 * @returns @c true if they are contiguous, @c false otherwise. 2949 * @param pWalkResultPrev The I/O walk result of the previous page. 2950 * @param pWalkResult The I/O walk result of the current page. 2951 */ 2952 DECL_FORCE_INLINE(bool) iommuAmdDteLookupIsAccessContig(PCIOWALKRESULT pWalkResultPrev, PCIOWALKRESULT pWalkResult) 2953 { 2954 #ifdef IOMMU_WITH_IOTLBE_CACHE 2955 if ( pWalkResultPrev->cShift == pWalkResult->cShift 2956 && pWalkResultPrev->fIoPerm == pWalkResult->fIoPerm 2957 && iommuAmdDteLookupIsAddrPhysContig(pWalkResultPrev, pWalkResult)) 2958 return true; 2959 return false; 2960 #else 2961 return iommuAmdDteLookupIsAddrPhysContig(pWalkResultPrev, pWalkResult); 2962 #endif 2963 } 2964 2965 2966 /** 2914 2967 * Looks up an I/O virtual address from the device table. 2915 2968 * … … 2965 3018 uint64_t offIova = uIova & X86_PAGE_4K_OFFSET_MASK; 2966 3019 uint64_t cbPages = 0; 2967 #ifdef IOMMU_WITH_IOTLBE_CACHE2968 3020 IOWALKRESULT WalkResultPrev; 2969 3021 RT_ZERO(WalkResultPrev); 2970 #endif2971 3022 for (;;) 2972 3023 { … … 2980 3031 uint64_t const offMask = ~(UINT64_C(0xffffffffffffffff) << WalkResult.cShift); 2981 3032 uint64_t const offSpa = uIova & offMask; 3033 Assert(!(WalkResult.GCPhysSpa & offMask)); 2982 3034 GCPhysSpa = WalkResult.GCPhysSpa | offSpa; 2983 #ifdef IOMMU_WITH_IOTLBE_CACHE 3035 2984 3036 /* Store the walk result from the first page. */ 2985 3037 WalkResultPrev = WalkResult; 2986 #endif2987 3038 } 2988 #ifdef IOMMU_WITH_IOTLBE_CACHE 2989 /* Check if addresses translated so far result in a physically contiguous region 2990 and that permissions and page sizes are identical for all pages in the access. */ 2991 else if ( (GCPhysSpa & X86_PAGE_4K_BASE_MASK) + cbPages == WalkResult.GCPhysSpa 2992 && WalkResultPrev.cShift == WalkResult.cShift 2993 && WalkResultPrev.fIoPerm == WalkResult.fIoPerm) 2994 { 2995 /* Paranoia. */ 2996 Assert((WalkResultPrev.GCPhysSpa & X86_PAGE_4K_BASE_MASK) 2997 + RT_BIT_64(WalkResultPrev.cShift) == WalkResult.GCPhysSpa); 2998 /* Store the walk result before moving on to the next page. */ 3039 /* Check if addresses translated so far result in a physically contiguous region. */ 3040 else if (iommuAmdDteLookupIsAccessContig(&WalkResultPrev, &WalkResult)) 2999 3041 WalkResultPrev = WalkResult; 3000 }3001 #else3002 /* Check if addresses translated so far result in a physically contiguous region. */3003 else if ( (GCPhysSpa & X86_PAGE_4K_BASE_MASK) + cbPages == WalkResult.GCPhysSpa)3004 { /* likely */ }3005 #endif3006 3042 else 3007 3043 {
Note:
See TracChangeset
for help on using the changeset viewer.