/*++ 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; }