X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4452a7af2eac33dbad800bcc91f2399d62c18f53..36401178fd6817c043cc00b0c00c7f723e58efae:/osfmk/i386/acpi.c?ds=sidebyside diff --git a/osfmk/i386/acpi.c b/osfmk/i386/acpi.c index a70821010..539a82fde 100644 --- a/osfmk/i386/acpi.c +++ b/osfmk/i386/acpi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2007 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -27,27 +27,31 @@ */ #include +#include #include #include #include +#include #include #include #include #include +#include +#include #include #include +#include +#if HIBERNATION #include +#endif #include extern void acpi_sleep_cpu(acpi_sleep_callback, void * refcon); extern char acpi_wake_start[]; extern char acpi_wake_end[]; -extern int serial_init(void); -extern unsigned int disableSerialOuput; - extern void set_kbd_leds(int leds); extern void fpinit(void); @@ -67,130 +71,166 @@ acpi_install_wake_handler(void) return ACPI_WAKE_ADDR; } -typedef struct acpi_hibernate_callback_data { - acpi_sleep_callback func; - void *refcon; -} acpi_hibernate_callback_data; +#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) { - boolean_t dohalt; - - acpi_hibernate_callback_data *data = (acpi_hibernate_callback_data *)refcon; + uint32_t mode; - if (current_cpu_datap()->cpu_hibernate) { + acpi_hibernate_callback_data_t *data = + (acpi_hibernate_callback_data_t *)refcon; - dohalt = hibernate_write_image(); - if (dohalt) - { - // off - HIBLOG("power off\n"); - if (PE_halt_restart) - (*PE_halt_restart)(kPEHaltCPU); - } - else + if (current_cpu_datap()->cpu_hibernate) { - // sleep - HIBLOG("sleep\n"); + cpu_IA32e_enable(current_cpu_datap()); + + mode = hibernate_write_image(); + + if( mode == kIOHibernatePostWriteHalt ) + { + // off + HIBLOG("power off\n"); + if (PE_halt_restart) (*PE_halt_restart)(kPEHaltCPU); + } + else if( mode == kIOHibernatePostWriteRestart ) + { + // restart + HIBLOG("restart\n"); + if (PE_halt_restart) (*PE_halt_restart)(kPERestartCPU); + } + else + { + // sleep + HIBLOG("sleep\n"); + + // should we come back via regular wake, set the state in memory. + cpu_datap(0)->cpu_hibernate = 0; + } + + /* + * If we're in 64-bit mode, drop back into legacy mode during sleep. + */ + cpu_IA32e_disable(current_cpu_datap()); - // should we come back via regular wake, set the state in memory. - cpu_datap(0)->cpu_hibernate = 0; } - } - (data->func)(data->refcon); + (data->func)(data->refcon); - /* should never get here! */ + /* should never get here! */ } +#endif + +static uint64_t acpi_sleep_abstime; void acpi_sleep_kernel(acpi_sleep_callback func, void *refcon) { - acpi_hibernate_callback_data data; - boolean_t did_hibernate; +#if HIBERNATION + acpi_hibernate_callback_data_t data; + boolean_t did_hibernate; +#endif + + kprintf("acpi_sleep_kernel hib=%d\n", + current_cpu_datap()->cpu_hibernate); - kprintf("acpi_sleep_kernel hib=%d\n", current_cpu_datap()->cpu_hibernate); + /* shutdown local APIC before passing control to BIOS */ + lapic_shutdown(); - /* shutdown local APIC before passing control to BIOS */ - lapic_shutdown(); +#if HIBERNATION + data.func = func; + data.refcon = refcon; +#endif - data.func = func; - data.refcon = refcon; + /* Save HPET state */ + hpet_save(); - /* Save HPET state */ - hpet_save(); + /* + * Turn off VT, otherwise switching to legacy mode will fail + */ + vmx_suspend(); - /* - * If we're in 64-bit mode, drop back into legacy mode during sleep. - */ - if (cpu_mode_is64bit()) { + /* + * If we're in 64-bit mode, drop back into legacy mode during sleep. + */ cpu_IA32e_disable(current_cpu_datap()); - kprintf("acpi_sleep_kernel legacy mode re-entered\n"); - } - - /* - * Save master CPU state and sleep platform. - * Will not return until platform is woken up, - * or if sleep failed. - */ - acpi_sleep_cpu(acpi_hibernate, &data); - - /* reset UART if kprintf is enabled */ - if (FALSE == disableSerialOuput) - serial_init(); - - kprintf("ret from acpi_sleep_cpu hib=%d\n", current_cpu_datap()->cpu_hibernate); - - if (current_cpu_datap()->cpu_hibernate) { - int i; - for (i=0; icpu_pmap->mapwindow[i].prv_CMAP = 0; + + acpi_sleep_abstime = mach_absolute_time(); + + /* + * Save master CPU state and sleep platform. + * Will not return until platform is woken up, + * or if sleep failed. + */ +#if HIBERNATION + acpi_sleep_cpu(acpi_hibernate, &data); +#else + acpi_sleep_cpu(func, refcon); +#endif + + /* reset UART if kprintf is enabled */ + if (FALSE == disable_serial_output) + serial_init(); + +#if HIBERNATION + if (current_cpu_datap()->cpu_hibernate) { + int i; + for (i = 0; i < PMAP_NWINDOWS; i++) + *current_cpu_datap()->cpu_pmap->mapwindow[i].prv_CMAP = 0; + current_cpu_datap()->cpu_hibernate = 0; + did_hibernate = TRUE; + + } else +#endif + { + did_hibernate = FALSE; } - current_cpu_datap()->cpu_hibernate = 0; - did_hibernate = TRUE; - - } else { - did_hibernate = FALSE; - } - - /* Re-enable 64-bit mode if necessary. */ - if (cpu_mode_is64bit()) { - cpu_IA32e_enable(current_cpu_datap()); - cpu_desc_load64(current_cpu_datap()); - kprintf("acpi_sleep_kernel 64-bit mode re-enabled\n"); - fast_syscall_init64(); - } else { - fast_syscall_init(); - } - - /* Re-enable machine check handling */ - mca_cpu_init(); - - /* restore MTRR settings */ - mtrr_update_cpu(); - - /* set up PAT following boot processor power up */ - pat_init(); - - if (did_hibernate) { - hibernate_machine_init(); - } - - /* re-enable and re-init local apic */ - if (lapic_probe()) - lapic_init(); - - /* Restore HPET state */ - hpet_restore(); - - /* let the realtime clock reset */ - rtc_sleep_wakeup(); - - fpinit(); - clear_fpu(); - - if (did_hibernate) { - enable_preemption(); - } + + /* Re-enable mode (including 64-bit if applicable) */ + cpu_mode_init(current_cpu_datap()); + + /* Re-enable machine check handling */ + mca_cpu_init(); + + /* restore MTRR settings */ + mtrr_update_cpu(); + + /* + * Restore VT mode + */ + vmx_resume(); + + /* set up PAT following boot processor power up */ + pat_init(); + + /* let the realtime clock reset */ + rtc_sleep_wakeup(acpi_sleep_abstime); + + if (did_hibernate) + hibernate_machine_init(); + + /* re-enable and re-init local apic */ + if (lapic_probe()) + lapic_init(); + + /* Restore HPET state */ + hpet_restore(); + + /* Restart tick interrupts from the LAPIC timer */ + rtc_lapic_start_ticking(); + + fpinit(); + clear_fpu(); + +#if HIBERNATION + if (did_hibernate) + enable_preemption(); + + kprintf("ret from acpi_sleep_cpu hib=%d\n", did_hibernate); +#endif }