Author: cgutman Date: Mon Dec 26 23:12:38 2011 New Revision: 54766
URL: http://svn.reactos.org/svn/reactos?rev=54766&view=rev Log: [NTOSKRNL] - Don't flush the TLB in MmEnableVirtualMapping and MmCreateVirtualMapping because the PTE is already invalid so it can't possibly be in the TLB per x86 spec - Added explanations of why flushes are needed or not needed in certain places - A few small code improvements - Should speed up ROS a bit by avoiding unnecessary TLB entry flushing
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Mon Dec 26 23:12:38 2011 @@ -457,22 +457,26 @@ */ Pte = InterlockedExchangePte(Pt, 0);
- WasValid = (PAGE_MASK(Pte) != 0); if (WasValid) { + /* Flush the TLB since we transitioned this PTE + * from valid to invalid so any stale translations + * are removed from the cache */ + MiFlushTlb(Pt, Address); + Pfn = PTE_TO_PFN(Pte); - MiFlushTlb(Pt, Address); - } - else - { + + if (FreePage) + { + MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn); + Pfn = 0; + } + } + else + { + MmUnmapPageTable(Pt); Pfn = 0; - MmUnmapPageTable(Pt); - } - - if (FreePage && WasValid) - { - MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn); }
/* @@ -524,7 +528,8 @@ */ Pte = InterlockedExchangePte(Pt, 0);
- //MiFlushTlb(Pt, Address); + /* We don't need to flush here because page file entries + * are invalid translations, so the processor won't cache them */ MmUnmapPageTable(Pt);
if(!(Pte & 0x800)) @@ -652,14 +657,10 @@ { Pte = *Pt; } while (Pte != InterlockedCompareExchangePte(Pt, Pte | PA_PRESENT, Pte)); - if (!(Pte & PA_PRESENT)) - { - MiFlushTlb(Pt, Address); - } - else - { - MmUnmapPageTable(Pt); - } + + /* We don't need to flush the TLB here because it + * won't cache translations for non-present pages */ + MmUnmapPageTable(Pt); }
BOOLEAN @@ -713,7 +714,10 @@ { KeBugCheck(MEMORY_MANAGEMENT); } - //MiFlushTlb(Pt, Address); + + /* We don't need to flush the TLB here because it + * only caches valid translations and a zero PTE + * is not a valid translation */ MmUnmapPageTable(Pt);
return(STATUS_SUCCESS); @@ -809,22 +813,16 @@ } oldPdeOffset = PdeOffset;
- Pte = InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes);; + Pte = InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes); /* There should not be anything valid here */ if (PAGE_MASK(Pte) != 0) { - PMMPFN Pfn1 = MiGetPfnEntry(PTE_TO_PFN(Pte)); - (void)Pfn1; DPRINT1("Bad PTE %lx\n", Pte); KeBugCheck(MEMORY_MANAGEMENT); } - /* flush if currently mapped, just continue editing if hyperspace - * NOTE : This check is similar to what is done in MiFlushTlb, but we - * don't use it because it would unmap the page table */ - if (Addr >= MmSystemRangeStart || (!IS_HYPERSPACE(Pt))) - { - KeInvalidateTlbEntry(Addr); - } + + /* We don't need to flush the TLB here because it only caches valid translations + * and we're moving this PTE from invalid to valid so it can't be cached right now */ }
ASSERT(Addr > Address); @@ -933,8 +931,9 @@ if(!PAGE_MASK(Pte)) { DPRINT1("Invalid Pte %lx\n", Pte); - __debugbreak(); - } + KeBugCheck(MEMORY_MANAGEMENT); + } + if((Pte & Attributes) != Attributes) MiFlushTlb(Pt, Address); else @@ -955,7 +954,7 @@
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr); Pte = MmGetPageEntryForProcess(NULL, vaddr); - if (Pte != 0 && Pte & PA_PRESENT) + if (Pte != 0 && (Pte & PA_PRESENT)) { p.QuadPart = PAGE_MASK(Pte); p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);