diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/mm/checkpfn.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/mm/checkpfn.c')
-rw-r--r-- | private/ntos/mm/checkpfn.c | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/private/ntos/mm/checkpfn.c b/private/ntos/mm/checkpfn.c new file mode 100644 index 000000000..332b373ec --- /dev/null +++ b/private/ntos/mm/checkpfn.c @@ -0,0 +1,538 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + checkpfn.c + +Abstract: + + This module contains routines for sanity checking the PFN database. + +Author: + + Lou Perazzoli (loup) 25-Apr-1989 + +Revision History: + +--*/ + +#include "mi.h" + +#if DBG + +PRTL_BITMAP CheckPfnBitMap; + + +VOID +MiCheckPfn ( + ) + +/*++ + +Routine Description: + + This routine checks each physical page in the PFN database to ensure + it is in the proper state. + +Arguments: + + None. + +Return Value: + + None. + +Environment: + + Kernel mode, APC's disabled. + +--*/ + +{ + PMMPFN Pfn1; + ULONG Link, Previous; + ULONG i; + PMMPTE PointerPte; + KIRQL PreviousIrql; + KIRQL OldIrql; + USHORT ValidCheck[4]; + USHORT ValidPage[4]; + PMMPFN PfnX; + + ValidCheck[0] = ValidCheck[1] = ValidCheck[2] = ValidCheck[3] = 0; + ValidPage[0] = ValidPage[1] = ValidPage[2] = ValidPage[3] = 0; + + if (CheckPfnBitMap == NULL) { + MiCreateBitMap ( &CheckPfnBitMap, MmNumberOfPhysicalPages, NonPagedPool); + } + RtlClearAllBits (CheckPfnBitMap); + + // + // Walk free list. + // + + KeRaiseIrql (APC_LEVEL, &PreviousIrql); + LOCK_PFN (OldIrql); + + Previous = MM_EMPTY_LIST; + Link = MmFreePageListHead.Flink; + for (i=0; i < MmFreePageListHead.Total; i++) { + if (Link == MM_EMPTY_LIST) { + DbgPrint("free list total count wrong\n"); + UNLOCK_PFN (OldIrql); + KeLowerIrql (PreviousIrql); + return; + } + RtlSetBits (CheckPfnBitMap, Link, 1L); + Pfn1 = MI_PFN_ELEMENT(Link); + if (Pfn1->u3.e2.ReferenceCount != 0) { + DbgPrint("non zero reference count on free list\n"); + MiFormatPfn(Pfn1); + + } + if (Pfn1->u3.e1.PageLocation != FreePageList) { + DbgPrint("page location not freelist\n"); + MiFormatPfn(Pfn1); + } + if (Pfn1->u2.Blink != Previous) { + DbgPrint("bad blink on free list\n"); + MiFormatPfn(Pfn1); + } + Previous = Link; + Link = Pfn1->u1.Flink; + + } + if (Link != MM_EMPTY_LIST) { + DbgPrint("free list total count wrong\n"); + Pfn1 = MI_PFN_ELEMENT(Link); + MiFormatPfn(Pfn1); + } + + // + // Walk zeroed list. + // + + Previous = MM_EMPTY_LIST; + Link = MmZeroedPageListHead.Flink; + for (i=0; i < MmZeroedPageListHead.Total; i++) { + if (Link == MM_EMPTY_LIST) { + DbgPrint("zero list total count wrong\n"); + UNLOCK_PFN (OldIrql); + KeLowerIrql (PreviousIrql); + return; + } + RtlSetBits (CheckPfnBitMap, Link, 1L); + Pfn1 = MI_PFN_ELEMENT(Link); + if (Pfn1->u3.e2.ReferenceCount != 0) { + DbgPrint("non zero reference count on zero list\n"); + MiFormatPfn(Pfn1); + + } + if (Pfn1->u3.e1.PageLocation != ZeroedPageList) { + DbgPrint("page location not zerolist\n"); + MiFormatPfn(Pfn1); + } + if (Pfn1->u2.Blink != Previous) { + DbgPrint("bad blink on zero list\n"); + MiFormatPfn(Pfn1); + } + Previous = Link; + Link = Pfn1->u1.Flink; + + } + if (Link != MM_EMPTY_LIST) { + DbgPrint("zero list total count wrong\n"); + Pfn1 = MI_PFN_ELEMENT(Link); + MiFormatPfn(Pfn1); + } + + // + // Walk Bad list. + // + Previous = MM_EMPTY_LIST; + Link = MmBadPageListHead.Flink; + for (i=0; i < MmBadPageListHead.Total; i++) { + if (Link == MM_EMPTY_LIST) { + DbgPrint("Bad list total count wrong\n"); + UNLOCK_PFN (OldIrql); + KeLowerIrql (PreviousIrql); + return; + } + RtlSetBits (CheckPfnBitMap, Link, 1L); + Pfn1 = MI_PFN_ELEMENT(Link); + if (Pfn1->u3.e2.ReferenceCount != 0) { + DbgPrint("non zero reference count on Bad list\n"); + MiFormatPfn(Pfn1); + + } + if (Pfn1->u3.e1.PageLocation != BadPageList) { + DbgPrint("page location not Badlist\n"); + MiFormatPfn(Pfn1); + } + if (Pfn1->u2.Blink != Previous) { + DbgPrint("bad blink on Bad list\n"); + MiFormatPfn(Pfn1); + } + Previous = Link; + Link = Pfn1->u1.Flink; + + } + if (Link != MM_EMPTY_LIST) { + DbgPrint("Bad list total count wrong\n"); + Pfn1 = MI_PFN_ELEMENT(Link); + MiFormatPfn(Pfn1); + } + + // + // Walk Standby list. + // + + Previous = MM_EMPTY_LIST; + Link = MmStandbyPageListHead.Flink; + for (i=0; i < MmStandbyPageListHead.Total; i++) { + if (Link == MM_EMPTY_LIST) { + DbgPrint("Standby list total count wrong\n"); + UNLOCK_PFN (OldIrql); + KeLowerIrql (PreviousIrql); + return; + } + RtlSetBits (CheckPfnBitMap, Link, 1L); + Pfn1 = MI_PFN_ELEMENT(Link); + if (Pfn1->u3.e2.ReferenceCount != 0) { + DbgPrint("non zero reference count on Standby list\n"); + MiFormatPfn(Pfn1); + + } + if (Pfn1->u3.e1.PageLocation != StandbyPageList) { + DbgPrint("page location not Standbylist\n"); + MiFormatPfn(Pfn1); + } + if (Pfn1->u2.Blink != Previous) { + DbgPrint("bad blink on Standby list\n"); + MiFormatPfn(Pfn1); + } + + // + // Check to see if referenced PTE is okay. + // + if (MI_IS_PFN_DELETED (Pfn1)) { + DbgPrint("Invalid pteaddress in standby list\n"); + MiFormatPfn(Pfn1); + + } else { + + OldIrql = 99; + if ((Pfn1->u3.e1.PrototypePte == 1) && + (MmIsAddressValid (Pfn1->PteAddress))) { + PointerPte = Pfn1->PteAddress; + } else { + PointerPte = MiMapPageInHyperSpace(Pfn1->PteFrame, + &OldIrql); + PointerPte = (PMMPTE)((ULONG)PointerPte + + MiGetByteOffset(Pfn1->PteAddress)); + } + if (PointerPte->u.Trans.PageFrameNumber != Link) { + DbgPrint("Invalid PFN - PTE address is wrong in standby list\n"); + MiFormatPfn(Pfn1); + MiFormatPte(PointerPte); + } + if (PointerPte->u.Soft.Transition == 0) { + DbgPrint("Pte not in transition for page on standby list\n"); + MiFormatPfn(Pfn1); + MiFormatPte(PointerPte); + } + if (OldIrql != 99) { + MiUnmapPageInHyperSpace (OldIrql); + OldIrql = 99; + } + + } + + Previous = Link; + Link = Pfn1->u1.Flink; + + } + if (Link != MM_EMPTY_LIST) { + DbgPrint("Standby list total count wrong\n"); + Pfn1 = MI_PFN_ELEMENT(Link); + MiFormatPfn(Pfn1); + } + + // + // Walk Modified list. + // + + Previous = MM_EMPTY_LIST; + Link = MmModifiedPageListHead.Flink; + for (i=0; i < MmModifiedPageListHead.Total; i++) { + if (Link == MM_EMPTY_LIST) { + DbgPrint("Modified list total count wrong\n"); + UNLOCK_PFN (OldIrql); + KeLowerIrql (PreviousIrql); + return; + } + RtlSetBits (CheckPfnBitMap, Link, 1L); + Pfn1 = MI_PFN_ELEMENT(Link); + if (Pfn1->u3.e2.ReferenceCount != 0) { + DbgPrint("non zero reference count on Modified list\n"); + MiFormatPfn(Pfn1); + + } + if (Pfn1->u3.e1.PageLocation != ModifiedPageList) { + DbgPrint("page location not Modifiedlist\n"); + MiFormatPfn(Pfn1); + } + if (Pfn1->u2.Blink != Previous) { + DbgPrint("bad blink on Modified list\n"); + MiFormatPfn(Pfn1); + } + // + // Check to see if referenced PTE is okay. + // + if (MI_IS_PFN_DELETED (Pfn1)) { + DbgPrint("Invalid pteaddress in modified list\n"); + MiFormatPfn(Pfn1); + + } else { + + if ((Pfn1->u3.e1.PrototypePte == 1) && + (MmIsAddressValid (Pfn1->PteAddress))) { + PointerPte = Pfn1->PteAddress; + } else { + PointerPte = MiMapPageInHyperSpace(Pfn1->PteFrame, &OldIrql); + PointerPte = (PMMPTE)((ULONG)PointerPte + + MiGetByteOffset(Pfn1->PteAddress)); + } + + if (PointerPte->u.Trans.PageFrameNumber != Link) { + DbgPrint("Invalid PFN - PTE address is wrong in modified list\n"); + MiFormatPfn(Pfn1); + MiFormatPte(PointerPte); + } + if (PointerPte->u.Soft.Transition == 0) { + DbgPrint("Pte not in transition for page on modified list\n"); + MiFormatPfn(Pfn1); + MiFormatPte(PointerPte); + } + + if (OldIrql != 99) { + MiUnmapPageInHyperSpace (OldIrql); + OldIrql = 99; + } + } + + Previous = Link; + Link = Pfn1->u1.Flink; + + } + if (Link != MM_EMPTY_LIST) { + DbgPrint("Modified list total count wrong\n"); + Pfn1 = MI_PFN_ELEMENT(Link); + MiFormatPfn(Pfn1); + } + // + // All non active pages have been scanned. Locate the + // active pages and make sure they are consistent. + // + + // + // set bit zero as page zero is reserved for now + // + + RtlSetBits (CheckPfnBitMap, 0L, 1L); + + Link = RtlFindClearBitsAndSet (CheckPfnBitMap, 1L, 0); + while (Link != 0xFFFFFFFF) { + Pfn1 = MI_PFN_ELEMENT (Link); + + // + // Make sure the PTE address is okay + // + + if ((Pfn1->PteAddress >= (PMMPTE)HYPER_SPACE) + && (Pfn1->u3.e1.PrototypePte == 0)) { + DbgPrint("pfn with illegal pte address\n"); + MiFormatPfn(Pfn1); + break; + } + + if (Pfn1->PteAddress < (PMMPTE)PTE_BASE) { + DbgPrint("pfn with illegal pte address\n"); + MiFormatPfn(Pfn1); + break; + } + +#ifdef _MIPS_ + + // + // ignore ptes mapped to kseg0 or kseg1. + // + + if ((Pfn1->PteAddress > (PMMPTE)0xc0200000) && + (Pfn1->PteAddress < (PMMPTE)0xc0300000)) { + + goto NoCheck; + } +#endif //MIPS + +#ifdef _PPC_ + + // + // ignore ptes mapped to PowerPC kernel BAT. + // + + if (MI_IS_PHYSICAL_ADDRESS(MiGetVirtualAddressMappedByPte(Pfn1->PteAddress))) { + + goto NoCheck; + } +#endif // _PPC_ + +#ifdef _ALPHA_ + + // + // ignore ptes mapped to ALPHA's 32-bit superpage. + // + + if ((Pfn1->PteAddress > (PMMPTE)0xc0100000) && + (Pfn1->PteAddress < (PMMPTE)0xc0180000)) { + + goto NoCheck; + } +#endif //ALPHA + + // + // Check to make sure the referenced PTE is for this page. + // + + if ((Pfn1->u3.e1.PrototypePte == 1) && + (MmIsAddressValid (Pfn1->PteAddress))) { + PointerPte = Pfn1->PteAddress; + } else { + PointerPte = MiMapPageInHyperSpace(Pfn1->PteFrame, &OldIrql); + PointerPte = (PMMPTE)((ULONG)PointerPte + + MiGetByteOffset(Pfn1->PteAddress)); + } + + if (PointerPte->u.Hard.PageFrameNumber != Link) { + DbgPrint("Invalid PFN - PTE address is wrong in active list\n"); + MiFormatPfn(Pfn1); + MiFormatPte(PointerPte); + } + if (PointerPte->u.Hard.Valid == 0) { + // + // if the page is a page table page it could be out of + // the working set yet a transition page is keeping it + // around in memory (ups the share count). + // + + if ((Pfn1->PteAddress < (PMMPTE)PDE_BASE) || + (Pfn1->PteAddress > (PMMPTE)PDE_TOP)) { + + DbgPrint("Pte not valid for page on active list\n"); + MiFormatPfn(Pfn1); + MiFormatPte(PointerPte); + } + } + + if (Pfn1->u3.e2.ReferenceCount != 1) { + DbgPrint("refcount not 1\n"); + MiFormatPfn(Pfn1); + } + + + // + // Check to make sure the PTE count for the frame is okay. + // + + if (Pfn1->u3.e1.PrototypePte == 1) { + PfnX = MI_PFN_ELEMENT(Pfn1->PteFrame); + for (i = 0; i < 4; i++) { + if (ValidPage[i] == 0) { + ValidPage[i] = (USHORT)Pfn1->PteFrame; + } + if (ValidPage[i] == (USHORT)Pfn1->PteFrame) { + ValidCheck[i] += 1; + break; + } + } + } + if (OldIrql != 99) { + MiUnmapPageInHyperSpace (OldIrql); + OldIrql = 99; + } + +#if defined(_MIPS_) || defined(_ALPHA_) || defined(_PPC_) +NoCheck: +#endif + Link = RtlFindClearBitsAndSet (CheckPfnBitMap, 1L, 0); + + } + + for (i = 0; i < 4; i++) { + if (ValidPage[i] == 0) { + break; + } + PfnX = MI_PFN_ELEMENT(ValidPage[i]); + } + + UNLOCK_PFN (OldIrql); + KeLowerIrql (PreviousIrql); + return; + +} + +VOID +MiDumpPfn ( ) + +{ + ULONG i; + PMMPFN Pfn1; + + Pfn1 = MI_PFN_ELEMENT (MmLowestPhysicalPage); + + for (i=0; i < MmNumberOfPhysicalPages; i++) { + MiFormatPfn (Pfn1); + Pfn1++; + } + return; +} + +VOID +MiFormatPfn ( + IN PMMPFN PointerPfn + ) + +{ + struct longs { + ULONG Flink; + ULONG Pteadd; + ULONG Blink; + ULONG Refcount; + ULONG Origpte; + ULONG Flags; + }; + + struct longs *Pfake; + ULONG i; + + i = PointerPfn - MmPfnDatabase; + + Pfake = (struct longs *)PointerPfn; + + DbgPrint("***PFN %lx flink %lx blink %lx ptecout-refcnt %lx\n", + i, + Pfake->Flink, + Pfake->Blink, + Pfake->Refcount); + + DbgPrint(" pteaddr %lx originalPTE %lx flags %lx \n", + Pfake->Pteadd, + Pfake->Origpte, + Pfake->Flags); + + return; + +} +#endif //DBG |