Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
4.9 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. checkpte.c
  5. Abstract:
  6. This module contains routines for sanity checking the page directory.
  7. Author:
  8. Lou Perazzoli (loup) 25-Apr-1989
  9. Revision History:
  10. --*/
  11. #include "mi.h"
  12. #if DBG
  13. #if !defined (_WIN64)
  14. VOID
  15. CheckValidPte (
  16. IN PMMPTE PointerPte
  17. );
  18. VOID
  19. CheckInvalidPte (
  20. IN PMMPTE PointerPte
  21. );
  22. VOID
  23. MiCheckPte (
  24. VOID
  25. )
  26. /*++
  27. Routine Description:
  28. This routine checks each page table page in an address space to
  29. ensure it is in the proper state.
  30. Arguments:
  31. None.
  32. Return Value:
  33. None.
  34. Environment:
  35. Kernel mode, APCs disabled.
  36. --*/
  37. {
  38. ULONG i;
  39. ULONG j;
  40. PMMPTE PointerPte;
  41. PMMPTE PointerPde;
  42. PMMPFN Pfn1;
  43. ULONG ValidCount;
  44. ULONG TransitionCount;
  45. KIRQL OldIrql;
  46. PEPROCESS TargetProcess;
  47. USHORT UsedPages;
  48. ULONG PdeValidCount;
  49. TargetProcess = PsGetCurrentProcess ();
  50. PointerPde = MiGetPdeAddress(0);
  51. UsedPages = 0;
  52. PdeValidCount = 1;
  53. LOCK_WS (TargetProcess);
  54. LOCK_PFN (OldIrql);
  55. for (i = 0; i < PDE_PER_PAGE; i += 1) {
  56. if (PointerPde->u.Hard.Valid) {
  57. if ((i < 512) || (i == 769) || (i== 896) ) {
  58. PdeValidCount += 1;
  59. }
  60. ValidCount = 0;
  61. TransitionCount = 0;
  62. CheckValidPte (PointerPde);
  63. PointerPte = MiGetPteAddress (i<<22);
  64. for (j=0; j < PTE_PER_PAGE; j += 1) {
  65. if ((PointerPte >= MiGetPteAddress(HYPER_SPACE)) &&
  66. (PointerPte < MiGetPteAddress(WORKING_SET_LIST))) {
  67. goto endloop;
  68. }
  69. if (PointerPte->u.Hard.Valid) {
  70. ValidCount += 1;
  71. CheckValidPte (PointerPte);
  72. } else {
  73. CheckInvalidPte (PointerPte);
  74. if ((PointerPte->u.Soft.Transition == 1) &&
  75. (PointerPte->u.Soft.Prototype == 0)) {
  76. //
  77. // Transition PTE, up the transition count.
  78. //
  79. TransitionCount += 1;
  80. }
  81. }
  82. if (PointerPte->u.Long != 0) {
  83. UsedPages += 1;
  84. }
  85. endloop:
  86. PointerPte += 1;
  87. }
  88. if ((i < 512) || (i == 896)) {
  89. if (MmWorkingSetList->UsedPageTableEntries[i] != UsedPages) {
  90. DbgPrint("used pages and page table used not equal %lx %lx %lx\n",
  91. i,MmWorkingSetList->UsedPageTableEntries[i], UsedPages);
  92. }
  93. }
  94. //
  95. // Check the share count for the page table page.
  96. //
  97. if ((i < 511) || (i == 896)) {
  98. Pfn1 = MI_PFN_ELEMENT (PointerPde->u.Hard.PageFrameNumber);
  99. if (Pfn1->u2.ShareCount != ((ULONG)1+ValidCount+TransitionCount)) {
  100. DbgPrint("share count for page table page bad - %lx %lx %lx\n",
  101. i,ValidCount, TransitionCount);
  102. MiFormatPfn(Pfn1);
  103. }
  104. }
  105. }
  106. PointerPde += 1;
  107. UsedPages = 0;
  108. }
  109. PointerPde = MiGetPteAddress (PDE_BASE);
  110. Pfn1 = MI_PFN_ELEMENT(PointerPde->u.Hard.PageFrameNumber);
  111. UNLOCK_PFN (OldIrql);
  112. UNLOCK_WS (TargetProcess);
  113. return;
  114. }
  115. VOID
  116. CheckValidPte (
  117. IN PMMPTE PointerPte
  118. )
  119. {
  120. PMMPFN Pfn1;
  121. PMMPTE PointerPde;
  122. if (MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) > MmNumberOfPhysicalPages) {
  123. return;
  124. }
  125. Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
  126. if (PointerPte->u.Hard.PageFrameNumber == 0) {
  127. DbgPrint("physical page zero mapped\n");
  128. MiFormatPte(PointerPte);
  129. MiFormatPfn(Pfn1);
  130. }
  131. if (Pfn1->u3.e1.PageLocation != ActiveAndValid) {
  132. DbgPrint("valid PTE with page frame not active and valid\n");
  133. MiFormatPfn(Pfn1);
  134. MiFormatPte(PointerPte);
  135. }
  136. if (Pfn1->u3.e1.PrototypePte == 0) {
  137. //
  138. // This is not a prototype PTE.
  139. //
  140. if (Pfn1->PteAddress != PointerPte) {
  141. DbgPrint("checkpte - Pfn PTE address and PTE address not equal\n");
  142. MiFormatPte(PointerPte);
  143. MiFormatPfn(Pfn1);
  144. return;
  145. }
  146. }
  147. if (!MmIsAddressValid(Pfn1->PteAddress)) {
  148. return;
  149. }
  150. PointerPde = MiGetPteAddress (Pfn1->PteAddress);
  151. if (PointerPde->u.Hard.Valid == 1) {
  152. if (MI_GET_PAGE_FRAME_FROM_PTE (PointerPde) != Pfn1->u4.PteFrame) {
  153. DbgPrint("checkpte - pteframe not right\n");
  154. MiFormatPfn(Pfn1);
  155. MiFormatPte(PointerPte);
  156. MiFormatPte(PointerPde);
  157. }
  158. }
  159. return;
  160. }
  161. #endif
  162. VOID
  163. CheckInvalidPte (
  164. IN PMMPTE PointerPte
  165. )
  166. {
  167. UNREFERENCED_PARAMETER (PointerPte);
  168. return;
  169. }
  170. #endif