diff --git a/reactos/ntoskrnl/include/internal/kd.h b/reactos/ntoskrnl/include/internal/kd.h index bc88f5eec03..3002bad4189 100644 --- a/reactos/ntoskrnl/include/internal/kd.h +++ b/reactos/ntoskrnl/include/internal/kd.h @@ -342,7 +342,8 @@ typedef enum _KDP_DEBUG_SERVICE KdSpare1 = 0x23, /* h */ KdSpare2 = 0x17, /* i */ KdSpare3 = 0x24, /* j */ - EnterDebugger = 0x25 /* k */ + EnterDebugger = 0x25, /* k */ + ThatsWhatSheSaid = 69 /* FIGURE IT OUT */ } KDP_DEBUG_SERVICE; /* Dispatch Table for Wrapper Functions */ diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index c1509c7f848..ada4602f478 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -293,6 +293,12 @@ typedef struct ULONG PagingRequestsInLastFifteenMinutes; } MM_STATS; +// +// These two mappings are actually used by Windows itself, based on the ASSERTS +// +#define StartOfAllocation ReadInProgress +#define EndOfAllocation WriteInProgress + typedef struct _MMPFNENTRY { USHORT Modified:1; @@ -1120,6 +1126,12 @@ MmInitializePageList( VOID ); +VOID +NTAPI +MmDumpPfnDatabase( + VOID +); + PFN_TYPE NTAPI MmGetContinuousPages( diff --git a/reactos/ntoskrnl/kd/kdmain.c b/reactos/ntoskrnl/kd/kdmain.c index 8874d2142c6..a37f4a61ec3 100644 --- a/reactos/ntoskrnl/kd/kdmain.c +++ b/reactos/ntoskrnl/kd/kdmain.c @@ -85,6 +85,10 @@ KdpServiceDispatcher(ULONG Service, case EnterDebugger: DbgBreakPoint(); break; + + case ThatsWhatSheSaid: + MmDumpPfnDatabase(); + break; default: break; diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 45f0307c577..020de2cb440 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -251,6 +251,94 @@ MmAllocEarlyPage(VOID) return Pfn; } +VOID +NTAPI +MmDumpPfnDatabase(VOID) +{ + ULONG i; + PPHYSICAL_PAGE Pfn1; + PCHAR State = "????", Consumer = "Unknown"; + KIRQL OldIrql; + + OldIrql = KfRaiseIrql(HIGH_LEVEL); + + // + // Loop the PFN database + // + for (i = 0; i <= MmHighestPhysicalPage; i++) + { + Pfn1 = MiGetPfnEntry(i); + + // + // Get the consumer + // + switch (Pfn1->Flags.Consumer) + { + case MC_NPPOOL: + + Consumer = "Nonpaged Pool"; + break; + + case MC_PPOOL: + + Consumer = "Paged Pool"; + break; + + case MC_CACHE: + + Consumer = "File System Cache"; + break; + + case MC_USER: + + Consumer = "Process Working Set"; + break; + + case MC_SYSTEM: + + Consumer = "System"; + break; + } + + // + // Get the type + // + switch (Pfn1->Flags.Type) + { + case MM_PHYSICAL_PAGE_USED: + + State = "Used"; + break; + + case MM_PHYSICAL_PAGE_FREE: + + State = "Free"; + Consumer = "Free"; + break; + + case MM_PHYSICAL_PAGE_BIOS: + + State = "BIOS"; + Consumer = "System Reserved"; + break; + } + + // + // Pretty-print the page + // + DbgPrint("0x%08p:\t%04s\t%20s\t(%02d.%02d.%02d) [%08p])\n", + i << PAGE_SHIFT, + State, + Consumer, + Pfn1->ReferenceCount, + Pfn1->MapCount, + Pfn1->LockCount, + Pfn1->RmapListHead); + } + + KeLowerIrql(OldIrql); +} + VOID NTAPI MmInitializePageList(VOID)