A few days ago I was troubleshooting some strange problems on a Citrix Server. After some investigation (I will write about that later) it was clear to me that there was a shortage of System Page Table Entries (PTE’s). Using perfmon you can see how many free System PTE’s are available:

perfcounter

Any value below 5000 is not good, values below 2000 are critical. In my case it wasn’t possible to view processes with Task Manager anymore.

Next I used WinDbg and attached to the Kernel (you can do that with File | Kernel Debug | Local | OK) and issued the !vm command:

WinDbg

WinDbg shows us a warning that a lot of PTE allocations have failed, we can also see that there’s enough Paged Pool and Non Paged Pool available.

So how do we find the guilty driver (usually it’s a driver)?

First we need to set a key in the registry

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
Modify the following value to either 0 (disabled) or 1 (enabled).
Value Name: TrackPtes
Value Type: REG_DWORD
Value Data: 1
Radix: Hex

Then we need to reboot and attach WinDbg again and issue the command !sysptes 4
This gives the following error however on Windows 2003: Unable to get System PTE individual lock consumer information. It happens because the public symbol files from Microsoft’s Symbol Server do not include the _PTE_TRACKER structure:

typedef struct _PTE_TRACKER {
LIST_ENTRY ListEntry;
PMDL Mdl; PFN_NUMBER Count;
PVOID SystemVa;
PVOID StartVa;
ULONG Offset;
ULONG Length;
PFN_NUMBER Page;
struct {
ULONG IoMapping: 1;
ULONG Matched: 1;
ULONG CacheAttribute : 2;
ULONG Spare : 28;
};
PVOID CallingAddress;
PVOID CallersCaller;
} PTE_TRACKER, *PPTE_TRACKER;

PTE_TRACKER PteTracker;

If you have Visual Studio installed you can add this structure to the PDB with the following command:

cl.exe /Zi /Gz /c /Fdntkrpamp /I”.\headers” /D_X86_=1 PteTracker.c

Or you can download the modified pdb: modified ntkrpamp.pdb (604)