+#if HIBERNATION
+ acpi_hibernate_callback_data_t data;
+#endif
+ boolean_t did_hibernate;
+ unsigned int cpu;
+ kern_return_t rc;
+ unsigned int my_cpu;
+ uint64_t start;
+ uint64_t elapsed = 0;
+ uint64_t elapsed_trace_start = 0;
+
+ kprintf("acpi_sleep_kernel hib=%d, cpu=%d\n",
+ current_cpu_datap()->cpu_hibernate, cpu_number());
+
+ /* Get all CPUs to be in the "off" state */
+ my_cpu = cpu_number();
+ for (cpu = 0; cpu < real_ncpus; cpu += 1) {
+ if (cpu == my_cpu)
+ continue;
+ rc = pmCPUExitHaltToOff(cpu);
+ if (rc != KERN_SUCCESS)
+ panic("Error %d trying to transition CPU %d to OFF",
+ rc, cpu);
+ }
+
+ /* shutdown local APIC before passing control to firmware */
+ lapic_shutdown();
+
+#if HIBERNATION
+ data.func = func;
+ data.refcon = refcon;
+#endif
+
+ /* Save power management timer state */
+ pmTimerSave();
+
+#if HYPERVISOR
+ /* Notify hypervisor that we are about to sleep */
+ hv_suspend();
+#endif
+
+ /*
+ * Enable FPU/SIMD unit for potential hibernate acceleration
+ */
+ clear_ts();
+
+ KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE, 0) | DBG_FUNC_START, 0, 0, 0, 0, 0);
+
+ save_kdebug_enable = kdebug_enable;
+ kdebug_enable = 0;
+
+ acpi_sleep_abstime = mach_absolute_time();
+
+#if CONFIG_SLEEP
+ /*
+ * Save master CPU state and sleep platform.
+ * Will not return until platform is woken up,
+ * or if sleep failed.
+ */
+ uint64_t old_cr3 = x86_64_pre_sleep();
+#if HIBERNATION
+ acpi_sleep_cpu(acpi_hibernate, &data);
+#else
+#if CONFIG_VMX
+ vmx_suspend();
+#endif
+ acpi_sleep_cpu(func, refcon);
+#endif
+
+ acpi_wake_abstime = mach_absolute_time();
+ /* Rebase TSC->absolute time conversion, using timestamp
+ * recorded before sleep.
+ */
+ rtc_nanotime_init(acpi_sleep_abstime);
+ acpi_wake_postrebase_abstime = start = mach_absolute_time();
+ assert(start >= acpi_sleep_abstime);
+
+ x86_64_post_sleep(old_cr3);
+
+#endif /* CONFIG_SLEEP */
+
+ /* Reset UART if kprintf is enabled.
+ * However kprintf should not be used before rtc_sleep_wakeup()
+ * for compatibility with firewire kprintf.
+ */
+
+ if (FALSE == disable_serial_output)
+ pal_serial_init();
+
+#if HIBERNATION
+ if (current_cpu_datap()->cpu_hibernate) {
+ did_hibernate = TRUE;
+
+ } else
+#endif
+ {
+ did_hibernate = FALSE;
+ }
+
+ /* Re-enable mode (including 64-bit if applicable) */
+ cpu_mode_init(current_cpu_datap());
+
+#if CONFIG_MCA
+ /* Re-enable machine check handling */
+ mca_cpu_init();
+#endif
+
+#if CONFIG_MTRR
+ /* restore MTRR settings */
+ mtrr_update_cpu();
+#endif
+
+ /* update CPU microcode */
+ ucode_update_wake();
+
+#if CONFIG_MTRR
+ /* set up PAT following boot processor power up */
+ pat_init();
+#endif
+
+#if CONFIG_VMX
+ /*
+ * Restore VT mode
+ */
+ vmx_resume(did_hibernate);
+#endif
+
+ /*
+ * Go through all of the CPUs and mark them as requiring
+ * a full restart.
+ */
+ pmMarkAllCPUsOff();