VirtualBox

Changeset 105593 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Aug 6, 2024 12:25:42 AM (4 months ago)
Author:
vboxsync
Message:

VMM/IEM: Some loop unroll and prefetch experimentation in iemTlbInvalidateLargePageWorkerInner. bugref:10727

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r105592 r105593  
    776776#if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
    777777
     778/** @todo graduate this to cdefs.h or asm-mem.h.   */
     779# if defined(_MM_HINT_T0) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
     780#  define MY_PREFETCH(a_pvAddr)     _mm_prefetch((const char *)(a_pvAddr), _MM_HINT_T0);
     781# elif defined(_MSC_VER) && (defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32))
     782#  define MY_PREFETCH(a_pvAddr)     __prefetch((a_pvAddr));
     783# elif defined(__GNUC__) || RT_CLANG_HAS_FEATURE(__builtin_prefetch)
     784#  define MY_PREFETCH(a_pvAddr)     __builtin_prefetch((a_pvAddr), 0 /*rw*/, 3 /*locality*/)
     785# else
     786#  define MY_PREFETCH(a_pvAddr)     ((void)0)
     787# endif
     788
    778789template<bool const a_fDataTlb, bool const a_f2MbLargePage, bool const a_fGlobal, bool const a_fNonGlobal>
    779 DECLINLINE(void) iemTlbInvalidateLargePageWorkerInner(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, RTGCPTR GCPtrInstrBufPcTag)
     790DECLINLINE(void) iemTlbInvalidateLargePageWorkerInner(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag,
     791                                                      RTGCPTR GCPtrInstrBufPcTag) RT_NOEXCEPT
    780792{
    781793    IEMTLBTRACE_LARGE_SCAN(pVCpu, a_fGlobal, a_fNonGlobal, a_fDataTlb);
    782 
    783     /*
    784      * Combine TAG values with the TLB revisions.
    785      */
    786     RTGCPTR GCPtrTagGlob = a_fGlobal ? GCPtrTag | pTlb->uTlbRevisionGlobal : 0;
    787     if (a_fNonGlobal)
    788         GCPtrTag |= pTlb->uTlbRevision;
     794    AssertCompile(IEMTLB_ENTRY_COUNT >= 16); /* prefetching + unroll assumption */
    789795
    790796    /*
     
    797803     *
    798804     * For our example with 2MB pages and a 256 entry TLB: 0xfffffffffffffeff
     805     *
     806     * MY_PREFETCH: Hope that prefetching 256 bytes at the time is okay for
     807     * relevant host architectures.
    799808     */
     809    /** @todo benchmark this code from the guest side.   */
    800810    bool const      fPartialScan = IEMTLB_ENTRY_COUNT > (a_f2MbLargePage ? 512 : 1024);
    801811    uintptr_t       idxEven      = fPartialScan ? IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag)             : 0;
     812    MY_PREFETCH(&pTlb->aEntries[0 + !a_fNonGlobal]);
     813    MY_PREFETCH(&pTlb->aEntries[2 + !a_fNonGlobal]);
     814    MY_PREFETCH(&pTlb->aEntries[4 + !a_fNonGlobal]);
     815    MY_PREFETCH(&pTlb->aEntries[6 + !a_fNonGlobal]);
    802816    uintptr_t const idxEvenEnd   = fPartialScan ? idxEven + ((a_f2MbLargePage ? 512 : 1024) * 2) : IEMTLB_ENTRY_COUNT * 2;
    803817    RTGCPTR const   GCPtrTagMask = fPartialScan ? ~(RTGCPTR)0
     
    806820
    807821    /*
     822     * Combine TAG values with the TLB revisions.
     823     */
     824    RTGCPTR GCPtrTagGlob = a_fGlobal ? GCPtrTag | pTlb->uTlbRevisionGlobal : 0;
     825    if (a_fNonGlobal)
     826        GCPtrTag |= pTlb->uTlbRevision;
     827
     828    /*
    808829     * Do the scanning.
    809830     */
    810     for (; idxEven < idxEvenEnd; idxEven += 2)
    811     {
    812         if (a_fNonGlobal)
    813         {
    814             if ((pTlb->aEntries[idxEven].uTag & GCPtrTagMask) == GCPtrTag)
    815             {
    816                 if (pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
    817                 {
    818                     IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[idxEven].GCPhys, idxEven, a_fDataTlb);
    819                     pTlb->aEntries[idxEven].uTag = 0;
    820                     if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
    821                         pVCpu->iem.s.cbInstrBufTotal = 0;
    822                 }
     831    for (; idxEven < idxEvenEnd; idxEven += 8)
     832    {
     833#define ONE_ITERATION(a_idxEvenIter) \
     834            if (a_fNonGlobal)  \
     835            { \
     836                if ((pTlb->aEntries[a_idxEvenIter].uTag & GCPtrTagMask) == GCPtrTag) \
     837                { \
     838                    if (pTlb->aEntries[a_idxEvenIter].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE) \
     839                    { \
     840                        IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[a_idxEvenIter].GCPhys, \
     841                                                     a_idxEvenIter, a_fDataTlb); \
     842                        pTlb->aEntries[a_idxEvenIter].uTag = 0; \
     843                        if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag) \
     844                            pVCpu->iem.s.cbInstrBufTotal = 0; \
     845                    } \
     846                } \
     847                GCPtrTag++; \
     848            } \
     849            \
     850            if (a_fGlobal) \
     851            { \
     852                if ((pTlb->aEntries[a_idxEvenIter + 1].uTag & GCPtrTagMask) == GCPtrTagGlob) \
     853                { \
     854                    if (pTlb->aEntries[a_idxEvenIter + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE) \
     855                    { \
     856                        IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[a_idxEvenIter + 1].GCPhys, \
     857                                                     a_idxEvenIter + 1, a_fDataTlb); \
     858                        pTlb->aEntries[a_idxEvenIter + 1].uTag = 0; \
     859                        if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag) \
     860                            pVCpu->iem.s.cbInstrBufTotal = 0; \
     861                    } \
     862                } \
     863                GCPtrTagGlob++; \
    823864            }
    824             GCPtrTag++;
    825         }
    826 
    827         if (a_fGlobal)
    828         {
    829             if ((pTlb->aEntries[idxEven + 1].uTag & GCPtrTagMask) == GCPtrTagGlob)
    830             {
    831                 if (pTlb->aEntries[idxEven + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
    832                 {
    833                     IEMTLBTRACE_LARGE_EVICT_SLOT(pVCpu, GCPtrTag, pTlb->aEntries[idxEven + 1].GCPhys, idxEven + 1, a_fDataTlb);
    834                     pTlb->aEntries[idxEven + 1].uTag = 0;
    835                     if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
    836                         pVCpu->iem.s.cbInstrBufTotal = 0;
    837                 }
    838             }
    839             GCPtrTagGlob++;
    840         }
    841     }
    842 
     865        if (idxEven < idxEvenEnd - 8)
     866        {
     867            MY_PREFETCH(&pTlb->aEntries[idxEven +  8 + !a_fNonGlobal]);
     868            MY_PREFETCH(&pTlb->aEntries[idxEven + 10 + !a_fNonGlobal]);
     869            MY_PREFETCH(&pTlb->aEntries[idxEven + 12 + !a_fNonGlobal]);
     870            MY_PREFETCH(&pTlb->aEntries[idxEven + 14 + !a_fNonGlobal]);
     871        }
     872        ONE_ITERATION(idxEven)
     873        ONE_ITERATION(idxEven + 2)
     874        ONE_ITERATION(idxEven + 4)
     875        ONE_ITERATION(idxEven + 6)
     876#undef ONE_ITERATION
     877    }
    843878}
    844879
    845880template<bool const a_fDataTlb, bool const a_f2MbLargePage>
    846 DECLINLINE(void) iemTlbInvalidateLargePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, RTGCPTR GCPtrInstrBufPcTag)
     881DECLINLINE(void) iemTlbInvalidateLargePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag,
     882                                                 RTGCPTR GCPtrInstrBufPcTag) RT_NOEXCEPT
    847883{
    848884    AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
     
    869905
    870906template<bool const a_fDataTlb>
    871 DECLINLINE(void) iemTlbInvalidatePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, uintptr_t idxEven)
     907DECLINLINE(void) iemTlbInvalidatePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, uintptr_t idxEven) RT_NOEXCEPT
    872908{
    873909    /*
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