X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8ad349bb6ed4a0be06e34c92be0d98b92e078db4..4452a7af2eac33dbad800bcc91f2399d62c18f53:/osfmk/i386/acpi.c diff --git a/osfmk/i386/acpi.c b/osfmk/i386/acpi.c index f351933cf..a70821010 100644 --- a/osfmk/i386/acpi.c +++ b/osfmk/i386/acpi.c @@ -1,31 +1,29 @@ /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the - * License may not be used to create, or enable the creation or - * redistribution of, unlawful or unlicensed copies of an Apple operating - * system, or to circumvent, violate, or enable the circumvention or - * violation of, any terms of an Apple operating system software license - * agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and * limitations under the License. - * - * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include @@ -33,7 +31,10 @@ #include #include #include +#include #include +#include +#include #include @@ -49,11 +50,13 @@ extern unsigned int disableSerialOuput; extern void set_kbd_leds(int leds); +extern void fpinit(void); + vm_offset_t acpi_install_wake_handler(void) { /* copy wake code to ACPI_WAKE_ADDR in low memory */ - bcopy_phys((addr64_t) kvtophys((vm_offset_t)acpi_wake_start), + bcopy_phys(kvtophys((vm_offset_t)acpi_wake_start), (addr64_t) ACPI_WAKE_ADDR, acpi_wake_end - acpi_wake_start); @@ -72,12 +75,28 @@ typedef struct acpi_hibernate_callback_data { static void acpi_hibernate(void *refcon) { - boolean_t hib; + boolean_t dohalt; acpi_hibernate_callback_data *data = (acpi_hibernate_callback_data *)refcon; if (current_cpu_datap()->cpu_hibernate) { - hib = hibernate_write_image(); + + dohalt = hibernate_write_image(); + if (dohalt) + { + // off + HIBLOG("power off\n"); + if (PE_halt_restart) + (*PE_halt_restart)(kPEHaltCPU); + } + else + { + // sleep + HIBLOG("sleep\n"); + + // should we come back via regular wake, set the state in memory. + cpu_datap(0)->cpu_hibernate = 0; + } } (data->func)(data->refcon); @@ -91,51 +110,85 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon) acpi_hibernate_callback_data data; boolean_t did_hibernate; - /* shutdown local APIC before passing control to BIOS */ - lapic_shutdown(); + kprintf("acpi_sleep_kernel hib=%d\n", current_cpu_datap()->cpu_hibernate); + + /* shutdown local APIC before passing control to BIOS */ + lapic_shutdown(); data.func = func; data.refcon = refcon; - /* - * Save master CPU state and sleep platform. - * Will not return until platform is woken up, - * or if sleep failed. - */ + /* Save HPET state */ + hpet_save(); + + /* + * If we're in 64-bit mode, drop back into legacy mode during sleep. + */ + if (cpu_mode_is64bit()) { + 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(); + /* 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 *) CM1 = 0; - * (int *) CM2 = 0; - * (int *) CM3 = 0; + int i; + for (i=0; icpu_pmap->mapwindow[i].prv_CMAP = 0; + } + current_cpu_datap()->cpu_hibernate = 0; + did_hibernate = TRUE; - current_cpu_datap()->cpu_hibernate = 0; + } else { + did_hibernate = FALSE; + } - did_hibernate = TRUE; + /* 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 { - did_hibernate = FALSE; + fast_syscall_init(); } - /* restore MTRR settings */ - mtrr_update_cpu(); + /* Re-enable machine check handling */ + mca_cpu_init(); + + /* restore MTRR settings */ + mtrr_update_cpu(); - /* set up PAT following boot processor power up */ - pat_init(); + /* 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(); + /* 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(); - /* let the realtime clock reset */ - rtc_sleep_wakeup(); + fpinit(); + clear_fpu(); if (did_hibernate) { enable_preemption();