Index: trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 105283)
+++ trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 105284)
@@ -222,4 +222,5 @@
         RTGCPTR uTagNoRev = (a_uValue); \
         uTagNoRev = IEMTLB_CALC_TAG_NO_REV(uTagNoRev); \
+        /** @todo do large page accounting */ \
         uintptr_t const idxEven = IEMTLB_TAG_TO_EVEN_INDEX(uTagNoRev); \
         if (pVCpu->iem.s.DataTlb.aEntries[idxEven].uTag == (uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevision)) \
@@ -638,4 +639,32 @@
 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
 /**
+ * Helper for doing large page accounting at TLB load time.
+ */
+template<bool const a_fGlobal>
+DECL_FORCE_INLINE(void) iemTlbLoadedLargePage(IEMTLB *pTlb, RTGCPTR uTagNoRev, bool f2MbLargePages)
+{
+    if (a_fGlobal)
+        pTlb->cTlbGlobalLargePageCurLoads++;
+    else
+        pTlb->cTlbNonGlobalLargePageCurLoads++;
+
+    AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
+    uint32_t const                 fMask = (f2MbLargePages ? _2M - 1U : _4M - 1U) >> GUEST_PAGE_SHIFT;
+    IEMTLB::LARGEPAGERANGE * const pRange = a_fGlobal
+                                          ? &pTlb->GlobalLargePageRange
+                                          : &pTlb->NonGlobalLargePageRange;
+    uTagNoRev &= ~(RTGCPTR)fMask;
+    if (uTagNoRev < pRange->uFirstTag)
+        pRange->uFirstTag = uTagNoRev;
+
+    uTagNoRev |= fMask;
+    if (uTagNoRev > pRange->uLastTag)
+        pRange->uLastTag = uTagNoRev;
+}
+#endif
+
+
+#if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
+/**
  * Worker for iemTlbInvalidateAll.
  */
@@ -659,4 +688,9 @@
             pTlb->aEntries[i * 2].uTag = 0;
     }
+
+    pTlb->cTlbNonGlobalLargePageCurLoads    = 0;
+    pTlb->NonGlobalLargePageRange.uLastTag  = 0;
+    pTlb->NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
+
     if (a_fGlobal)
     {
@@ -672,4 +706,8 @@
                 pTlb->aEntries[i * 2 + 1].uTag = 0;
         }
+
+        pTlb->cTlbGlobalLargePageCurLoads    = 0;
+        pTlb->GlobalLargePageRange.uLastTag  = 0;
+        pTlb->GlobalLargePageRange.uFirstTag = UINT64_MAX;
     }
 }
@@ -729,5 +767,83 @@
 
 #if defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB)
-template<bool a_fDataTlb>
+
+template<bool const a_fDataTlb, bool const a_f2MbLargePage, bool const a_fGlobal, bool const a_fNonGlobal>
+DECLINLINE(void) iemTlbInvalidateLargePageWorkerInner(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, RTGCPTR GCPtrInstrBufPcTag)
+{
+    /* Combine TAG values with the TLB revisions. */
+    RTGCPTR GCPtrTagGlob = a_fGlobal ? GCPtrTag | pTlb->uTlbRevisionGlobal : 0;
+    if (a_fNonGlobal)
+        GCPtrTag |= pTlb->uTlbRevision;
+
+    /* Set up the scan. */
+    bool const      fPartialScan = IEMTLB_ENTRY_COUNT >= (a_f2MbLargePage ? 512 : 1024);
+    uintptr_t       idxEven      = fPartialScan ? IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag) : 0;
+    uintptr_t const idxEvenEnd   = fPartialScan ? idxEven + (a_f2MbLargePage ? 512 : 1024) : IEMTLB_ENTRY_COUNT;
+    RTGCPTR const   GCPtrTagMask = fPartialScan
+                                 ? ~(RTGCPTR)0
+                                 :   ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK
+                                   & ~(RTGCPTR)(   (  RT_BIT_64((a_f2MbLargePage ? 9 : 10) - IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO)
+                                                    - 1U)
+                                                << IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO);
+
+    /*
+     * Do the scanning.
+     */
+    for (idxEven = 0; idxEven < idxEvenEnd; idxEven += 2)
+    {
+        if (a_fNonGlobal)
+        {
+            if ((pTlb->aEntries[idxEven].uTag & GCPtrTagMask) == GCPtrTag)
+            {
+                if (pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
+                {
+                    pTlb->aEntries[idxEven].uTag = 0;
+                    if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
+                        pVCpu->iem.s.cbInstrBufTotal = 0;
+                }
+            }
+            GCPtrTag++;
+        }
+
+        if (a_fGlobal)
+        {
+            if ((pTlb->aEntries[idxEven + 1].uTag & GCPtrTagMask) == GCPtrTagGlob)
+            {
+                if (pTlb->aEntries[idxEven + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
+                {
+                    pTlb->aEntries[idxEven + 1].uTag = 0;
+                    if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
+                        pVCpu->iem.s.cbInstrBufTotal = 0;
+                }
+            }
+            GCPtrTagGlob++;
+        }
+    }
+
+}
+
+template<bool const a_fDataTlb, bool const a_f2MbLargePage>
+DECLINLINE(void) iemTlbInvalidateLargePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, RTGCPTR GCPtrInstrBufPcTag)
+{
+    AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
+
+    GCPtrTag &= ~(RTGCPTR)(RT_BIT_64((a_f2MbLargePage ? 21 : 22) - GUEST_PAGE_SHIFT) - 1U);
+    if (   pTlb->GlobalLargePageRange.uFirstTag >= GCPtrTag
+        && pTlb->GlobalLargePageRange.uLastTag  <= GCPtrTag)
+    {
+        if (   pTlb->NonGlobalLargePageRange.uFirstTag < GCPtrTag
+            || pTlb->NonGlobalLargePageRange.uLastTag  > GCPtrTag)
+            iemTlbInvalidateLargePageWorkerInner<a_fDataTlb, a_f2MbLargePage, true, false>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
+        else
+            iemTlbInvalidateLargePageWorkerInner<a_fDataTlb, a_f2MbLargePage, true, true>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
+    }
+    else if (   pTlb->NonGlobalLargePageRange.uFirstTag < GCPtrTag
+             || pTlb->NonGlobalLargePageRange.uLastTag  > GCPtrTag)
+    { /* Large pages aren't as likely in the non-global TLB half. */ }
+    else
+        iemTlbInvalidateLargePageWorkerInner<a_fDataTlb, a_f2MbLargePage, false, true>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
+}
+
+template<bool const a_fDataTlb>
 DECLINLINE(void) iemTlbInvalidatePageWorker(PVMCPUCC pVCpu, IEMTLB *pTlb, RTGCPTR GCPtrTag, uintptr_t idxEven)
 {
@@ -761,118 +877,20 @@
      * ASSUMES that tag calculation is a right shift by GUEST_PAGE_SHIFT.
      */
-    if (fMaybeLargePage)
-    {
-        AssertCompile(IEMTLB_CALC_TAG_NO_REV((RTGCPTR)0x8731U << GUEST_PAGE_SHIFT) == 0x8731U);
-        RTGCPTR const GCPtrInstrBufPcTag = IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc);
-        if ((pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE) && (pVCpu->cpum.GstCtx.cr0 & X86_CR0_PG))
-        {
-            /* 2MB large page */
-            GCPtrTag             &= ~(RTGCPTR)(RT_BIT_64(21 - GUEST_PAGE_SHIFT) - 1U);
-            RTGCPTR GCPtrTagGlob = GCPtrTag | pTlb->uTlbRevisionGlobal;
-            GCPtrTag            |= pTlb->uTlbRevision;
-
-# if IEMTLB_ENTRY_COUNT >= 512
-            idxEven = IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag);
-            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)0;
-            uintptr_t const idxEvenEnd   = idxEven + 512;
+    if (   fMaybeLargePage
+# if 0 /** @todo do accurate counts or currently loaded large stuff and we can use those  */
+        && (pTlb->cTlbGlobalLargePageCurLoads || pTlb->cTlbNonGlobalLargePageCurLoads))
 # else
-            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK
-                                         & ~(RTGCPTR)(   (RT_BIT_64(9 - IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO) - 1U)
-                                                      << IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO);
-            uintptr_t const idxEvenEnd   = IEMTLB_ENTRY_COUNT;
+        && (pTlb->GlobalLargePageRange.uLastTag || pTlb->NonGlobalLargePageRange.uLastTag))
 # endif
-            for (idxEven = 0; idxEven < idxEvenEnd; idxEven += 2)
-            {
-                if ((pTlb->aEntries[idxEven].uTag & GCPtrTagMask) == GCPtrTag)
-                {
-                    if (pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
-                    {
-                        pTlb->aEntries[idxEven].uTag = 0;
-                        if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
-                            pVCpu->iem.s.cbInstrBufTotal = 0;
-                        fMaybeLargePage = true;
-                    }
-                    else
-                    {
-                        Assert(fMaybeLargePage == -1);
-                        break;
-                    }
-                }
-                if ((pTlb->aEntries[idxEven + 1].uTag & GCPtrTagMask) == GCPtrTagGlob)
-                {
-                    if (pTlb->aEntries[idxEven + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
-                    {
-                        pTlb->aEntries[idxEven + 1].uTag = 0;
-                        if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
-                            pVCpu->iem.s.cbInstrBufTotal = 0;
-                        fMaybeLargePage = true;
-                    }
-                    else
-                    {
-                        Assert(fMaybeLargePage == -1);
-                        break;
-                    }
-                }
-                GCPtrTag++;
-                GCPtrTagGlob++;
-            }
-        }
+    {
+        RTGCPTR const GCPtrInstrBufPcTag = a_fDataTlb ? 0 : IEMTLB_CALC_TAG_NO_REV(pVCpu->iem.s.uInstrBufPc);
+        if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE)
+            iemTlbInvalidateLargePageWorker<a_fDataTlb, true>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
         else
-        {
-            /* 4MB large page */
-            GCPtrTag             &= ~(RTGCPTR)(RT_BIT_64(22 - GUEST_PAGE_SHIFT) - 1U);
-            RTGCPTR GCPtrTagGlob = GCPtrTag | pTlb->uTlbRevisionGlobal;
-            GCPtrTag            |= pTlb->uTlbRevision;
-
-# if IEMTLB_ENTRY_COUNT >= 1024
-            idxEven = IEMTLB_TAG_TO_EVEN_INDEX(GCPtrTag);
-            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)0;
-            uintptr_t const idxEvenEnd   = idxEven + 1024;
-# else
-            RTGCPTR const   GCPtrTagMask = ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK
-                                         & ~(RTGCPTR)(   (RT_BIT_64(10 - IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO) - 1U)
-                                                      << IEMTLB_ENTRY_COUNT_AS_POWER_OF_TWO);
-            uintptr_t const idxEvenEnd   = IEMTLB_ENTRY_COUNT;
-# endif
-            for (idxEven = 0; idxEven < idxEvenEnd; idxEven += 2)
-            {
-                if ((pTlb->aEntries[idxEven].uTag & GCPtrTagMask) == GCPtrTag)
-                {
-                    if (pTlb->aEntries[idxEven].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
-                    {
-                        pTlb->aEntries[idxEven].uTag = 0;
-                        if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
-                            pVCpu->iem.s.cbInstrBufTotal = 0;
-                        fMaybeLargePage = true;
-                    }
-                    else
-                    {
-                        Assert(fMaybeLargePage == -1);
-                        break;
-                    }
-                }
-                if ((pTlb->aEntries[idxEven + 1].uTag & GCPtrTagMask) == GCPtrTagGlob)
-                {
-                    if (pTlb->aEntries[idxEven + 1].fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE)
-                    {
-                        pTlb->aEntries[idxEven + 1].uTag = 0;
-                        if (!a_fDataTlb && GCPtrTag == GCPtrInstrBufPcTag)
-                            pVCpu->iem.s.cbInstrBufTotal = 0;
-                        fMaybeLargePage = true;
-                    }
-                    else
-                    {
-                        Assert(fMaybeLargePage == -1);
-                        break;
-                    }
-                }
-                GCPtrTag++;
-                GCPtrTagGlob++;
-            }
-        }
-    }
-}
-#endif
-
+            iemTlbInvalidateLargePageWorker<a_fDataTlb, false>(pVCpu, pTlb, GCPtrTag, GCPtrInstrBufPcTag);
+    }
+}
+
+#endif /* defined(IEM_WITH_CODE_TLB) || defined(IEM_WITH_DATA_TLB) */
 
 /**
@@ -1229,4 +1247,6 @@
                 pTlbe--;
                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.CodeTlb.uTlbRevision;
+                if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
+                    iemTlbLoadedLargePage<false>(&pVCpu->iem.s.CodeTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
             }
             else
@@ -1234,4 +1254,6 @@
                 pVCpu->iem.s.CodeTlb.cTlbCoreGlobalLoads++;
                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal;
+                if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
+                    iemTlbLoadedLargePage<true>(&pVCpu->iem.s.CodeTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
             }
             pTlbe->fFlagsAndPhysRev = (~WalkFast.fEffective & (X86_PTE_US | X86_PTE_RW | X86_PTE_D | X86_PTE_A))
@@ -6773,4 +6795,6 @@
                 pTlbe--;
                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevision;
+                if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
+                    iemTlbLoadedLargePage<false>(&pVCpu->iem.s.DataTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
             }
             else
@@ -6778,4 +6802,6 @@
                 pVCpu->iem.s.DataTlb.cTlbCoreGlobalLoads++;
                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevisionGlobal;
+                if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
+                    iemTlbLoadedLargePage<true>(&pVCpu->iem.s.DataTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
             }
         }
@@ -7165,4 +7191,6 @@
                 pTlbe--;
                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevision;
+                if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
+                    iemTlbLoadedLargePage<false>(&pVCpu->iem.s.DataTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
             }
             else
@@ -7173,4 +7201,6 @@
                     pVCpu->iem.s.DataTlb.cTlbCoreGlobalLoads++;
                 pTlbe->uTag         = uTagNoRev | pVCpu->iem.s.DataTlb.uTlbRevisionGlobal;
+                if (WalkFast.fInfo & PGM_WALKINFO_BIG_PAGE)
+                    iemTlbLoadedLargePage<true>(&pVCpu->iem.s.DataTlb, uTagNoRev, RT_BOOL(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE));
             }
         }
Index: trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 105283)
+++ trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 105284)
@@ -206,4 +206,10 @@
 #endif
         pVCpu->iem.s.CodeTlb.uTlbPhysRev        = pVCpu->iem.s.DataTlb.uTlbPhysRev        = uInitialTlbPhysRev;
+#ifndef VBOX_VMM_TARGET_ARMV8
+        pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
+        pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uFirstTag    = UINT64_MAX;
+        pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
+        pVCpu->iem.s.DataTlb.GlobalLargePageRange.uFirstTag    = UINT64_MAX;
+#endif
 
         /*
@@ -343,4 +349,18 @@
                         "Code TLB revision rollovers",                  "/IEM/CPU%u/Tlb/Code/PhysicalRevisionRollovers", idCpu);
 
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbGlobalLargePageCurLoads,  STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Code TLB global large page loads since flush", "/IEM/CPU%u/Tlb/Code/LargePageGlobalCurLoads", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Code TLB global large page range: lowest tag", "/IEM/CPU%u/Tlb/Code/LargePageGlobalFirstTag", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Code TLB global large page range: last tag",   "/IEM/CPU%u/Tlb/Code/LargePageGlobalLastTag", idCpu);
+
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNonGlobalLargePageCurLoads,  STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Code TLB non-global large page loads since flush", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalCurLoads", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Code TLB non-global large page range: lowest tag", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalFirstTag", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Code TLB non-global large page range: last tag",   "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalLastTag", idCpu);
+
         STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreMisses,      STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
                         "Code TLB misses",                              "/IEM/CPU%u/Tlb/Code/Misses", idCpu);
@@ -416,4 +436,18 @@
         STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbPhysRevRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
                         "Data TLB revision rollovers",                  "/IEM/CPU%u/Tlb/Data/PhysicalRevisionRollovers", idCpu);
+
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbGlobalLargePageCurLoads,  STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Data TLB global large page loads since flush", "/IEM/CPU%u/Tlb/Data/LargePageGlobalCurLoads", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.GlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Data TLB global large page range: lowest tag", "/IEM/CPU%u/Tlb/Data/LargePageGlobalFirstTag", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.GlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Data TLB global large page range: last tag",   "/IEM/CPU%u/Tlb/Data/LargePageGlobalLastTag", idCpu);
+
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNonGlobalLargePageCurLoads,  STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Data TLB non-global large page loads since flush", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalCurLoads", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Data TLB non-global large page range: lowest tag", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalFirstTag", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
+                        "Data TLB non-global large page range: last tag",   "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalLastTag", idCpu);
 
         STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreMisses,      STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
Index: trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMInternal.h	(revision 105283)
+++ trunk/src/VBox/VMM/include/IEMInternal.h	(revision 105284)
@@ -571,4 +571,27 @@
     uint64_t            uTlbRevisionGlobal;
 
+    /** Large page tag range.
+     *
+     * This is used to avoid scanning a large page's worth of TLB entries for each
+     * INVLPG instruction, and only to do so iff we've loaded any and when the
+     * address is in this range.  This is kept up to date when we loading new TLB
+     * entries.
+     */
+    struct LARGEPAGERANGE
+    {
+        /** The lowest large page address tag, UINT64_MAX if none. */
+        uint64_t        uFirstTag;
+        /** The highest large page address tag (with offset mask part set), 0 if none. */
+        uint64_t        uLastTag;
+    }
+    /** Large page range for non-global pages. */
+                        NonGlobalLargePageRange,
+    /** Large page range for global pages. */
+                        GlobalLargePageRange;
+    /** Number of non-global entries for large pages loaded since last TLB flush. */
+    uint32_t            cTlbNonGlobalLargePageCurLoads;
+    /** Number of global entries for large pages loaded since last TLB flush. */
+    uint32_t            cTlbGlobalLargePageCurLoads;
+
     /* Statistics: */
 
@@ -630,5 +653,5 @@
     uint32_t            cTlbPhysRevRollovers;
 
-    uint32_t            au32Padding[10];
+    /*uint32_t            au32Padding[2];*/
 
     /** The TLB entries.
