VirtualBox

Changeset 90478 in vbox for trunk/src


Ignore:
Timestamp:
Aug 2, 2021 2:15:42 PM (4 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Avoid looking up the DTE cache twice when looking up DTE entries. Reduced total size of the IOTLB cache to 64.

File:
1 edited

Legend:

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

    r90448 r90478  
    8181#ifdef IOMMU_WITH_IOTLBE_CACHE
    8282/** The maximum number of IOTLB entries. */
    83 # define IOMMU_IOTLBE_MAX                           96
     83# define IOMMU_IOTLBE_MAX                           64
    8484/** The mask of bits covering the domain ID in the IOTLBE key. */
    8585# define IOMMU_IOTLB_DOMAIN_ID_MASK                 UINT64_C(0xffffff0000000000)
     
    183183#endif  /* IOMMU_WITH_DTE_CACHE */
    184184
    185 /** Acquires the PDM lock (returns a_rcBusy on contention). */
     185/** Acquires the IOMMU lock (returns a_rcBusy on contention). */
    186186#define IOMMU_LOCK_RET(a_pDevIns, a_pThisCC, a_rcBusy)  \
    187187    do { \
     
    193193    } while (0)
    194194
    195 /** Acquires the PDM lock (can fail under extraordinary circumstance in in ring-0). */
     195/** Acquires the IOMMU lock (can fail under extraordinary circumstance in ring-0). */
    196196#define IOMMU_LOCK(a_pDevIns, a_pThisCC) \
    197197    do { \
     
    900900
    901901/**
    902  * Adds a device-table entry to the cache.
    903  *
    904  * @returns VBox status code.
    905  * @retval  VERR_OUT_OF_RESOURCES if the cache is full.
     902 * Adds a DTE cache entry at the given index.
     903 *
     904 * @param   pThis       The shared IOMMU device state.
     905 * @param   idxDte      The index of the DTE cache entry.
     906 * @param   idDevice    The device ID (bus, device, function).
     907 * @param   fOrMask     Device flags to set, see IOMMU_DTE_CACHE_F_XXX.
     908 * @param   idDomain    The domain ID.
     909 *
     910 * @remarks Requires the cache lock to be taken.
     911 */
     912DECL_FORCE_INLINE(void) iommuAmdDteCacheAddAtIndex(PIOMMU pThis, uint16_t idxDte, uint16_t idDevice, uint16_t fFlags,
     913                                                   uint16_t idDomain)
     914{
     915    pThis->aDeviceIds[idxDte]         = idDevice;
     916    pThis->aDteCache[idxDte].fFlags   = fFlags;
     917    pThis->aDteCache[idxDte].idDomain = idDomain;
     918}
     919
     920
     921/**
     922 * Adds a DTE cache entry.
    906923 *
    907924 * @param   pDevIns     The IOMMU instance data.
     
    909926 * @param   pDte        The device table entry.
    910927 */
    911 static int iommuAmdDteCacheAdd(PPDMDEVINS pDevIns, uint16_t idDevice, PCDTE_T pDte)
    912 {
    913     int rc = VINF_SUCCESS;
     928static void iommuAmdDteCacheAdd(PPDMDEVINS pDevIns, uint16_t idDevice, PCDTE_T pDte)
     929{
    914930    uint16_t const fFlags   = iommuAmdGetBasicDevFlags(pDte) | IOMMU_DTE_CACHE_F_PRESENT;
    915931    uint16_t const idDomain = pDte->n.u16DomainId;
     
    920936    uint16_t const cDteCache = RT_ELEMENTS(pThis->aDteCache);
    921937    uint16_t idxDte = iommuAmdDteCacheEntryLookup(pThis, idDevice);
    922     if (idxDte >= cDteCache)
    923     {
    924         idxDte = iommuAmdDteCacheEntryGetUnused(pThis);
    925         if (idxDte < cDteCache)
    926         {
    927             pThis->aDeviceIds[idxDte] = idDevice;
    928             pThis->aDteCache[idxDte].fFlags   = fFlags;
    929             pThis->aDteCache[idxDte].idDomain = idDomain;
    930         }
    931         else
    932             rc = VERR_OUT_OF_RESOURCES;
    933     }
    934     /* else: A DTE cache entry already exists, do nothing. */
     938    if (   idxDte >= cDteCache                                              /* Not found. */
     939        && (idxDte = iommuAmdDteCacheEntryGetUnused(pThis)) < cDteCache)    /* Get new/unused slot index. */
     940        iommuAmdDteCacheAddAtIndex(pThis, idxDte, idDevice, fFlags, idDomain);
    935941
    936942    IOMMU_CACHE_UNLOCK(pDevIns, pThis);
    937     return rc;
    938 }
    939 
    940 
    941 /**
    942  * Adds one or more I/O device flags if the device is already present in the cache.
     943}
     944
     945
     946/**
     947 * Updates flags for an existing DTE cache entry given its index.
     948 *
     949 * @param   pThis       The shared IOMMU device state.
     950 * @param   idxDte      The index of the DTE cache entry.
     951 * @param   fOrMask     Device flags to add to the existing flags, see
     952 *                      IOMMU_DTE_CACHE_F_XXX.
     953 * @param   fAndMask    Device flags to remove from the existing flags, see
     954 *                      IOMMU_DTE_CACHE_F_XXX.
     955 *
     956 * @remarks Requires the cache lock to be taken.
     957 */
     958DECL_FORCE_INLINE(void) iommuAmdDteCacheUpdateFlagsForIndex(PIOMMU pThis, uint16_t idxDte, uint16_t fOrMask, uint16_t fAndMask)
     959{
     960    uint16_t const fOldFlags = pThis->aDteCache[idxDte].fFlags;
     961    uint16_t const fNewFlags = (fOldFlags | fOrMask) & ~fAndMask;
     962    Assert(fOldFlags & IOMMU_DTE_CACHE_F_PRESENT);
     963    pThis->aDteCache[idxDte].fFlags = fNewFlags;
     964}
     965
     966
     967/**
     968 * Adds a new DTE cache entry or updates flags for an existing DTE cache entry.
     969 * If the cache is full, nothing happens.
     970 *
     971 * @param   pDevIns     The IOMMU instance data.
     972 * @param   pDte                The device table entry.
     973 * @param   idDevice    The device ID (bus, device, function).
     974 * @param   fOrMask     Device flags to add to the existing flags, see
     975 *                      IOMMU_DTE_CACHE_F_XXX.
     976 * @param   fAndMask    Device flags to remove from the existing flags, see
     977 *                      IOMMU_DTE_CACHE_F_XXX.
     978 */
     979static void iommuAmdDteCacheAddOrUpdateFlags(PPDMDEVINS pDevIns, PCDTE_T pDte, uint16_t idDevice, uint16_t fOrMask,
     980                                             uint16_t fAndMask)
     981{
     982    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     983    IOMMU_CACHE_LOCK(pDevIns, pThis);
     984
     985    uint16_t const cDteCache = RT_ELEMENTS(pThis->aDteCache);
     986    uint16_t idxDte = iommuAmdDteCacheEntryLookup(pThis, idDevice);
     987    if (idxDte < cDteCache)
     988        iommuAmdDteCacheUpdateFlagsForIndex(pThis, idxDte, fOrMask, fAndMask);
     989    else if ((idxDte = iommuAmdDteCacheEntryGetUnused(pThis)) < cDteCache)
     990    {
     991        uint16_t const fFlags = (iommuAmdGetBasicDevFlags(pDte) | IOMMU_DTE_CACHE_F_PRESENT | fOrMask) & ~fAndMask;
     992        iommuAmdDteCacheAddAtIndex(pThis, idxDte, idDevice, fFlags, pDte->n.u16DomainId);
     993    }
     994    /* else: cache is full, shouldn't really happen. */
     995
     996    IOMMU_CACHE_UNLOCK(pDevIns, pThis);
     997}
     998
     999
     1000/**
     1001 * Updates flags for an existing DTE cache entry.
    9431002 *
    9441003 * @param   pDevIns     The IOMMU instance data.
     
    9561015    uint16_t const cDteCache = RT_ELEMENTS(pThis->aDteCache);
    9571016    uint16_t const idxDte = iommuAmdDteCacheEntryLookup(pThis, idDevice);
    958     if (   idxDte < cDteCache
    959         && (pThis->aDteCache[idxDte].fFlags & IOMMU_DTE_CACHE_F_PRESENT))
    960     {
    961         uint16_t const fNewFlags = (pThis->aDteCache[idxDte].fFlags | fOrMask) & ~fAndMask;
    962         pThis->aDteCache[idxDte].fFlags = fNewFlags;
    963     }
     1017    if (idxDte < cDteCache)
     1018        iommuAmdDteCacheUpdateFlagsForIndex(pThis, idxDte, fOrMask, fAndMask);
    9641019
    9651020    IOMMU_CACHE_UNLOCK(pDevIns, pThis);
     
    39834038    if (RT_SUCCESS(rc))
    39844039    {
    3985 #ifdef IOMMU_WITH_IOTLBE_CACHE
    3986         iommuAmdDteCacheAdd(pDevIns, idDevice, &Dte);
    3987 #endif
    39884040        if (Dte.n.u1Valid)
    39894041        {
     
    40354087                    {
    40364088                        /* Update that addresses requires translation (cumulative permissions of DTE and I/O page tables). */
    4037                         iommuAmdDteCacheUpdateFlags(pDevIns, idDevice, IOMMU_DTE_CACHE_F_ADDR_TRANSLATE, 0 /* fAndMask */);
     4089                        iommuAmdDteCacheAddOrUpdateFlags(pDevIns, &Dte, idDevice, IOMMU_DTE_CACHE_F_ADDR_TRANSLATE,
     4090                                                         0 /* fAndMask */);
    40384091                        /* Update IOTLB for the contiguous range of I/O virtual addresses. */
    40394092                        iommuAmdIotlbAddRange(pDevIns, Aux.idDomain, uIova & X86_PAGE_4K_BASE_MASK, cbContiguous, &AddrOut);
     
    40534106#ifdef IOMMU_WITH_IOTLBE_CACHE
    40544107                    /* Update that addresses permissions of DTE apply (but omit address translation). */
    4055                     iommuAmdDteCacheUpdateFlags(pDevIns, idDevice, IOMMU_DTE_CACHE_F_IO_PERM, IOMMU_DTE_CACHE_F_ADDR_TRANSLATE);
     4108                    iommuAmdDteCacheAddOrUpdateFlags(pDevIns, &Dte, idDevice, IOMMU_DTE_CACHE_F_IO_PERM,
     4109                                                     IOMMU_DTE_CACHE_F_ADDR_TRANSLATE);
    40564110#endif
    40574111                }
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