]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/acpi.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / osfmk / i386 / acpi.c
index fd73f24ff8462de4da16539ea74e21808bd8a8f0..955301c6d72bc6d3a6feec828fefe5ec11b39b50 100644 (file)
@@ -35,6 +35,9 @@
 #if CONFIG_MTRR
 #include <i386/mtrr.h>
 #endif
+#if HYPERVISOR
+#include <kern/hv_support.h>
+#endif
 #if CONFIG_VMX
 #include <i386/vmx/vmx_cpu.h>
 #endif
@@ -71,6 +74,7 @@ extern void   acpi_wake_prot(void);
 #endif
 extern kern_return_t IOCPURunPlatformQuiesceActions(void);
 extern kern_return_t IOCPURunPlatformActiveActions(void);
+extern kern_return_t IOCPURunPlatformHaltRestartActions(uint32_t message);
 
 extern void    fpinit(void);
 
@@ -85,12 +89,7 @@ acpi_install_wake_handler(void)
 #endif
 }
 
-#if HIBERNATION
-struct acpi_hibernate_callback_data {
-       acpi_sleep_callback func;
-       void *refcon;
-};
-typedef struct acpi_hibernate_callback_data acpi_hibernate_callback_data_t;
+#if CONFIG_SLEEP
 
 unsigned int           save_kdebug_enable = 0;
 static uint64_t                acpi_sleep_abstime;
@@ -98,7 +97,13 @@ static uint64_t              acpi_idle_abstime;
 static uint64_t                acpi_wake_abstime, acpi_wake_postrebase_abstime;
 boolean_t              deep_idle_rebase = TRUE;
 
-#if CONFIG_SLEEP
+#if HIBERNATION
+struct acpi_hibernate_callback_data {
+       acpi_sleep_callback func;
+       void *refcon;
+};
+typedef struct acpi_hibernate_callback_data acpi_hibernate_callback_data_t;
+
 static void
 acpi_hibernate(void *refcon)
 {
@@ -115,12 +120,14 @@ acpi_hibernate(void *refcon)
                {
                        // off
                        HIBLOG("power off\n");
+                       IOCPURunPlatformHaltRestartActions(kPEHaltCPU);
                        if (PE_halt_restart) (*PE_halt_restart)(kPEHaltCPU);
                }
                else if( mode == kIOHibernatePostWriteRestart )
                {
                        // restart
                        HIBLOG("restart\n");
+                       IOCPURunPlatformHaltRestartActions(kPERestartCPU);
                        if (PE_halt_restart) (*PE_halt_restart)(kPERestartCPU);
                }
                else
@@ -133,6 +140,10 @@ acpi_hibernate(void *refcon)
                }
 
        }
+
+#if CONFIG_VMX
+       vmx_suspend();
+#endif
        kdebug_enable = 0;
 
        IOCPURunPlatformQuiesceActions();
@@ -143,8 +154,8 @@ acpi_hibernate(void *refcon)
 
        /* should never get here! */
 }
-#endif /* CONFIG_SLEEP */
 #endif /* HIBERNATION */
+#endif /* CONFIG_SLEEP */
 
 extern void                    slave_pstart(void);
 extern void                    hibernate_rebuild_vm_structs(void);
@@ -190,11 +201,9 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
        /* Save power management timer state */
        pmTimerSave();
 
-#if CONFIG_VMX
-       /* 
-        * Turn off VT, otherwise switching to legacy mode will fail
-        */
-       vmx_suspend();
+#if HYPERVISOR
+       /* Notify hypervisor that we are about to sleep */
+       hv_suspend();
 #endif
 
        /*
@@ -219,10 +228,19 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
 #if HIBERNATION
        acpi_sleep_cpu(acpi_hibernate, &data);
 #else
+#if CONFIG_VMX
+       vmx_suspend();
+#endif
        acpi_sleep_cpu(func, refcon);
 #endif
 
-       start = mach_absolute_time();
+       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);
 
@@ -262,16 +280,16 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
        /* 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();
-#endif
-
-#if CONFIG_MTRR
-       /* set up PAT following boot processor power up */
-       pat_init();
+       vmx_resume(did_hibernate);
 #endif
 
        /*
@@ -285,20 +303,19 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
        if (lapic_probe())
                lapic_configure();
 
+#if HIBERNATION
        hibernate_rebuild_vm_structs();
+#endif
 
        elapsed += mach_absolute_time() - start;
-       acpi_wake_abstime = mach_absolute_time();
 
-       /* let the realtime clock reset */
-       rtc_sleep_wakeup(acpi_sleep_abstime);
-       acpi_wake_postrebase_abstime = mach_absolute_time();
+       rtc_decrementer_configure();
        kdebug_enable = save_kdebug_enable;
 
        if (kdebug_enable == 0) {
                if (wake_nkdbufs) {
                        start = mach_absolute_time();
-                       start_kern_tracing(wake_nkdbufs, TRUE);
+                       kdebug_trace_start(wake_nkdbufs, NULL, TRUE);
                        elapsed_trace_start += mach_absolute_time() - start;
                }
        }
@@ -310,6 +327,7 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
 
        IOCPURunPlatformActiveActions();
 
+#if HIBERNATION
        if (did_hibernate) {
                elapsed += mach_absolute_time() - start;
                
@@ -321,6 +339,7 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
 
                KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE, 0) | DBG_FUNC_END, 0, 0, 0, 0, 0);
        } else
+#endif /* HIBERNATION */
                KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE, 0) | DBG_FUNC_END, 0, 0, 0, 0, 0);
 
        /* Restore power management register state */
@@ -367,12 +386,6 @@ acpi_idle_kernel(acpi_sleep_callback func, void *refcon)
 
        assert(cpu_number() == master_cpu);
 
-       /*
-        * Effectively set the boot cpu offline.
-        * This will stop further deadlines being set.
-        */
-       cpu_datap(master_cpu)->cpu_running = FALSE;
-
        /* Cancel any pending deadline */
        setPop(0);
        while (lapic_is_interrupting(LAPIC_TIMER_VECTOR)) {
@@ -420,7 +433,7 @@ acpi_idle_kernel(acpi_sleep_callback func, void *refcon)
                kdebug_enable = save_kdebug_enable;
        }
        acpi_wake_postrebase_abstime = mach_absolute_time();
-       cpu_datap(master_cpu)->cpu_running = TRUE;
+       assert(mach_absolute_time() >= acpi_idle_abstime);
 
        KERNEL_DEBUG_CONSTANT(
                MACHDBG_CODE(DBG_MACH_SCHED, MACH_DEEP_IDLE) | DBG_FUNC_END,
@@ -429,7 +442,7 @@ acpi_idle_kernel(acpi_sleep_callback func, void *refcon)
        /* Like S3 sleep, turn on tracing if trace_wake boot-arg is present */ 
        if (kdebug_enable == 0) {
                if (wake_nkdbufs)
-                       start_kern_tracing(wake_nkdbufs, TRUE);
+                       kdebug_trace_start(wake_nkdbufs, NULL, TRUE);
        }
 
        IOCPURunPlatformActiveActions();