VirtualBox

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


Ignore:
Timestamp:
Jul 8, 2024 9:29:14 AM (7 months ago)
Author:
vboxsync
Message:

VMM/IEM: Increase TLB size to 8192 on arm; quick fix for 2M/4M page problem with invlpg. On AMD64 we stick to 256 TLB entries for VM struct size reasons. bugref:10687

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

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

    r105137 r105177  
    728728
    729729
     730#if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
     731template<bool a_fDataTlb>
     732DECLINLINE(void) iemTlbInvalidatePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, uintptr_t idxEven)
     733{
     734    /*
     735     * Flush the entry pair.
     736     *
     737     * We ASSUME that the guest hasn't tricked us into loading one of these
     738     * from a large page and the other from a regular 4KB page.  This is made
     739     * much less of a problem, in that the guest would also have to flip the
     740     * G bit to accomplish this.
     741     */
     742    bool fMaybeLargePage = true;
     743    if (pTlb->aEntries[idxEven].uTag == (GCPtrTag | pTlb->uTlbRevision))
     744    {
     745        pTlb->aEntries[idxEven].uTag = 0;
     746        fMaybeLargePage = RT_BOOL(pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE);
     747        if (!a_fDataTlb && GCPtrTag == IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc))
     748            pVCpu->iem.s.cbInstrBufTotal = 0;
     749    }
     750    if (pTlb->aEntries[idxEven + 1].uTag == (GCPtrTag | pTlb->uTlbRevisionGlobal))
     751    {
     752        pTlb->aEntries[idxEven + 1].uTag = 0;
     753        fMaybeLargePage = RT_BOOL(pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE);
     754        if (!a_fDataTlb && GCPtrTag == IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc))
     755            pVCpu->iem.s.cbInstrBufTotal = 0;
     756    }
     757
     758    /*
     759     * If we cannot rule out a large page, we have to scan all the 4K TLB
     760     * entries such a page covers to ensure we evict all relevant entries.
     761     * ASSUMES that tag calculation is a right shift by GUEST_PAGE_SHIFT.
     762     */
     763    if (fMaybeLargePage)
     764    {
     765        AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
     766        RTGCPTR const GCPtrInstrBufPcTag = IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc);
     767        if ((pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE) && (pVCpu->cpum.GstCtx.cr0 & X86_CR0_PG))
     768        {
     769            /* 2MB large page */
     770            GCPtrTag             &= ~(RTGCPTR)(RT_BIT_64(21 - GUEST_PAGE_SHIFT) - 1U);
     771            RTGCPTR GCPtrTagGlob = GCPtrTag | pTlb->uTlbRevisionGlobal;
     772            GCPtrTag            |= pTlb->uTlbRevision;
     773
     774# if IEMTLB_ENTRY_COUNT >= 512
     775            idxEven = IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag);
     776            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)0;
     777            uintptr_t const idxEvenEnd   = idxEven + 512;
     778# else
     779            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK
     780                                         & ~(RTGCPTR)(   (RT_BIT_64(9 - IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO) - 1U)
     781                                                      << IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO);
     782            uintptr_t const idxEvenEnd   = IEMTLB_ENTRY_COUNT;
     783# endif
     784            for (idxEven = 0; idxEven < idxEvenEnd; idxEven += 2)
     785            {
     786                if ((pTlb->aEntries[idxEven].uTag & GCPtrTagMask) == GCPtrTag)
     787                {
     788                    Assert(pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); /* bad guest */
     789                    pTlb->aEntries[idxEven].uTag = 0;
     790                    if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
     791                        pVCpu->iem.s.cbInstrBufTotal = 0;
     792                }
     793                if ((pTlb->aEntries[idxEven + 1].uTag & GCPtrTagMask) == GCPtrTagGlob)
     794                {
     795                    Assert(pTlb->aEntries[idxEven + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); /* bad guest */
     796                    pTlb->aEntries[idxEven + 1].uTag = 0;
     797                    if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
     798                        pVCpu->iem.s.cbInstrBufTotal = 0;
     799                }
     800                GCPtrTag++;
     801                GCPtrTagGlob++;
     802            }
     803        }
     804        else
     805        {
     806            /* 4MB large page */
     807            GCPtrTag             &= ~(RTGCPTR)(RT_BIT_64(22 - GUEST_PAGE_SHIFT) - 1U);
     808            RTGCPTR GCPtrTagGlob = GCPtrTag | pTlb->uTlbRevisionGlobal;
     809            GCPtrTag            |= pTlb->uTlbRevision;
     810
     811# if IEMTLB_ENTRY_COUNT >= 1024
     812            idxEven = IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag);
     813            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)0;
     814            uintptr_t const idxEvenEnd   = idxEven + 1024;
     815# else
     816            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK
     817                                         & ~(RTGCPTR)(   (RT_BIT_64(10 - IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO) - 1U)
     818                                                      << IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO);
     819            uintptr_t const idxEvenEnd   = IEMTLB_ENTRY_COUNT;
     820# endif
     821            for (idxEven = 0; idxEven < idxEvenEnd; idxEven += 2)
     822            {
     823                if ((pTlb->aEntries[idxEven].uTag & GCPtrTagMask) == GCPtrTag)
     824                {
     825                    Assert(pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); /* bad guest */
     826                    pTlb->aEntries[idxEven].uTag = 0;
     827                    if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
     828                        pVCpu->iem.s.cbInstrBufTotal = 0;
     829                }
     830                if ((pTlb->aEntries[idxEven + 1].uTag & GCPtrTagMask) == GCPtrTagGlob)
     831                {
     832                    Assert(pTlb->aEntries[idxEven + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE); /* bad guest */
     833                    pTlb->aEntries[idxEven + 1].uTag = 0;
     834                    if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
     835                        pVCpu->iem.s.cbInstrBufTotal = 0;
     836                }
     837                GCPtrTag++;
     838                GCPtrTagGlob++;
     839            }
     840        }
     841    }
     842}
     843#endif
     844
     845
    730846/**
    731847 * Invalidates a page in the TLBs.
     
    745861
    746862# ifdef IEM_WITH_CODE_TLB
    747     if (pVCpu->iem.s.CodeTlb.aEntries[idxEven].uTag == (GCPtr | pVCpu->iem.s.CodeTlb.uTlbRevision))
    748     {
    749         pVCpu->iem.s.CodeTlb.aEntries[idxEven].uTag = 0;
    750         if (GCPtr == IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc))
    751             pVCpu->iem.s.cbInstrBufTotal = 0;
    752     }
    753     if (pVCpu->iem.s.CodeTlb.aEntries[idxEven + 1].uTag == (GCPtr | pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal))
    754     {
    755         pVCpu->iem.s.CodeTlb.aEntries[idxEven + 1].uTag = 0;
    756         if (GCPtr == IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc))
    757             pVCpu->iem.s.cbInstrBufTotal = 0;
    758     }
     863    iemTlbInvalidatePageWorker<false>(pVCpu, &pVCpu->iem.s.CodeTlb, GCPtr, idxEven);
    759864# endif
    760 
    761865# ifdef IEM_WITH_DATA_TLB
    762     if (pVCpu->iem.s.DataTlb.aEntries[idxEven].uTag == (GCPtr | pVCpu->iem.s.DataTlb.uTlbRevision))
    763         pVCpu->iem.s.DataTlb.aEntries[idxEven].uTag = 0;
    764     if (pVCpu->iem.s.DataTlb.aEntries[idxEven + 1].uTag == (GCPtr | pVCpu->iem.s.DataTlb.uTlbRevisionGlobal))
    765         pVCpu->iem.s.DataTlb.aEntries[idxEven + 1].uTag = 0;
     866    iemTlbInvalidatePageWorker<true>(pVCpu, &pVCpu->iem.s.DataTlb, GCPtr, idxEven);
    766867# endif
    767868#else
     
    11031204            }
    11041205            pTlbe->fFlagsAndPhysRev = (~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A))
    1105                                     | (WalkFast.fEffective >> X86_PTE_PAE_BIT_NX) /*IEMTLBE_F_PT_NO_EXEC*/;
     1206                                    | (WalkFast.fEffective >> X86_PTE_PAE_BIT_NX) /*IEMTLBE_F_PT_NO_EXEC*/
     1207                                    | (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE);
    11061208            RTGCPHYS const GCPhysPg = WalkFast.GCPhys & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK;
    11071209            pTlbe->GCPhys           = GCPhysPg;
     
    66576759            pTlbe->uTag = uTagNoRev;
    66586760        }
    6659         pTlbe->fFlagsAndPhysRev = ~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A); /* skipping NX */
     6761        pTlbe->fFlagsAndPhysRev = (~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A) /* skipping NX */)
     6762                                | (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE);
    66606763        RTGCPHYS const GCPhysPg = WalkFast.GCPhys & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK;
    66616764        pTlbe->GCPhys           = GCPhysPg;
     
    70517154            pTlbe->uTag = uTagNoRev;
    70527155        }
    7053         pTlbe->fFlagsAndPhysRev = ~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A); /* skipping NX */
     7156        pTlbe->fFlagsAndPhysRev = (~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A) /* skipping NX */)
     7157                                | (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE);
    70547158        RTGCPHYS const GCPhysPg = WalkFast.GCPhys & ~(RTGCPHYS)GUEST_PAGE_OFFSET_MASK;
    70557159        pTlbe->GCPhys           = GCPhysPg;
  • trunk/src/VBox/VMM/VMMR3/IEMR3.cpp

    r105036 r105177  
    10391039static void iemR3InfoTlbPrintSlot(PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, IEMTLBENTRY const *pTlbe, uint32_t uSlot)
    10401040{
    1041     pHlp->pfnPrintf(pHlp, "%02x: %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s/%s%s%s/%s %s\n",
     1041    pHlp->pfnPrintf(pHlp, "%02x: %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s%s/%s%s%s/%s %s\n",
    10421042                    uSlot,
    10431043                    (pTlbe->uTag & IEMTLB_REVISION_MASK) == pTlb->uTlbRevision ? "valid  "
     
    10511051                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED  ? "-"  : "A",
    10521052                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY     ? "-"  : "D",
     1053                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE   ? "-"  : "S",
    10531054                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_WRITE     ? "-"  : "w",
    10541055                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_READ      ? "-"  : "r",
  • trunk/src/VBox/VMM/include/IEMInternal-armv8.h

    r104956 r105177  
    286286/** @name IEMTLBE_F_XXX - TLB entry flags (IEMTLBENTRY::fFlagsAndPhysRev)
    287287 * @{  */
    288 #define IEMTLBE_F_PT_NO_EXEC        RT_BIT_64(0) /**< Page tables: Not executable. */
    289 #define IEMTLBE_F_PT_NO_WRITE       RT_BIT_64(1) /**< Page tables: Not writable. */
    290 #define IEMTLBE_F_PT_NO_USER        RT_BIT_64(2) /**< Page tables: Not user accessible (supervisor only). */
    291 #define IEMTLBE_F_PG_NO_WRITE       RT_BIT_64(3) /**< Phys page:   Not writable (access handler, ROM, whatever). */
    292 #define IEMTLBE_F_PG_NO_READ        RT_BIT_64(4) /**< Phys page:   Not readable (MMIO / access handler, ROM) */
    293 #define IEMTLBE_F_PT_NO_ACCESSED    RT_BIT_64(5) /**< Phys tables: Not accessed (need to be marked accessed). */
    294 #define IEMTLBE_F_PT_NO_DIRTY       RT_BIT_64(6) /**< Page tables: Not dirty (needs to be made dirty on write). */
    295 #define IEMTLBE_F_NO_MAPPINGR3      RT_BIT_64(7) /**< TLB entry:   The IEMTLBENTRY::pMappingR3 member is invalid. */
    296 #define IEMTLBE_F_PG_UNASSIGNED     RT_BIT_64(8) /**< Phys page:   Unassigned memory (not RAM, ROM, MMIO2 or MMIO). */
    297 #define IEMTLBE_F_PG_CODE_PAGE      RT_BIT_64(9) /**< Phys page:   Code page. */
    298 #define IEMTLBE_F_PHYS_REV          UINT64_C(0xfffffffffffffc00) /**< Physical revision mask. @sa IEMTLB_PHYS_REV_INCR */
     288#define IEMTLBE_F_PT_NO_EXEC        RT_BIT_64(0)  /**< Page tables: Not executable. */
     289#define IEMTLBE_F_PT_NO_WRITE       RT_BIT_64(1)  /**< Page tables: Not writable. */
     290#define IEMTLBE_F_PT_NO_USER        RT_BIT_64(2)  /**< Page tables: Not user accessible (supervisor only). */
     291#define IEMTLBE_F_PG_NO_WRITE       RT_BIT_64(3)  /**< Phys page:   Not writable (access handler, ROM, whatever). */
     292#define IEMTLBE_F_PG_NO_READ        RT_BIT_64(4)  /**< Phys page:   Not readable (MMIO / access handler, ROM) */
     293#define IEMTLBE_F_PT_NO_ACCESSED    RT_BIT_64(5)  /**< Phys tables: Not accessed (need to be marked accessed). */
     294#define IEMTLBE_F_PT_NO_DIRTY       RT_BIT_64(6)  /**< Page tables: Not dirty (needs to be made dirty on write). */
     295#define IEMTLBE_F_PT_LARGE_PAGE     RT_BIT_64(7)  /**< Page tables: Large 2 or 4 MiB page (for flushing). */
     296#define IEMTLBE_F_NO_MAPPINGR3      RT_BIT_64(8)  /**< TLB entry:   The IEMTLBENTRY::pMappingR3 member is invalid. */
     297#define IEMTLBE_F_PG_UNASSIGNED     RT_BIT_64(9)  /**< Phys page:   Unassigned memory (not RAM, ROM, MMIO2 or MMIO). */
     298#define IEMTLBE_F_PG_CODE_PAGE      RT_BIT_64(10) /**< Phys page:   Code page. */
     299#define IEMTLBE_F_PHYS_REV          UINT64_C(0xfffffffffffff800) /**< Physical revision mask. @sa IEMTLB_PHYS_REV_INCR */
    299300/** @} */
    300301
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r105123 r105177  
    500500/** @name IEMTLBE_F_XXX - TLB entry flags (IEMTLBENTRY::fFlagsAndPhysRev)
    501501 * @{  */
    502 #define IEMTLBE_F_PT_NO_EXEC        RT_BIT_64(0) /**< Page tables: Not executable. */
    503 #define IEMTLBE_F_PT_NO_WRITE       RT_BIT_64(1) /**< Page tables: Not writable. */
    504 #define IEMTLBE_F_PT_NO_USER        RT_BIT_64(2) /**< Page tables: Not user accessible (supervisor only). */
    505 #define IEMTLBE_F_PG_NO_WRITE       RT_BIT_64(3) /**< Phys page:   Not writable (access handler, ROM, whatever). */
    506 #define IEMTLBE_F_PG_NO_READ        RT_BIT_64(4) /**< Phys page:   Not readable (MMIO / access handler, ROM) */
    507 #define IEMTLBE_F_PT_NO_ACCESSED    RT_BIT_64(5) /**< Phys tables: Not accessed (need to be marked accessed). */
    508 #define IEMTLBE_F_PT_NO_DIRTY       RT_BIT_64(6) /**< Page tables: Not dirty (needs to be made dirty on write). */
    509 #define IEMTLBE_F_NO_MAPPINGR3      RT_BIT_64(7) /**< TLB entry:   The IEMTLBENTRY::pMappingR3 member is invalid. */
    510 #define IEMTLBE_F_PG_UNASSIGNED     RT_BIT_64(8) /**< Phys page:   Unassigned memory (not RAM, ROM, MMIO2 or MMIO). */
    511 #define IEMTLBE_F_PG_CODE_PAGE      RT_BIT_64(9) /**< Phys page:   Code page. */
    512 #define IEMTLBE_F_PHYS_REV          UINT64_C(0xfffffffffffffc00) /**< Physical revision mask. @sa IEMTLB_PHYS_REV_INCR */
     502#define IEMTLBE_F_PT_NO_EXEC        RT_BIT_64(0)  /**< Page tables: Not executable. */
     503#define IEMTLBE_F_PT_NO_WRITE       RT_BIT_64(1)  /**< Page tables: Not writable. */
     504#define IEMTLBE_F_PT_NO_USER        RT_BIT_64(2)  /**< Page tables: Not user accessible (supervisor only). */
     505#define IEMTLBE_F_PG_NO_WRITE       RT_BIT_64(3)  /**< Phys page:   Not writable (access handler, ROM, whatever). */
     506#define IEMTLBE_F_PG_NO_READ        RT_BIT_64(4)  /**< Phys page:   Not readable (MMIO / access handler, ROM) */
     507#define IEMTLBE_F_PT_NO_ACCESSED    RT_BIT_64(5)  /**< Phys tables: Not accessed (need to be marked accessed). */
     508#define IEMTLBE_F_PT_NO_DIRTY       RT_BIT_64(6)  /**< Page tables: Not dirty (needs to be made dirty on write). */
     509#define IEMTLBE_F_PT_LARGE_PAGE     RT_BIT_64(7)  /**< Page tables: Large 2 or 4 MiB page (for flushing). */
     510#define IEMTLBE_F_NO_MAPPINGR3      RT_BIT_64(8)  /**< TLB entry:   The IEMTLBENTRY::pMappingR3 member is invalid. */
     511#define IEMTLBE_F_PG_UNASSIGNED     RT_BIT_64(9)  /**< Phys page:   Unassigned memory (not RAM, ROM, MMIO2 or MMIO). */
     512#define IEMTLBE_F_PG_CODE_PAGE      RT_BIT_64(10) /**< Phys page:   Code page. */
     513#define IEMTLBE_F_PHYS_REV          UINT64_C(0xfffffffffffff800) /**< Physical revision mask. @sa IEMTLB_PHYS_REV_INCR */
    513514/** @} */
    514515AssertCompile(PGMIEMGCPHYS2PTR_F_NO_WRITE     == IEMTLBE_F_PG_NO_WRITE);
     
    517518AssertCompile(PGMIEMGCPHYS2PTR_F_UNASSIGNED   == IEMTLBE_F_PG_UNASSIGNED);
    518519AssertCompile(PGMIEMGCPHYS2PTR_F_CODE_PAGE    == IEMTLBE_F_PG_CODE_PAGE);
     520AssertCompile(PGM_WALKINFO_BIG_PAGE           == IEMTLBE_F_PT_LARGE_PAGE);
    519521/** The bits set by PGMPhysIemGCPhys2PtrNoLock. */
    520522#define IEMTLBE_GCPHYS2PTR_MASK     (  PGMIEMGCPHYS2PTR_F_NO_WRITE \
     
    529531 * from a 8-bit register without an additional AND instruction.
    530532 * See also @bugref{10687}. */
    531 #define IEMTLB_ENTRY_COUNT                      1024
    532 #define IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO      10
     533#if defined(RT_ARCH_AMD64)
     534# define IEMTLB_ENTRY_COUNT                      256
     535# define IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO      8
     536#else
     537# define IEMTLB_ENTRY_COUNT                      8192
     538# define IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO      13
     539#endif
    533540AssertCompile(RT_BIT_32(IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO) == IEMTLB_ENTRY_COUNT);
    534541
     
    637644/** IEMTLB::uTlbPhysRev increment.
    638645 * @sa IEMTLBE_F_PHYS_REV */
    639 #define IEMTLB_PHYS_REV_INCR    RT_BIT_64(10)
     646#define IEMTLB_PHYS_REV_INCR    RT_BIT_64(11)
     647AssertCompile(IEMTLBE_F_PHYS_REV == ~(IEMTLB_PHYS_REV_INCR - 1U));
     648
    640649/**
    641650 * Calculates the TLB tag for a virtual address but without TLB revision.
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