Windows 2000 Non-Paged Pool Memory Allocation

Windows 2000 manages non-paged pool memory allocations for device drivers by reserving a dedicated region of physical RAM that is guaranteed never to be swapped to the paging file. This architecture ensures that critical kernel-mode components, interrupt service routines, and device drivers can access memory instantly without triggering fatal page faults at elevated Interrupt Request Levels (IRQLs). The operating system relies on specific kernel APIs, lookaside lists, and strict allocation size limits configured during system initialization to govern how drivers request, track, and release this finite resource.

The Role of Non-Paged Pool Memory

The non-paged pool resides in the system virtual address space, which by default occupies the upper 2 GB range (0x80000000 to 0xFFFFFFFF) of the 32-bit virtual address map. Unlike paged pool memory or user-mode virtual memory, every page in the non-paged pool is mapped directly to a page frame in physical RAM.

Windows 2000 sizes the non-paged pool dynamically during the boot phase based on the amount of installed physical memory, up to an architectural maximum of approximately 256 MB. Because this memory pool is strictly limited, driver developers must only use it when necessary to prevent pool exhaustion, which destabilizes the operating system.

Allocation APIs and Pool Types

Device drivers request non-paged memory using core executive memory management routines:

  • ExAllocatePool and ExAllocatePoolWithTag: The primary functions used to allocate system memory. Drivers specify the NonPagedPool pool type flag to request physical, unpageable memory.
  • Pool Variants: Drivers can specify variations such as NonPagedPoolMustSucceed (deprecated due to the risk of system crashes if memory is unavailable) or NonPagedPoolCacheAligned to align buffers along processor cache line boundaries.
  • Pool Tagging: Microsoft strongly encouraged using ExAllocatePoolWithTag in Windows 2000. This function attaches a four-character ASCII tag (in reverse byte order) to the allocation. Windows tracks these tags, allowing administrators and developers to detect memory leaks and identify the offending driver using the Poolmon utility.

IRQL Constraints and Fault Prevention

The memory manager enforces strict rules based on the processor's IRQL:

  1. Low IRQL (PASSIVE_LEVEL to APC_LEVEL): Drivers can allocate from either the paged pool or non-paged pool. Page faults can be serviced normally by the memory manager's paging I/O subsystem.
  2. Elevated IRQL (DISPATCH_LEVEL and above): The memory manager cannot handle page faults at or above DISPATCH_LEVEL because the page fault handler itself runs at APC_LEVEL and requires thread scheduling, which is disabled at higher IRQLs. If code executing at DISPATCH_LEVEL accesses memory that has been paged out, the system halts with a PAGE_FAULT_IN_NONPAGED_AREA or IRQL_NOT_LESS_OR_EQUAL Bug Check (Blue Screen of Death).

Consequently, any data structures, I/O request packets (IRPs), deferred procedure call (DPC) contexts, or buffers accessed within interrupt routines or dispatch routines must strictly reside in the non-paged pool.

Lookaside Lists for Rapid Allocation

To optimize allocation speed and reduce memory fragmentation caused by frequent allocations and deallocations of fixed-size blocks, Windows 2000 provides non-paged lookaside lists:

  • A driver initializes a list using ExInitializeNPagedLookasideList.
  • Drivers draw from the list using ExAllocateFromNPagedLookasideList and return blocks using ExFreeToNPagedLookasideList.
  • The system maintains these pre-allocated, fixed-size buffers directly in the non-paged pool, bypassing the general pool allocator overhead and using atomic operations to safely allocate buffers at DISPATCH_LEVEL.

Deallocation and Cleanup

When allocated memory is no longer required, the driver must explicitly return it to the pool using ExFreePool or ExFreePoolWithTag. Windows 2000 does not automatically reclaim non-paged pool memory assigned to kernel-mode drivers upon thread completion or driver unloading. Any failure to free non-paged pool memory permanently reduces the available physical RAM for the duration of that boot session.