Changeset 90110 in vbox
- Timestamp:
- Jul 9, 2021 10:13:34 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r90031 r90110 801 801 802 802 803 /**804 * Checks whether two consecutive I/O page lookup results translates to a physically805 * contiguous region.806 *807 * @returns @c true if they are contiguous, @c false otherwise.808 * @param pPageLookupPrev The I/O page lookup result of the previous page.809 * @param pPageLookup The I/O page lookup result of the current page.810 */811 static bool iommuAmdLookupIsAccessContig(PCIOPAGELOOKUP pPageLookupPrev, PCIOPAGELOOKUP pPageLookup)812 {813 size_t const cbPrev = RT_BIT_64(pPageLookupPrev->cShift);814 RTGCPHYS const GCPhysPrev = pPageLookupPrev->GCPhysSpa;815 RTGCPHYS const GCPhys = pPageLookup->GCPhysSpa;816 817 /* Paranoia: Ensure offset bits are 0. */818 Assert(!(GCPhysPrev & X86_GET_PAGE_OFFSET_MASK(pPageLookupPrev->cShift)));819 Assert(!(GCPhys & X86_GET_PAGE_OFFSET_MASK(pPageLookup->cShift)));820 821 /* Paranoia: Ensure permissions are identical. */822 Assert(pPageLookupPrev->fPerm == pPageLookup->fPerm);823 824 return GCPhysPrev + cbPrev == GCPhys;825 }826 827 828 803 #ifdef IOMMU_WITH_DTE_CACHE 829 804 /** … … 3535 3510 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysDte, pDte, sizeof(*pDte)); 3536 3511 if (RT_SUCCESS(rc)) 3537 return rc;3512 return VINF_SUCCESS; 3538 3513 3539 3514 /* Raise a device table hardware error. */ … … 3606 3581 * Note: This MUST be checked prior to checking the root page table level below! 3607 3582 */ 3608 uint8_t const fDtePerm 3583 uint8_t const fDtePerm = (pDte->au64[0] >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK; 3609 3584 if ((fPerm & fDtePerm) == fPerm) 3610 3585 { /* likely */ } … … 3898 3873 PCIOMMUOPAUX pAux, PIOADDRRANGE pAddrOut, size_t *pcbPages) 3899 3874 { 3900 AssertPtr(pfnIoPageLookup);3901 AssertPtr(pAddrIn);3902 AssertPtr(pAddrOut);3903 3904 3875 int rc; 3905 3876 size_t const cbIova = pAddrIn->cb; … … 3910 3881 uint64_t uIovaPage = pAddrIn->uAddr & X86_PAGE_4K_BASE_MASK; 3911 3882 uint64_t offIova = pAddrIn->uAddr & X86_PAGE_4K_OFFSET_MASK; 3912 uint64_t cbPages = 0; 3883 size_t cbPages = 0; 3884 size_t const cbPage = X86_PAGE_4K_SIZE; 3913 3885 3914 3886 IOPAGELOOKUP PageLookupPrev; … … 3916 3888 for (;;) 3917 3889 { 3890 /* Lookup the physical page corresponding to the I/O virtual address. */ 3918 3891 IOPAGELOOKUP PageLookup; 3919 3892 rc = pfnIoPageLookup(pDevIns, uIovaPage, fPerm, pAux, &PageLookup); 3920 3893 if (RT_SUCCESS(rc)) 3921 3894 { 3922 Assert(PageLookup.cShift >= X86_PAGE_4K_SHIFT); 3895 /* Validate results of the translation. */ 3896 Assert(PageLookup.cShift >= X86_PAGE_4K_SHIFT && PageLookup.cShift <= 51); 3897 Assert(!(PageLookup.GCPhysSpa & X86_GET_PAGE_OFFSET_MASK(PageLookup.cShift))); 3898 Assert((PageLookup.fPerm & fPerm) == fPerm); 3923 3899 3924 3900 /* Store the translated address before continuing to access more pages. */ … … 3927 3903 uint64_t const offMask = X86_GET_PAGE_OFFSET_MASK(PageLookup.cShift); 3928 3904 uint64_t const offSpa = uIova & offMask; 3929 AssertMsg(!(PageLookup.GCPhysSpa & offMask), ("GCPhysSpa=%#RX64 offMask=%#RX64\n",3930 PageLookup.GCPhysSpa, offMask));3931 3905 GCPhysSpa = PageLookup.GCPhysSpa | offSpa; 3932 3906 } 3933 /* Check if addresses translated so far result in a physically contiguous region. */ 3934 else if (!iommuAmdLookupIsAccessContig(&PageLookupPrev, &PageLookup)) 3907 /* 3908 * Check if translated address results in a physically contiguous region. 3909 * Also ensure that the permissions for all pages in this range are identical 3910 * because we specify a common permission while adding pages in this range 3911 * to the IOTLB cache. 3912 */ 3913 else if ( PageLookupPrev.GCPhysSpa + cbPage == PageLookup.GCPhysSpa 3914 && PageLookupPrev.fPerm == PageLookup.fPerm) 3915 { /* likely */ } 3916 else 3935 3917 { 3918 Assert(cbRemaining > 0); 3936 3919 rc = VERR_OUT_OF_RANGE; 3937 3920 break; … … 3942 3925 3943 3926 /* Update size of all pages read thus far. */ 3944 uint64_t const cbPage = RT_BIT_64(PageLookup.cShift);3945 3927 cbPages += cbPage; 3946 3928 … … 3948 3930 if (cbRemaining > cbPage - offIova) 3949 3931 { 3950 cbRemaining -= (cbPage - offIova); 3951 uIovaPage += cbPage; 3952 offIova = 0; /* Afterfirst page, remaining pages are accessed from offset 0. */3932 cbRemaining -= (cbPage - offIova); /* Calculate how much more we need to access. */ 3933 uIovaPage += cbPage; /* Update address of the next access. */ 3934 offIova = 0; /* After the first page, remaining pages are accessed from offset 0. */ 3953 3935 } 3954 3936 else … … 3963 3945 } 3964 3946 3965 pAddrOut->uAddr = GCPhysSpa; /* Update the translated address. */3966 pAddrOut->cb = cbIova - cbRemaining; /* Update the size of the contiguous memory region. */3967 pAddrOut->fPerm = PageLookupPrev.fPerm; /* Update the allowed permissions for this access. */3947 pAddrOut->uAddr = GCPhysSpa; /* Update the translated address. */ 3948 pAddrOut->cb = cbIova - cbRemaining; /* Update the size of the contiguous memory region. */ 3949 pAddrOut->fPerm = PageLookupPrev.fPerm; /* Update the allowed permissions for this access. */ 3968 3950 if (pcbPages) 3969 *pcbPages = cbPages; /* Update the size (in bytes) of the pages accessed. */3951 *pcbPages = cbPages; /* Update the size (in bytes) of the pages accessed. */ 3970 3952 return rc; 3971 3953 } … … 4027 4009 Aux.idDomain = Dte.n.u16DomainId; 4028 4010 4011 size_t cbPages; 4029 4012 IOADDRRANGE AddrOut; 4030 4013 4031 4014 /* Lookup the address from the DTE and I/O page tables.*/ 4032 size_t cbPages = 0;4033 4015 rc = iommuAmdLookupIoAddrRange(pDevIns, iommuAmdDteLookupPage, &AddrIn, &Aux, &AddrOut, &cbPages); 4034 4016 GCPhysSpa = AddrOut.uAddr; 4035 4017 cbContiguous = AddrOut.cb; 4036 4018 4037 /* If we stopped since translation resulted in non-contiguous physical addresses, 4038 what we translated so far is still valid. */ 4019 /* 4020 * If we stopped since translation resulted in non-contiguous physical addresses 4021 * or permissions aren't identical for all pages in the access, what we translated 4022 * thus far is still valid. 4023 */ 4039 4024 if (rc == VERR_OUT_OF_RANGE) 4040 4025 { … … 4043 4028 STAM_COUNTER_INC(&pThis->StatAccessDteNonContig); NOREF(pThis); 4044 4029 } 4045 4046 if (rc == VERR_IOMMU_ADDR_ACCESS_DENIED) 4030 else if (rc == VERR_IOMMU_ADDR_ACCESS_DENIED) 4047 4031 STAM_COUNTER_INC(&pThis->StatAccessDtePermDenied); 4048 4032 … … 4051 4035 { 4052 4036 /* Update that addresses requires translation (cumulative permissions of DTE and I/O page tables). */ 4053 iommuAmdDteCacheAdd(pDevIns, idDevice, &Dte, IOMMU_DTE_CACHE_F_ADDR_TRANSLATE);4037 iommuAmdDteCacheAdd(pDevIns, Aux.idDevice, &Dte, IOMMU_DTE_CACHE_F_ADDR_TRANSLATE); 4054 4038 /* Update IOTLB for the contiguous range of I/O virtual addresses. */ 4055 iommuAmdIotlbAddRange(pDevIns, Dte.n.u16DomainId, uIova& X86_PAGE_4K_BASE_MASK, cbPages,4056 GCPhysSpa& X86_PAGE_4K_BASE_MASK, AddrOut.fPerm);4039 iommuAmdIotlbAddRange(pDevIns, Aux.idDomain, AddrIn.uAddr & X86_PAGE_4K_BASE_MASK, cbPages, 4040 AddrOut.uAddr & X86_PAGE_4K_BASE_MASK, AddrOut.fPerm); 4057 4041 } 4058 4042 #endif
Note:
See TracChangeset
for help on using the changeset viewer.