DRAFT: Take more than your usual care.

Memory Limit for Hibernation Support

In most Windows versions, support for hibernation is lost if physical memory is present above some maximum address. Microsoft documents this in a Knowledge Base article You cannot put a computer that has more than 4GB of memory into hibernation in Windows XP, in Windows Server 2003, in Windows Vista, or in Windows Server 2008. As so often, Microsoft’s details are not quite correct. For one thing, the limit is not to the amount of memory but to the highest physical memory address, which distinction the article leaves to a Note. More significantly, some of the cited versions have no limit and others have a significantly raised limit. The article has perhaps been revised to include newer versions in default of better information from the programmers. This documentation error might pass as unremarkable except that Microsoft’s details are repeated around the Internet as if verified, and may become accepted as truth until more people actually do have 4GB of RAM and start seeing for themselves.

A quick summary of the memory limits follows:

Version Maximum Physical Address for Hibernation Support
Windows XP SP2 and SP3
Windows Server 2003 SP1 and SP2
4GB
32-bit Windows Vista
32-bit Windows 7
none
64-bit Windows Vista
64-bit Windows 7
16TB

The limit in question is coded as a test that the Windows kernel applies near the end of its internal routine PopFilterCapabilities. A system might otherwise support hibernation, but if it fails this test, then all the kernel’s reports of system power capabilities will mark the S4 sleep state, i.e., hibernation, as unsupported. At user-interface level, the Power applet in the Control Panel will not show a tab for Hibernation.

This notion of disabling hibernation support on a system that has everything else in place for supporting it dates from the original Windows 2000, but not as a memory requirement. Instead, hibernation is disabled if the kernel is using the CPU feature known as Physical Address Extension (PAE). For any version of 32-bit Windows to know of any memory at or above 4GB, you need to have PAE enabled and be running the PAE kernel. However, the converse is not true: you can have PAE enabled (wastefully) even if all your memory is below 4GB. This test for PAE persists through all known Windows 2000 service packs and in Windows XP up to and including SP1.

Development of the test into a memory limit begins (chronologically) with the original Windows Server 2003. This version applies quite a complex test. Support for hibernation is withdrawn if PAE is enabled unless all the following are true:

On most processors therefore, the original Windows Server 2003 retains the PAE test: boot the PAE kernel and you lose hibernation support. Quite what Microsoft intended for AMD processors is unclear—note anyway that the NOEXECUTE option is not documented for the original Windows Server 2003—but it is nonetheless the first sign of a memory limit for hibernation.

Simplification to testing only for memory begins with Windows XP SP2 and Windows Server 2003 SP1 (both 32-bit and 64-bit). Hibernation is disabled if the kernel knows of any physical memory at or above 4GB.

The test is removed altogether from 32-bit Windows Vista, including its service packs and therefore also the original Windows Server 2008. Let it be stressed: these 32-bit Windows versions have no memory limit for hibernation. A memory limit is retained for 64-bit Windows Vista, but the maximum physical address is raised to 16TB.

Windows 7, and therefore also Windows Server 2008 SP1, changes the code so that hibernation is disabled if any of several system power logging entries are present. Logging entries were introduced with version 5.2, i.e., Windows Server 2003. Every logging entry has a reason. The one for having too high a physical memory address is SPSD_REASON_MEMORYLIMIT. No entry for this reason is ever inserted by the 32-bit kernel for Windows 7, which means that 32-bit Windows 7 also has no memory limit for hibernation. For 64-bit Windows 7, the kernel inserts a memory-limit logging entry if any physical memory is found at or above 16TB.

Note that logging entries can be inserted from outside the kernel, via the exported (but undocumented) ZwPowerInformation function, using the SystemPowerLoggingEntry value for the POWER_INFORMATION_LEVEL.