-
-Sleep:
-
-- PMRootDomain calls IOHibernateSystemSleep() before system sleep
-(devices awake, normal execution context)
-- IOHibernateSystemSleep opens the hibernation file (or partition) at the bsd level,
- grabs its extents and searches for a polling driver willing to work with that IOMedia.
- The BSD code makes an ioctl to the storage driver to get the partition base offset to
- the disk, and other ioctls to get the transfer constraints
- If successful, the file is written to make sure its initially not bootable (in case of
- later failure) and nvram set to point to the first block of the file. (Has to be done
- here so blocking is possible in nvram support).
- hibernate_setup() in osfmk is called to allocate page bitmaps for all dram, and
- page out any pages it wants to (currently zero, but probably some percentage of memory).
- Its assumed just allocating pages will cause the VM system to naturally select the best
- pages for eviction. It also copies processor flags needed for the restore path and sets
- a flag in the boot processor proc info.
- gIOHibernateState = kIOHibernateStateHibernating.
-- Regular sleep progresses - some drivers may inspect the root domain property
- kIOHibernateStateKey to modify behavior. The platform driver saves state to memory
- as usual but leaves motherboard I/O on.
-- Eventually the platform calls ml_ppc_sleep() in the shutdown context on the last cpu,
- at which point memory is ready to be saved. mapping_hibernate_flush() is called to get
- all ppc RC bits out of the hash table and caches into the mapping structures.
-- hibernate_write_image() is called (still in shutdown context, no blocking or preemption).
- hibernate_page_list_setall() is called to get a bitmap of dram pages that need to be saved.
- All pages are assumed to be saved (as part of the wired image) unless explicitly subtracted
- by hibernate_page_list_setall(), avoiding having to find arch dependent low level bits.
- The image header and block list are written. The header includes the second file extent so
- only the header block is needed to read the file, regardless of filesystem.
- The kernel segment "__HIB" is written uncompressed to the image. This segment of code and data
- (only) is used to decompress the image during wake/boot.
- Some additional pages are removed from the bitmaps - the buffers used for hibernation.
- The bitmaps are written to the image.
- More areas are removed from the bitmaps (after they have been written to the image) - the
- segment "__HIB" pages and interrupt stack.
- Each wired page is compressed and written and then each non-wired page. Compression and
- disk writes are in parallel.
- The image header is written to the start of the file and the polling driver closed.
- The machine powers down (or sleeps).
-
-Boot/Wake:
-
-- BootX sees the boot-image nvram variable containing the device and block number of the image,
- reads the header and if the signature is correct proceeds. The boot-image variable is cleared.
-- BootX reads the portion of the image used for wired pages, to memory. Its assumed this will fit
- in the OF memory environment, and the image is decrypted. There is no decompression in BootX,
- that is in the kernel's __HIB section.
-- BootX copies the "__HIB" section to its correct position in memory, quiesces and calls its entry
- hibernate_kernel_entrypoint(), passing the location of the image in memory. Translation is off,
- only code & data in that section is safe to call since all the other wired pages are still
- compressed in the image.
-- hibernate_kernel_entrypoint() removes pages occupied by the raw image from the page bitmaps.
- It uses the bitmaps to work out which pages can be uncompressed from the image to their final
- location directly, and copies those that can't to interim free pages. When the image has been
- completed, the copies are uncompressed, overwriting the wired image pages.
- hibernate_restore_phys_page() (in osfmk since its arch dependent, but part of the "__HIB" section)
- is used to get pages into place for 64bit.
-- the reset vector is called (at least on ppc), the kernel proceeds on a normal wake, with some
- changes conditional on the per proc flag - before VM is turned on the boot cpu, all mappings
- are removed from the software strutures, and the hash table is reinitialized.
-- After the platform CPU init code is called, hibernate_machine_init() is called to restore the rest
- of memory, using the polled mode driver, before other threads can run or any devices are turned on.
- This reduces the memory usage for BootX and allows decompression in parallel with disk reads,
- for the remaining non wired pages.
-- The polling driver is closed down and regular wake proceeds. When the kernel calls iokit to wake
- (normal execution context) hibernate_teardown() in osmfk is called to release any memory, the file
- is closed via bsd.
-
-Polled Mode I/O:
-
-IOHibernateSystemSleep() finds a polled mode interface to the ATA controller via a property in the
-registry, specifying an object of calls IOPolledInterface.
-
-Before the system goes to sleep it searches from the IOMedia object (could be a filesystem or
-partition) that the image is going to live, looking for polled interface properties. If it finds
-one the IOMedia object is passed to a "probe" call for the interface to accept or reject. All the
-interfaces found are kept in an ordered list.
-
-There is an Open/Close pair of calls made to each of the interfaces at various stages since there are
-few different contexts things happen in:
-
-- there is an Open/Close (Preflight) made before any part of the system has slept (I/O is all
-up and running) and after wake - this is safe to allocate memory and do anything. The device
-ignores sleep requests from that point since its a waste of time if it goes to sleep and
-immediately wakes back up for the image write.
-
-- there is an Open/Close (BeforeSleep) pair made around the image write operations that happen
-immediately before sleep. These can't block or allocate memory - the I/O system is asleep apart
-from the low level bits (motherboard I/O etc). There is only one thread running. The close can be
-used to flush and set the disk to sleep.
-
-- there is an Open/Close (AfterSleep) pair made around the image read operations that happen
-immediately after sleep. These can't block or allocate memory. This is happening after the platform
-expert has woken the low level bits of the system, but most of the I/O system has not. There is only
-one thread running.
-
-For the actual I/O, all the ops are with respect to a single IOMemoryDescriptor that was passed
-(prepared) to the Preflight Open() call. There is a read/write op, buffer offset to the IOMD for
-the data, an offset to the disk and length (block aligned 64 bit numbers), and completion callback.
-Each I/O is async but only one is ever outstanding. The polled interface has a checkForWork call
-that is called for the hardware to check for events, and complete the I/O via the callback.
-The hibernate path uses the same transfer constraints the regular cluster I/O path in BSD uses
-to restrict I/O ops.
-*/
+ *
+ * Sleep:
+ *
+ * - PMRootDomain calls IOHibernateSystemSleep() before system sleep
+ * (devices awake, normal execution context)
+ * - IOHibernateSystemSleep opens the hibernation file (or partition) at the bsd level,
+ * grabs its extents and searches for a polling driver willing to work with that IOMedia.
+ * The BSD code makes an ioctl to the storage driver to get the partition base offset to
+ * the disk, and other ioctls to get the transfer constraints
+ * If successful, the file is written to make sure its initially not bootable (in case of
+ * later failure) and nvram set to point to the first block of the file. (Has to be done
+ * here so blocking is possible in nvram support).
+ * hibernate_setup() in osfmk is called to allocate page bitmaps for all dram, and
+ * page out any pages it wants to (currently zero, but probably some percentage of memory).
+ * Its assumed just allocating pages will cause the VM system to naturally select the best
+ * pages for eviction. It also copies processor flags needed for the restore path and sets
+ * a flag in the boot processor proc info.
+ * gIOHibernateState = kIOHibernateStateHibernating.
+ * - Regular sleep progresses - some drivers may inspect the root domain property
+ * kIOHibernateStateKey to modify behavior. The platform driver saves state to memory
+ * as usual but leaves motherboard I/O on.
+ * - Eventually the platform calls ml_ppc_sleep() in the shutdown context on the last cpu,
+ * at which point memory is ready to be saved. mapping_hibernate_flush() is called to get
+ * all ppc RC bits out of the hash table and caches into the mapping structures.
+ * - hibernate_write_image() is called (still in shutdown context, no blocking or preemption).
+ * hibernate_page_list_setall() is called to get a bitmap of dram pages that need to be saved.
+ * All pages are assumed to be saved (as part of the wired image) unless explicitly subtracted
+ * by hibernate_page_list_setall(), avoiding having to find arch dependent low level bits.
+ * The image header and block list are written. The header includes the second file extent so
+ * only the header block is needed to read the file, regardless of filesystem.
+ * The kernel segment "__HIB" is written uncompressed to the image. This segment of code and data
+ * (only) is used to decompress the image during wake/boot.
+ * Some additional pages are removed from the bitmaps - the buffers used for hibernation.
+ * The bitmaps are written to the image.
+ * More areas are removed from the bitmaps (after they have been written to the image) - the
+ * segment "__HIB" pages and interrupt stack.
+ * Each wired page is compressed and written and then each non-wired page. Compression and
+ * disk writes are in parallel.
+ * The image header is written to the start of the file and the polling driver closed.
+ * The machine powers down (or sleeps).
+ *
+ * Boot/Wake:
+ *
+ * - BootX sees the boot-image nvram variable containing the device and block number of the image,
+ * reads the header and if the signature is correct proceeds. The boot-image variable is cleared.
+ * - BootX reads the portion of the image used for wired pages, to memory. Its assumed this will fit
+ * in the OF memory environment, and the image is decrypted. There is no decompression in BootX,
+ * that is in the kernel's __HIB section.
+ * - BootX copies the "__HIB" section to its correct position in memory, quiesces and calls its entry
+ * hibernate_kernel_entrypoint(), passing the location of the image in memory. Translation is off,
+ * only code & data in that section is safe to call since all the other wired pages are still
+ * compressed in the image.
+ * - hibernate_kernel_entrypoint() removes pages occupied by the raw image from the page bitmaps.
+ * It uses the bitmaps to work out which pages can be uncompressed from the image to their final
+ * location directly, and copies those that can't to interim free pages. When the image has been
+ * completed, the copies are uncompressed, overwriting the wired image pages.
+ * hibernate_restore_phys_page() (in osfmk since its arch dependent, but part of the "__HIB" section)
+ * is used to get pages into place for 64bit.
+ * - the reset vector is called (at least on ppc), the kernel proceeds on a normal wake, with some
+ * changes conditional on the per proc flag - before VM is turned on the boot cpu, all mappings
+ * are removed from the software strutures, and the hash table is reinitialized.
+ * - After the platform CPU init code is called, hibernate_machine_init() is called to restore the rest
+ * of memory, using the polled mode driver, before other threads can run or any devices are turned on.
+ * This reduces the memory usage for BootX and allows decompression in parallel with disk reads,
+ * for the remaining non wired pages.
+ * - The polling driver is closed down and regular wake proceeds. When the kernel calls iokit to wake
+ * (normal execution context) hibernate_teardown() in osmfk is called to release any memory, the file
+ * is closed via bsd.
+ *
+ * Polled Mode I/O:
+ *
+ * IOHibernateSystemSleep() finds a polled mode interface to the ATA controller via a property in the
+ * registry, specifying an object of calls IOPolledInterface.
+ *
+ * Before the system goes to sleep it searches from the IOMedia object (could be a filesystem or
+ * partition) that the image is going to live, looking for polled interface properties. If it finds
+ * one the IOMedia object is passed to a "probe" call for the interface to accept or reject. All the
+ * interfaces found are kept in an ordered list.
+ *
+ * There is an Open/Close pair of calls made to each of the interfaces at various stages since there are
+ * few different contexts things happen in:
+ *
+ * - there is an Open/Close (Preflight) made before any part of the system has slept (I/O is all
+ * up and running) and after wake - this is safe to allocate memory and do anything. The device
+ * ignores sleep requests from that point since its a waste of time if it goes to sleep and
+ * immediately wakes back up for the image write.
+ *
+ * - there is an Open/Close (BeforeSleep) pair made around the image write operations that happen
+ * immediately before sleep. These can't block or allocate memory - the I/O system is asleep apart
+ * from the low level bits (motherboard I/O etc). There is only one thread running. The close can be
+ * used to flush and set the disk to sleep.
+ *
+ * - there is an Open/Close (AfterSleep) pair made around the image read operations that happen
+ * immediately after sleep. These can't block or allocate memory. This is happening after the platform
+ * expert has woken the low level bits of the system, but most of the I/O system has not. There is only
+ * one thread running.
+ *
+ * For the actual I/O, all the ops are with respect to a single IOMemoryDescriptor that was passed
+ * (prepared) to the Preflight Open() call. There is a read/write op, buffer offset to the IOMD for
+ * the data, an offset to the disk and length (block aligned 64 bit numbers), and completion callback.
+ * Each I/O is async but only one is ever outstanding. The polled interface has a checkForWork call
+ * that is called for the hardware to check for events, and complete the I/O via the callback.
+ * The hibernate path uses the same transfer constraints the regular cluster I/O path in BSD uses
+ * to restrict I/O ops.
+ */