Tuesday 18 November 2008

WinNT page replacement

Page replacement call stack: MmAccessFault -> MiDispatchFault -> MiAllocateWsle -> MiDoReplacement -> MiTrimWorkingSet -> decides which pages should be removed from the working set and adjusts firstFree and NextSlot accordingly. (the page is included to FirstFree position unless there is no free position left, in which case NextSlot is the one to be replaced.) besides direct page fault handling the KeBalanceSetManager thread -> MmWorkingSetManager -> if (MiComputeSystemTrimCriteria) -> MiProcessWorkingSets -> MiTrimWorkingSet and MiAgeWorkingSet: Aging pages by turning off access bits and incrementing age counts for pages which haven't been accessed.

example call stacks:

Prototype PTE:
f3dffb48 80837fc0 nt!MiFreeWsle+0x67 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 1360]
f3dffb80 808380fc nt!MiReplaceWorkingSetEntry+0xcc [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 730]
f3dffbb4 808381e3 nt!MiDoReplacement+0xee [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 390]
f3dffbd0 80848ec9 nt!MiAllocateWsle+0x4b [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 189]
f3dffbe8 8084a60a nt!MiAddValidPageToWorkingSet+0x6d [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 6359]
f3dffc24 8084b622 nt!MiCompleteProtoPteFault+0x274 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 3660]
f3dffc58 8084c05a nt!MiResolveProtoPteFault+0x4c [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 3103]
f3dffcf0 80857954 nt!MiDispatchFault+0x832 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 1040]
f3dffd4c 80886278 nt!MmAccessFault+0x9c0 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\mmfault.c @ 2001]
f3dffd4c 7c819e44 nt!_KiTrap0E+0xdc [C:\Users\bgerofi\code\WinNTKernel\base\ntos\ke\i386\trap.asm @ 5527]

Transition PTE:
f3dffb98 80837fc0 nt!MiFreeWsle+0x59 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 1356]
f3dffbd0 808380fc nt!MiReplaceWorkingSetEntry+0xcc [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 730]
f3dffc04 808381e3 nt!MiDoReplacement+0xee [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 390]
f3dffc20 80848ec9 nt!MiAllocateWsle+0x4b [c:\users\bgerofi\code\winntkernel\base\ntos\mm\wslist.c @ 189]
f3dffc38 8084b5a7 nt!MiAddValidPageToWorkingSet+0x6d [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 6359]
f3dffc6c 8084c225 nt!MiResolveTransitionFault+0x539 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 2484]
f3dffcf0 80857954 nt!MiDispatchFault+0x9fd [c:\users\bgerofi\code\winntkernel\base\ntos\mm\pagfault.c @ 1072]
f3dffd4c 80886278 nt!MmAccessFault+0x9c0 [c:\users\bgerofi\code\winntkernel\base\ntos\mm\mmfault.c @ 2001]
f3dffd4c 77eaae5f nt!_KiTrap0E+0xdc [C:\Users\bgerofi\code\WinNTKernel\base\ntos\ke\i386\trap.asm @ 5527]

in this case MiReplaceWorkingSetEntry() is where the actual decision is made regarding which page to replace, the search starts from NextSlot (which is determined/maintained by MiTrimWorkingSet()).
The "WsleAllocationAny" flag value determines that any of the entries which fulfills the aging requirement is okay, while "WsleAllocationReplace" attempts to replace the first that is possible to replace. (Note that the entire working set could be locked in which case the replacement fails) Replacing an entry in fact means removing one and therefore setting FirstFree which is in trun used in MiAllocateWsle().

Saturday 15 November 2008

WinNT working set issue..

When u debug the working set, strange issue:

!process 0 0
check the name and the address

dt _EPROCESS address
dt _MMSUPPORT address+0x1e8
dt PMMWSL address+0x1e8+0x028

you will get c0502000 all the time, this is because the pointer stores a virtualaddress in the process address space but WinDBG will show you the structure in the active process address space.
(seems like WinDBG translates the virtual addresses according to the current rocess page table?)
You have to achieve to be in the debugger while the current process is the one u are investigating, for instance by adding a system call and "Run To Cursor": in the debugger to your syscall..