X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2a1bd2d3eef5c7a7bb14f4bb9fdbca9a96ee4752..HEAD:/iokit/Kernel/IOPMrootDomain.cpp diff --git a/iokit/Kernel/IOPMrootDomain.cpp b/iokit/Kernel/IOPMrootDomain.cpp index 2aec3e5c3..4231fad39 100644 --- a/iokit/Kernel/IOPMrootDomain.cpp +++ b/iokit/Kernel/IOPMrootDomain.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include "IOKitKernelInternal.h" #if HIBERNATION #include @@ -519,8 +520,8 @@ static UInt32 gWillShutdown = 0; static UInt32 gPagingOff = 0; static UInt32 gSleepWakeUUIDIsSet = false; static uint32_t gAggressivesState = 0; -static uint32_t gHaltTimeMaxLog; -static uint32_t gHaltTimeMaxPanic; +uint32_t gHaltTimeMaxLog; +uint32_t gHaltTimeMaxPanic; IOLock * gHaltLogLock; static char * gHaltLog; enum { kHaltLogSize = 2048 }; @@ -605,6 +606,7 @@ static char gShutdownReasonString[80]; static bool gWakeReasonSysctlRegistered = false; static bool gBootReasonSysctlRegistered = false; static bool gShutdownReasonSysctlRegistered = false; +static bool gWillShutdownSysctlRegistered = false; static AbsoluteTime gUserActiveAbsTime; static AbsoluteTime gUserInactiveAbsTime; @@ -977,6 +979,18 @@ IOSystemShutdownNotification(int stage) return; } + if (kIOSystemShutdownNotificationTerminateDEXTs == stage) { + uint64_t nano, millis; + startTime = mach_absolute_time(); + IOServicePH::systemHalt(); + absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano); + millis = nano / NSEC_PER_MSEC; + if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) { + printf("IOServicePH::systemHalt took %qd ms\n", millis); + } + return; + } + assert(kIOSystemShutdownNotificationStageProcessExit == stage); IOLockLock(gHaltLogLock); @@ -1002,7 +1016,6 @@ IOSystemShutdownNotification(int stage) } } - extern "C" int sync_internal(void); /* @@ -1171,11 +1184,11 @@ sysctl_sleepwaketime SYSCTL_HANDLER_ARGS } static SYSCTL_PROC(_kern, OID_AUTO, sleeptime, - CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", ""); static SYSCTL_PROC(_kern, OID_AUTO, waketime, - CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", ""); SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, ""); @@ -1184,11 +1197,15 @@ SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, & SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, ""); static int -sysctl_willshutdown -(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) +sysctl_willshutdown SYSCTL_HANDLER_ARGS { - int new_value, changed; - int error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed); + int new_value, changed, error; + + if (!gWillShutdownSysctlRegistered) { + return ENOENT; + } + + error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed); if (changed) { if (!gWillShutdown && (new_value == 1)) { IOPMRootDomainWillShutdown(); @@ -1200,12 +1217,9 @@ sysctl_willshutdown } static SYSCTL_PROC(_kern, OID_AUTO, willshutdown, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_willshutdown, "I", ""); -extern struct sysctl_oid sysctl__kern_iokittest; -extern struct sysctl_oid sysctl__debug_iokit; - #if defined(XNU_TARGET_OS_OSX) static int @@ -1241,11 +1255,11 @@ sysctl_progressmeter } static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_progressmeterenable, "I", ""); static SYSCTL_PROC(_kern, OID_AUTO, progressmeter, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_progressmeter, "I", ""); #endif /* defined(XNU_TARGET_OS_OSX) */ @@ -1269,7 +1283,7 @@ sysctl_consoleoptions } static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_consoleoptions, "I", ""); @@ -1280,7 +1294,7 @@ sysctl_progressoptions SYSCTL_HANDLER_ARGS } static SYSCTL_PROC(_kern, OID_AUTO, progressoptions, - CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, + CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", ""); @@ -1290,20 +1304,32 @@ sysctl_wakereason SYSCTL_HANDLER_ARGS char wr[sizeof(gWakeReasonString)]; wr[0] = '\0'; - if (gRootDomain) { + if (gRootDomain && gWakeReasonSysctlRegistered) { gRootDomain->copyWakeReasonString(wr, sizeof(wr)); + } else { + return ENOENT; } return sysctl_io_string(req, wr, 0, 0, NULL); } SYSCTL_PROC(_kern, OID_AUTO, wakereason, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_wakereason, "A", "wakereason"); -SYSCTL_STRING(_kern, OID_AUTO, bootreason, - CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, - gBootReasonString, sizeof(gBootReasonString), ""); +static int +sysctl_bootreason SYSCTL_HANDLER_ARGS +{ + if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) { + return ENOENT; + } + + return sysctl_io_string(req, gBootReasonString, 0, 0, NULL); +} + +SYSCTL_PROC(_kern, OID_AUTO, bootreason, + CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, + NULL, 0, sysctl_bootreason, "A", ""); static int sysctl_shutdownreason SYSCTL_HANDLER_ARGS @@ -1311,15 +1337,17 @@ sysctl_shutdownreason SYSCTL_HANDLER_ARGS char sr[sizeof(gShutdownReasonString)]; sr[0] = '\0'; - if (gRootDomain) { + if (gRootDomain && gShutdownReasonSysctlRegistered) { gRootDomain->copyShutdownReasonString(sr, sizeof(sr)); + } else { + return ENOENT; } return sysctl_io_string(req, sr, 0, 0, NULL); } SYSCTL_PROC(_kern, OID_AUTO, shutdownreason, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_shutdownreason, "A", "shutdownreason"); static int @@ -1341,7 +1369,7 @@ sysctl_targettype SYSCTL_HANDLER_ARGS } SYSCTL_PROC(_hw, OID_AUTO, targettype, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_targettype, "A", "targettype"); static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, ""); @@ -1373,7 +1401,7 @@ sysctl_aotmetrics SYSCTL_HANDLER_ARGS } static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics, - CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", ""); @@ -1422,7 +1450,7 @@ sysctl_aotmodebits } static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED, NULL, 0, sysctl_aotmodebits, "I", ""); static int @@ -1447,7 +1475,7 @@ sysctl_aotmode } static SYSCTL_PROC(_kern, OID_AUTO, aotmode, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, NULL, 0, sysctl_aotmode, "I", ""); //****************************************************************************** @@ -1748,24 +1776,7 @@ IOPMrootDomain::start( IOService * nub ) // read swd_panic boot-arg PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic)); - sysctl_register_oid(&sysctl__kern_sleeptime); - sysctl_register_oid(&sysctl__kern_waketime); - sysctl_register_oid(&sysctl__kern_willshutdown); - sysctl_register_oid(&sysctl__kern_iokittest); - sysctl_register_oid(&sysctl__debug_iokit); - sysctl_register_oid(&sysctl__hw_targettype); - -#if defined(XNU_TARGET_OS_OSX) - sysctl_register_oid(&sysctl__kern_progressmeterenable); - sysctl_register_oid(&sysctl__kern_progressmeter); - sysctl_register_oid(&sysctl__kern_wakereason); -#endif /* defined(XNU_TARGET_OS_OSX) */ - sysctl_register_oid(&sysctl__kern_consoleoptions); - sysctl_register_oid(&sysctl__kern_progressoptions); - - sysctl_register_oid(&sysctl__kern_aotmode); - sysctl_register_oid(&sysctl__kern_aotmodebits); - sysctl_register_oid(&sysctl__kern_aotmetrics); + gWillShutdownSysctlRegistered = true; #if HIBERNATION #if defined(__arm64__) @@ -2971,6 +2982,9 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState ) // Until the platform driver can claim its wake reasons strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(), sizeof(gWakeReasonString)); + if (!gWakeReasonSysctlRegistered) { + gWakeReasonSysctlRegistered = true; + } WAKEEVENT_UNLOCK(); } @@ -3060,6 +3074,15 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState ) isRTCAlarmWake = true; fullWakeReason = kFullWakeReasonLocalUser; requestUserActive(this, "RTC debug alarm"); + } else { +#if HIBERNATION + OSSharedPtr hibOptionsProp = copyProperty(kIOHibernateOptionsKey); + OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get()); + if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) { + fullWakeReason = kFullWakeReasonLocalUser; + requestUserActive(this, "hibernate user wake"); + } +#endif } // stay awake for at least 30 seconds @@ -5993,6 +6016,27 @@ IOPMrootDomain::overrideOurPowerChange( _currentCapability, changeFlags, request->getTag()); + +#if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT + /* + * ASBM send lowBattery notifications every 1 second until the device + * enters hibernation. This queues up multiple sleep requests. + * After the device wakes from hibernation, none of these previously + * queued sleep requests are valid. + * lowBattteryCondition variable is set when ASBM notifies rootDomain + * and is cleared at the very last point in sleep. + * Any attempt to sleep with reason kIOPMSleepReasonLowPower without + * lowBatteryCondition is invalid + */ + if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) { + if (!lowBatteryCondition) { + DLOG("Duplicate lowBattery sleep"); + *inOutChangeFlags |= kIOPMNotDone; + return; + } + } +#endif + if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) { // Assertion may have been taken in AOT leading to changePowerStateTo(AOT) *inOutChangeFlags |= kIOPMNotDone; @@ -6006,15 +6050,6 @@ IOPMrootDomain::overrideOurPowerChange( return; } -#if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT - if (lowBatteryCondition && (desiredPowerState < currentPowerState)) { - // Reject sleep requests when lowBatteryCondition is TRUE to - // avoid racing with the impending system shutdown. - *inOutChangeFlags |= kIOPMNotDone; - return; - } -#endif - if (desiredPowerState < currentPowerState) { if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) { // Root domain is dropping power state from ON->SLEEP. @@ -8147,23 +8182,9 @@ IOPMrootDomain::handlePowerNotification( UInt32 msg ) * Power Emergency */ if (msg & kIOPMPowerEmergency) { - DLOG("Low battery notification received\n"); -#if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT - // Wait for the next low battery notification if the system state is - // in transition. - if ((_systemTransitionType == kSystemTransitionNone) && - CAP_CURRENT(kIOPMSystemCapabilityCPU) && - !systemBooting && !systemShutdown && !gWillShutdown) { - // Setting lowBatteryCondition will prevent system sleep - lowBatteryCondition = true; - - // Notify userspace to initiate system shutdown - messageClients(kIOPMMessageRequestSystemShutdown); - } -#else + DLOG("Received kIOPMPowerEmergency"); lowBatteryCondition = true; privateSleepSystem(kIOPMSleepReasonLowPower); -#endif } /* @@ -10683,9 +10704,6 @@ IOPMrootDomain::claimSystemWakeEvent( // Lazy registration until the platform driver stops registering // the same name. gWakeReasonSysctlRegistered = true; -#if !defined(XNU_TARGET_OS_OSX) - sysctl_register_oid(&sysctl__kern_wakereason); -#endif /* !defined(XNU_TARGET_OS_OSX) */ } if (addWakeReason) { _systemWakeEventsArray->setObject(dict.get()); @@ -10728,8 +10746,7 @@ IOPMrootDomain::claimSystemBootEvent( if (!gBootReasonSysctlRegistered) { // Lazy sysctl registration after setting gBootReasonString strlcat(gBootReasonString, reason, sizeof(gBootReasonString)); - sysctl_register_oid(&sysctl__kern_bootreason); - gBootReasonSysctlRegistered = true; + os_atomic_store(&gBootReasonSysctlRegistered, true, release); } WAKEEVENT_UNLOCK(); } @@ -10758,10 +10775,7 @@ IOPMrootDomain::claimSystemShutdownEvent( } strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString)); - if (!gShutdownReasonSysctlRegistered) { - sysctl_register_oid(&sysctl__kern_shutdownreason); - gShutdownReasonSysctlRegistered = true; - } + gShutdownReasonSysctlRegistered = true; WAKEEVENT_UNLOCK(); }