12df1fe9cSrandyf /* 22df1fe9cSrandyf * CDDL HEADER START 32df1fe9cSrandyf * 42df1fe9cSrandyf * The contents of this file are subject to the terms of the 52df1fe9cSrandyf * Common Development and Distribution License (the "License"). 62df1fe9cSrandyf * You may not use this file except in compliance with the License. 72df1fe9cSrandyf * 82df1fe9cSrandyf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92df1fe9cSrandyf * or http://www.opensolaris.org/os/licensing. 102df1fe9cSrandyf * See the License for the specific language governing permissions 112df1fe9cSrandyf * and limitations under the License. 122df1fe9cSrandyf * 132df1fe9cSrandyf * When distributing Covered Code, include this CDDL HEADER in each 142df1fe9cSrandyf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152df1fe9cSrandyf * If applicable, add the following below this CDDL HEADER, with the 162df1fe9cSrandyf * fields enclosed by brackets "[]" replaced with your own identifying 172df1fe9cSrandyf * information: Portions Copyright [yyyy] [name of copyright owner] 182df1fe9cSrandyf * 192df1fe9cSrandyf * CDDL HEADER END 202df1fe9cSrandyf */ 212df1fe9cSrandyf 222df1fe9cSrandyf /* 23aa2aa9a6SDana Myers * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 242df1fe9cSrandyf * Use is subject to license terms. 25*385cc6b4SJerry Jelinek * Copyright 2016, Joyent, Inc. 262df1fe9cSrandyf */ 272df1fe9cSrandyf 282df1fe9cSrandyf #include <sys/types.h> 292df1fe9cSrandyf #include <sys/smp_impldefs.h> 302df1fe9cSrandyf #include <sys/promif.h> 312df1fe9cSrandyf 322df1fe9cSrandyf #include <sys/kmem.h> 332df1fe9cSrandyf #include <sys/archsystm.h> 342df1fe9cSrandyf #include <sys/cpuvar.h> 352df1fe9cSrandyf #include <sys/pte.h> 362df1fe9cSrandyf #include <vm/seg_kmem.h> 372df1fe9cSrandyf #include <sys/epm.h> 38c36fc336Srandyf #include <sys/cpr.h> 392df1fe9cSrandyf #include <sys/machsystm.h> 402df1fe9cSrandyf #include <sys/clock.h> 412df1fe9cSrandyf 422df1fe9cSrandyf #include <sys/cpr_wakecode.h> 432df1fe9cSrandyf #include <sys/acpi/acpi.h> 442df1fe9cSrandyf 452df1fe9cSrandyf #ifdef OLDPMCODE 462df1fe9cSrandyf #include "acpi.h" 472df1fe9cSrandyf #endif 482df1fe9cSrandyf 492df1fe9cSrandyf #include <sys/x86_archext.h> 502df1fe9cSrandyf #include <sys/reboot.h> 512df1fe9cSrandyf #include <sys/cpu_module.h> 522df1fe9cSrandyf #include <sys/kdi.h> 532df1fe9cSrandyf 542df1fe9cSrandyf /* 552df1fe9cSrandyf * S3 stuff 562df1fe9cSrandyf */ 572df1fe9cSrandyf 582df1fe9cSrandyf int acpi_rtc_wake = 0x0; /* wake in N seconds */ 592df1fe9cSrandyf 602df1fe9cSrandyf #if 0 /* debug */ 612df1fe9cSrandyf static uint8_t branchbuf[64 * 1024]; /* for the HDT branch trace stuff */ 622df1fe9cSrandyf #endif /* debug */ 632df1fe9cSrandyf 642df1fe9cSrandyf extern int boothowto; 652df1fe9cSrandyf 662df1fe9cSrandyf #define BOOTCPU 0 /* cpu 0 is always the boot cpu */ 672df1fe9cSrandyf 682df1fe9cSrandyf extern void kernel_wc_code(void); 692df1fe9cSrandyf extern tod_ops_t *tod_ops; 702df1fe9cSrandyf extern int flushes_require_xcalls; 712df1fe9cSrandyf extern int tsc_gethrtime_enable; 722df1fe9cSrandyf 732df1fe9cSrandyf extern cpuset_t cpu_ready_set; 742df1fe9cSrandyf 752df1fe9cSrandyf 762df1fe9cSrandyf /* 772df1fe9cSrandyf * This is what we've all been waiting for! 782df1fe9cSrandyf */ 792df1fe9cSrandyf int 802df1fe9cSrandyf acpi_enter_sleepstate(s3a_t *s3ap) 812df1fe9cSrandyf { 822df1fe9cSrandyf ACPI_PHYSICAL_ADDRESS wakephys = s3ap->s3a_wakephys; 832df1fe9cSrandyf caddr_t wakevirt = rm_platter_va; 842df1fe9cSrandyf /*LINTED*/ 852df1fe9cSrandyf wakecode_t *wp = (wakecode_t *)wakevirt; 862df1fe9cSrandyf uint_t Sx = s3ap->s3a_state; 872df1fe9cSrandyf 882df1fe9cSrandyf PT(PT_SWV); 892df1fe9cSrandyf /* Set waking vector */ 90*385cc6b4SJerry Jelinek if (AcpiSetFirmwareWakingVector(wakephys, NULL) != AE_OK) { 912df1fe9cSrandyf PT(PT_SWV_FAIL); 922df1fe9cSrandyf PMD(PMD_SX, ("Can't SetFirmwareWakingVector(%lx)\n", 932df1fe9cSrandyf (long)wakephys)) 942df1fe9cSrandyf goto insomnia; 952df1fe9cSrandyf } 962df1fe9cSrandyf 972df1fe9cSrandyf PT(PT_EWE); 982df1fe9cSrandyf /* Enable wake events */ 992df1fe9cSrandyf if (AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, 0) != AE_OK) { 1002df1fe9cSrandyf PT(PT_EWE_FAIL); 1012df1fe9cSrandyf PMD(PMD_SX, ("Can't EnableEvent(POWER_BUTTON)\n")) 1022df1fe9cSrandyf } 1032df1fe9cSrandyf if (acpi_rtc_wake > 0) { 104db2bae30SDana Myers /* clear the RTC bit first */ 105aa2aa9a6SDana Myers (void) AcpiWriteBitRegister(ACPI_BITREG_RT_CLOCK_STATUS, 1); 1062df1fe9cSrandyf PT(PT_RTCW); 1072df1fe9cSrandyf if (AcpiEnableEvent(ACPI_EVENT_RTC, 0) != AE_OK) { 1082df1fe9cSrandyf PT(PT_RTCW_FAIL); 1092df1fe9cSrandyf PMD(PMD_SX, ("Can't EnableEvent(RTC)\n")) 1102df1fe9cSrandyf } 1112df1fe9cSrandyf 1122df1fe9cSrandyf /* 1132df1fe9cSrandyf * Set RTC to wake us in a wee while. 1142df1fe9cSrandyf */ 1152df1fe9cSrandyf mutex_enter(&tod_lock); 1162df1fe9cSrandyf PT(PT_TOD); 1172df1fe9cSrandyf TODOP_SETWAKE(tod_ops, acpi_rtc_wake); 1182df1fe9cSrandyf mutex_exit(&tod_lock); 1192df1fe9cSrandyf } 1202df1fe9cSrandyf 1212df1fe9cSrandyf /* 1222df1fe9cSrandyf * Prepare for sleep ... could've done this earlier? 1232df1fe9cSrandyf */ 1242df1fe9cSrandyf PT(PT_SXP); 1252df1fe9cSrandyf PMD(PMD_SX, ("Calling AcpiEnterSleepStatePrep(%d) ...\n", Sx)) 1262df1fe9cSrandyf if (AcpiEnterSleepStatePrep(Sx) != AE_OK) { 1272df1fe9cSrandyf PMD(PMD_SX, ("... failed\n!")) 1282df1fe9cSrandyf goto insomnia; 1292df1fe9cSrandyf } 1302df1fe9cSrandyf 1312df1fe9cSrandyf switch (s3ap->s3a_test_point) { 1322df1fe9cSrandyf case DEVICE_SUSPEND_TO_RAM: 133c36fc336Srandyf case FORCE_SUSPEND_TO_RAM: 1342df1fe9cSrandyf case LOOP_BACK_PASS: 1352df1fe9cSrandyf return (0); 1362df1fe9cSrandyf case LOOP_BACK_FAIL: 1372df1fe9cSrandyf return (1); 1382df1fe9cSrandyf default: 139c36fc336Srandyf ASSERT(s3ap->s3a_test_point == LOOP_BACK_NONE); 1402df1fe9cSrandyf } 1412df1fe9cSrandyf 1422df1fe9cSrandyf /* 1432df1fe9cSrandyf * Tell the hardware to sleep. 1442df1fe9cSrandyf */ 1452df1fe9cSrandyf PT(PT_SXE); 1462df1fe9cSrandyf PMD(PMD_SX, ("Calling AcpiEnterSleepState(%d) ...\n", Sx)) 1472df1fe9cSrandyf if (AcpiEnterSleepState(Sx) != AE_OK) { 1482df1fe9cSrandyf PT(PT_SXE_FAIL); 1492df1fe9cSrandyf PMD(PMD_SX, ("... failed!\n")) 1502df1fe9cSrandyf } 1512df1fe9cSrandyf 1522df1fe9cSrandyf insomnia: 1532df1fe9cSrandyf PT(PT_INSOM); 1542df1fe9cSrandyf /* cleanup is done in the caller */ 1552df1fe9cSrandyf return (1); 1562df1fe9cSrandyf } 1572df1fe9cSrandyf 1582df1fe9cSrandyf int 1592df1fe9cSrandyf acpi_exit_sleepstate(s3a_t *s3ap) 1602df1fe9cSrandyf { 1612df1fe9cSrandyf int Sx = s3ap->s3a_state; 1622df1fe9cSrandyf 1632df1fe9cSrandyf PT(PT_WOKE); 1642df1fe9cSrandyf PMD(PMD_SX, ("!We woke up!\n")) 1652df1fe9cSrandyf 1662df1fe9cSrandyf PT(PT_LSS); 167*385cc6b4SJerry Jelinek if (AcpiLeaveSleepStatePrep(Sx) != AE_OK) { 168*385cc6b4SJerry Jelinek PT(PT_LSS_FAIL); 169*385cc6b4SJerry Jelinek PMD(PMD_SX, ("Problem with LeaveSleepState!\n")) 170*385cc6b4SJerry Jelinek } 171*385cc6b4SJerry Jelinek 1722df1fe9cSrandyf if (AcpiLeaveSleepState(Sx) != AE_OK) { 1732df1fe9cSrandyf PT(PT_LSS_FAIL); 1742df1fe9cSrandyf PMD(PMD_SX, ("Problem with LeaveSleepState!\n")) 1752df1fe9cSrandyf } 1762df1fe9cSrandyf 177076d97abSPhi Tran PT(PT_CPB); 178076d97abSPhi Tran if (AcpiClearEvent(ACPI_EVENT_POWER_BUTTON) != AE_OK) { 179076d97abSPhi Tran PT(PT_CPB_FAIL); 180076d97abSPhi Tran PMD(PMD_SX, ("Problem w/ ClearEvent(POWER_BUTTON)\n")) 1812df1fe9cSrandyf } 1822df1fe9cSrandyf if (acpi_rtc_wake > 0 && 1832df1fe9cSrandyf AcpiDisableEvent(ACPI_EVENT_RTC, 0) != AE_OK) { 1842df1fe9cSrandyf PT(PT_DRTC_FAIL); 1852df1fe9cSrandyf PMD(PMD_SX, ("Problem w/ DisableEvent(RTC)\n")) 1862df1fe9cSrandyf } 1872df1fe9cSrandyf 1882df1fe9cSrandyf PMD(PMD_SX, ("Exiting acpi_sleepstate() => 0\n")) 1892df1fe9cSrandyf 1902df1fe9cSrandyf return (0); 1912df1fe9cSrandyf } 192