/*++ Copyright (c) 1989 Microsoft Corporation Module Name: checkpte.c Abstract: This module contains routines for sanity checking the page directory. Author: Lou Perazzoli (loup) 25-Apr-1989 Revision History: --*/ #include "mi.h" #if DBG #if !defined (_WIN64) VOID CheckValidPte ( IN PMMPTE PointerPte ); VOID CheckInvalidPte ( IN PMMPTE PointerPte ); VOID MiCheckPte ( VOID ) /*++ Routine Description: This routine checks each page table page in an address space to ensure it is in the proper state. Arguments: None. Return Value: None. Environment: Kernel mode, APCs disabled. --*/ { ULONG i; ULONG j; PMMPTE PointerPte; PMMPTE PointerPde; PMMPFN Pfn1; ULONG ValidCount; ULONG TransitionCount; KIRQL OldIrql; PEPROCESS TargetProcess; USHORT UsedPages; ULONG PdeValidCount; TargetProcess = PsGetCurrentProcess (); PointerPde = MiGetPdeAddress(0); UsedPages = 0; PdeValidCount = 1; LOCK_WS (TargetProcess); LOCK_PFN (OldIrql); for (i = 0; i < PDE_PER_PAGE; i += 1) { if (PointerPde->u.Hard.Valid) { if ((i < 512) || (i == 769) || (i== 896) ) { PdeValidCount += 1; } ValidCount = 0; TransitionCount = 0; CheckValidPte (PointerPde); PointerPte = MiGetPteAddress (i<<22); for (j=0; j < PTE_PER_PAGE; j += 1) { if ((PointerPte >= MiGetPteAddress(HYPER_SPACE)) && (PointerPte < MiGetPteAddress(WORKING_SET_LIST))) { goto endloop; } if (PointerPte->u.Hard.Valid) { ValidCount += 1; CheckValidPte (PointerPte); } else { CheckInvalidPte (PointerPte); if ((PointerPte->u.Soft.Transition == 1) && (PointerPte->u.Soft.Prototype == 0)) { // // Transition PTE, up the transition count. // TransitionCount += 1; } } if (PointerPte->u.Long != 0) { UsedPages += 1; } endloop: PointerPte += 1; } if ((i < 512) || (i == 896)) { if (MmWorkingSetList->UsedPageTableEntries[i] != UsedPages) { DbgPrint("used pages and page table used not equal %lx %lx %lx\n", i,MmWorkingSetList->UsedPageTableEntries[i], UsedPages); } } // // Check the share count for the page table page. // if ((i < 511) || (i == 896)) { Pfn1 = MI_PFN_ELEMENT (PointerPde->u.Hard.PageFrameNumber); if (Pfn1->u2.ShareCount != ((ULONG)1+ValidCount+TransitionCount)) { DbgPrint("share count for page table page bad - %lx %lx %lx\n", i,ValidCount, TransitionCount); MiFormatPfn(Pfn1); } } } PointerPde += 1; UsedPages = 0; } PointerPde = MiGetPteAddress (PDE_BASE); Pfn1 = MI_PFN_ELEMENT(PointerPde->u.Hard.PageFrameNumber); UNLOCK_PFN (OldIrql); UNLOCK_WS (TargetProcess); return; } VOID CheckValidPte ( IN PMMPTE PointerPte ) { PMMPFN Pfn1; PMMPTE PointerPde; if (MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) > MmNumberOfPhysicalPages) { return; } Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber); if (PointerPte->u.Hard.PageFrameNumber == 0) { DbgPrint("physical page zero mapped\n"); MiFormatPte(PointerPte); MiFormatPfn(Pfn1); } if (Pfn1->u3.e1.PageLocation != ActiveAndValid) { DbgPrint("valid PTE with page frame not active and valid\n"); MiFormatPfn(Pfn1); MiFormatPte(PointerPte); } if (Pfn1->u3.e1.PrototypePte == 0) { // // This is not a prototype PTE. // if (Pfn1->PteAddress != PointerPte) { DbgPrint("checkpte - Pfn PTE address and PTE address not equal\n"); MiFormatPte(PointerPte); MiFormatPfn(Pfn1); return; } } if (!MmIsAddressValid(Pfn1->PteAddress)) { return; } PointerPde = MiGetPteAddress (Pfn1->PteAddress); if (PointerPde->u.Hard.Valid == 1) { if (MI_GET_PAGE_FRAME_FROM_PTE (PointerPde) != Pfn1->u4.PteFrame) { DbgPrint("checkpte - pteframe not right\n"); MiFormatPfn(Pfn1); MiFormatPte(PointerPte); MiFormatPte(PointerPde); } } return; } #endif VOID CheckInvalidPte ( IN PMMPTE PointerPte ) { UNREFERENCED_PARAMETER (PointerPte); return; } #endif