Introduction
The cache is an integral part of the operating system and its hybrid kernel. Roughly speaking, it's just a virtual memory region in the kernel address space, on which the Cache Manager maps file data to provide quick access to them in the future. This access is frequently used by the File System Driver (FSD) or the Windows Memory Manager (VMM). Instead of reading file data from disk every time a user or system needs to access to it, the OS kernel calls the Cache Manager in an attempt to get this data from memory. In turn, the Cache Manager is a set of function in the kernel executable file ntoskrnl.exe, which starts with a prefix Cc. These functions are private, so to get to their names, you need to configure the symbol server settings in WinDbg or IDA.
Learning the Windows Cache Manager is quite a difficult task for beginners. This Windows kernel subsystem is closely related to the VMM, so if you don't have enough knowledge in it, try to understand the basic concepts without going into complicated technical aspects. In addition, you should have some knowledge in the field of file system drivers (FSD), because they are the most frequent clients of the Cache Manager. It's worth to note that the cache concept exists only at the level of file system, lower drivers on the device stack like the volume manager, partition manager, disk driver, and disk port driver don't use it.
This blog post is dedicated to the technical aspects of the Windows Cache Manager and designed for the skilled Windows Internals readers. If you lack knowledge on this topic, read the corresponding chapter in the Windows Internals book and then get back to this post. I would say that this blog post is some kind of technical addition to the chapter about the cache in the book (or I hope it claims..).
Let's take a look at some terms for newbie.
Working Set (WS) - the set of pages in the user mode or kernel mode address space that are currently resident in physical memory. The kernel mode working set called System Working Set.
PTE (Page Table Entry) - a structure that is used by the CPU and VMM to translate virtual addresses to physical ones.
Proto-PTE (Prototype PTE, PPTE) - a special type of so called Software PTE that is used only by the VMM (not CPU) to work with section objects (memory-mapped files) and serves as an intermediate level for the translation mapped section pages to the real hardware PTE. PPTE is a key structure for understanding the section objects.
Segment Control Area (or just Control Area, CA) - a structure that contains information required for performing I/O operations with file data in or from the mapped file. It's stored in the non-paged pool. With the help of CA the VMM can address the same file as binary and as executable.
The basic concepts
The memory region in the kernel mode address space occupied by the cache starts with the value of the VMM variable MmSystemCacheStart and ends with the value of MmSystemCacheEnd. Thus, if X - is a pointer to the memory region that belongs to the cache, then MmSystemCacheStart<=X<=MmSystemCacheEnd. File data in this region are mapped into slots, 256KB blocks of data. The cache has two features, which are a consequence of the fact that the VMM is responsible for its internal implementation.
- The section objects maintained by the VMM are used to map file data into slots. Thus, the VMM is responsible for paging file data.
- Cache virtual pages can be unloaded to the page file.
These features emphasize the fact that the Cache Manager doesn't know for sure whether the file data is in physical memory or not. Undocumented structure called Virtual Address Control Block (VACB) is used to describe the cache slots, which are reserved in the paged pool. The control blocks are addressed from CcVacbs variable. Each of these blocks controls a specific slot. The variable CcNumberVacbs stores the number of slots.
VACB has the following format.There are two VACBs lists.- CcVacbFreeList. It's a list of free VACBs, i e those VACBs that are ready for use.
- CcVacbLru. A list of all other structures. A VACB has free status if its .ActiveCount field is zero. When reused, the slot address is re-mapped. The following WinDbg command confirms these facts.
VOID CcInitializeCacheMap (__in PFILE_OBJECT FileObject, __in PCC_FILE_SIZES FileSizes, __in BOOLEAN PinAccess, __in PCACHE_MANAGER_CALLBACKS Callbacks, __in PVOID LazyWriteContext)
This function is responsible for.
- It creates and initializes the shared cache map if it doesn't exist yet (FileObject->SectionObjectPointer->SharedCacheMap is zeroed), SharedCacheMap->FileObject is initialized by the first file object for which the map is created.
- It creates the section object with MmCreateSection. Further, this section will be used to map file data into cache slots.
- Creates a VACB index array with CcCreateVacbArray. This function initializes fields .Vacbs and .SectionSize.
If the FSD needs to read data from the cache, it calls CcCopyRead.
- The cache PTEs start from address that stores in MmSystemCachePteBase (usually it matches the address of the beginning of the page table, 0xC0000000).
- Free cache slots are linked to MMPTE_LIST list to provide quick access to them (see WRK for more info about this structure). The pointer to the head of the list is stored in MmFirstFreeSystemCache. The field .NextEntry in MMPTE_LIST stores a value that points to the next field (next block of PTEs). This value is relative to MmSystemCachePteBase. The MiInitializeSystemCache function is responsible for initializing of the PTEs cache list. The PTEs for the cache are reserved by adjacent blocks, i e to cover 256KB, the block is included 64 PTEs, see MiInitializeSystemCache.