214 lines
5 KiB
C
214 lines
5 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
filecach.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 15-Aug-1993
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
DECLARE_API( filecache )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays physical memory usage by drivers.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG result;
|
|
ULONG NumberOfPtes;
|
|
ULONG PteCount;
|
|
ULONG ReadCount;
|
|
ULONG64 SystemCacheWsLoc;
|
|
ULONG64 SystemCacheStart;
|
|
ULONG64 SystemCacheEnd;
|
|
ULONG64 SystemCacheStartPte;
|
|
ULONG64 SystemCacheEndPte;
|
|
ULONG Transition = 0;
|
|
ULONG Valid;
|
|
ULONG ValidShift, ValidSize;
|
|
ULONG64 PfnIndex;
|
|
ULONG PteSize;
|
|
ULONG PfnSize;
|
|
ULONG HighPage;
|
|
ULONG LowPage;
|
|
ULONG64 Pte;
|
|
ULONG64 PfnDb;
|
|
ULONG64 Pfn;
|
|
ULONG64 PfnStart;
|
|
ULONG64 PfnArray;
|
|
ULONG64 PfnArrayOffset;
|
|
ULONG NumberOfPteToRead;
|
|
ULONG WorkingSetSize, PeakWorkingSetSize;
|
|
ULONG64 BufferedAddress=0;
|
|
CHAR Buffer[2048];
|
|
|
|
INIT_API();
|
|
|
|
dprintf("***** Dump file cache******\n");
|
|
|
|
SystemCacheStart = GetNtDebuggerDataPtrValue( MmSystemCacheStart );
|
|
if (!SystemCacheStart) {
|
|
dprintf("unable to get SystemCacheStart\n");
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
SystemCacheEnd = GetNtDebuggerDataPtrValue( MmSystemCacheEnd );
|
|
if (!SystemCacheEnd) {
|
|
dprintf("unable to get SystemCacheEnd\n");
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
SystemCacheWsLoc = GetNtDebuggerData( MmSystemCacheWs );
|
|
if (!SystemCacheWsLoc) {
|
|
dprintf("unable to get MmSystemCacheWs\n");
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
PfnDb = GetNtDebuggerData( MmPfnDatabase );
|
|
if (!PfnDb) {
|
|
dprintf("unable to get MmPfnDatabase\n");
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
PteSize = GetTypeSize("nt!_MMPTE");
|
|
NumberOfPteToRead = PageSize / PteSize - 16;
|
|
|
|
if (GetFieldValue(SystemCacheWsLoc,
|
|
"nt!_MMSUPPORT",
|
|
"WorkingSetSize",
|
|
WorkingSetSize)) {
|
|
dprintf("unable to get system cache list\n");
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
GetFieldValue(SystemCacheWsLoc,"nt!_MMSUPPORT","PeakWorkingSetSize",PeakWorkingSetSize);
|
|
|
|
dprintf("File Cache Information\n");
|
|
dprintf(" Current size %ld kb\n",WorkingSetSize*
|
|
(PageSize / 1024));
|
|
dprintf(" Peak size %ld kb\n",PeakWorkingSetSize*
|
|
(PageSize / 1024));
|
|
|
|
|
|
if (!ReadPointer(PfnDb,&PfnStart)) {
|
|
dprintf("unable to get PFN database address\n");
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
SystemCacheStartPte = DbgGetPteAddress (SystemCacheStart);
|
|
SystemCacheEndPte = DbgGetPteAddress (SystemCacheEnd);
|
|
NumberOfPtes = (ULONG) ( 1 + (SystemCacheEndPte - SystemCacheStartPte) / PteSize);
|
|
|
|
//
|
|
// Read in all the PTEs mapping the system cache.
|
|
//
|
|
|
|
dprintf(" Loading file cache database (%u PTEs)\r", NumberOfPtes);
|
|
GetBitFieldOffset("nt!_MMPTE", "u.Hard.Valid", &ValidShift, &ValidSize);
|
|
|
|
// dprintf("Valid off %d, num %d ", ValidShift, ValidSize);
|
|
Valid = 0;
|
|
ZeroMemory(Buffer, sizeof(Buffer));
|
|
for (PteCount = 0;
|
|
PteCount < NumberOfPtes;
|
|
PteCount += 1) {
|
|
|
|
if (CheckControlC()) {
|
|
EXIT_API();
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Read a chunk at a time
|
|
//
|
|
if ((SystemCacheStartPte + (PteCount+1)* PteSize) > BufferedAddress + sizeof(Buffer) ) {
|
|
|
|
BufferedAddress = (SystemCacheStartPte + PteCount * PteSize);
|
|
if (!ReadMemory(BufferedAddress,
|
|
Buffer,
|
|
sizeof(Buffer),
|
|
&result)) {
|
|
dprintf("Unable to read memory at %p\n", BufferedAddress);
|
|
PteCount += sizeof(Buffer) / PteSize;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Pte = (SystemCacheStartPte + PteCount * PteSize) - BufferedAddress;
|
|
|
|
//
|
|
// Too many ptes, so do the Valid checking directly instead of calling DbgGetValid
|
|
//
|
|
if ((*((PULONG) &Buffer[(ULONG) Pte]) >> ValidShift) & 1) {
|
|
Valid += 1;
|
|
}
|
|
|
|
if (!(PteCount % (NumberOfPtes/100))) {
|
|
dprintf(" Loading file cache database (%02d%% of %u PTEs)\r", PteCount*100/NumberOfPtes, NumberOfPtes);
|
|
}
|
|
|
|
}
|
|
|
|
dprintf("\n");
|
|
|
|
dprintf(" File cache PTEs loaded, loading PFNs...\n");
|
|
|
|
|
|
HighPage = Valid;
|
|
LowPage = 0;
|
|
|
|
//
|
|
// Allocate a local PFN array (only) large enough to hold data about
|
|
// each valid PTE we've found.
|
|
//
|
|
|
|
dprintf(" File cache has %ld valid pages\n",Valid);
|
|
|
|
PfnSize = GetTypeSize("nt!_MMPFN");
|
|
|
|
Pte = SystemCacheStartPte;
|
|
|
|
dprintf(" File cache PFN data extracted\n");
|
|
|
|
MemoryUsage (PfnStart,LowPage,HighPage, 1);
|
|
|
|
EXIT_API();
|
|
return S_OK;
|
|
}
|