VirtualBox

Changeset 90110 in vbox


Ignore:
Timestamp:
Jul 9, 2021 10:13:34 AM (4 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Fixed more issues in address translation resulting in non-contiguous physical addresses.
The IOTLB cache still has issues with this and thus remains disabled.

File:
1 edited

Legend:

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

    r90031 r90110  
    801801
    802802
    803 /**
    804  * Checks whether two consecutive I/O page lookup results translates to a physically
    805  * 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 
    828803#ifdef IOMMU_WITH_DTE_CACHE
    829804/**
     
    35353510        int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysDte, pDte, sizeof(*pDte));
    35363511        if (RT_SUCCESS(rc))
    3537             return rc;
     3512            return VINF_SUCCESS;
    35383513
    35393514        /* Raise a device table hardware error. */
     
    36063581     * Note: This MUST be checked prior to checking the root page table level below!
    36073582     */
    3608     uint8_t const fDtePerm  = (pDte->au64[0] >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK;
     3583    uint8_t const fDtePerm = (pDte->au64[0] >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK;
    36093584    if ((fPerm & fDtePerm) == fPerm)
    36103585    { /* likely */ }
     
    38983873                                     PCIOMMUOPAUX pAux, PIOADDRRANGE pAddrOut, size_t *pcbPages)
    38993874{
    3900     AssertPtr(pfnIoPageLookup);
    3901     AssertPtr(pAddrIn);
    3902     AssertPtr(pAddrOut);
    3903 
    39043875    int            rc;
    39053876    size_t const   cbIova      = pAddrIn->cb;
     
    39103881    uint64_t       uIovaPage   = pAddrIn->uAddr & X86_PAGE_4K_BASE_MASK;
    39113882    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;
    39133885
    39143886    IOPAGELOOKUP PageLookupPrev;
     
    39163888    for (;;)
    39173889    {
     3890        /* Lookup the physical page corresponding to the I/O virtual address. */
    39183891        IOPAGELOOKUP PageLookup;
    39193892        rc = pfnIoPageLookup(pDevIns, uIovaPage, fPerm, pAux, &PageLookup);
    39203893        if (RT_SUCCESS(rc))
    39213894        {
    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);
    39233899
    39243900            /* Store the translated address before continuing to access more pages. */
     
    39273903                uint64_t const offMask = X86_GET_PAGE_OFFSET_MASK(PageLookup.cShift);
    39283904                uint64_t const offSpa  = uIova & offMask;
    3929                 AssertMsg(!(PageLookup.GCPhysSpa & offMask), ("GCPhysSpa=%#RX64 offMask=%#RX64\n",
    3930                                                               PageLookup.GCPhysSpa, offMask));
    39313905                GCPhysSpa = PageLookup.GCPhysSpa | offSpa;
    39323906            }
    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
    39353917            {
     3918                Assert(cbRemaining > 0);
    39363919                rc = VERR_OUT_OF_RANGE;
    39373920                break;
     
    39423925
    39433926            /* Update size of all pages read thus far. */
    3944             uint64_t const cbPage = RT_BIT_64(PageLookup.cShift);
    39453927            cbPages += cbPage;
    39463928
     
    39483930            if (cbRemaining > cbPage - offIova)
    39493931            {
    3950                 cbRemaining -= (cbPage - offIova);  /* Calculate how much more we need to access. */
    3951                 uIovaPage   += cbPage;              /* Update address of the next access. */
    3952                 offIova      = 0;                   /* After first 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. */
    39533935            }
    39543936            else
     
    39633945    }
    39643946
    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. */
    39683950    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. */
    39703952    return rc;
    39713953}
     
    40274009                    Aux.idDomain = Dte.n.u16DomainId;
    40284010
     4011                    size_t cbPages;
    40294012                    IOADDRRANGE AddrOut;
    40304013
    40314014                    /* Lookup the address from the DTE and I/O page tables.*/
    4032                     size_t cbPages = 0;
    40334015                    rc = iommuAmdLookupIoAddrRange(pDevIns, iommuAmdDteLookupPage, &AddrIn, &Aux, &AddrOut, &cbPages);
    40344016                    GCPhysSpa    = AddrOut.uAddr;
    40354017                    cbContiguous = AddrOut.cb;
    40364018
    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                     */
    40394024                    if (rc == VERR_OUT_OF_RANGE)
    40404025                    {
     
    40434028                        STAM_COUNTER_INC(&pThis->StatAccessDteNonContig); NOREF(pThis);
    40444029                    }
    4045 
    4046                     if (rc == VERR_IOMMU_ADDR_ACCESS_DENIED)
     4030                    else if (rc == VERR_IOMMU_ADDR_ACCESS_DENIED)
    40474031                        STAM_COUNTER_INC(&pThis->StatAccessDtePermDenied);
    40484032
     
    40514035                    {
    40524036                        /* 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);
    40544038                        /* 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);
    40574041                    }
    40584042#endif
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