1 /* 2 * Copyright (c) 1998-2020 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #define IOKIT_ENABLE_SHARED_PTR 30 31 #include <libkern/c++/OSKext.h> 32 #include <libkern/c++/OSMetaClass.h> 33 #include <libkern/OSAtomic.h> 34 #include <libkern/OSDebug.h> 35 #include <IOKit/IOWorkLoop.h> 36 #include <IOKit/IOCommandGate.h> 37 #include <IOKit/IOTimerEventSource.h> 38 #include <IOKit/IOPlatformExpert.h> 39 #include <IOKit/IOCPU.h> 40 #include <IOKit/IOPlatformActions.h> 41 #include <IOKit/IOKitDebug.h> 42 #include <IOKit/IOTimeStamp.h> 43 #include <IOKit/pwr_mgt/IOPMlog.h> 44 #include <IOKit/pwr_mgt/RootDomain.h> 45 #include <IOKit/pwr_mgt/IOPMPrivate.h> 46 #include <IOKit/IODeviceTreeSupport.h> 47 #include <IOKit/IOMessage.h> 48 #include <IOKit/IOReturn.h> 49 #include <IOKit/IONVRAM.h> 50 #include "RootDomainUserClient.h" 51 #include "IOKit/pwr_mgt/IOPowerConnection.h" 52 #include "IOPMPowerStateQueue.h" 53 #include <IOKit/IOCatalogue.h> 54 #include <IOKit/IOReportMacros.h> 55 #include <IOKit/IOLib.h> 56 #include <IOKit/IOKitKeys.h> 57 #include "IOKitKernelInternal.h" 58 #if HIBERNATION 59 #include <IOKit/IOHibernatePrivate.h> 60 #if __arm64__ 61 #include <arm64/ppl/ppl_hib.h> 62 #endif /* __arm64__ */ 63 #endif /* HIBERNATION */ 64 #include <console/video_console.h> 65 #include <sys/syslog.h> 66 #include <sys/sysctl.h> 67 #include <sys/vnode.h> 68 #include <sys/vnode_internal.h> 69 #include <sys/fcntl.h> 70 #include <os/log.h> 71 #include <pexpert/protos.h> 72 #include <AssertMacros.h> 73 74 #include <sys/time.h> 75 #include "IOServicePrivate.h" // _IOServiceInterestNotifier 76 #include "IOServicePMPrivate.h" 77 78 #include <libkern/zlib.h> 79 #include <os/cpp_util.h> 80 #include <libkern/c++/OSBoundedArrayRef.h> 81 82 __BEGIN_DECLS 83 #include <mach/shared_region.h> 84 #include <kern/clock.h> 85 __END_DECLS 86 87 #if defined(__i386__) || defined(__x86_64__) 88 __BEGIN_DECLS 89 #include "IOPMrootDomainInternal.h" 90 const char *processor_to_datastring(const char *prefix, processor_t target_processor); 91 __END_DECLS 92 #endif 93 94 #define kIOPMrootDomainClass "IOPMrootDomain" 95 #define LOG_PREFIX "PMRD: " 96 97 98 #define MSG(x...) \ 99 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false) 100 101 #define LOG(x...) \ 102 do { kprintf(LOG_PREFIX x); } while (false) 103 104 #if DEVELOPMENT || DEBUG 105 #define DEBUG_LOG(x...) do { \ 106 if (kIOLogPMRootDomain & gIOKitDebug) \ 107 kprintf(LOG_PREFIX x); \ 108 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \ 109 } while (false) 110 #else 111 #define DEBUG_LOG(x...) 112 #endif 113 114 #define DLOG(x...) do { \ 115 if (kIOLogPMRootDomain & gIOKitDebug) \ 116 kprintf(LOG_PREFIX x); \ 117 else \ 118 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \ 119 } while (false) 120 121 #define DMSG(x...) do { \ 122 if (kIOLogPMRootDomain & gIOKitDebug) { \ 123 kprintf(LOG_PREFIX x); \ 124 } \ 125 } while (false) 126 127 128 #define _LOG(x...) 129 130 #define CHECK_THREAD_CONTEXT 131 #ifdef CHECK_THREAD_CONTEXT 132 static IOWorkLoop * gIOPMWorkLoop = NULL; 133 #define ASSERT_GATED() \ 134 do { \ 135 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \ 136 panic("RootDomain: not inside PM gate"); \ 137 } \ 138 } while(false) 139 #else 140 #define ASSERT_GATED() 141 #endif /* CHECK_THREAD_CONTEXT */ 142 143 #define CAP_LOSS(c) \ 144 (((_pendingCapability & (c)) == 0) && \ 145 ((_currentCapability & (c)) != 0)) 146 147 #define CAP_GAIN(c) \ 148 (((_currentCapability & (c)) == 0) && \ 149 ((_pendingCapability & (c)) != 0)) 150 151 #define CAP_CHANGE(c) \ 152 (((_currentCapability ^ _pendingCapability) & (c)) != 0) 153 154 #define CAP_CURRENT(c) \ 155 ((_currentCapability & (c)) != 0) 156 157 #define CAP_HIGHEST(c) \ 158 ((_highestCapability & (c)) != 0) 159 160 #define CAP_PENDING(c) \ 161 ((_pendingCapability & (c)) != 0) 162 163 // rdar://problem/9157444 164 #if defined(__i386__) || defined(__x86_64__) 165 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20 166 #endif 167 168 // Event types for IOPMPowerStateQueue::submitPowerEvent() 169 enum { 170 kPowerEventFeatureChanged = 1, // 1 171 kPowerEventReceivedPowerNotification, // 2 172 kPowerEventSystemBootCompleted, // 3 173 kPowerEventSystemShutdown, // 4 174 kPowerEventUserDisabledSleep, // 5 175 kPowerEventRegisterSystemCapabilityClient, // 6 176 kPowerEventRegisterKernelCapabilityClient, // 7 177 kPowerEventPolicyStimulus, // 8 178 kPowerEventAssertionCreate, // 9 179 kPowerEventAssertionRelease, // 10 180 kPowerEventAssertionSetLevel, // 11 181 kPowerEventQueueSleepWakeUUID, // 12 182 kPowerEventPublishSleepWakeUUID, // 13 183 kPowerEventSetDisplayPowerOn, // 14 184 kPowerEventPublishWakeType, // 15 185 kPowerEventAOTEvaluate // 16 186 }; 187 188 // For evaluatePolicy() 189 // List of stimuli that affects the root domain policy. 190 enum { 191 kStimulusDisplayWranglerSleep, // 0 192 kStimulusDisplayWranglerWake, // 1 193 kStimulusAggressivenessChanged, // 2 194 kStimulusDemandSystemSleep, // 3 195 kStimulusAllowSystemSleepChanged, // 4 196 kStimulusDarkWakeActivityTickle, // 5 197 kStimulusDarkWakeEntry, // 6 198 kStimulusDarkWakeReentry, // 7 199 kStimulusDarkWakeEvaluate, // 8 200 kStimulusNoIdleSleepPreventers, // 9 201 kStimulusEnterUserActiveState, // 10 202 kStimulusLeaveUserActiveState // 11 203 }; 204 205 // Internal power state change reasons 206 // Must be less than kIOPMSleepReasonClamshell=101 207 enum { 208 kCPSReasonNone = 0, // 0 209 kCPSReasonInit, // 1 210 kCPSReasonWake, // 2 211 kCPSReasonIdleSleepPrevent, // 3 212 kCPSReasonIdleSleepAllow, // 4 213 kCPSReasonPowerOverride, // 5 214 kCPSReasonPowerDownCancel, // 6 215 kCPSReasonAOTExit, // 7 216 kCPSReasonAdjustPowerState, // 8 217 kCPSReasonDarkWakeCannotSleep, // 9 218 kCPSReasonIdleSleepEnabled, // 10 219 kCPSReasonEvaluatePolicy, // 11 220 kCPSReasonSustainFullWake, // 12 221 kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1) 222 }; 223 224 extern "C" { 225 IOReturn OSKextSystemSleepOrWake( UInt32 ); 226 } 227 extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); 228 extern "C" addr64_t kvtophys(vm_offset_t va); 229 extern "C" boolean_t kdp_has_polled_corefile(); 230 231 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t ); 232 static void notifySystemShutdown( IOService * root, uint32_t messageType ); 233 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t ); 234 static void pmEventTimeStamp(uint64_t *recordTS); 235 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t ); 236 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t ); 237 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address); 238 239 static int IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt); 240 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt); 241 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d" 242 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second 243 244 // "IOPMSetSleepSupported" callPlatformFunction name 245 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction; 246 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction; 247 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey; 248 249 static OSSharedPtr<const OSSymbol> gIOPMPSExternalConnectedKey; 250 static OSSharedPtr<const OSSymbol> gIOPMPSExternalChargeCapableKey; 251 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryInstalledKey; 252 static OSSharedPtr<const OSSymbol> gIOPMPSIsChargingKey; 253 static OSSharedPtr<const OSSymbol> gIOPMPSAtWarnLevelKey; 254 static OSSharedPtr<const OSSymbol> gIOPMPSAtCriticalLevelKey; 255 static OSSharedPtr<const OSSymbol> gIOPMPSCurrentCapacityKey; 256 static OSSharedPtr<const OSSymbol> gIOPMPSMaxCapacityKey; 257 static OSSharedPtr<const OSSymbol> gIOPMPSDesignCapacityKey; 258 static OSSharedPtr<const OSSymbol> gIOPMPSTimeRemainingKey; 259 static OSSharedPtr<const OSSymbol> gIOPMPSAmperageKey; 260 static OSSharedPtr<const OSSymbol> gIOPMPSVoltageKey; 261 static OSSharedPtr<const OSSymbol> gIOPMPSCycleCountKey; 262 static OSSharedPtr<const OSSymbol> gIOPMPSMaxErrKey; 263 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterInfoKey; 264 static OSSharedPtr<const OSSymbol> gIOPMPSLocationKey; 265 static OSSharedPtr<const OSSymbol> gIOPMPSErrorConditionKey; 266 static OSSharedPtr<const OSSymbol> gIOPMPSManufacturerKey; 267 static OSSharedPtr<const OSSymbol> gIOPMPSManufactureDateKey; 268 static OSSharedPtr<const OSSymbol> gIOPMPSModelKey; 269 static OSSharedPtr<const OSSymbol> gIOPMPSSerialKey; 270 static OSSharedPtr<const OSSymbol> gIOPMPSLegacyBatteryInfoKey; 271 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryHealthKey; 272 static OSSharedPtr<const OSSymbol> gIOPMPSHealthConfidenceKey; 273 static OSSharedPtr<const OSSymbol> gIOPMPSCapacityEstimatedKey; 274 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryChargeStatusKey; 275 static OSSharedPtr<const OSSymbol> gIOPMPSBatteryTemperatureKey; 276 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsKey; 277 static OSSharedPtr<const OSSymbol> gIOPMPSChargerConfigurationKey; 278 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsIDKey; 279 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsWattsKey; 280 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsRevisionKey; 281 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSerialNumberKey; 282 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsFamilyKey; 283 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsAmperageKey; 284 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsDescriptionKey; 285 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsPMUConfigurationKey; 286 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSourceIDKey; 287 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsErrorFlagsKey; 288 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsSharedSourceKey; 289 static OSSharedPtr<const OSSymbol> gIOPMPSAdapterDetailsCloakedKey; 290 static OSSharedPtr<const OSSymbol> gIOPMPSInvalidWakeSecondsKey; 291 static OSSharedPtr<const OSSymbol> gIOPMPSPostChargeWaitSecondsKey; 292 static OSSharedPtr<const OSSymbol> gIOPMPSPostDishargeWaitSecondsKey; 293 294 #define kIOSleepSupportedKey "IOSleepSupported" 295 #define kIOPMSystemCapabilitiesKey "System Capabilities" 296 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict" 297 298 #define kIORequestWranglerIdleKey "IORequestIdle" 299 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds 300 301 #define kIOSleepWakeFailureString "SleepWakeFailureString" 302 #define kIOEFIBootRomFailureKey "wake-failure" 303 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic" 304 305 #define kRD_AllPowerSources (kIOPMSupportedOnAC \ 306 | kIOPMSupportedOnBatt \ 307 | kIOPMSupportedOnUPS) 308 309 #define kLocalEvalClamshellCommand (1 << 15) 310 #define kIdleSleepRetryInterval (3 * 60) 311 312 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID) 313 314 enum { 315 kWranglerPowerStateMin = 0, 316 kWranglerPowerStateSleep = 2, 317 kWranglerPowerStateDim = 3, 318 kWranglerPowerStateMax = 4 319 }; 320 321 enum { 322 OFF_STATE = 0, 323 RESTART_STATE = 1, 324 SLEEP_STATE = 2, 325 AOT_STATE = 3, 326 ON_STATE = 4, 327 NUM_POWER_STATES 328 }; 329 330 const char * 331 getPowerStateString( uint32_t state ) 332 { 333 #define POWER_STATE(x) {(uint32_t) x, #x} 334 335 static const IONamedValue powerStates[] = { 336 POWER_STATE( OFF_STATE ), 337 POWER_STATE( RESTART_STATE ), 338 POWER_STATE( SLEEP_STATE ), 339 POWER_STATE( AOT_STATE ), 340 POWER_STATE( ON_STATE ), 341 { 0, NULL } 342 }; 343 return IOFindNameForValue(state, powerStates); 344 } 345 346 #define ON_POWER kIOPMPowerOn 347 #define RESTART_POWER kIOPMRestart 348 #define SLEEP_POWER kIOPMAuxPowerOn 349 350 static IOPMPowerState 351 ourPowerStates[NUM_POWER_STATES] = 352 { 353 { .version = 1, 354 .capabilityFlags = 0, 355 .outputPowerCharacter = 0, 356 .inputPowerRequirement = 0 }, 357 { .version = 1, 358 .capabilityFlags = kIOPMRestartCapability, 359 .outputPowerCharacter = kIOPMRestart, 360 .inputPowerRequirement = RESTART_POWER }, 361 { .version = 1, 362 .capabilityFlags = kIOPMSleepCapability, 363 .outputPowerCharacter = kIOPMSleep, 364 .inputPowerRequirement = SLEEP_POWER }, 365 { .version = 1, 366 .capabilityFlags = kIOPMAOTCapability, 367 .outputPowerCharacter = kIOPMAOTPower, 368 .inputPowerRequirement = ON_POWER }, 369 { .version = 1, 370 .capabilityFlags = kIOPMPowerOn, 371 .outputPowerCharacter = kIOPMPowerOn, 372 .inputPowerRequirement = ON_POWER }, 373 }; 374 375 #define kIOPMRootDomainWakeTypeSleepService "SleepService" 376 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance" 377 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer" 378 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery" 379 #define kIOPMRootDomainWakeTypeUser "User" 380 #define kIOPMRootDomainWakeTypeAlarm "Alarm" 381 #define kIOPMRootDomainWakeTypeNetwork "Network" 382 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity" 383 #define kIOPMRootDomainWakeTypeNotification "Notification" 384 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError" 385 386 // Special interest that entitles the interested client from receiving 387 // all system messages. Only used by powerd. 388 // 389 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest" 390 391 // Entitlement required for root domain clients 392 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property" 393 394 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock) 395 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock) 396 397 /* 398 * Aggressiveness 399 */ 400 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock) 401 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock) 402 403 #define kAggressivesMinValue 1 404 405 const char * 406 getAggressivenessTypeString( uint32_t type ) 407 { 408 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x} 409 410 static const IONamedValue aggressivenessTypes[] = { 411 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ), 412 AGGRESSIVENESS_TYPE( kPMMinutesToDim ), 413 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ), 414 AGGRESSIVENESS_TYPE( kPMMinutesToSleep ), 415 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ), 416 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ), 417 AGGRESSIVENESS_TYPE( kPMPowerSource), 418 AGGRESSIVENESS_TYPE( kPMMotionSensor ), 419 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ), 420 { 0, NULL } 421 }; 422 return IOFindNameForValue(type, aggressivenessTypes); 423 } 424 425 enum { 426 kAggressivesStateBusy = 0x01, 427 kAggressivesStateQuickSpindown = 0x02 428 }; 429 430 struct AggressivesRecord { 431 uint32_t flags; 432 uint32_t type; 433 uint32_t value; 434 }; 435 436 struct AggressivesRequest { 437 queue_chain_t chain; 438 uint32_t options; 439 uint32_t dataType; 440 union { 441 OSSharedPtr<IOService> service; 442 AggressivesRecord record; 443 } data; 444 }; 445 446 enum { 447 kAggressivesRequestTypeService = 1, 448 kAggressivesRequestTypeRecord 449 }; 450 451 enum { 452 kAggressivesOptionSynchronous = 0x00000001, 453 kAggressivesOptionQuickSpindownEnable = 0x00000100, 454 kAggressivesOptionQuickSpindownDisable = 0x00000200, 455 kAggressivesOptionQuickSpindownMask = 0x00000300 456 }; 457 458 enum { 459 kAggressivesRecordFlagModified = 0x00000001, 460 kAggressivesRecordFlagMinValue = 0x00000002 461 }; 462 463 // System Sleep Preventers 464 465 enum { 466 kPMUserDisabledAllSleep = 1, 467 kPMSystemRestartBootingInProgress, 468 kPMConfigPreventSystemSleep, 469 kPMChildPreventSystemSleep, 470 kPMCPUAssertion, 471 kPMPCIUnsupported, 472 }; 473 474 const char * 475 getSystemSleepPreventerString( uint32_t preventer ) 476 { 477 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x} 478 static const IONamedValue systemSleepPreventers[] = { 479 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ), 480 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ), 481 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ), 482 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ), 483 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ), 484 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ), 485 { 0, NULL } 486 }; 487 return IOFindNameForValue(preventer, systemSleepPreventers); 488 } 489 490 // gDarkWakeFlags 491 enum { 492 kDarkWakeFlagPromotionNone = 0x0000, 493 kDarkWakeFlagPromotionEarly = 0x0001, // promote before gfx clamp 494 kDarkWakeFlagPromotionLate = 0x0002, // promote after gfx clamp 495 kDarkWakeFlagPromotionMask = 0x0003, 496 kDarkWakeFlagAlarmIsDark = 0x0100, 497 kDarkWakeFlagAudioNotSuppressed = 0x0200, 498 kDarkWakeFlagUserWakeWorkaround = 0x1000 499 }; 500 501 // gClamshellFlags 502 // The workaround for 9157444 is enabled at compile time using the 503 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below. 504 enum { 505 kClamshell_WAR_38378787 = 0x00000001, 506 kClamshell_WAR_47715679 = 0x00000002, 507 kClamshell_WAR_58009435 = 0x00000004 508 }; 509 510 // acceptSystemWakeEvents() 511 enum { 512 kAcceptSystemWakeEvents_Disable = 0, 513 kAcceptSystemWakeEvents_Enable, 514 kAcceptSystemWakeEvents_Reenable 515 }; 516 517 static IOPMrootDomain * gRootDomain; 518 static IORootParent * gPatriarch; 519 static IONotifier * gSysPowerDownNotifier = NULL; 520 static UInt32 gSleepOrShutdownPending = 0; 521 static UInt32 gWillShutdown = 0; 522 static UInt32 gPagingOff = 0; 523 static UInt32 gSleepWakeUUIDIsSet = false; 524 static uint32_t gAggressivesState = 0; 525 static uint32_t gHaltTimeMaxLog; 526 static uint32_t gHaltTimeMaxPanic; 527 IOLock * gHaltLogLock; 528 static char * gHaltLog; 529 enum { kHaltLogSize = 2048 }; 530 static size_t gHaltLogPos; 531 static uint64_t gHaltStartTime; 532 static char gKextNameBuf[64]; 533 static size_t gKextNamePos; 534 static bool gKextNameEnd; 535 536 uuid_string_t bootsessionuuid_string; 537 538 #if defined(XNU_TARGET_OS_OSX) 539 #if DISPLAY_WRANGLER_PRESENT 540 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone; 541 #elif CONFIG_ARROW 542 // Enable temporary full wake promotion workarounds 543 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround; 544 #else 545 // Enable full wake promotion workarounds 546 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround; 547 #endif 548 #else /* !defined(XNU_TARGET_OS_OSX) */ 549 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly; 550 #endif /* !defined(XNU_TARGET_OS_OSX) */ 551 552 static uint32_t gNoIdleFlag = 0; 553 static uint32_t gSwdPanic = 1; 554 static uint32_t gSwdSleepTimeout = 0; 555 static uint32_t gSwdWakeTimeout = 0; 556 static uint32_t gSwdSleepWakeTimeout = 0; 557 static PMStatsStruct gPMStats; 558 #if DEVELOPMENT || DEBUG 559 static uint32_t swd_panic_phase; 560 #endif 561 562 static uint32_t gClamshellFlags = 0 563 #if defined(__i386__) || defined(__x86_64__) 564 | kClamshell_WAR_58009435 565 #endif 566 ; 567 568 #if HIBERNATION 569 570 #if defined(__arm64__) 571 static IOReturn 572 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params) 573 { 574 uint32_t sleepType = kIOPMSleepTypeDeepIdle; 575 576 assert(vars->signature == kIOPMSystemSleepPolicySignature); 577 assert(vars->version == kIOPMSystemSleepPolicyVersion); 578 579 // Hibernation enabled and either user forced hibernate or low battery sleep 580 if ((vars->hibernateMode & kIOHibernateModeOn) && 581 ppl_hib_hibernation_supported() && 582 (((vars->hibernateMode & kIOHibernateModeSleep) == 0) || 583 (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) { 584 sleepType = kIOPMSleepTypeHibernate; 585 } 586 params->version = kIOPMSystemSleepParametersVersion; 587 params->sleepType = sleepType; 588 return kIOReturnSuccess; 589 } 590 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler; 591 #else /* defined(__arm64__) */ 592 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL; 593 #endif /* defined(__arm64__) */ 594 595 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL; 596 static void * gSleepPolicyTarget; 597 #endif 598 599 struct timeval gIOLastSleepTime; 600 struct timeval gIOLastWakeTime; 601 AbsoluteTime gIOLastWakeAbsTime; 602 AbsoluteTime gIOLastSleepAbsTime; 603 604 struct timeval gIOLastUserSleepTime; 605 606 static char gWakeReasonString[128]; 607 static char gBootReasonString[80]; 608 static char gShutdownReasonString[80]; 609 static bool gWakeReasonSysctlRegistered = false; 610 static bool gBootReasonSysctlRegistered = false; 611 static bool gShutdownReasonSysctlRegistered = false; 612 static AbsoluteTime gUserActiveAbsTime; 613 static AbsoluteTime gUserInactiveAbsTime; 614 615 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION) 616 static bool gSpinDumpBufferFull = false; 617 #endif 618 619 z_stream swd_zs; 620 vm_offset_t swd_zs_zmem; 621 //size_t swd_zs_zsize; 622 size_t swd_zs_zoffset; 623 #if defined(__i386__) || defined(__x86_64__) 624 IOCPU *currentShutdownTarget = NULL; 625 #endif 626 627 static unsigned int gPMHaltBusyCount; 628 static unsigned int gPMHaltIdleCount; 629 static int gPMHaltDepth; 630 static uint32_t gPMHaltMessageType; 631 static IOLock * gPMHaltLock = NULL; 632 static OSSharedPtr<OSArray> gPMHaltArray; 633 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey; 634 static bool gPMQuiesced; 635 636 // Constants used as arguments to IOPMrootDomain::informCPUStateChange 637 #define kCPUUnknownIndex 9999999 638 enum { 639 kInformAC = 0, 640 kInformLid = 1, 641 kInformableCount = 2 642 }; 643 644 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut; 645 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel; 646 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow; 647 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt; 648 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow; 649 650 #define kBadPMFeatureID 0 651 652 /* 653 * PMSettingHandle 654 * Opaque handle passed to clients of registerPMSettingController() 655 */ 656 class PMSettingHandle : public OSObject 657 { 658 OSDeclareFinalStructors( PMSettingHandle ); 659 friend class PMSettingObject; 660 661 private: 662 PMSettingObject *pmso; 663 void free(void) APPLE_KEXT_OVERRIDE; 664 }; 665 666 /* 667 * PMSettingObject 668 * Internal object to track each PM setting controller 669 */ 670 class PMSettingObject : public OSObject 671 { 672 OSDeclareFinalStructors( PMSettingObject ); 673 friend class IOPMrootDomain; 674 675 private: 676 queue_head_t calloutQueue; 677 thread_t waitThread; 678 IOPMrootDomain *parent; 679 PMSettingHandle *pmsh; 680 IOPMSettingControllerCallback func; 681 OSObject *target; 682 uintptr_t refcon; 683 uint32_t *publishedFeatureID; 684 uint32_t settingCount; 685 bool disabled; 686 687 void free(void) APPLE_KEXT_OVERRIDE; 688 689 public: 690 static PMSettingObject *pmSettingObject( 691 IOPMrootDomain *parent_arg, 692 IOPMSettingControllerCallback handler_arg, 693 OSObject *target_arg, 694 uintptr_t refcon_arg, 695 uint32_t supportedPowerSources, 696 const OSSymbol *settings[], 697 OSObject **handle_obj); 698 699 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object); 700 void clientHandleFreed(void); 701 }; 702 703 struct PMSettingCallEntry { 704 queue_chain_t link; 705 thread_t thread; 706 }; 707 708 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock) 709 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock) 710 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT) 711 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true) 712 713 /* 714 * PMTraceWorker 715 * Internal helper object for logging trace points to RTC 716 * IOPMrootDomain and only IOPMrootDomain should instantiate 717 * exactly one of these. 718 */ 719 720 typedef void (*IOPMTracePointHandler)( 721 void * target, uint32_t code, uint32_t data ); 722 723 class PMTraceWorker : public OSObject 724 { 725 OSDeclareDefaultStructors(PMTraceWorker); 726 public: 727 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t; 728 729 static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * ); 730 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t); 731 void tracePoint(uint8_t phase); 732 void traceDetail(uint32_t detail); 733 void traceComponentWakeProgress(uint32_t component, uint32_t data); 734 int recordTopLevelPCIDevice(IOService *); 735 void RTC_TRACE(void); 736 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE; 737 738 IOPMTracePointHandler tracePointHandler; 739 void * tracePointTarget; 740 uint64_t getPMStatusCode(); 741 uint8_t getTracePhase(); 742 uint32_t getTraceData(); 743 private: 744 IOPMrootDomain *owner; 745 IOLock *pmTraceWorkerLock; 746 OSSharedPtr<OSArray> pciDeviceBitMappings; 747 748 uint8_t addedToRegistry; 749 uint8_t tracePhase; 750 uint32_t traceData32; 751 uint8_t loginWindowData; 752 uint8_t coreDisplayData; 753 uint8_t coreGraphicsData; 754 }; 755 756 /* 757 * PMAssertionsTracker 758 * Tracks kernel and user space PM assertions 759 */ 760 class PMAssertionsTracker : public OSObject 761 { 762 OSDeclareFinalStructors(PMAssertionsTracker); 763 public: 764 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * ); 765 766 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *); 767 IOReturn releaseAssertion(IOPMDriverAssertionID); 768 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel); 769 IOReturn setUserAssertionLevels(IOPMDriverAssertionType); 770 771 OSSharedPtr<OSArray> copyAssertionsArray(void); 772 IOPMDriverAssertionType getActivatedAssertions(void); 773 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType); 774 775 IOReturn handleCreateAssertion(OSData *); 776 IOReturn handleReleaseAssertion(IOPMDriverAssertionID); 777 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel); 778 IOReturn handleSetUserAssertionLevels(void * arg0); 779 void publishProperties(void); 780 void reportCPUBitAccounting(void); 781 782 private: 783 /* 784 * this should be treated as POD, as it's byte-copied around 785 * and we cannot rely on d'tor firing at the right time 786 */ 787 typedef struct { 788 IOPMDriverAssertionID id; 789 IOPMDriverAssertionType assertionBits; 790 uint64_t createdTime; 791 uint64_t modifiedTime; 792 const OSSymbol *ownerString; 793 IOService *ownerService; 794 uint64_t registryEntryID; 795 IOPMDriverAssertionLevel level; 796 uint64_t assertCPUStartTime; 797 uint64_t assertCPUDuration; 798 } PMAssertStruct; 799 800 uint32_t tabulateProducerCount; 801 uint32_t tabulateConsumerCount; 802 803 uint64_t maxAssertCPUDuration; 804 uint64_t maxAssertCPUEntryId; 805 806 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *); 807 void tabulate(void); 808 void updateCPUBitAccounting(PMAssertStruct * assertStruct); 809 810 IOPMrootDomain *owner; 811 OSSharedPtr<OSArray> assertionsArray; 812 IOLock *assertionsArrayLock; 813 IOPMDriverAssertionID issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */ 814 IOPMDriverAssertionType assertionsKernel; 815 IOPMDriverAssertionType assertionsUser; 816 IOPMDriverAssertionType assertionsCombined; 817 }; 818 819 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject); 820 821 /* 822 * PMHaltWorker 823 * Internal helper object for Shutdown/Restart notifications. 824 */ 825 #define kPMHaltMaxWorkers 8 826 #define kPMHaltTimeoutMS 100 827 828 class PMHaltWorker : public OSObject 829 { 830 OSDeclareFinalStructors( PMHaltWorker ); 831 832 public: 833 IOService * service;// service being worked on 834 AbsoluteTime startTime; // time when work started 835 int depth; // work on nubs at this PM-tree depth 836 int visits; // number of nodes visited (debug) 837 IOLock * lock; 838 bool timeout;// service took too long 839 840 static PMHaltWorker * worker( void ); 841 static void main( void * arg, wait_result_t waitResult ); 842 static void work( PMHaltWorker * me ); 843 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now ); 844 virtual void free( void ) APPLE_KEXT_OVERRIDE; 845 }; 846 847 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject ) 848 849 850 #define super IOService 851 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService) 852 853 boolean_t 854 IOPMRootDomainGetWillShutdown(void) 855 { 856 return gWillShutdown != 0; 857 } 858 859 static void 860 IOPMRootDomainWillShutdown(void) 861 { 862 if (OSCompareAndSwap(0, 1, &gWillShutdown)) { 863 IOService::willShutdown(); 864 for (int i = 0; i < 100; i++) { 865 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) { 866 break; 867 } 868 IOSleep( 100 ); 869 } 870 } 871 } 872 873 extern "C" IONotifier * 874 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref) 875 { 876 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach(); 877 } 878 879 extern "C" IONotifier * 880 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref) 881 { 882 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach(); 883 } 884 885 extern "C" IOReturn 886 acknowledgeSleepWakeNotification(void * PMrefcon) 887 { 888 return gRootDomain->allowPowerChange((unsigned long)PMrefcon ); 889 } 890 891 extern "C" IOReturn 892 vetoSleepWakeNotification(void * PMrefcon) 893 { 894 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon ); 895 } 896 897 extern "C" IOReturn 898 rootDomainRestart( void ) 899 { 900 return gRootDomain->restartSystem(); 901 } 902 903 extern "C" IOReturn 904 rootDomainShutdown( void ) 905 { 906 return gRootDomain->shutdownSystem(); 907 } 908 909 static void 910 halt_log_putc(char c) 911 { 912 if (gHaltLogPos >= (kHaltLogSize - 2)) { 913 return; 914 } 915 gHaltLog[gHaltLogPos++] = c; 916 } 917 918 extern "C" void 919 _doprnt_log(const char *fmt, 920 va_list *argp, 921 void (*putc)(char), 922 int radix); 923 924 static int 925 halt_log(const char *fmt, ...) 926 { 927 va_list listp; 928 929 va_start(listp, fmt); 930 _doprnt_log(fmt, &listp, &halt_log_putc, 16); 931 va_end(listp); 932 933 return 0; 934 } 935 936 extern "C" void 937 halt_log_enter(const char * what, const void * pc, uint64_t time) 938 { 939 uint64_t nano, millis; 940 941 if (!gHaltLog) { 942 return; 943 } 944 absolutetime_to_nanoseconds(time, &nano); 945 millis = nano / NSEC_PER_MSEC; 946 if (millis < 100) { 947 return; 948 } 949 950 IOLockLock(gHaltLogLock); 951 if (pc) { 952 halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc)); 953 OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log, 954 OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse); 955 } else { 956 halt_log("%s: %qd ms\n", what, millis); 957 } 958 959 gHaltLog[gHaltLogPos] = 0; 960 IOLockUnlock(gHaltLogLock); 961 } 962 963 extern uint32_t gFSState; 964 965 extern "C" void 966 IOSystemShutdownNotification(int stage) 967 { 968 uint64_t startTime; 969 970 if (kIOSystemShutdownNotificationStageRootUnmount == stage) { 971 #if defined(XNU_TARGET_OS_OSX) 972 uint64_t nano, millis; 973 startTime = mach_absolute_time(); 974 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC); 975 absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano); 976 millis = nano / NSEC_PER_MSEC; 977 if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) { 978 printf("waitQuiet() for unmount %qd ms\n", millis); 979 } 980 #endif /* defined(XNU_TARGET_OS_OSX) */ 981 return; 982 } 983 984 assert(kIOSystemShutdownNotificationStageProcessExit == stage); 985 986 IOLockLock(gHaltLogLock); 987 if (!gHaltLog) { 988 gHaltLog = IONew(char, kHaltLogSize); 989 gHaltStartTime = mach_absolute_time(); 990 if (gHaltLog) { 991 halt_log_putc('\n'); 992 } 993 } 994 IOLockUnlock(gHaltLogLock); 995 996 startTime = mach_absolute_time(); 997 IOPMRootDomainWillShutdown(); 998 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime); 999 #if HIBERNATION 1000 startTime = mach_absolute_time(); 1001 IOHibernateSystemPostWake(true); 1002 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime); 1003 #endif 1004 if (OSCompareAndSwap(0, 1, &gPagingOff)) { 1005 gRootDomain->handlePlatformHaltRestart(kPEPagingOff); 1006 } 1007 } 1008 1009 1010 extern "C" int sync_internal(void); 1011 1012 /* 1013 * A device is always in the highest power state which satisfies its driver, 1014 * its policy-maker, and any power children it has, but within the constraint 1015 * of the power state provided by its parent. The driver expresses its desire by 1016 * calling changePowerStateTo(), the policy-maker expresses its desire by calling 1017 * changePowerStateToPriv(), and the children express their desires by calling 1018 * requestPowerDomainState(). 1019 * 1020 * The Root Power Domain owns the policy for idle and demand sleep for the system. 1021 * It is a power-managed IOService just like the others in the system. 1022 * It implements several power states which map to what we see as Sleep and On. 1023 * 1024 * The sleep policy is as follows: 1025 * 1. Sleep is prevented if the case is open so that nobody will think the machine 1026 * is off and plug/unplug cards. 1027 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero. 1028 * 3. System cannot Sleep if some object in the tree is in a power state marked 1029 * kIOPMPreventSystemSleep. 1030 * 1031 * These three conditions are enforced using the "driver clamp" by calling 1032 * changePowerStateTo(). For example, if the case is opened, 1033 * changePowerStateTo(ON_STATE) is called to hold the system on regardless 1034 * of the desires of the children of the root or the state of the other clamp. 1035 * 1036 * Demand Sleep is initiated by pressing the front panel power button, closing 1037 * the clamshell, or selecting the menu item. In this case the root's parent 1038 * actually initiates the power state change so that the root domain has no 1039 * choice and does not give applications the opportunity to veto the change. 1040 * 1041 * Idle Sleep occurs if no objects in the tree are in a state marked 1042 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding 1043 * the root on, so it sets the "policy-maker clamp" by calling 1044 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires. 1045 * This timer is set for the difference between the sleep timeout slider and the 1046 * display dim timeout slider. When the timer expires, it releases its clamp and 1047 * now nothing is holding it awake, so it falls asleep. 1048 * 1049 * Demand sleep is prevented when the system is booting. When preferences are 1050 * transmitted by the loginwindow at the end of boot, a flag is cleared, 1051 * and this allows subsequent Demand Sleep. 1052 */ 1053 1054 //****************************************************************************** 1055 1056 IOPMrootDomain * 1057 IOPMrootDomain::construct( void ) 1058 { 1059 IOPMrootDomain *root; 1060 1061 root = new IOPMrootDomain; 1062 if (root) { 1063 root->init(); 1064 } 1065 1066 return root; 1067 } 1068 1069 //****************************************************************************** 1070 // updateConsoleUsersCallout 1071 // 1072 //****************************************************************************** 1073 1074 static void 1075 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1) 1076 { 1077 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0; 1078 rootDomain->updateConsoleUsers(); 1079 } 1080 1081 void 1082 IOPMrootDomain::updateConsoleUsers(void) 1083 { 1084 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn); 1085 if (tasksSuspended) { 1086 tasksSuspended = FALSE; 1087 updateTasksSuspend(); 1088 } 1089 } 1090 1091 void 1092 IOPMrootDomain::updateTasksSuspend(void) 1093 { 1094 bool newSuspend; 1095 1096 newSuspend = (tasksSuspended || _aotTasksSuspended); 1097 if (newSuspend == tasksSuspendState) { 1098 return; 1099 } 1100 tasksSuspendState = newSuspend; 1101 tasks_system_suspend(newSuspend); 1102 } 1103 1104 //****************************************************************************** 1105 1106 static void 1107 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 ) 1108 { 1109 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0; 1110 uint32_t notifyRef = (uint32_t)(uintptr_t) p1; 1111 uint32_t powerState = rootDomain->getPowerState(); 1112 1113 DLOG("disk_sync_callout ps=%u\n", powerState); 1114 1115 if (ON_STATE == powerState) { 1116 sync_internal(); 1117 1118 #if HIBERNATION 1119 // Block sleep until trim issued on previous wake path is completed. 1120 IOHibernateSystemPostWake(true); 1121 #endif 1122 } 1123 #if HIBERNATION 1124 else { 1125 IOHibernateSystemPostWake(false); 1126 1127 rootDomain->sleepWakeDebugSaveSpinDumpFile(); 1128 } 1129 #endif 1130 1131 rootDomain->allowPowerChange(notifyRef); 1132 DLOG("disk_sync_callout finish\n"); 1133 } 1134 1135 //****************************************************************************** 1136 static UInt32 1137 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime ) 1138 { 1139 AbsoluteTime endTime; 1140 UInt64 nano = 0; 1141 1142 clock_get_uptime(&endTime); 1143 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) { 1144 *elapsedTime = 0; 1145 } else { 1146 SUB_ABSOLUTETIME(&endTime, startTime); 1147 absolutetime_to_nanoseconds(endTime, &nano); 1148 *elapsedTime = endTime; 1149 } 1150 1151 return (UInt32)(nano / NSEC_PER_MSEC); 1152 } 1153 1154 //****************************************************************************** 1155 1156 static int 1157 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS 1158 { 1159 struct timeval *swt = (struct timeval *)arg1; 1160 struct proc *p = req->p; 1161 1162 if (p == kernproc) { 1163 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL); 1164 } else if (proc_is64bit(p)) { 1165 struct user64_timeval t = {}; 1166 t.tv_sec = swt->tv_sec; 1167 t.tv_usec = swt->tv_usec; 1168 return sysctl_io_opaque(req, &t, sizeof(t), NULL); 1169 } else { 1170 struct user32_timeval t = {}; 1171 t.tv_sec = (typeof(t.tv_sec))swt->tv_sec; 1172 t.tv_usec = swt->tv_usec; 1173 return sysctl_io_opaque(req, &t, sizeof(t), NULL); 1174 } 1175 } 1176 1177 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime, 1178 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1179 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", ""); 1180 1181 static SYSCTL_PROC(_kern, OID_AUTO, waketime, 1182 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1183 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", ""); 1184 1185 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, ""); 1186 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, ""); 1187 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, ""); 1188 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, ""); 1189 1190 static int 1191 sysctl_willshutdown 1192 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 1193 { 1194 int new_value, changed; 1195 int error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed); 1196 if (changed) { 1197 if (!gWillShutdown && (new_value == 1)) { 1198 IOPMRootDomainWillShutdown(); 1199 } else { 1200 error = EINVAL; 1201 } 1202 } 1203 return error; 1204 } 1205 1206 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown, 1207 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1208 NULL, 0, sysctl_willshutdown, "I", ""); 1209 1210 extern struct sysctl_oid sysctl__kern_iokittest; 1211 extern struct sysctl_oid sysctl__debug_iokit; 1212 1213 #if defined(XNU_TARGET_OS_OSX) 1214 1215 static int 1216 sysctl_progressmeterenable 1217 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 1218 { 1219 int error; 1220 int new_value, changed; 1221 1222 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed); 1223 1224 if (changed) { 1225 vc_enable_progressmeter(new_value); 1226 } 1227 1228 return error; 1229 } 1230 1231 static int 1232 sysctl_progressmeter 1233 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 1234 { 1235 int error; 1236 int new_value, changed; 1237 1238 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed); 1239 1240 if (changed) { 1241 vc_set_progressmeter(new_value); 1242 } 1243 1244 return error; 1245 } 1246 1247 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable, 1248 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1249 NULL, 0, sysctl_progressmeterenable, "I", ""); 1250 1251 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter, 1252 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1253 NULL, 0, sysctl_progressmeter, "I", ""); 1254 1255 #endif /* defined(XNU_TARGET_OS_OSX) */ 1256 1257 1258 1259 static int 1260 sysctl_consoleoptions 1261 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 1262 { 1263 int error, changed; 1264 uint32_t new_value; 1265 1266 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed); 1267 1268 if (changed) { 1269 vc_user_options.options = new_value; 1270 } 1271 1272 return error; 1273 } 1274 1275 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions, 1276 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1277 NULL, 0, sysctl_consoleoptions, "I", ""); 1278 1279 1280 static int 1281 sysctl_progressoptions SYSCTL_HANDLER_ARGS 1282 { 1283 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL); 1284 } 1285 1286 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions, 1287 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, 1288 NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", ""); 1289 1290 1291 static int 1292 sysctl_wakereason SYSCTL_HANDLER_ARGS 1293 { 1294 char wr[sizeof(gWakeReasonString)]; 1295 1296 wr[0] = '\0'; 1297 if (gRootDomain) { 1298 gRootDomain->copyWakeReasonString(wr, sizeof(wr)); 1299 } 1300 1301 return sysctl_io_string(req, wr, 0, 0, NULL); 1302 } 1303 1304 SYSCTL_PROC(_kern, OID_AUTO, wakereason, 1305 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1306 NULL, 0, sysctl_wakereason, "A", "wakereason"); 1307 1308 SYSCTL_STRING(_kern, OID_AUTO, bootreason, 1309 CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1310 gBootReasonString, sizeof(gBootReasonString), ""); 1311 1312 static int 1313 sysctl_shutdownreason SYSCTL_HANDLER_ARGS 1314 { 1315 char sr[sizeof(gShutdownReasonString)]; 1316 1317 sr[0] = '\0'; 1318 if (gRootDomain) { 1319 gRootDomain->copyShutdownReasonString(sr, sizeof(sr)); 1320 } 1321 1322 return sysctl_io_string(req, sr, 0, 0, NULL); 1323 } 1324 1325 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason, 1326 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1327 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason"); 1328 1329 static int 1330 sysctl_targettype SYSCTL_HANDLER_ARGS 1331 { 1332 IOService * root; 1333 OSSharedPtr<OSObject> obj; 1334 OSData * data; 1335 char tt[32]; 1336 1337 tt[0] = '\0'; 1338 root = IOService::getServiceRoot(); 1339 if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) { 1340 if ((data = OSDynamicCast(OSData, obj.get()))) { 1341 strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt)); 1342 } 1343 } 1344 return sysctl_io_string(req, tt, 0, 0, NULL); 1345 } 1346 1347 SYSCTL_PROC(_hw, OID_AUTO, targettype, 1348 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1349 NULL, 0, sysctl_targettype, "A", "targettype"); 1350 1351 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, ""); 1352 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, ""); 1353 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, ""); 1354 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, ""); 1355 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, ""); 1356 #if DEVELOPMENT || DEBUG 1357 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, ""); 1358 #if defined(XNU_TARGET_OS_OSX) 1359 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, ""); 1360 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, ""); 1361 #endif /* defined(XNU_TARGET_OS_OSX) */ 1362 #endif /* DEVELOPMENT || DEBUG */ 1363 1364 //****************************************************************************** 1365 // AOT 1366 1367 static int 1368 sysctl_aotmetrics SYSCTL_HANDLER_ARGS 1369 { 1370 if (NULL == gRootDomain) { 1371 return ENOENT; 1372 } 1373 if (NULL == gRootDomain->_aotMetrics) { 1374 return ENOENT; 1375 } 1376 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL); 1377 } 1378 1379 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics, 1380 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, 1381 NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", ""); 1382 1383 1384 static int 1385 update_aotmode(uint32_t mode) 1386 { 1387 int result; 1388 1389 if (!gIOPMWorkLoop) { 1390 return ENOENT; 1391 } 1392 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) { 1393 unsigned int oldCount; 1394 1395 if (mode && !gRootDomain->_aotMetrics) { 1396 gRootDomain->_aotMetrics = IONewZero(IOPMAOTMetrics, 1); 1397 if (!gRootDomain->_aotMetrics) { 1398 return ENOMEM; 1399 } 1400 } 1401 1402 oldCount = gRootDomain->idleSleepPreventersCount(); 1403 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask); 1404 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount); 1405 return 0; 1406 }); 1407 return result; 1408 } 1409 1410 static int 1411 sysctl_aotmodebits 1412 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 1413 { 1414 int error, changed; 1415 uint32_t new_value; 1416 1417 if (NULL == gRootDomain) { 1418 return ENOENT; 1419 } 1420 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed); 1421 if (changed && gIOPMWorkLoop) { 1422 error = update_aotmode(new_value); 1423 } 1424 1425 return error; 1426 } 1427 1428 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits, 1429 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 1430 NULL, 0, sysctl_aotmodebits, "I", ""); 1431 1432 static int 1433 sysctl_aotmode 1434 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 1435 { 1436 int error, changed; 1437 uint32_t new_value; 1438 1439 if (NULL == gRootDomain) { 1440 return ENOENT; 1441 } 1442 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed); 1443 if (changed && gIOPMWorkLoop) { 1444 if (new_value) { 1445 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers; 1446 } 1447 error = update_aotmode(new_value); 1448 } 1449 1450 return error; 1451 } 1452 1453 static SYSCTL_PROC(_kern, OID_AUTO, aotmode, 1454 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, 1455 NULL, 0, sysctl_aotmode, "I", ""); 1456 1457 //****************************************************************************** 1458 1459 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey; 1460 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey; 1461 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey; 1462 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey; 1463 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey; 1464 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey; 1465 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey; 1466 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey; 1467 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey; 1468 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey; 1469 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey; 1470 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey; 1471 1472 //****************************************************************************** 1473 // start 1474 // 1475 //****************************************************************************** 1476 1477 #define kRootDomainSettingsCount 20 1478 #define kRootDomainNoPublishSettingsCount 4 1479 1480 bool 1481 IOPMrootDomain::start( IOService * nub ) 1482 { 1483 OSSharedPtr<OSIterator> psIterator; 1484 OSSharedPtr<OSDictionary> tmpDict; 1485 1486 super::start(nub); 1487 1488 gRootDomain = this; 1489 gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey); 1490 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey); 1491 gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey); 1492 gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey); 1493 gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey); 1494 gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey); 1495 gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey); 1496 gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey); 1497 gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey); 1498 gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey); 1499 gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey); 1500 gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey); 1501 1502 gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut); 1503 gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel); 1504 gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow); 1505 gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt); 1506 gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow); 1507 1508 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported"); 1509 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage"); 1510 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser); 1511 1512 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] = 1513 { 1514 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey), 1515 gIOPMSettingAutoWakeSecondsKey, 1516 gIOPMSettingAutoPowerSecondsKey, 1517 gIOPMSettingAutoWakeCalendarKey, 1518 gIOPMSettingAutoPowerCalendarKey, 1519 gIOPMSettingDebugWakeRelativeKey, 1520 gIOPMSettingDebugPowerRelativeKey, 1521 OSSymbol::withCString(kIOPMSettingWakeOnRingKey), 1522 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey), 1523 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey), 1524 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey), 1525 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey), 1526 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey), 1527 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey), 1528 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey), 1529 OSSymbol::withCString(kIOPMStateConsoleShutdown), 1530 OSSymbol::withCString(kIOPMSettingProModeControl), 1531 OSSymbol::withCString(kIOPMSettingProModeDefer), 1532 gIOPMSettingSilentRunningKey, 1533 gIOPMSettingLowLatencyAudioModeKey, 1534 }; 1535 1536 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] = 1537 { 1538 OSSymbol::withCString(kIOPMSettingProModeControl), 1539 OSSymbol::withCString(kIOPMSettingProModeDefer), 1540 gIOPMSettingSilentRunningKey, 1541 gIOPMSettingLowLatencyAudioModeKey, 1542 }; 1543 1544 #if DEVELOPMENT || DEBUG 1545 #if defined(XNU_TARGET_OS_OSX) 1546 PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags)); 1547 PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags)); 1548 #endif /* defined(XNU_TARGET_OS_OSX) */ 1549 #endif /* DEVELOPMENT || DEBUG */ 1550 1551 PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag)); 1552 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout)); 1553 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout)); 1554 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout)); 1555 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic)); 1556 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog)); 1557 1558 queue_init(&aggressivesQueue); 1559 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this); 1560 aggressivesData = OSData::withCapacity( 1561 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4)); 1562 1563 featuresDictLock = IOLockAlloc(); 1564 settingsCtrlLock = IOLockAlloc(); 1565 wakeEventLock = IOLockAlloc(); 1566 gHaltLogLock = IOLockAlloc(); 1567 setPMRootDomain(this); 1568 1569 extraSleepTimer = thread_call_allocate( 1570 idleSleepTimerExpired, 1571 (thread_call_param_t) this); 1572 1573 powerButtonDown = thread_call_allocate( 1574 powerButtonDownCallout, 1575 (thread_call_param_t) this); 1576 1577 powerButtonUp = thread_call_allocate( 1578 powerButtonUpCallout, 1579 (thread_call_param_t) this); 1580 1581 diskSyncCalloutEntry = thread_call_allocate( 1582 &disk_sync_callout, 1583 (thread_call_param_t) this); 1584 updateConsoleUsersEntry = thread_call_allocate( 1585 &updateConsoleUsersCallout, 1586 (thread_call_param_t) this); 1587 1588 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 1589 fullWakeThreadCall = thread_call_allocate_with_options( 1590 OSMemberFunctionCast(thread_call_func_t, this, 1591 &IOPMrootDomain::fullWakeDelayedWork), 1592 (thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL, 1593 THREAD_CALL_OPTIONS_ONCE); 1594 #endif 1595 1596 setProperty(kIOSleepSupportedKey, true); 1597 1598 bzero(&gPMStats, sizeof(gPMStats)); 1599 1600 pmTracer = PMTraceWorker::tracer(this); 1601 1602 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this); 1603 1604 userDisabledAllSleep = false; 1605 systemBooting = true; 1606 idleSleepEnabled = false; 1607 sleepSlider = 0; 1608 idleSleepTimerPending = false; 1609 wrangler = NULL; 1610 clamshellClosed = false; 1611 clamshellExists = false; 1612 #if DISPLAY_WRANGLER_PRESENT 1613 clamshellDisabled = true; 1614 #else 1615 clamshellDisabled = false; 1616 #endif 1617 clamshellIgnoreClose = false; 1618 acAdaptorConnected = true; 1619 clamshellSleepDisableMask = 0; 1620 gWakeReasonString[0] = '\0'; 1621 1622 // Initialize to user active. 1623 // Will never transition to user inactive w/o wrangler. 1624 fullWakeReason = kFullWakeReasonLocalUser; 1625 userIsActive = userWasActive = true; 1626 clock_get_uptime(&gUserActiveAbsTime); 1627 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue); 1628 1629 // Set the default system capabilities at boot. 1630 _currentCapability = kIOPMSystemCapabilityCPU | 1631 kIOPMSystemCapabilityGraphics | 1632 kIOPMSystemCapabilityAudio | 1633 kIOPMSystemCapabilityNetwork; 1634 1635 _pendingCapability = _currentCapability; 1636 _desiredCapability = _currentCapability; 1637 _highestCapability = _currentCapability; 1638 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64); 1639 1640 queuedSleepWakeUUIDString = NULL; 1641 initializeBootSessionUUID(); 1642 pmStatsAppResponses = OSArray::withCapacity(5); 1643 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey); 1644 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey); 1645 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey); 1646 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey); 1647 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey); 1648 _statsPowerCapsKey = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey); 1649 assertOnWakeSecs = -1;// Invalid value to prevent updates 1650 1651 pmStatsLock = IOLockAlloc(); 1652 idxPMCPUClamshell = kCPUUnknownIndex; 1653 idxPMCPULimitedPower = kCPUUnknownIndex; 1654 1655 tmpDict = OSDictionary::withCapacity(1); 1656 setProperty(kRootDomainSupportedFeatures, tmpDict.get()); 1657 1658 // Set a default "SystemPowerProfileOverrideDict" for platform 1659 // drivers without any overrides. 1660 if (!propertyExists(kIOPMSystemDefaultOverrideKey)) { 1661 tmpDict = OSDictionary::withCapacity(1); 1662 setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get()); 1663 } 1664 1665 settingsCallbacks = OSDictionary::withCapacity(1); 1666 1667 // Create a list of the valid PM settings that we'll relay to 1668 // interested clients in setProperties() => setPMSetting() 1669 allowedPMSettings = OSArray::withObjects( 1670 (const OSObject **)settingsArr, 1671 kRootDomainSettingsCount, 1672 0); 1673 1674 // List of PM settings that should not automatically publish itself 1675 // as a feature when registered by a listener. 1676 noPublishPMSettings = OSArray::withObjects( 1677 (const OSObject **)noPublishSettingsArr, 1678 kRootDomainNoPublishSettingsCount, 1679 0); 1680 1681 fPMSettingsDict = OSDictionary::withCapacity(5); 1682 preventIdleSleepList = OSSet::withCapacity(8); 1683 preventSystemSleepList = OSSet::withCapacity(2); 1684 1685 PMinit(); // creates gIOPMWorkLoop 1686 gIOPMWorkLoop = getIOPMWorkloop(); 1687 1688 // Create IOPMPowerStateQueue used to queue external power 1689 // events, and to handle those events on the PM work loop. 1690 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue( 1691 this, OSMemberFunctionCast(IOEventSource::Action, this, 1692 &IOPMrootDomain::dispatchPowerEvent)); 1693 gIOPMWorkLoop->addEventSource(pmPowerStateQueue); 1694 1695 _aotMode = 0; 1696 _aotTimerES = IOTimerEventSource::timerEventSource(this, 1697 OSMemberFunctionCast(IOTimerEventSource::Action, 1698 this, &IOPMrootDomain::aotEvaluate)); 1699 gIOPMWorkLoop->addEventSource(_aotTimerES.get()); 1700 1701 // create our power parent 1702 gPatriarch = new IORootParent; 1703 gPatriarch->init(); 1704 gPatriarch->attach(this); 1705 gPatriarch->start(this); 1706 gPatriarch->addPowerChild(this); 1707 1708 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES); 1709 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit); 1710 1711 // install power change handler 1712 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL); 1713 1714 #if DISPLAY_WRANGLER_PRESENT 1715 wranglerIdleSettings = OSDictionary::withCapacity(1); 1716 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32); 1717 1718 if (wranglerIdleSettings && wranglerIdlePeriod) { 1719 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey, 1720 wranglerIdlePeriod.get()); 1721 } 1722 1723 #endif /* DISPLAY_WRANGLER_PRESENT */ 1724 1725 lowLatencyAudioNotifierDict = OSDictionary::withCapacity(2); 1726 lowLatencyAudioNotifyStateSym = OSSymbol::withCString("LowLatencyAudioNotifyState"); 1727 lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp"); 1728 lowLatencyAudioNotifyStateVal = OSNumber::withNumber(0ull, 32); 1729 lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64); 1730 1731 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym && 1732 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) { 1733 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get()); 1734 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get()); 1735 } 1736 1737 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient"); 1738 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get()))); 1739 1740 // IOBacklightDisplay can take a long time to load at boot, or it may 1741 // not load at all if you're booting with clamshell closed. We publish 1742 // 'DisplayDims' here redundantly to get it published early and at all. 1743 OSSharedPtr<OSDictionary> matching; 1744 matching = serviceMatching("IOPMPowerSource"); 1745 psIterator = getMatchingServices(matching.get()); 1746 1747 if (psIterator && psIterator->getNextObject()) { 1748 // There's at least one battery on the system, so we publish 1749 // 'DisplayDims' support for the LCD. 1750 publishFeature("DisplayDims"); 1751 } 1752 1753 // read swd_panic boot-arg 1754 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic)); 1755 sysctl_register_oid(&sysctl__kern_sleeptime); 1756 sysctl_register_oid(&sysctl__kern_waketime); 1757 sysctl_register_oid(&sysctl__kern_willshutdown); 1758 sysctl_register_oid(&sysctl__kern_iokittest); 1759 sysctl_register_oid(&sysctl__debug_iokit); 1760 sysctl_register_oid(&sysctl__hw_targettype); 1761 1762 #if defined(XNU_TARGET_OS_OSX) 1763 sysctl_register_oid(&sysctl__kern_progressmeterenable); 1764 sysctl_register_oid(&sysctl__kern_progressmeter); 1765 sysctl_register_oid(&sysctl__kern_wakereason); 1766 #endif /* defined(XNU_TARGET_OS_OSX) */ 1767 sysctl_register_oid(&sysctl__kern_consoleoptions); 1768 sysctl_register_oid(&sysctl__kern_progressoptions); 1769 1770 sysctl_register_oid(&sysctl__kern_aotmode); 1771 sysctl_register_oid(&sysctl__kern_aotmodebits); 1772 sysctl_register_oid(&sysctl__kern_aotmetrics); 1773 1774 #if HIBERNATION 1775 #if defined(__arm64__) 1776 if (ppl_hib_hibernation_supported()) { 1777 publishFeature(kIOHibernateFeatureKey); 1778 } 1779 #endif /* defined(__arm64__) */ 1780 IOHibernateSystemInit(this); 1781 #endif 1782 1783 registerService(); // let clients find us 1784 1785 return true; 1786 } 1787 1788 //****************************************************************************** 1789 // setProperties 1790 // 1791 // Receive a setProperty call 1792 // The "System Boot" property means the system is completely booted. 1793 //****************************************************************************** 1794 1795 IOReturn 1796 IOPMrootDomain::setProperties( OSObject * props_obj ) 1797 { 1798 IOReturn return_value = kIOReturnSuccess; 1799 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj); 1800 OSBoolean *b = NULL; 1801 OSNumber *n = NULL; 1802 const OSSymbol *key = NULL; 1803 OSObject *obj = NULL; 1804 OSSharedPtr<OSCollectionIterator> iter; 1805 1806 if (!dict) { 1807 return kIOReturnBadArgument; 1808 } 1809 1810 bool clientEntitled = false; 1811 { 1812 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty); 1813 clientEntitled = (obj == kOSBooleanTrue); 1814 } 1815 1816 if (!clientEntitled) { 1817 const char * errorSuffix = NULL; 1818 1819 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root. 1820 // That API can set 6 possible keys that are checked below. 1821 if ((dict->getCount() == 1) && 1822 (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) || 1823 dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) || 1824 dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) || 1825 dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) || 1826 dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) || 1827 dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) { 1828 return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator); 1829 if (return_value != kIOReturnSuccess) { 1830 errorSuffix = "privileged"; 1831 } 1832 } else { 1833 return_value = kIOReturnNotPermitted; 1834 errorSuffix = "entitled"; 1835 } 1836 1837 if (return_value != kIOReturnSuccess) { 1838 OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain); 1839 DLOG("%s failed, process %s is not %s\n", __func__, 1840 procName ? procName->getCStringNoCopy() : "", errorSuffix); 1841 return return_value; 1842 } 1843 } 1844 1845 OSSharedPtr<const OSSymbol> publish_simulated_battery_string = OSSymbol::withCString("SoftwareSimulatedBatteries"); 1846 OSSharedPtr<const OSSymbol> boot_complete_string = OSSymbol::withCString("System Boot Complete"); 1847 OSSharedPtr<const OSSymbol> sys_shutdown_string = OSSymbol::withCString("System Shutdown"); 1848 OSSharedPtr<const OSSymbol> stall_halt_string = OSSymbol::withCString("StallSystemAtHalt"); 1849 OSSharedPtr<const OSSymbol> battery_warning_disabled_string = OSSymbol::withCString("BatteryWarningsDisabled"); 1850 OSSharedPtr<const OSSymbol> idle_seconds_string = OSSymbol::withCString("System Idle Seconds"); 1851 OSSharedPtr<const OSSymbol> sleepdisabled_string = OSSymbol::withCString("SleepDisabled"); 1852 OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string = OSSymbol::withCString(kIOPMSleepWakeUUIDKey); 1853 OSSharedPtr<const OSSymbol> loginwindow_progress_string = OSSymbol::withCString(kIOPMLoginWindowProgressKey); 1854 OSSharedPtr<const OSSymbol> coredisplay_progress_string = OSSymbol::withCString(kIOPMCoreDisplayProgressKey); 1855 OSSharedPtr<const OSSymbol> coregraphics_progress_string = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey); 1856 #if DEBUG || DEVELOPMENT 1857 OSSharedPtr<const OSSymbol> clamshell_close_string = OSSymbol::withCString("IOPMTestClamshellClose"); 1858 OSSharedPtr<const OSSymbol> clamshell_open_string = OSSymbol::withCString("IOPMTestClamshellOpen"); 1859 OSSharedPtr<const OSSymbol> ac_detach_string = OSSymbol::withCString("IOPMTestACDetach"); 1860 OSSharedPtr<const OSSymbol> ac_attach_string = OSSymbol::withCString("IOPMTestACAttach"); 1861 OSSharedPtr<const OSSymbol> desktopmode_set_string = OSSymbol::withCString("IOPMTestDesktopModeSet"); 1862 OSSharedPtr<const OSSymbol> desktopmode_remove_string = OSSymbol::withCString("IOPMTestDesktopModeRemove"); 1863 #endif 1864 1865 #if HIBERNATION 1866 OSSharedPtr<const OSSymbol> hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey); 1867 OSSharedPtr<const OSSymbol> hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey); 1868 OSSharedPtr<const OSSymbol> hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey); 1869 OSSharedPtr<const OSSymbol> hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey); 1870 OSSharedPtr<const OSSymbol> hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey); 1871 OSSharedPtr<const OSSymbol> hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey); 1872 #endif 1873 1874 iter = OSCollectionIterator::withCollection(dict); 1875 if (!iter) { 1876 return_value = kIOReturnNoMemory; 1877 goto exit; 1878 } 1879 1880 while ((key = (const OSSymbol *) iter->getNextObject()) && 1881 (obj = dict->getObject(key))) { 1882 if (key->isEqualTo(publish_simulated_battery_string.get())) { 1883 if (OSDynamicCast(OSBoolean, obj)) { 1884 publishResource(key, kOSBooleanTrue); 1885 } 1886 } else if (key->isEqualTo(idle_seconds_string.get())) { 1887 if ((n = OSDynamicCast(OSNumber, obj))) { 1888 setProperty(key, n); 1889 idleSeconds = n->unsigned32BitValue(); 1890 } 1891 } else if (key->isEqualTo(boot_complete_string.get())) { 1892 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted); 1893 } else if (key->isEqualTo(sys_shutdown_string.get())) { 1894 if ((b = OSDynamicCast(OSBoolean, obj))) { 1895 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b); 1896 } 1897 } else if (key->isEqualTo(battery_warning_disabled_string.get())) { 1898 setProperty(key, obj); 1899 } 1900 #if HIBERNATION 1901 else if (key->isEqualTo(hibernatemode_string.get()) || 1902 key->isEqualTo(hibernatefilemin_string.get()) || 1903 key->isEqualTo(hibernatefilemax_string.get()) || 1904 key->isEqualTo(hibernatefreeratio_string.get()) || 1905 key->isEqualTo(hibernatefreetime_string.get())) { 1906 if ((n = OSDynamicCast(OSNumber, obj))) { 1907 setProperty(key, n); 1908 } 1909 } else if (key->isEqualTo(hibernatefile_string.get())) { 1910 OSString * str = OSDynamicCast(OSString, obj); 1911 if (str) { 1912 setProperty(key, str); 1913 } 1914 } 1915 #endif 1916 else if (key->isEqualTo(sleepdisabled_string.get())) { 1917 if ((b = OSDynamicCast(OSBoolean, obj))) { 1918 setProperty(key, b); 1919 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b); 1920 } 1921 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) { 1922 obj->retain(); 1923 pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj); 1924 } else if (key->isEqualTo(loginwindow_progress_string.get())) { 1925 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) { 1926 uint32_t data = n->unsigned32BitValue(); 1927 pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data); 1928 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data); 1929 } 1930 } else if (key->isEqualTo(coredisplay_progress_string.get())) { 1931 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) { 1932 uint32_t data = n->unsigned32BitValue(); 1933 pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data); 1934 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data); 1935 } 1936 } else if (key->isEqualTo(coregraphics_progress_string.get())) { 1937 if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) { 1938 uint32_t data = n->unsigned32BitValue(); 1939 pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data); 1940 kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data); 1941 } 1942 } else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) || 1943 key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) || 1944 key->isEqualTo(kIOPMAutoPowerOffEnabledKey) || 1945 key->isEqualTo(stall_halt_string.get())) { 1946 if ((b = OSDynamicCast(OSBoolean, obj))) { 1947 setProperty(key, b); 1948 } 1949 } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) || 1950 key->isEqualTo(kIOPMDeepSleepTimerKey) || 1951 key->isEqualTo(kIOPMAutoPowerOffDelayKey) || 1952 key->isEqualTo(kIOPMAutoPowerOffTimerKey)) { 1953 if ((n = OSDynamicCast(OSNumber, obj))) { 1954 setProperty(key, n); 1955 } 1956 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) { 1957 if (kOSBooleanTrue == obj) { 1958 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask); 1959 } else { 1960 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask); 1961 } 1962 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask); 1963 } 1964 #if DEBUG || DEVELOPMENT 1965 else if (key->isEqualTo(clamshell_close_string.get())) { 1966 DLOG("SetProperties: setting clamshell close\n"); 1967 UInt32 msg = kIOPMClamshellClosed; 1968 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg); 1969 } else if (key->isEqualTo(clamshell_open_string.get())) { 1970 DLOG("SetProperties: setting clamshell open\n"); 1971 UInt32 msg = kIOPMClamshellOpened; 1972 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg); 1973 } else if (key->isEqualTo(ac_detach_string.get())) { 1974 DLOG("SetProperties: setting ac detach\n"); 1975 UInt32 msg = kIOPMSetACAdaptorConnected; 1976 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg); 1977 } else if (key->isEqualTo(ac_attach_string.get())) { 1978 DLOG("SetProperties: setting ac attach\n"); 1979 UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue; 1980 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg); 1981 } else if (key->isEqualTo(desktopmode_set_string.get())) { 1982 DLOG("SetProperties: setting desktopmode"); 1983 UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue; 1984 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg); 1985 } else if (key->isEqualTo(desktopmode_remove_string.get())) { 1986 DLOG("SetProperties: removing desktopmode\n"); 1987 UInt32 msg = kIOPMSetDesktopMode; 1988 pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg); 1989 } 1990 #endif 1991 // Relay our allowed PM settings onto our registered PM clients 1992 else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) { 1993 return_value = setPMSetting(key, obj); 1994 if (kIOReturnSuccess != return_value) { 1995 break; 1996 } 1997 } else { 1998 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy()); 1999 } 2000 } 2001 2002 exit: 2003 return return_value; 2004 } 2005 2006 // MARK: - 2007 // MARK: Aggressiveness 2008 2009 //****************************************************************************** 2010 // setAggressiveness 2011 // 2012 // Override IOService::setAggressiveness() 2013 //****************************************************************************** 2014 2015 IOReturn 2016 IOPMrootDomain::setAggressiveness( 2017 unsigned long type, 2018 unsigned long value ) 2019 { 2020 return setAggressiveness( type, value, 0 ); 2021 } 2022 2023 /* 2024 * Private setAggressiveness() with an internal options argument. 2025 */ 2026 IOReturn 2027 IOPMrootDomain::setAggressiveness( 2028 unsigned long type, 2029 unsigned long value, 2030 IOOptionBits options ) 2031 { 2032 AggressivesRequest * entry; 2033 AggressivesRequest * request; 2034 bool found = false; 2035 2036 if ((type > UINT_MAX) || (value > UINT_MAX)) { 2037 return kIOReturnBadArgument; 2038 } 2039 2040 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) { 2041 DLOG("setAggressiveness(%x) %s = %u\n", 2042 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value); 2043 } else { 2044 DEBUG_LOG("setAggressiveness(%x) %s = %u\n", 2045 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value); 2046 } 2047 2048 request = IONew(AggressivesRequest, 1); 2049 if (!request) { 2050 return kIOReturnNoMemory; 2051 } 2052 2053 memset(request, 0, sizeof(*request)); 2054 request->options = options; 2055 request->dataType = kAggressivesRequestTypeRecord; 2056 request->data.record.type = (uint32_t) type; 2057 request->data.record.value = (uint32_t) value; 2058 2059 AGGRESSIVES_LOCK(); 2060 2061 // Update disk quick spindown flag used by getAggressiveness(). 2062 // Never merge requests with quick spindown flags set. 2063 2064 if (options & kAggressivesOptionQuickSpindownEnable) { 2065 gAggressivesState |= kAggressivesStateQuickSpindown; 2066 } else if (options & kAggressivesOptionQuickSpindownDisable) { 2067 gAggressivesState &= ~kAggressivesStateQuickSpindown; 2068 } else { 2069 // Coalesce requests with identical aggressives types. 2070 // Deal with callers that calls us too "aggressively". 2071 2072 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain) 2073 { 2074 if ((entry->dataType == kAggressivesRequestTypeRecord) && 2075 (entry->data.record.type == type) && 2076 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) { 2077 entry->data.record.value = (uint32_t) value; 2078 found = true; 2079 break; 2080 } 2081 } 2082 } 2083 2084 if (!found) { 2085 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain); 2086 } 2087 2088 AGGRESSIVES_UNLOCK(); 2089 2090 if (found) { 2091 IODelete(request, AggressivesRequest, 1); 2092 } 2093 2094 if (options & kAggressivesOptionSynchronous) { 2095 handleAggressivesRequests(); // not truly synchronous 2096 } else { 2097 thread_call_enter(aggressivesThreadCall); 2098 } 2099 2100 return kIOReturnSuccess; 2101 } 2102 2103 //****************************************************************************** 2104 // getAggressiveness 2105 // 2106 // Override IOService::setAggressiveness() 2107 // Fetch the aggressiveness factor with the given type. 2108 //****************************************************************************** 2109 2110 IOReturn 2111 IOPMrootDomain::getAggressiveness( 2112 unsigned long type, 2113 unsigned long * outLevel ) 2114 { 2115 uint32_t value = 0; 2116 int source = 0; 2117 2118 if (!outLevel || (type > UINT_MAX)) { 2119 return kIOReturnBadArgument; 2120 } 2121 2122 AGGRESSIVES_LOCK(); 2123 2124 // Disk quick spindown in effect, report value = 1 2125 2126 if ((gAggressivesState & kAggressivesStateQuickSpindown) && 2127 (type == kPMMinutesToSpinDown)) { 2128 value = kAggressivesMinValue; 2129 source = 1; 2130 } 2131 2132 // Consult the pending request queue. 2133 2134 if (!source) { 2135 AggressivesRequest * entry; 2136 2137 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain) 2138 { 2139 if ((entry->dataType == kAggressivesRequestTypeRecord) && 2140 (entry->data.record.type == type) && 2141 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) { 2142 value = entry->data.record.value; 2143 source = 2; 2144 break; 2145 } 2146 } 2147 } 2148 2149 // Consult the backend records. 2150 2151 if (!source && aggressivesData) { 2152 AggressivesRecord * record; 2153 int i, count; 2154 2155 count = aggressivesData->getLength() / sizeof(AggressivesRecord); 2156 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy(); 2157 2158 for (i = 0; i < count; i++, record++) { 2159 if (record->type == type) { 2160 value = record->value; 2161 source = 3; 2162 break; 2163 } 2164 } 2165 } 2166 2167 AGGRESSIVES_UNLOCK(); 2168 2169 if (source) { 2170 *outLevel = (unsigned long) value; 2171 return kIOReturnSuccess; 2172 } else { 2173 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type); 2174 *outLevel = 0; // default return = 0, driver may not check for error 2175 return kIOReturnInvalid; 2176 } 2177 } 2178 2179 //****************************************************************************** 2180 // joinAggressiveness 2181 // 2182 // Request from IOService to join future aggressiveness broadcasts. 2183 //****************************************************************************** 2184 2185 IOReturn 2186 IOPMrootDomain::joinAggressiveness( 2187 IOService * service ) 2188 { 2189 AggressivesRequest * request; 2190 2191 if (!service || (service == this)) { 2192 return kIOReturnBadArgument; 2193 } 2194 2195 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service)); 2196 2197 request = IONew(AggressivesRequest, 1); 2198 if (!request) { 2199 return kIOReturnNoMemory; 2200 } 2201 2202 memset(request, 0, sizeof(*request)); 2203 request->dataType = kAggressivesRequestTypeService; 2204 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives() 2205 2206 AGGRESSIVES_LOCK(); 2207 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain); 2208 AGGRESSIVES_UNLOCK(); 2209 2210 thread_call_enter(aggressivesThreadCall); 2211 2212 return kIOReturnSuccess; 2213 } 2214 2215 //****************************************************************************** 2216 // handleAggressivesRequests 2217 // 2218 // Backend thread processes all incoming aggressiveness requests in the queue. 2219 //****************************************************************************** 2220 2221 static void 2222 handleAggressivesFunction( 2223 thread_call_param_t param1, 2224 thread_call_param_t param2 ) 2225 { 2226 if (param1) { 2227 ((IOPMrootDomain *) param1)->handleAggressivesRequests(); 2228 } 2229 } 2230 2231 void 2232 IOPMrootDomain::handleAggressivesRequests( void ) 2233 { 2234 AggressivesRecord * start; 2235 AggressivesRecord * record; 2236 AggressivesRequest * request; 2237 queue_head_t joinedQueue; 2238 int i, count; 2239 bool broadcast; 2240 bool found; 2241 bool pingSelf = false; 2242 2243 AGGRESSIVES_LOCK(); 2244 2245 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData || 2246 queue_empty(&aggressivesQueue)) { 2247 goto unlock_done; 2248 } 2249 2250 gAggressivesState |= kAggressivesStateBusy; 2251 count = aggressivesData->getLength() / sizeof(AggressivesRecord); 2252 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy(); 2253 2254 do{ 2255 broadcast = false; 2256 queue_init(&joinedQueue); 2257 2258 do{ 2259 // Remove request from the incoming queue in FIFO order. 2260 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain); 2261 switch (request->dataType) { 2262 case kAggressivesRequestTypeRecord: 2263 // Update existing record if found. 2264 found = false; 2265 for (i = 0, record = start; i < count; i++, record++) { 2266 if (record->type == request->data.record.type) { 2267 found = true; 2268 2269 if (request->options & kAggressivesOptionQuickSpindownEnable) { 2270 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) { 2271 broadcast = true; 2272 record->flags |= (kAggressivesRecordFlagMinValue | 2273 kAggressivesRecordFlagModified); 2274 DLOG("disk spindown accelerated, was %u min\n", 2275 record->value); 2276 } 2277 } else if (request->options & kAggressivesOptionQuickSpindownDisable) { 2278 if (record->flags & kAggressivesRecordFlagMinValue) { 2279 broadcast = true; 2280 record->flags |= kAggressivesRecordFlagModified; 2281 record->flags &= ~kAggressivesRecordFlagMinValue; 2282 DLOG("disk spindown restored to %u min\n", 2283 record->value); 2284 } 2285 } else if (record->value != request->data.record.value) { 2286 record->value = request->data.record.value; 2287 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) { 2288 broadcast = true; 2289 record->flags |= kAggressivesRecordFlagModified; 2290 } 2291 } 2292 break; 2293 } 2294 } 2295 2296 // No matching record, append a new record. 2297 if (!found && 2298 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) { 2299 AggressivesRecord newRecord; 2300 2301 newRecord.flags = kAggressivesRecordFlagModified; 2302 newRecord.type = request->data.record.type; 2303 newRecord.value = request->data.record.value; 2304 if (request->options & kAggressivesOptionQuickSpindownEnable) { 2305 newRecord.flags |= kAggressivesRecordFlagMinValue; 2306 DLOG("disk spindown accelerated\n"); 2307 } 2308 2309 aggressivesData->appendBytes(&newRecord, sizeof(newRecord)); 2310 2311 // OSData may have switched to another (larger) buffer. 2312 count = aggressivesData->getLength() / sizeof(AggressivesRecord); 2313 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy(); 2314 broadcast = true; 2315 } 2316 2317 // Finished processing the request, release it. 2318 IODelete(request, AggressivesRequest, 1); 2319 break; 2320 2321 case kAggressivesRequestTypeService: 2322 // synchronizeAggressives() will free request. 2323 queue_enter(&joinedQueue, request, AggressivesRequest *, chain); 2324 break; 2325 2326 default: 2327 panic("bad aggressives request type %x\n", request->dataType); 2328 break; 2329 } 2330 } while (!queue_empty(&aggressivesQueue)); 2331 2332 // Release the lock to perform work, with busy flag set. 2333 if (!queue_empty(&joinedQueue) || broadcast) { 2334 AGGRESSIVES_UNLOCK(); 2335 if (!queue_empty(&joinedQueue)) { 2336 synchronizeAggressives(&joinedQueue, start, count); 2337 } 2338 if (broadcast) { 2339 broadcastAggressives(start, count); 2340 } 2341 AGGRESSIVES_LOCK(); 2342 } 2343 2344 // Remove the modified flag from all records. 2345 for (i = 0, record = start; i < count; i++, record++) { 2346 if ((record->flags & kAggressivesRecordFlagModified) && 2347 ((record->type == kPMMinutesToDim) || 2348 (record->type == kPMMinutesToSleep))) { 2349 pingSelf = true; 2350 } 2351 2352 record->flags &= ~kAggressivesRecordFlagModified; 2353 } 2354 2355 // Check the incoming queue again since new entries may have been 2356 // added while lock was released above. 2357 } while (!queue_empty(&aggressivesQueue)); 2358 2359 gAggressivesState &= ~kAggressivesStateBusy; 2360 2361 unlock_done: 2362 AGGRESSIVES_UNLOCK(); 2363 2364 // Root domain is interested in system and display sleep slider changes. 2365 // Submit a power event to handle those changes on the PM work loop. 2366 2367 if (pingSelf && pmPowerStateQueue) { 2368 pmPowerStateQueue->submitPowerEvent( 2369 kPowerEventPolicyStimulus, 2370 (void *) kStimulusAggressivenessChanged ); 2371 } 2372 } 2373 2374 //****************************************************************************** 2375 // synchronizeAggressives 2376 // 2377 // Push all known aggressiveness records to one or more IOService. 2378 //****************************************************************************** 2379 2380 void 2381 IOPMrootDomain::synchronizeAggressives( 2382 queue_head_t * joinedQueue, 2383 const AggressivesRecord * array, 2384 int count ) 2385 { 2386 OSSharedPtr<IOService> service; 2387 AggressivesRequest * request; 2388 const AggressivesRecord * record; 2389 IOPMDriverCallEntry callEntry; 2390 uint32_t value; 2391 int i; 2392 2393 while (!queue_empty(joinedQueue)) { 2394 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain); 2395 if (request->dataType == kAggressivesRequestTypeService) { 2396 // retained by joinAggressiveness(), so take ownership 2397 service = os::move(request->data.service); 2398 } else { 2399 service.reset(); 2400 } 2401 2402 IODelete(request, AggressivesRequest, 1); 2403 request = NULL; 2404 2405 if (service) { 2406 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) { 2407 for (i = 0, record = array; i < count; i++, record++) { 2408 value = record->value; 2409 if (record->flags & kAggressivesRecordFlagMinValue) { 2410 value = kAggressivesMinValue; 2411 } 2412 2413 _LOG("synchronizeAggressives 0x%x = %u to %s\n", 2414 record->type, value, service->getName()); 2415 service->setAggressiveness(record->type, value); 2416 } 2417 service->deassertPMDriverCall(&callEntry); 2418 } 2419 } 2420 } 2421 } 2422 2423 //****************************************************************************** 2424 // broadcastAggressives 2425 // 2426 // Traverse PM tree and call setAggressiveness() for records that have changed. 2427 //****************************************************************************** 2428 2429 void 2430 IOPMrootDomain::broadcastAggressives( 2431 const AggressivesRecord * array, 2432 int count ) 2433 { 2434 OSSharedPtr<IORegistryIterator> iter; 2435 IORegistryEntry *entry; 2436 OSSharedPtr<IORegistryEntry> child; 2437 IOPowerConnection *connect; 2438 IOService *service; 2439 const AggressivesRecord *record; 2440 IOPMDriverCallEntry callEntry; 2441 uint32_t value; 2442 int i; 2443 2444 iter = IORegistryIterator::iterateOver( 2445 this, gIOPowerPlane, kIORegistryIterateRecursively); 2446 if (iter) { 2447 do{ 2448 // !! reset the iterator 2449 iter->reset(); 2450 while ((entry = iter->getNextObject())) { 2451 connect = OSDynamicCast(IOPowerConnection, entry); 2452 if (!connect || !connect->getReadyFlag()) { 2453 continue; 2454 } 2455 2456 child = connect->copyChildEntry(gIOPowerPlane); 2457 if (child) { 2458 if ((service = OSDynamicCast(IOService, child.get()))) { 2459 if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) { 2460 for (i = 0, record = array; i < count; i++, record++) { 2461 if (record->flags & kAggressivesRecordFlagModified) { 2462 value = record->value; 2463 if (record->flags & kAggressivesRecordFlagMinValue) { 2464 value = kAggressivesMinValue; 2465 } 2466 _LOG("broadcastAggressives %x = %u to %s\n", 2467 record->type, value, service->getName()); 2468 service->setAggressiveness(record->type, value); 2469 } 2470 } 2471 service->deassertPMDriverCall(&callEntry); 2472 } 2473 } 2474 } 2475 } 2476 }while (!entry && !iter->isValid()); 2477 } 2478 } 2479 2480 //***************************************** 2481 // stackshot on power button press 2482 // *************************************** 2483 static void 2484 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t ) 2485 { 2486 /* Power button pressed during wake 2487 * Take a stackshot 2488 */ 2489 DEBUG_LOG("Powerbutton: down. Taking stackshot\n"); 2490 ((IOPMrootDomain *)us)->takeStackshot(false); 2491 } 2492 2493 static void 2494 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t) 2495 { 2496 /* Power button released. 2497 * Delete any stackshot data 2498 */ 2499 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n"); 2500 ((IOPMrootDomain *)us)->deleteStackshot(); 2501 } 2502 //************************************************************************* 2503 // 2504 2505 // MARK: - 2506 // MARK: System Sleep 2507 2508 //****************************************************************************** 2509 // startIdleSleepTimer 2510 // 2511 //****************************************************************************** 2512 2513 void 2514 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds ) 2515 { 2516 AbsoluteTime deadline; 2517 2518 ASSERT_GATED(); 2519 if (gNoIdleFlag) { 2520 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag); 2521 return; 2522 } 2523 if (inSeconds) { 2524 clock_interval_to_deadline(inSeconds, kSecondScale, &deadline); 2525 thread_call_enter_delayed(extraSleepTimer, deadline); 2526 idleSleepTimerPending = true; 2527 } else { 2528 thread_call_enter(extraSleepTimer); 2529 } 2530 DLOG("idle timer set for %u seconds\n", inSeconds); 2531 } 2532 2533 //****************************************************************************** 2534 // cancelIdleSleepTimer 2535 // 2536 //****************************************************************************** 2537 2538 void 2539 IOPMrootDomain::cancelIdleSleepTimer( void ) 2540 { 2541 ASSERT_GATED(); 2542 if (idleSleepTimerPending) { 2543 DLOG("idle timer cancelled\n"); 2544 thread_call_cancel(extraSleepTimer); 2545 idleSleepTimerPending = false; 2546 2547 if (!assertOnWakeSecs && gIOLastWakeAbsTime) { 2548 AbsoluteTime now; 2549 clock_usec_t microsecs; 2550 clock_get_uptime(&now); 2551 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 2552 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs); 2553 if (assertOnWakeReport) { 2554 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs); 2555 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs); 2556 } 2557 } 2558 } 2559 } 2560 2561 //****************************************************************************** 2562 // idleSleepTimerExpired 2563 // 2564 //****************************************************************************** 2565 2566 static void 2567 idleSleepTimerExpired( 2568 thread_call_param_t us, thread_call_param_t ) 2569 { 2570 ((IOPMrootDomain *)us)->handleSleepTimerExpiration(); 2571 } 2572 2573 //****************************************************************************** 2574 // handleSleepTimerExpiration 2575 // 2576 // The time between the sleep idle timeout and the next longest one has elapsed. 2577 // It's time to sleep. Start that by removing the clamp that's holding us awake. 2578 //****************************************************************************** 2579 2580 void 2581 IOPMrootDomain::handleSleepTimerExpiration( void ) 2582 { 2583 if (!gIOPMWorkLoop->inGate()) { 2584 gIOPMWorkLoop->runAction( 2585 OSMemberFunctionCast(IOWorkLoop::Action, this, 2586 &IOPMrootDomain::handleSleepTimerExpiration), 2587 this); 2588 return; 2589 } 2590 2591 DLOG("sleep timer expired\n"); 2592 ASSERT_GATED(); 2593 2594 idleSleepTimerPending = false; 2595 setQuickSpinDownTimeout(); 2596 adjustPowerState(true); 2597 } 2598 2599 //****************************************************************************** 2600 // getTimeToIdleSleep 2601 // 2602 // Returns number of seconds left before going into idle sleep. 2603 // Caller has to make sure that idle sleep is allowed at the time of calling 2604 // this function 2605 //****************************************************************************** 2606 2607 uint32_t 2608 IOPMrootDomain::getTimeToIdleSleep( void ) 2609 { 2610 AbsoluteTime now, lastActivityTime; 2611 uint64_t nanos; 2612 uint32_t minutesSinceUserInactive = 0; 2613 uint32_t sleepDelay = 0; 2614 2615 if (!idleSleepEnabled) { 2616 return 0xffffffff; 2617 } 2618 2619 if (userActivityTime) { 2620 lastActivityTime = userActivityTime; 2621 } else { 2622 lastActivityTime = userBecameInactiveTime; 2623 } 2624 2625 // Ignore any lastActivityTime that predates the last system wake. 2626 // The goal is to avoid a sudden idle sleep right after a dark wake 2627 // due to sleepDelay=0 computed below. The alternative 60s minimum 2628 // timeout should be large enough to allow dark wake to complete, 2629 // at which point the idle timer will be promptly cancelled. 2630 clock_get_uptime(&now); 2631 if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) && 2632 (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) { 2633 SUB_ABSOLUTETIME(&now, &lastActivityTime); 2634 absolutetime_to_nanoseconds(now, &nanos); 2635 minutesSinceUserInactive = nanos / (60000000000ULL); 2636 2637 if (minutesSinceUserInactive >= sleepSlider) { 2638 sleepDelay = 0; 2639 } else { 2640 sleepDelay = sleepSlider - minutesSinceUserInactive; 2641 } 2642 } else { 2643 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n", 2644 lastActivityTime, now, gIOLastWakeAbsTime); 2645 sleepDelay = sleepSlider; 2646 } 2647 2648 DLOG("user inactive %u min, time to idle sleep %u min\n", 2649 minutesSinceUserInactive, sleepDelay); 2650 2651 return sleepDelay * 60; 2652 } 2653 2654 //****************************************************************************** 2655 // setQuickSpinDownTimeout 2656 // 2657 //****************************************************************************** 2658 2659 void 2660 IOPMrootDomain::setQuickSpinDownTimeout( void ) 2661 { 2662 ASSERT_GATED(); 2663 setAggressiveness( 2664 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable ); 2665 } 2666 2667 //****************************************************************************** 2668 // restoreUserSpinDownTimeout 2669 // 2670 //****************************************************************************** 2671 2672 void 2673 IOPMrootDomain::restoreUserSpinDownTimeout( void ) 2674 { 2675 ASSERT_GATED(); 2676 setAggressiveness( 2677 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable ); 2678 } 2679 2680 //****************************************************************************** 2681 // sleepSystem 2682 // 2683 //****************************************************************************** 2684 2685 /* public */ 2686 IOReturn 2687 IOPMrootDomain::sleepSystem( void ) 2688 { 2689 return sleepSystemOptions(NULL); 2690 } 2691 2692 /* private */ 2693 IOReturn 2694 IOPMrootDomain::sleepSystemOptions( OSDictionary *options ) 2695 { 2696 OSObject *obj = NULL; 2697 OSString *reason = NULL; 2698 /* sleepSystem is a public function, and may be called by any kernel driver. 2699 * And that's bad - drivers should sleep the system by calling 2700 * receivePowerNotification() instead. Drivers should not use sleepSystem. 2701 * 2702 * Note that user space app calls to IOPMSleepSystem() will also travel 2703 * this code path and thus be correctly identified as software sleeps. 2704 */ 2705 2706 if (options && options->getObject("OSSwitch")) { 2707 // Log specific sleep cause for OS Switch hibernation 2708 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate); 2709 } 2710 2711 if (options && (obj = options->getObject("Sleep Reason"))) { 2712 reason = OSDynamicCast(OSString, obj); 2713 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) { 2714 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency); 2715 } 2716 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) { 2717 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit); 2718 } 2719 } 2720 2721 return privateSleepSystem( kIOPMSleepReasonSoftware); 2722 } 2723 2724 /* private */ 2725 IOReturn 2726 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason ) 2727 { 2728 /* Called from both gated and non-gated context */ 2729 2730 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) { 2731 return kIOReturnNotPermitted; 2732 } 2733 2734 pmPowerStateQueue->submitPowerEvent( 2735 kPowerEventPolicyStimulus, 2736 (void *) kStimulusDemandSystemSleep, 2737 sleepReason); 2738 2739 return kIOReturnSuccess; 2740 } 2741 2742 //****************************************************************************** 2743 // powerChangeDone 2744 // 2745 // This overrides powerChangeDone in IOService. 2746 //****************************************************************************** 2747 void 2748 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState ) 2749 { 2750 #if !__i386__ && !__x86_64__ 2751 uint64_t timeSinceReset = 0; 2752 #endif 2753 uint64_t now; 2754 unsigned long newState; 2755 clock_sec_t secs; 2756 clock_usec_t microsecs; 2757 uint32_t lastDebugWakeSeconds; 2758 clock_sec_t adjWakeTime; 2759 IOPMCalendarStruct nowCalendar; 2760 2761 ASSERT_GATED(); 2762 newState = getPowerState(); 2763 DLOG("PowerChangeDone: %s->%s\n", 2764 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState())); 2765 2766 if (previousPowerState == newState) { 2767 return; 2768 } 2769 2770 notifierThread = current_thread(); 2771 switch (getPowerState()) { 2772 case SLEEP_STATE: { 2773 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) { 2774 secs = 0; 2775 microsecs = 0; 2776 PEGetUTCTimeOfDay(&secs, µsecs); 2777 2778 adjWakeTime = 0; 2779 if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) { 2780 IOLog("use _calendarWakeAlarmUTC\n"); 2781 adjWakeTime = _calendarWakeAlarmUTC; 2782 } else if (_aotExit || (kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) { 2783 IOLog("accelerate _aotWakeTime for exit\n"); 2784 adjWakeTime = secs; 2785 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) { 2786 IOLog("accelerate _aotWakeTime for assertion\n"); 2787 adjWakeTime = secs; 2788 } 2789 if (adjWakeTime) { 2790 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar); 2791 } 2792 2793 IOPMConvertSecondsToCalendar(secs, &nowCalendar); 2794 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar)); 2795 2796 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar); 2797 assert(kIOReturnSuccess == ret); 2798 } 2799 if (_aotLastWakeTime) { 2800 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime; 2801 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) { 2802 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0], 2803 gWakeReasonString, 2804 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount])); 2805 } 2806 } 2807 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags; 2808 if (_aotTimerScheduled) { 2809 _aotTimerES->cancelTimeout(); 2810 _aotTimerScheduled = false; 2811 } 2812 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable); 2813 2814 // re-enable this timer for next sleep 2815 cancelIdleSleepTimer(); 2816 2817 if (clamshellExists) { 2818 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 2819 if (gClamshellFlags & kClamshell_WAR_58009435) { 2820 // Disable clamshell sleep until system has completed full wake. 2821 // This prevents a system sleep request (due to a clamshell close) 2822 // from being queued until the end of system full wake - even if 2823 // other clamshell disable bits outside of our control is wrong. 2824 setClamShellSleepDisable(true, kClamshellSleepDisableInternal); 2825 } 2826 #endif 2827 2828 // Log the last known clamshell state before system sleep 2829 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 2830 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, 2831 desktopMode, acAdaptorConnected); 2832 } 2833 2834 clock_get_calendar_absolute_and_microtime(&secs, µsecs, &now); 2835 logtime(secs); 2836 gIOLastSleepTime.tv_sec = secs; 2837 gIOLastSleepTime.tv_usec = microsecs; 2838 if (!_aotLastWakeTime) { 2839 gIOLastUserSleepTime = gIOLastSleepTime; 2840 } 2841 2842 gIOLastWakeTime.tv_sec = 0; 2843 gIOLastWakeTime.tv_usec = 0; 2844 gIOLastSleepAbsTime = now; 2845 2846 if (wake2DarkwakeDelay && sleepDelaysReport) { 2847 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs; 2848 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition 2849 2850 SUB_ABSOLUTETIME(&now, &ts_sleepStart); 2851 absolutetime_to_microtime(now, &darkwake2SleepSecs, µsecs); 2852 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, µsecs); 2853 HISTREPORT_TALLYVALUE(sleepDelaysReport, 2854 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs)); 2855 2856 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs); 2857 wake2DarkwakeDelay = 0; 2858 } 2859 #if HIBERNATION 2860 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : ""); 2861 2862 IOHibernateSystemHasSlept(); 2863 2864 evaluateSystemSleepPolicyFinal(); 2865 #else 2866 LOG("System Sleep\n"); 2867 #endif 2868 if (thermalWarningState) { 2869 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey); 2870 if (event) { 2871 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown); 2872 } 2873 } 2874 assertOnWakeSecs = 0; 2875 lowBatteryCondition = false; 2876 thermalEmergencyState = false; 2877 2878 #if DEVELOPMENT || DEBUG 2879 extern int g_should_log_clock_adjustments; 2880 if (g_should_log_clock_adjustments) { 2881 clock_sec_t secs = 0; 2882 clock_usec_t microsecs = 0; 2883 uint64_t now_b = mach_absolute_time(); 2884 2885 secs = 0; 2886 microsecs = 0; 2887 PEGetUTCTimeOfDay(&secs, µsecs); 2888 2889 uint64_t now_a = mach_absolute_time(); 2890 os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n", 2891 __func__, (unsigned long)secs, microsecs, now_b, now_a); 2892 } 2893 #endif 2894 2895 getPlatform()->sleepKernel(); 2896 2897 // The CPU(s) are off at this point, 2898 // Code will resume execution here upon wake. 2899 2900 clock_get_uptime(&gIOLastWakeAbsTime); 2901 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime); 2902 _highestCapability = 0; 2903 2904 #if HIBERNATION 2905 IOHibernateSystemWake(); 2906 #endif 2907 2908 // sleep transition complete 2909 gSleepOrShutdownPending = 0; 2910 2911 // trip the reset of the calendar clock 2912 clock_wakeup_calendar(); 2913 clock_get_calendar_microtime(&secs, µsecs); 2914 gIOLastWakeTime.tv_sec = secs; 2915 gIOLastWakeTime.tv_usec = microsecs; 2916 2917 // aot 2918 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) { 2919 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid; 2920 secs = 0; 2921 microsecs = 0; 2922 PEGetUTCTimeOfDay(&secs, µsecs); 2923 IOPMConvertSecondsToCalendar(secs, &nowCalendar); 2924 IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar)); 2925 _aotMetrics->sleepCount++; 2926 _aotLastWakeTime = gIOLastWakeAbsTime; 2927 if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) { 2928 _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1] 2929 = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000); 2930 _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1] 2931 = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000); 2932 } 2933 2934 if (_aotTestTime) { 2935 if (_aotWakeTimeUTC <= secs) { 2936 _aotTestTime = _aotTestTime + _aotTestInterval; 2937 } 2938 setWakeTime(_aotTestTime); 2939 } 2940 } 2941 2942 #if HIBERNATION 2943 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : ""); 2944 #endif 2945 2946 lastSleepReason = 0; 2947 2948 lastDebugWakeSeconds = _debugWakeSeconds; 2949 _debugWakeSeconds = 0; 2950 _scheduledAlarmMask = 0; 2951 _nextScheduledAlarmType = NULL; 2952 2953 darkWakeExit = false; 2954 darkWakePowerClamped = false; 2955 darkWakePostTickle = false; 2956 darkWakeHibernateError = false; 2957 darkWakeToSleepASAP = true; 2958 darkWakeLogClamp = true; 2959 sleepTimerMaintenance = false; 2960 sleepToStandby = false; 2961 wranglerTickled = false; 2962 userWasActive = false; 2963 isRTCAlarmWake = false; 2964 clamshellIgnoreClose = false; 2965 fullWakeReason = kFullWakeReasonNone; 2966 2967 #if defined(__i386__) || defined(__x86_64__) 2968 kdebugTrace(kPMLogSystemWake, 0, 0, 0); 2969 2970 OSSharedPtr<OSObject> wakeTypeProp = copyProperty(kIOPMRootDomainWakeTypeKey); 2971 OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey); 2972 OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get()); 2973 OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get()); 2974 2975 if (wakeReason && (wakeReason->getLength() >= 2) && 2976 gWakeReasonString[0] == '\0') { 2977 WAKEEVENT_LOCK(); 2978 // Until the platform driver can claim its wake reasons 2979 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(), 2980 sizeof(gWakeReasonString)); 2981 WAKEEVENT_UNLOCK(); 2982 } 2983 2984 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) { 2985 lowBatteryCondition = true; 2986 darkWakeMaintenance = true; 2987 } else { 2988 #if HIBERNATION 2989 OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey); 2990 OSNumber * hibOptions = OSDynamicCast( OSNumber, hibOptionsProp.get()); 2991 if (hibernateAborted || ((hibOptions && 2992 !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) { 2993 // Hibernate aborted, or EFI brought up graphics 2994 darkWakeExit = true; 2995 if (hibernateAborted) { 2996 DLOG("Hibernation aborted\n"); 2997 } else { 2998 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue()); 2999 } 3000 } else 3001 #endif 3002 if (wakeType && ( 3003 wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) || 3004 wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) { 3005 // User wake or RTC alarm 3006 darkWakeExit = true; 3007 if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) { 3008 isRTCAlarmWake = true; 3009 } 3010 } else if (wakeType && 3011 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) { 3012 // SMC standby timer trumps SleepX 3013 darkWakeMaintenance = true; 3014 sleepTimerMaintenance = true; 3015 } else if ((lastDebugWakeSeconds != 0) && 3016 ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) { 3017 // SleepX before maintenance 3018 darkWakeExit = true; 3019 } else if (wakeType && 3020 wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) { 3021 darkWakeMaintenance = true; 3022 } else if (wakeType && 3023 wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) { 3024 darkWakeMaintenance = true; 3025 darkWakeSleepService = true; 3026 #if HIBERNATION 3027 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) { 3028 sleepToStandby = true; 3029 } 3030 #endif 3031 } else if (wakeType && 3032 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) { 3033 darkWakeMaintenance = true; 3034 darkWakeHibernateError = true; 3035 } else { 3036 // Unidentified wake source, resume to full wake if debug 3037 // alarm is pending. 3038 3039 if (lastDebugWakeSeconds && 3040 (!wakeReason || wakeReason->isEqualTo(""))) { 3041 darkWakeExit = true; 3042 } 3043 } 3044 } 3045 3046 if (darkWakeExit) { 3047 darkWakeToSleepASAP = false; 3048 fullWakeReason = kFullWakeReasonLocalUser; 3049 reportUserInput(); 3050 } else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) { 3051 handleSetDisplayPowerOn(true); 3052 } else if (!darkWakeMaintenance) { 3053 // Early/late tickle for non-maintenance wake. 3054 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) { 3055 darkWakePostTickle = true; 3056 } 3057 } 3058 #else /* !__i386__ && !__x86_64__ */ 3059 timeSinceReset = ml_get_time_since_reset(); 3060 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset); 3061 3062 if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) { 3063 wranglerTickled = true; 3064 fullWakeReason = kFullWakeReasonLocalUser; 3065 requestUserActive(this, "Full wake on dark wake promotion boot-arg"); 3066 } else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) { 3067 isRTCAlarmWake = true; 3068 fullWakeReason = kFullWakeReasonLocalUser; 3069 requestUserActive(this, "RTC debug alarm"); 3070 } 3071 3072 // stay awake for at least 30 seconds 3073 startIdleSleepTimer(30); 3074 #endif 3075 sleepCnt++; 3076 3077 thread_call_enter(updateConsoleUsersEntry); 3078 3079 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake); 3080 break; 3081 } 3082 #if !__i386__ && !__x86_64__ 3083 case ON_STATE: 3084 case AOT_STATE: 3085 { 3086 DLOG("Force re-evaluating aggressiveness\n"); 3087 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */ 3088 pmPowerStateQueue->submitPowerEvent( 3089 kPowerEventPolicyStimulus, 3090 (void *) kStimulusNoIdleSleepPreventers ); 3091 3092 // After changing to ON_STATE, invalidate any previously queued 3093 // request to change to a state less than ON_STATE. This isn't 3094 // necessary for AOT_STATE or if the device has only one running 3095 // state since the changePowerStateToPriv() issued at the tail 3096 // end of SLEEP_STATE case should take care of that. 3097 if (getPowerState() == ON_STATE) { 3098 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake); 3099 } 3100 break; 3101 } 3102 #endif /* !__i386__ && !__x86_64__ */ 3103 } 3104 notifierThread = NULL; 3105 } 3106 3107 //****************************************************************************** 3108 // requestPowerDomainState 3109 // 3110 // Extend implementation in IOService. Running on PM work loop thread. 3111 //****************************************************************************** 3112 3113 IOReturn 3114 IOPMrootDomain::requestPowerDomainState( 3115 IOPMPowerFlags childDesire, 3116 IOPowerConnection * childConnection, 3117 unsigned long specification ) 3118 { 3119 // Idle and system sleep prevention flags affects driver desire. 3120 // Children desire are irrelevant so they are cleared. 3121 3122 return super::requestPowerDomainState(0, childConnection, specification); 3123 } 3124 3125 3126 static void 3127 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size) 3128 { 3129 if (!preventers->getCount()) { 3130 return; 3131 } 3132 3133 char *buf_iter = buf + strlen(buf); 3134 char *buf_end = buf + buf_size; 3135 3136 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get()); 3137 OSObject *obj = NULL; 3138 3139 while ((obj = iterator->getNextObject())) { 3140 IOService *srv = OSDynamicCast(IOService, obj); 3141 if (buf_iter < buf_end) { 3142 buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName()); 3143 } else { 3144 DLOG("Print buffer exhausted for sleep preventers list\n"); 3145 break; 3146 } 3147 } 3148 } 3149 3150 //****************************************************************************** 3151 // updatePreventIdleSleepList 3152 // 3153 // Called by IOService on PM work loop. 3154 // Returns true if PM policy recognized the driver's desire to prevent idle 3155 // sleep and updated the list of idle sleep preventers. Returns false otherwise 3156 //****************************************************************************** 3157 3158 bool 3159 IOPMrootDomain::updatePreventIdleSleepList( 3160 IOService * service, bool addNotRemove) 3161 { 3162 unsigned int oldCount; 3163 3164 oldCount = idleSleepPreventersCount(); 3165 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount); 3166 } 3167 3168 bool 3169 IOPMrootDomain::updatePreventIdleSleepListInternal( 3170 IOService * service, bool addNotRemove, unsigned int oldCount) 3171 { 3172 unsigned int newCount; 3173 3174 ASSERT_GATED(); 3175 3176 #if defined(XNU_TARGET_OS_OSX) 3177 // Only the display wrangler and no-idle-sleep kernel assertions 3178 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag 3179 // reported by drivers in their power state table is ignored. 3180 if (service && (service != wrangler) && (service != this)) { 3181 return false; 3182 } 3183 #endif 3184 3185 if (service) { 3186 if (addNotRemove) { 3187 preventIdleSleepList->setObject(service); 3188 DLOG("Added %s to idle sleep preventers list (Total %u)\n", 3189 service->getName(), preventIdleSleepList->getCount()); 3190 } else if (preventIdleSleepList->member(service)) { 3191 preventIdleSleepList->removeObject(service); 3192 DLOG("Removed %s from idle sleep preventers list (Total %u)\n", 3193 service->getName(), preventIdleSleepList->getCount()); 3194 } 3195 3196 if (preventIdleSleepList->getCount()) { 3197 char buf[256] = "Idle Sleep Preventers:"; 3198 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf)); 3199 DLOG("%s\n", buf); 3200 } 3201 } 3202 3203 newCount = idleSleepPreventersCount(); 3204 3205 if ((oldCount == 0) && (newCount != 0)) { 3206 // Driver added to empty prevent list. 3207 // Update the driver desire to prevent idle sleep. 3208 // Driver desire does not prevent demand sleep. 3209 3210 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent); 3211 } else if ((oldCount != 0) && (newCount == 0)) { 3212 // Last driver removed from prevent list. 3213 // Drop the driver clamp to allow idle sleep. 3214 3215 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow); 3216 evaluatePolicy( kStimulusNoIdleSleepPreventers ); 3217 } 3218 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(), 3219 &newCount, sizeof(newCount)); 3220 3221 #if defined(XNU_TARGET_OS_OSX) 3222 if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) { 3223 DLOG("Cannot cancel idle sleep\n"); 3224 return false; // do not idle-cancel 3225 } 3226 #endif 3227 3228 return true; 3229 } 3230 3231 //****************************************************************************** 3232 // startSpinDump 3233 //****************************************************************************** 3234 3235 void 3236 IOPMrootDomain::startSpinDump(uint32_t spindumpKind) 3237 { 3238 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind); 3239 } 3240 3241 //****************************************************************************** 3242 // preventSystemSleepListUpdate 3243 // 3244 // Called by IOService on PM work loop. 3245 //****************************************************************************** 3246 3247 void 3248 IOPMrootDomain::updatePreventSystemSleepList( 3249 IOService * service, bool addNotRemove ) 3250 { 3251 unsigned int oldCount, newCount; 3252 3253 ASSERT_GATED(); 3254 if (this == service) { 3255 return; 3256 } 3257 3258 oldCount = preventSystemSleepList->getCount(); 3259 if (addNotRemove) { 3260 preventSystemSleepList->setObject(service); 3261 DLOG("Added %s to system sleep preventers list (Total %u)\n", 3262 service->getName(), preventSystemSleepList->getCount()); 3263 if (!assertOnWakeSecs && gIOLastWakeAbsTime) { 3264 AbsoluteTime now; 3265 clock_usec_t microsecs; 3266 clock_get_uptime(&now); 3267 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 3268 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs); 3269 if (assertOnWakeReport) { 3270 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs); 3271 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs); 3272 } 3273 } 3274 } else if (preventSystemSleepList->member(service)) { 3275 preventSystemSleepList->removeObject(service); 3276 DLOG("Removed %s from system sleep preventers list (Total %u)\n", 3277 service->getName(), preventSystemSleepList->getCount()); 3278 3279 if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) { 3280 // Lost all system sleep preventers. 3281 // Send stimulus if system sleep was blocked, and is in dark wake. 3282 evaluatePolicy( kStimulusDarkWakeEvaluate ); 3283 } 3284 } 3285 3286 newCount = preventSystemSleepList->getCount(); 3287 if (newCount) { 3288 char buf[256] = "System Sleep Preventers:"; 3289 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf)); 3290 DLOG("%s\n", buf); 3291 } 3292 3293 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(), 3294 &newCount, sizeof(newCount)); 3295 } 3296 3297 void 3298 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList) 3299 { 3300 OSSharedPtr<OSCollectionIterator> iterator; 3301 OSObject *object = NULL; 3302 OSSharedPtr<OSArray> array; 3303 3304 if (!gIOPMWorkLoop->inGate()) { 3305 gIOPMWorkLoop->runAction( 3306 OSMemberFunctionCast(IOWorkLoop::Action, this, 3307 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList), 3308 this, (void *)idleSleepList, (void *)systemSleepList); 3309 return; 3310 } 3311 3312 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) { 3313 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get()); 3314 array = OSArray::withCapacity(5); 3315 3316 if (iterator && array) { 3317 while ((object = iterator->getNextObject())) { 3318 IOService *service = OSDynamicCast(IOService, object); 3319 if (service) { 3320 OSSharedPtr<const OSSymbol> name = service->copyName(); 3321 if (name) { 3322 array->setObject(name.get()); 3323 } 3324 } 3325 } 3326 } 3327 *idleSleepList = array.detach(); 3328 } 3329 3330 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) { 3331 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get()); 3332 array = OSArray::withCapacity(5); 3333 3334 if (iterator && array) { 3335 while ((object = iterator->getNextObject())) { 3336 IOService *service = OSDynamicCast(IOService, object); 3337 if (service) { 3338 OSSharedPtr<const OSSymbol> name = service->copyName(); 3339 if (name) { 3340 array->setObject(name.get()); 3341 } 3342 } 3343 } 3344 } 3345 *systemSleepList = array.detach(); 3346 } 3347 } 3348 3349 void 3350 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList) 3351 { 3352 OSSharedPtr<OSCollectionIterator> iterator; 3353 OSObject *object = NULL; 3354 OSSharedPtr<OSArray> array; 3355 3356 if (!gIOPMWorkLoop->inGate()) { 3357 gIOPMWorkLoop->runAction( 3358 OSMemberFunctionCast(IOWorkLoop::Action, this, 3359 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID), 3360 this, (void *)idleSleepList, (void *)systemSleepList); 3361 return; 3362 } 3363 3364 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) { 3365 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get()); 3366 array = OSArray::withCapacity(5); 3367 3368 if (iterator && array) { 3369 while ((object = iterator->getNextObject())) { 3370 IOService *service = OSDynamicCast(IOService, object); 3371 if (service) { 3372 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2); 3373 OSSharedPtr<const OSSymbol> name = service->copyName(); 3374 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64); 3375 if (dict && name && id) { 3376 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get()); 3377 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get()); 3378 array->setObject(dict.get()); 3379 } 3380 } 3381 } 3382 } 3383 *idleSleepList = array.detach(); 3384 } 3385 3386 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) { 3387 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get()); 3388 array = OSArray::withCapacity(5); 3389 3390 if (iterator && array) { 3391 while ((object = iterator->getNextObject())) { 3392 IOService *service = OSDynamicCast(IOService, object); 3393 if (service) { 3394 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2); 3395 OSSharedPtr<const OSSymbol> name = service->copyName(); 3396 OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64); 3397 if (dict && name && id) { 3398 dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get()); 3399 dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get()); 3400 array->setObject(dict.get()); 3401 } 3402 } 3403 } 3404 } 3405 *systemSleepList = array.detach(); 3406 } 3407 } 3408 3409 //****************************************************************************** 3410 // tellChangeDown 3411 // 3412 // Override the superclass implementation to send a different message type. 3413 //****************************************************************************** 3414 3415 bool 3416 IOPMrootDomain::tellChangeDown( unsigned long stateNum ) 3417 { 3418 DLOG("tellChangeDown %s->%s\n", 3419 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum)); 3420 3421 if (SLEEP_STATE == stateNum) { 3422 // Legacy apps were already told in the full->dark transition 3423 if (!ignoreTellChangeDown) { 3424 tracePoint( kIOPMTracePointSleepApplications ); 3425 } else { 3426 tracePoint( kIOPMTracePointSleepPriorityClients ); 3427 } 3428 } 3429 3430 if (!ignoreTellChangeDown) { 3431 userActivityAtSleep = userActivityCount; 3432 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep); 3433 3434 if (SLEEP_STATE == stateNum) { 3435 hibernateAborted = false; 3436 3437 // Direct callout into OSKext so it can disable kext unloads 3438 // during sleep/wake to prevent deadlocks. 3439 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep ); 3440 3441 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep); 3442 3443 // Two change downs are sent by IOServicePM. Ignore the 2nd. 3444 // But tellClientsWithResponse() must be called for both. 3445 ignoreTellChangeDown = true; 3446 } 3447 } 3448 3449 return super::tellClientsWithResponse( kIOMessageSystemWillSleep ); 3450 } 3451 3452 //****************************************************************************** 3453 // askChangeDown 3454 // 3455 // Override the superclass implementation to send a different message type. 3456 // This must be idle sleep since we don't ask during any other power change. 3457 //****************************************************************************** 3458 3459 bool 3460 IOPMrootDomain::askChangeDown( unsigned long stateNum ) 3461 { 3462 DLOG("askChangeDown %s->%s\n", 3463 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum)); 3464 3465 // Don't log for dark wake entry 3466 if (kSystemTransitionSleep == _systemTransitionType) { 3467 tracePoint( kIOPMTracePointSleepApplications ); 3468 } 3469 3470 return super::tellClientsWithResponse( kIOMessageCanSystemSleep ); 3471 } 3472 3473 //****************************************************************************** 3474 // askChangeDownDone 3475 // 3476 // An opportunity for root domain to cancel the power transition, 3477 // possibily due to an assertion created by powerd in response to 3478 // kIOMessageCanSystemSleep. 3479 // 3480 // Idle sleep: 3481 // full -> dark wake transition 3482 // 1. Notify apps and powerd with kIOMessageCanSystemSleep 3483 // 2. askChangeDownDone() 3484 // dark -> sleep transition 3485 // 1. Notify powerd with kIOMessageCanSystemSleep 3486 // 2. askChangeDownDone() 3487 // 3488 // Demand sleep: 3489 // full -> dark wake transition 3490 // 1. Notify powerd with kIOMessageCanSystemSleep 3491 // 2. askChangeDownDone() 3492 // dark -> sleep transition 3493 // 1. Notify powerd with kIOMessageCanSystemSleep 3494 // 2. askChangeDownDone() 3495 //****************************************************************************** 3496 3497 void 3498 IOPMrootDomain::askChangeDownDone( 3499 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel ) 3500 { 3501 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n", 3502 *inOutChangeFlags, *cancel, 3503 _systemTransitionType, 3504 _currentCapability, _pendingCapability); 3505 3506 if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) { 3507 // Dark->Sleep transition. 3508 // Check if there are any deny sleep assertions. 3509 // lastSleepReason already set by handleOurPowerChangeStart() 3510 3511 if (!checkSystemCanSleep(lastSleepReason)) { 3512 // Cancel dark wake to sleep transition. 3513 // Must re-scan assertions upon entering dark wake. 3514 3515 *cancel = true; 3516 DLOG("cancel dark->sleep\n"); 3517 } 3518 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) { 3519 uint64_t now = mach_continuous_time(); 3520 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous) 3521 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) { 3522 *cancel = true; 3523 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous); 3524 } 3525 } 3526 } 3527 } 3528 3529 //****************************************************************************** 3530 // systemDidNotSleep 3531 // 3532 // Work common to both canceled or aborted sleep. 3533 //****************************************************************************** 3534 3535 void 3536 IOPMrootDomain::systemDidNotSleep( void ) 3537 { 3538 // reset console lock state 3539 thread_call_enter(updateConsoleUsersEntry); 3540 3541 if (idleSleepEnabled) { 3542 if (!wrangler) { 3543 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 3544 startIdleSleepTimer(kIdleSleepRetryInterval); 3545 #else 3546 startIdleSleepTimer(idleSeconds); 3547 #endif 3548 } else if (!userIsActive) { 3549 // Manually start the idle sleep timer besides waiting for 3550 // the user to become inactive. 3551 startIdleSleepTimer(kIdleSleepRetryInterval); 3552 } 3553 } 3554 3555 preventTransitionToUserActive(false); 3556 IOService::setAdvisoryTickleEnable( true ); 3557 3558 // After idle revert and cancel, send a did-change message to powerd 3559 // to balance the previous will-change message. Kernel clients do not 3560 // need this since sleep cannot be canceled once they are notified. 3561 3562 if (toldPowerdCapWillChange && systemCapabilityNotifier && 3563 (_pendingCapability != _currentCapability) && 3564 ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) { 3565 // Differs from a real capability gain change where notifyRef != 0, 3566 // but it is zero here since no response is expected. 3567 3568 IOPMSystemCapabilityChangeParameters params; 3569 3570 bzero(¶ms, sizeof(params)); 3571 params.fromCapabilities = _pendingCapability; 3572 params.toCapabilities = _currentCapability; 3573 params.changeFlags = kIOPMSystemCapabilityDidChange; 3574 3575 DLOG("MESG cap %x->%x did change\n", 3576 params.fromCapabilities, params.toCapabilities); 3577 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(), 3578 ¶ms, sizeof(params)); 3579 } 3580 } 3581 3582 //****************************************************************************** 3583 // tellNoChangeDown 3584 // 3585 // Notify registered applications and kernel clients that we are not dropping 3586 // power. 3587 // 3588 // We override the superclass implementation so we can send a different message 3589 // type to the client or application being notified. 3590 // 3591 // This must be a vetoed idle sleep, since no other power change can be vetoed. 3592 //****************************************************************************** 3593 3594 void 3595 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum ) 3596 { 3597 DLOG("tellNoChangeDown %s->%s\n", 3598 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum)); 3599 3600 // Sleep canceled, clear the sleep trace point. 3601 tracePoint(kIOPMTracePointSystemUp); 3602 3603 systemDidNotSleep(); 3604 return tellClients( kIOMessageSystemWillNotSleep ); 3605 } 3606 3607 //****************************************************************************** 3608 // tellChangeUp 3609 // 3610 // Notify registered applications and kernel clients that we are raising power. 3611 // 3612 // We override the superclass implementation so we can send a different message 3613 // type to the client or application being notified. 3614 //****************************************************************************** 3615 3616 void 3617 IOPMrootDomain::tellChangeUp( unsigned long stateNum ) 3618 { 3619 DLOG("tellChangeUp %s->%s\n", 3620 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum)); 3621 3622 ignoreTellChangeDown = false; 3623 3624 if (stateNum == ON_STATE) { 3625 // Direct callout into OSKext so it can disable kext unloads 3626 // during sleep/wake to prevent deadlocks. 3627 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn ); 3628 3629 // Notify platform that sleep was cancelled or resumed. 3630 getPlatform()->callPlatformFunction( 3631 sleepMessagePEFunction.get(), false, 3632 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn, 3633 NULL, NULL, NULL); 3634 3635 if (getPowerState() == ON_STATE) { 3636 // Sleep was cancelled by idle cancel or revert 3637 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) { 3638 // rdar://problem/50363791 3639 // If system is in dark wake and sleep is cancelled, do not 3640 // send SystemWillPowerOn/HasPoweredOn messages to kernel 3641 // priority clients. They haven't yet seen a SystemWillSleep 3642 // message before the cancellation. So make sure the kernel 3643 // client bit is cleared in _systemMessageClientMask before 3644 // invoking the tellClients() below. This bit may have been 3645 // set by handleOurPowerChangeStart() anticipating a successful 3646 // sleep and setting the filter mask ahead of time allows the 3647 // SystemWillSleep message to go through. 3648 _systemMessageClientMask &= ~kSystemMessageClientKernel; 3649 } 3650 3651 systemDidNotSleep(); 3652 tellClients( kIOMessageSystemWillPowerOn ); 3653 } 3654 3655 tracePoint( kIOPMTracePointWakeApplications ); 3656 tellClients( kIOMessageSystemHasPoweredOn ); 3657 } 3658 } 3659 3660 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \ 3661 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \ 3662 ((params)->fromCapabilities & (flag)) && \ 3663 (((params)->toCapabilities & (flag)) == 0)) 3664 3665 #define CAP_DID_CHANGE_TO_ON(params, flag) \ 3666 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \ 3667 ((params)->toCapabilities & (flag)) && \ 3668 (((params)->fromCapabilities & (flag)) == 0)) 3669 3670 #define CAP_DID_CHANGE_TO_OFF(params, flag) \ 3671 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \ 3672 ((params)->fromCapabilities & (flag)) && \ 3673 (((params)->toCapabilities & (flag)) == 0)) 3674 3675 #define CAP_WILL_CHANGE_TO_ON(params, flag) \ 3676 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \ 3677 ((params)->toCapabilities & (flag)) && \ 3678 (((params)->fromCapabilities & (flag)) == 0)) 3679 3680 //****************************************************************************** 3681 // sysPowerDownHandler 3682 // 3683 // Perform a vfs sync before system sleep. 3684 //****************************************************************************** 3685 3686 IOReturn 3687 IOPMrootDomain::sysPowerDownHandler( 3688 void * target, void * refCon, 3689 UInt32 messageType, IOService * service, 3690 void * messageArgs, vm_size_t argSize ) 3691 { 3692 static UInt32 lastSystemMessageType = 0; 3693 IOReturn ret = 0; 3694 3695 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType)); 3696 3697 // rdar://problem/50363791 3698 // Sanity check to make sure the SystemWill/Has message types are 3699 // received in the expected order for all kernel priority clients. 3700 if (messageType == kIOMessageSystemWillSleep || 3701 messageType == kIOMessageSystemWillPowerOn || 3702 messageType == kIOMessageSystemHasPoweredOn) { 3703 switch (messageType) { 3704 case kIOMessageSystemWillPowerOn: 3705 assert(lastSystemMessageType == kIOMessageSystemWillSleep); 3706 break; 3707 case kIOMessageSystemHasPoweredOn: 3708 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn); 3709 break; 3710 } 3711 3712 lastSystemMessageType = messageType; 3713 } 3714 3715 if (!gRootDomain) { 3716 return kIOReturnUnsupported; 3717 } 3718 3719 if (messageType == kIOMessageSystemCapabilityChange) { 3720 IOPMSystemCapabilityChangeParameters * params = 3721 (IOPMSystemCapabilityChangeParameters *) messageArgs; 3722 3723 // Interested applications have been notified of an impending power 3724 // change and have acked (when applicable). 3725 // This is our chance to save whatever state we can before powering 3726 // down. 3727 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c, 3728 // via callout 3729 3730 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n", 3731 params->fromCapabilities, params->toCapabilities, 3732 params->changeFlags); 3733 3734 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) { 3735 // We will ack within 20 seconds 3736 params->maxWaitForReply = 20 * 1000 * 1000; 3737 3738 #if HIBERNATION 3739 gRootDomain->evaluateSystemSleepPolicyEarly(); 3740 3741 // add in time we could spend freeing pages 3742 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) { 3743 params->maxWaitForReply = kCapabilityClientMaxWait; 3744 } 3745 DLOG("sysPowerDownHandler max wait %d s\n", 3746 (int) (params->maxWaitForReply / 1000 / 1000)); 3747 #endif 3748 3749 // Notify platform that sleep has begun, after the early 3750 // sleep policy evaluation. 3751 getPlatform()->callPlatformFunction( 3752 sleepMessagePEFunction.get(), false, 3753 (void *)(uintptr_t) kIOMessageSystemWillSleep, 3754 NULL, NULL, NULL); 3755 3756 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) { 3757 // Purposely delay the ack and hope that shutdown occurs quickly. 3758 // Another option is not to schedule the thread and wait for 3759 // ack timeout... 3760 AbsoluteTime deadline; 3761 clock_interval_to_deadline( 30, kSecondScale, &deadline ); 3762 thread_call_enter1_delayed( 3763 gRootDomain->diskSyncCalloutEntry, 3764 (thread_call_param_t)(uintptr_t) params->notifyRef, 3765 deadline ); 3766 } else { 3767 thread_call_enter1( 3768 gRootDomain->diskSyncCalloutEntry, 3769 (thread_call_param_t)(uintptr_t) params->notifyRef); 3770 } 3771 } 3772 #if HIBERNATION 3773 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) { 3774 // We will ack within 110 seconds 3775 params->maxWaitForReply = 110 * 1000 * 1000; 3776 3777 thread_call_enter1( 3778 gRootDomain->diskSyncCalloutEntry, 3779 (thread_call_param_t)(uintptr_t) params->notifyRef); 3780 } 3781 #endif 3782 ret = kIOReturnSuccess; 3783 } 3784 3785 return ret; 3786 } 3787 3788 //****************************************************************************** 3789 // handleQueueSleepWakeUUID 3790 // 3791 // Called from IOPMrootDomain when we're initiating a sleep, 3792 // or indirectly from PM configd when PM decides to clear the UUID. 3793 // PM clears the UUID several minutes after successful wake from sleep, 3794 // so that we might associate App spindumps with the immediately previous 3795 // sleep/wake. 3796 // 3797 // @param obj has a retain on it. We're responsible for releasing that retain. 3798 //****************************************************************************** 3799 3800 void 3801 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj) 3802 { 3803 OSSharedPtr<OSString> str; 3804 3805 if (kOSBooleanFalse == obj) { 3806 handlePublishSleepWakeUUID(false); 3807 } else { 3808 str.reset(OSDynamicCast(OSString, obj), OSNoRetain); 3809 if (str) { 3810 // This branch caches the UUID for an upcoming sleep/wake 3811 queuedSleepWakeUUIDString = str; 3812 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy()); 3813 } 3814 } 3815 } 3816 //****************************************************************************** 3817 // handlePublishSleepWakeUUID 3818 // 3819 // Called from IOPMrootDomain when we're initiating a sleep, 3820 // or indirectly from PM configd when PM decides to clear the UUID. 3821 // PM clears the UUID several minutes after successful wake from sleep, 3822 // so that we might associate App spindumps with the immediately previous 3823 // sleep/wake. 3824 //****************************************************************************** 3825 3826 void 3827 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish ) 3828 { 3829 ASSERT_GATED(); 3830 3831 /* 3832 * Clear the current UUID 3833 */ 3834 if (gSleepWakeUUIDIsSet) { 3835 DLOG("SleepWake UUID cleared\n"); 3836 3837 gSleepWakeUUIDIsSet = false; 3838 3839 removeProperty(kIOPMSleepWakeUUIDKey); 3840 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared); 3841 } 3842 3843 /* 3844 * Optionally, publish a new UUID 3845 */ 3846 if (queuedSleepWakeUUIDString && shouldPublish) { 3847 OSSharedPtr<OSString> publishThisUUID; 3848 3849 publishThisUUID = queuedSleepWakeUUIDString; 3850 3851 if (publishThisUUID) { 3852 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get()); 3853 } 3854 3855 gSleepWakeUUIDIsSet = true; 3856 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet); 3857 3858 queuedSleepWakeUUIDString.reset(); 3859 } 3860 } 3861 3862 //****************************************************************************** 3863 // IOPMGetSleepWakeUUIDKey 3864 // 3865 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key. 3866 // To get the full key -- a C string -- the buffer must large enough for 3867 // the end-of-string character. 3868 // The key is expected to be an UUID string 3869 //****************************************************************************** 3870 3871 extern "C" bool 3872 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len) 3873 { 3874 if (!gSleepWakeUUIDIsSet) { 3875 return false; 3876 } 3877 3878 if (buffer != NULL) { 3879 OSSharedPtr<OSString> string = 3880 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey)); 3881 3882 if (!string) { 3883 *buffer = '\0'; 3884 } else { 3885 strlcpy(buffer, string->getCStringNoCopy(), buf_len); 3886 } 3887 } 3888 3889 return true; 3890 } 3891 3892 //****************************************************************************** 3893 // lowLatencyAudioNotify 3894 // 3895 // Used to send an update about low latency audio activity to interested 3896 // clients. To keep the overhead minimal the OSDictionary used here 3897 // is initialized at boot. 3898 //****************************************************************************** 3899 3900 void 3901 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state) 3902 { 3903 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym && 3904 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) { 3905 lowLatencyAudioNotifyTimestampVal->setValue(time); 3906 lowLatencyAudioNotifyStateVal->setValue(state); 3907 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get()); 3908 } else { 3909 DLOG("LowLatencyAudioNotify error\n"); 3910 } 3911 return; 3912 } 3913 3914 //****************************************************************************** 3915 // IOPMrootDomainRTNotifier 3916 // 3917 // Used by performance controller to update the timestamp and state associated 3918 // with low latency audio activity in the system. 3919 //****************************************************************************** 3920 3921 extern "C" void 3922 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state) 3923 { 3924 gRootDomain->lowLatencyAudioNotify(time, state); 3925 return; 3926 } 3927 3928 //****************************************************************************** 3929 // initializeBootSessionUUID 3930 // 3931 // Initialize the boot session uuid at boot up and sets it into registry. 3932 //****************************************************************************** 3933 3934 void 3935 IOPMrootDomain::initializeBootSessionUUID(void) 3936 { 3937 uuid_t new_uuid; 3938 uuid_string_t new_uuid_string; 3939 3940 uuid_generate(new_uuid); 3941 uuid_unparse_upper(new_uuid, new_uuid_string); 3942 memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t)); 3943 3944 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string); 3945 } 3946 3947 //****************************************************************************** 3948 // Root domain uses the private and tagged changePowerState methods for 3949 // tracking and logging purposes. 3950 //****************************************************************************** 3951 3952 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x) 3953 3954 static uint32_t 3955 nextRequestTag( IOPMRequestTag tag ) 3956 { 3957 static SInt16 msb16 = 1; 3958 uint16_t id = OSAddAtomic16(1, &msb16); 3959 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag); 3960 } 3961 3962 // TODO: remove this shim function and exported symbol 3963 IOReturn 3964 IOPMrootDomain::changePowerStateTo( unsigned long ordinal ) 3965 { 3966 return changePowerStateWithTagTo(ordinal, kCPSReasonNone); 3967 } 3968 3969 // TODO: remove this shim function and exported symbol 3970 IOReturn 3971 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal ) 3972 { 3973 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone); 3974 } 3975 3976 IOReturn 3977 IOPMrootDomain::changePowerStateWithOverrideTo( 3978 IOPMPowerStateIndex ordinal, IOPMRequestTag reason ) 3979 { 3980 uint32_t tag = nextRequestTag(reason); 3981 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag); 3982 3983 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) { 3984 return kIOReturnUnsupported; 3985 } 3986 3987 return super::changePowerStateWithOverrideTo(ordinal, tag); 3988 } 3989 3990 IOReturn 3991 IOPMrootDomain::changePowerStateWithTagTo( 3992 IOPMPowerStateIndex ordinal, IOPMRequestTag reason ) 3993 { 3994 uint32_t tag = nextRequestTag(reason); 3995 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag); 3996 3997 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) { 3998 return kIOReturnUnsupported; 3999 } 4000 4001 return super::changePowerStateWithTagTo(ordinal, tag); 4002 } 4003 4004 IOReturn 4005 IOPMrootDomain::changePowerStateWithTagToPriv( 4006 IOPMPowerStateIndex ordinal, IOPMRequestTag reason ) 4007 { 4008 uint32_t tag = nextRequestTag(reason); 4009 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag); 4010 4011 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) { 4012 return kIOReturnUnsupported; 4013 } 4014 4015 return super::changePowerStateWithTagToPriv(ordinal, tag); 4016 } 4017 4018 //****************************************************************************** 4019 // activity detect 4020 // 4021 //****************************************************************************** 4022 4023 bool 4024 IOPMrootDomain::activitySinceSleep(void) 4025 { 4026 return userActivityCount != userActivityAtSleep; 4027 } 4028 4029 bool 4030 IOPMrootDomain::abortHibernation(void) 4031 { 4032 #if __arm64__ 4033 // don't allow hibernation to be aborted on ARM due to user activity 4034 // since once ApplePMGR decides we're hibernating, we can't turn back 4035 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support 4036 return false; 4037 #else 4038 bool ret = activitySinceSleep(); 4039 4040 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) { 4041 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep); 4042 hibernateAborted = true; 4043 } 4044 return ret; 4045 #endif 4046 } 4047 4048 extern "C" int 4049 hibernate_should_abort(void) 4050 { 4051 if (gRootDomain) { 4052 return gRootDomain->abortHibernation(); 4053 } else { 4054 return 0; 4055 } 4056 } 4057 4058 //****************************************************************************** 4059 // willNotifyPowerChildren 4060 // 4061 // Called after all interested drivers have all acknowledged the power change, 4062 // but before any power children is informed. Dispatched though a thread call, 4063 // so it is safe to perform work that might block on a sleeping disk. PM state 4064 // machine (not thread) will block w/o timeout until this function returns. 4065 //****************************************************************************** 4066 4067 void 4068 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState ) 4069 { 4070 OSSharedPtr<OSDictionary> dict; 4071 OSSharedPtr<OSNumber> secs; 4072 4073 if (SLEEP_STATE == newPowerState) { 4074 notifierThread = current_thread(); 4075 if (!tasksSuspended) { 4076 AbsoluteTime deadline; 4077 tasksSuspended = TRUE; 4078 updateTasksSuspend(); 4079 4080 clock_interval_to_deadline(10, kSecondScale, &deadline); 4081 #if defined(XNU_TARGET_OS_OSX) 4082 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline)); 4083 #endif /* defined(XNU_TARGET_OS_OSX) */ 4084 } 4085 4086 _aotReadyToFullWake = false; 4087 #if 0 4088 if (_aotLingerTime) { 4089 uint64_t deadline; 4090 IOLog("aot linger no return\n"); 4091 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline); 4092 clock_delay_until(deadline); 4093 } 4094 #endif 4095 if (!_aotMode) { 4096 _aotTestTime = 0; 4097 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid; 4098 if (_aotMetrics) { 4099 bzero(_aotMetrics, sizeof(IOPMAOTMetrics)); 4100 } 4101 } else if (!_aotNow && !_debugWakeSeconds) { 4102 _aotNow = true; 4103 _aotExit = false; 4104 _aotPendingFlags = 0; 4105 _aotTasksSuspended = true; 4106 _aotLastWakeTime = 0; 4107 bzero(_aotMetrics, sizeof(IOPMAOTMetrics)); 4108 if (kIOPMAOTModeCycle & _aotMode) { 4109 clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval); 4110 _aotTestTime = mach_continuous_time() + _aotTestInterval; 4111 setWakeTime(_aotTestTime); 4112 } 4113 uint32_t lingerSecs; 4114 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) { 4115 lingerSecs = 0; 4116 } 4117 clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime); 4118 clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow); 4119 clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow); 4120 } 4121 4122 #if HIBERNATION 4123 IOHibernateSystemSleep(); 4124 IOHibernateIOKitSleep(); 4125 #endif 4126 if (gRootDomain->activitySinceSleep()) { 4127 dict = OSDictionary::withCapacity(1); 4128 secs = OSNumber::withNumber(1, 32); 4129 4130 if (dict && secs) { 4131 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get()); 4132 gRootDomain->setProperties(dict.get()); 4133 MSG("Reverting sleep with relative wake\n"); 4134 } 4135 } 4136 4137 notifierThread = NULL; 4138 } 4139 } 4140 4141 //****************************************************************************** 4142 // willTellSystemCapabilityDidChange 4143 // 4144 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root 4145 // domain is raising its power state, immediately after notifying interested 4146 // drivers and power children. 4147 //****************************************************************************** 4148 4149 void 4150 IOPMrootDomain::willTellSystemCapabilityDidChange( void ) 4151 { 4152 if ((_systemTransitionType == kSystemTransitionWake) && 4153 !CAP_GAIN(kIOPMSystemCapabilityGraphics)) { 4154 // After powering up drivers, dark->full promotion on the current wake 4155 // transition is no longer possible. That is because the next machine 4156 // state will issue the system capability change messages. 4157 // The darkWakePowerClamped flag may already be set if the system has 4158 // at least one driver that was power clamped due to dark wake. 4159 // This function sets the darkWakePowerClamped flag in case there 4160 // is no power-clamped driver in the system. 4161 // 4162 // Last opportunity to exit dark wake using: 4163 // requestFullWake( kFullWakeReasonLocalUser ); 4164 4165 if (!darkWakePowerClamped) { 4166 if (darkWakeLogClamp) { 4167 AbsoluteTime now; 4168 uint64_t nsec; 4169 4170 clock_get_uptime(&now); 4171 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 4172 absolutetime_to_nanoseconds(now, &nsec); 4173 DLOG("dark wake promotion disabled at %u ms\n", 4174 ((int)((nsec) / NSEC_PER_MSEC))); 4175 } 4176 darkWakePowerClamped = true; 4177 } 4178 } 4179 } 4180 4181 //****************************************************************************** 4182 // sleepOnClamshellClosed 4183 // 4184 // contains the logic to determine if the system should sleep when the clamshell 4185 // is closed. 4186 //****************************************************************************** 4187 4188 bool 4189 IOPMrootDomain::shouldSleepOnClamshellClosed( void ) 4190 { 4191 if (!clamshellExists) { 4192 return false; 4193 } 4194 4195 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 4196 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected); 4197 4198 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask; 4199 } 4200 4201 bool 4202 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void ) 4203 { 4204 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell 4205 // closed && battery 4206 if (!clamshellExists) { 4207 return false; 4208 } 4209 4210 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 4211 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected); 4212 4213 return !acAdaptorConnected && !clamshellSleepDisableMask; 4214 } 4215 4216 void 4217 IOPMrootDomain::sendClientClamshellNotification( void ) 4218 { 4219 /* Only broadcast clamshell alert if clamshell exists. */ 4220 if (!clamshellExists) { 4221 return; 4222 } 4223 4224 setProperty(kAppleClamshellStateKey, 4225 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse); 4226 4227 setProperty(kAppleClamshellCausesSleepKey, 4228 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse); 4229 4230 /* Argument to message is a bitfiel of 4231 * ( kClamshellStateBit | kClamshellSleepBit ) 4232 */ 4233 messageClients(kIOPMMessageClamshellStateChange, 4234 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0) 4235 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0))); 4236 } 4237 4238 //****************************************************************************** 4239 // getSleepSupported 4240 // 4241 // Deprecated 4242 //****************************************************************************** 4243 4244 IOOptionBits 4245 IOPMrootDomain::getSleepSupported( void ) 4246 { 4247 return platformSleepSupport; 4248 } 4249 4250 //****************************************************************************** 4251 // setSleepSupported 4252 // 4253 // Deprecated 4254 //****************************************************************************** 4255 4256 void 4257 IOPMrootDomain::setSleepSupported( IOOptionBits flags ) 4258 { 4259 DLOG("setSleepSupported(%x)\n", (uint32_t) flags); 4260 OSBitOrAtomic(flags, &platformSleepSupport); 4261 } 4262 4263 //****************************************************************************** 4264 // setClamShellSleepDisable 4265 // 4266 //****************************************************************************** 4267 4268 void 4269 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask ) 4270 { 4271 uint32_t oldMask; 4272 4273 // User client calls this in non-gated context 4274 if (gIOPMWorkLoop->inGate() == false) { 4275 gIOPMWorkLoop->runAction( 4276 OSMemberFunctionCast(IOWorkLoop::Action, this, 4277 &IOPMrootDomain::setClamShellSleepDisable), 4278 (OSObject *) this, 4279 (void *) disable, (void *)(uintptr_t) bitmask); 4280 return; 4281 } 4282 4283 oldMask = clamshellSleepDisableMask; 4284 if (disable) { 4285 clamshellSleepDisableMask |= bitmask; 4286 } else { 4287 clamshellSleepDisableMask &= ~bitmask; 4288 } 4289 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask); 4290 4291 if (clamshellExists && clamshellClosed && 4292 (clamshellSleepDisableMask != oldMask) && 4293 (clamshellSleepDisableMask == 0)) { 4294 handlePowerNotification(kLocalEvalClamshellCommand); 4295 } 4296 } 4297 4298 //****************************************************************************** 4299 // wakeFromDoze 4300 // 4301 // Deprecated. 4302 //****************************************************************************** 4303 4304 void 4305 IOPMrootDomain::wakeFromDoze( void ) 4306 { 4307 // Preserve symbol for familes (IOUSBFamily and IOGraphics) 4308 } 4309 4310 //****************************************************************************** 4311 // recordRTCAlarm 4312 // 4313 // Record the earliest scheduled RTC alarm to determine whether a RTC wake 4314 // should be a dark wake or a full wake. Both Maintenance and SleepService 4315 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake 4316 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on 4317 // PMSettings are ignored. 4318 // 4319 // Caller serialized using settingsCtrlLock. 4320 //****************************************************************************** 4321 4322 void 4323 IOPMrootDomain::recordRTCAlarm( 4324 const OSSymbol *type, 4325 OSObject *object ) 4326 { 4327 uint32_t previousAlarmMask = _scheduledAlarmMask; 4328 4329 if (type == gIOPMSettingDebugWakeRelativeKey) { 4330 OSNumber * n = OSDynamicCast(OSNumber, object); 4331 if (n) { 4332 // Debug wake has highest scheduling priority so it overrides any 4333 // pre-existing alarm. 4334 uint32_t debugSecs = n->unsigned32BitValue(); 4335 _nextScheduledAlarmType.reset(type, OSRetain); 4336 _nextScheduledAlarmUTC = debugSecs; 4337 4338 _debugWakeSeconds = debugSecs; 4339 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask); 4340 DLOG("next alarm (%s) in %u secs\n", 4341 type->getCStringNoCopy(), debugSecs); 4342 } 4343 } else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) || 4344 (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) || 4345 (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) { 4346 OSData * data = OSDynamicCast(OSData, object); 4347 if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) { 4348 const IOPMCalendarStruct * cs; 4349 bool replaceNextAlarm = false; 4350 clock_sec_t secs; 4351 4352 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy(); 4353 secs = IOPMConvertCalendarToSeconds(cs); 4354 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs)); 4355 4356 // Update the next scheduled alarm type 4357 if ((_nextScheduledAlarmType == NULL) || 4358 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) && 4359 (secs < _nextScheduledAlarmUTC))) { 4360 replaceNextAlarm = true; 4361 } 4362 4363 if (type == gIOPMSettingAutoWakeCalendarKey.get()) { 4364 if (cs->year) { 4365 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs); 4366 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask); 4367 } else { 4368 // TODO: can this else-block be removed? 4369 _calendarWakeAlarmUTC = 0; 4370 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask); 4371 } 4372 } 4373 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) { 4374 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask); 4375 } 4376 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) { 4377 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask); 4378 } 4379 4380 if (replaceNextAlarm) { 4381 _nextScheduledAlarmType.reset(type, OSRetain); 4382 _nextScheduledAlarmUTC = secs; 4383 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs)); 4384 } 4385 } 4386 } 4387 4388 if (_scheduledAlarmMask != previousAlarmMask) { 4389 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask); 4390 } 4391 } 4392 4393 // MARK: - 4394 // MARK: Features 4395 4396 //****************************************************************************** 4397 // publishFeature 4398 // 4399 // Adds a new feature to the supported features dictionary 4400 //****************************************************************************** 4401 4402 void 4403 IOPMrootDomain::publishFeature( const char * feature ) 4404 { 4405 publishFeature(feature, kRD_AllPowerSources, NULL); 4406 } 4407 4408 //****************************************************************************** 4409 // publishFeature (with supported power source specified) 4410 // 4411 // Adds a new feature to the supported features dictionary 4412 //****************************************************************************** 4413 4414 void 4415 IOPMrootDomain::publishFeature( 4416 const char *feature, 4417 uint32_t supportedWhere, 4418 uint32_t *uniqueFeatureID) 4419 { 4420 static uint16_t next_feature_id = 500; 4421 4422 OSSharedPtr<OSNumber> new_feature_data; 4423 OSNumber *existing_feature = NULL; 4424 OSArray *existing_feature_arr_raw = NULL; 4425 OSSharedPtr<OSArray> existing_feature_arr; 4426 OSObject *osObj = NULL; 4427 uint32_t feature_value = 0; 4428 4429 supportedWhere &= kRD_AllPowerSources; // mask off any craziness! 4430 4431 if (!supportedWhere) { 4432 // Feature isn't supported anywhere! 4433 return; 4434 } 4435 4436 if (next_feature_id > 5000) { 4437 // Far, far too many features! 4438 return; 4439 } 4440 4441 if (featuresDictLock) { 4442 IOLockLock(featuresDictLock); 4443 } 4444 4445 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures); 4446 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get()); 4447 OSSharedPtr<OSDictionary> features; 4448 4449 // Create new features dict if necessary 4450 if (origFeatures) { 4451 features = OSDictionary::withDictionary(origFeatures); 4452 } else { 4453 features = OSDictionary::withCapacity(1); 4454 } 4455 4456 // Create OSNumber to track new feature 4457 4458 next_feature_id += 1; 4459 if (uniqueFeatureID) { 4460 // We don't really mind if the calling kext didn't give us a place 4461 // to stash their unique id. Many kexts don't plan to unload, and thus 4462 // have no need to remove themselves later. 4463 *uniqueFeatureID = next_feature_id; 4464 } 4465 4466 feature_value = (uint32_t)next_feature_id; 4467 feature_value <<= 16; 4468 feature_value += supportedWhere; 4469 4470 new_feature_data = OSNumber::withNumber( 4471 (unsigned long long)feature_value, 32); 4472 4473 // Does features object already exist? 4474 if ((osObj = features->getObject(feature))) { 4475 if ((existing_feature = OSDynamicCast(OSNumber, osObj))) { 4476 // We need to create an OSArray to hold the now 2 elements. 4477 existing_feature_arr = OSArray::withObjects( 4478 (const OSObject **)&existing_feature, 1, 2); 4479 } else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) { 4480 // Add object to existing array 4481 existing_feature_arr = OSArray::withArray( 4482 existing_feature_arr_raw, 4483 existing_feature_arr_raw->getCount() + 1); 4484 } 4485 4486 if (existing_feature_arr) { 4487 existing_feature_arr->setObject(new_feature_data.get()); 4488 features->setObject(feature, existing_feature_arr.get()); 4489 } 4490 } else { 4491 // The easy case: no previously existing features listed. We simply 4492 // set the OSNumber at key 'feature' and we're on our way. 4493 features->setObject(feature, new_feature_data.get()); 4494 } 4495 4496 setProperty(kRootDomainSupportedFeatures, features.get()); 4497 4498 if (featuresDictLock) { 4499 IOLockUnlock(featuresDictLock); 4500 } 4501 4502 // Notify EnergySaver and all those in user space so they might 4503 // re-populate their feature specific UI 4504 if (pmPowerStateQueue) { 4505 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged ); 4506 } 4507 } 4508 4509 //****************************************************************************** 4510 // removePublishedFeature 4511 // 4512 // Removes previously published feature 4513 //****************************************************************************** 4514 4515 IOReturn 4516 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID ) 4517 { 4518 IOReturn ret = kIOReturnError; 4519 uint32_t feature_value = 0; 4520 uint16_t feature_id = 0; 4521 bool madeAChange = false; 4522 4523 OSSymbol *dictKey = NULL; 4524 OSSharedPtr<OSCollectionIterator> dictIterator; 4525 OSArray *arrayMember = NULL; 4526 OSNumber *numberMember = NULL; 4527 OSObject *osObj = NULL; 4528 OSNumber *osNum = NULL; 4529 OSSharedPtr<OSArray> arrayMemberCopy; 4530 4531 if (kBadPMFeatureID == removeFeatureID) { 4532 return kIOReturnNotFound; 4533 } 4534 4535 if (featuresDictLock) { 4536 IOLockLock(featuresDictLock); 4537 } 4538 4539 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures); 4540 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get()); 4541 OSSharedPtr<OSDictionary> features; 4542 4543 if (origFeatures) { 4544 // Any modifications to the dictionary are made to the copy to prevent 4545 // races & crashes with userland clients. Dictionary updated 4546 // automically later. 4547 features = OSDictionary::withDictionary(origFeatures); 4548 } else { 4549 features = NULL; 4550 ret = kIOReturnNotFound; 4551 goto exit; 4552 } 4553 4554 // We iterate 'features' dictionary looking for an entry tagged 4555 // with 'removeFeatureID'. If found, we remove it from our tracking 4556 // structures and notify the OS via a general interest message. 4557 4558 dictIterator = OSCollectionIterator::withCollection(features.get()); 4559 if (!dictIterator) { 4560 goto exit; 4561 } 4562 4563 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) { 4564 osObj = features->getObject(dictKey); 4565 4566 // Each Feature is either tracked by an OSNumber 4567 if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) { 4568 feature_value = numberMember->unsigned32BitValue(); 4569 feature_id = (uint16_t)(feature_value >> 16); 4570 4571 if (feature_id == (uint16_t)removeFeatureID) { 4572 // Remove this node 4573 features->removeObject(dictKey); 4574 madeAChange = true; 4575 break; 4576 } 4577 4578 // Or tracked by an OSArray of OSNumbers 4579 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) { 4580 unsigned int arrayCount = arrayMember->getCount(); 4581 4582 for (unsigned int i = 0; i < arrayCount; i++) { 4583 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i)); 4584 if (!osNum) { 4585 continue; 4586 } 4587 4588 feature_value = osNum->unsigned32BitValue(); 4589 feature_id = (uint16_t)(feature_value >> 16); 4590 4591 if (feature_id == (uint16_t)removeFeatureID) { 4592 // Remove this node 4593 if (1 == arrayCount) { 4594 // If the array only contains one element, remove 4595 // the whole thing. 4596 features->removeObject(dictKey); 4597 } else { 4598 // Otherwise remove the element from a copy of the array. 4599 arrayMemberCopy = OSArray::withArray(arrayMember); 4600 if (arrayMemberCopy) { 4601 arrayMemberCopy->removeObject(i); 4602 features->setObject(dictKey, arrayMemberCopy.get()); 4603 } 4604 } 4605 4606 madeAChange = true; 4607 break; 4608 } 4609 } 4610 } 4611 } 4612 4613 if (madeAChange) { 4614 ret = kIOReturnSuccess; 4615 4616 setProperty(kRootDomainSupportedFeatures, features.get()); 4617 4618 // Notify EnergySaver and all those in user space so they might 4619 // re-populate their feature specific UI 4620 if (pmPowerStateQueue) { 4621 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged ); 4622 } 4623 } else { 4624 ret = kIOReturnNotFound; 4625 } 4626 4627 exit: 4628 if (featuresDictLock) { 4629 IOLockUnlock(featuresDictLock); 4630 } 4631 return ret; 4632 } 4633 4634 //****************************************************************************** 4635 // publishPMSetting (private) 4636 // 4637 // Should only be called by PMSettingObject to publish a PM Setting as a 4638 // supported feature. 4639 //****************************************************************************** 4640 4641 void 4642 IOPMrootDomain::publishPMSetting( 4643 const OSSymbol * feature, uint32_t where, uint32_t * featureID ) 4644 { 4645 if (noPublishPMSettings && 4646 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) { 4647 // Setting found in noPublishPMSettings array 4648 *featureID = kBadPMFeatureID; 4649 return; 4650 } 4651 4652 publishFeature( 4653 feature->getCStringNoCopy(), where, featureID); 4654 } 4655 4656 //****************************************************************************** 4657 // setPMSetting (private) 4658 // 4659 // Internal helper to relay PM settings changes from user space to individual 4660 // drivers. Should be called only by IOPMrootDomain::setProperties. 4661 //****************************************************************************** 4662 4663 IOReturn 4664 IOPMrootDomain::setPMSetting( 4665 const OSSymbol *type, 4666 OSObject *object ) 4667 { 4668 PMSettingCallEntry *entries = NULL; 4669 OSSharedPtr<OSArray> chosen; 4670 const OSArray *array; 4671 PMSettingObject *pmso; 4672 thread_t thisThread; 4673 int i, j, count, capacity; 4674 bool ok = false; 4675 IOReturn ret; 4676 4677 if (NULL == type) { 4678 return kIOReturnBadArgument; 4679 } 4680 4681 PMSETTING_LOCK(); 4682 4683 // Update settings dict so changes are visible from copyPMSetting(). 4684 fPMSettingsDict->setObject(type, object); 4685 4686 // Prep all PMSetting objects with the given 'type' for callout. 4687 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type)); 4688 if (!array || ((capacity = array->getCount()) == 0)) { 4689 goto unlock_exit; 4690 } 4691 4692 // Array to retain PMSetting objects targeted for callout. 4693 chosen = OSArray::withCapacity(capacity); 4694 if (!chosen) { 4695 goto unlock_exit; // error 4696 } 4697 entries = IONew(PMSettingCallEntry, capacity); 4698 if (!entries) { 4699 goto unlock_exit; // error 4700 } 4701 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity); 4702 4703 thisThread = current_thread(); 4704 4705 for (i = 0, j = 0; i < capacity; i++) { 4706 pmso = (PMSettingObject *) array->getObject(i); 4707 if (pmso->disabled) { 4708 continue; 4709 } 4710 entries[j].thread = thisThread; 4711 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link); 4712 chosen->setObject(pmso); 4713 j++; 4714 } 4715 count = j; 4716 if (!count) { 4717 goto unlock_exit; 4718 } 4719 4720 PMSETTING_UNLOCK(); 4721 4722 // Call each pmso in the chosen array. 4723 for (i = 0; i < count; i++) { 4724 pmso = (PMSettingObject *) chosen->getObject(i); 4725 ret = pmso->dispatchPMSetting(type, object); 4726 if (ret == kIOReturnSuccess) { 4727 // At least one setting handler was successful 4728 ok = true; 4729 #if DEVELOPMENT || DEBUG 4730 } else { 4731 // Log the handler and kext that failed 4732 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func); 4733 if (kextName) { 4734 DLOG("PMSetting(%s) error 0x%x from %s\n", 4735 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy()); 4736 } 4737 #endif 4738 } 4739 } 4740 4741 PMSETTING_LOCK(); 4742 for (i = 0; i < count; i++) { 4743 pmso = (PMSettingObject *) chosen->getObject(i); 4744 queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link); 4745 if (pmso->waitThread) { 4746 PMSETTING_WAKEUP(pmso); 4747 } 4748 } 4749 4750 if (ok) { 4751 recordRTCAlarm(type, object); 4752 } 4753 unlock_exit: 4754 PMSETTING_UNLOCK(); 4755 4756 if (entries) { 4757 IODelete(entries, PMSettingCallEntry, capacity); 4758 } 4759 4760 return kIOReturnSuccess; 4761 } 4762 4763 //****************************************************************************** 4764 // copyPMSetting (public) 4765 // 4766 // Allows kexts to safely read setting values, without being subscribed to 4767 // notifications. 4768 //****************************************************************************** 4769 4770 OSSharedPtr<OSObject> 4771 IOPMrootDomain::copyPMSetting( 4772 OSSymbol *whichSetting) 4773 { 4774 OSSharedPtr<OSObject> obj; 4775 4776 if (!whichSetting) { 4777 return NULL; 4778 } 4779 4780 PMSETTING_LOCK(); 4781 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain); 4782 PMSETTING_UNLOCK(); 4783 4784 return obj; 4785 } 4786 4787 //****************************************************************************** 4788 // registerPMSettingController (public) 4789 // 4790 // direct wrapper to registerPMSettingController with uint32_t power source arg 4791 //****************************************************************************** 4792 4793 IOReturn 4794 IOPMrootDomain::registerPMSettingController( 4795 const OSSymbol * settings[], 4796 IOPMSettingControllerCallback func, 4797 OSObject *target, 4798 uintptr_t refcon, 4799 OSObject **handle) 4800 { 4801 return registerPMSettingController( 4802 settings, 4803 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS), 4804 func, target, refcon, handle); 4805 } 4806 4807 //****************************************************************************** 4808 // registerPMSettingController (public) 4809 // 4810 // Kexts may register for notifications when a particular setting is changed. 4811 // A list of settings is available in IOPM.h. 4812 // Arguments: 4813 // * settings - An OSArray containing OSSymbols. Caller should populate this 4814 // array with a list of settings caller wants notifications from. 4815 // * func - A C function callback of the type IOPMSettingControllerCallback 4816 // * target - caller may provide an OSObject *, which PM will pass as an 4817 // target to calls to "func" 4818 // * refcon - caller may provide an void *, which PM will pass as an 4819 // argument to calls to "func" 4820 // * handle - This is a return argument. We will populate this pointer upon 4821 // call success. Hold onto this and pass this argument to 4822 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext 4823 // Returns: 4824 // kIOReturnSuccess on success 4825 //****************************************************************************** 4826 4827 IOReturn 4828 IOPMrootDomain::registerPMSettingController( 4829 const OSSymbol * settings[], 4830 uint32_t supportedPowerSources, 4831 IOPMSettingControllerCallback func, 4832 OSObject *target, 4833 uintptr_t refcon, 4834 OSObject **handle) 4835 { 4836 PMSettingObject *pmso = NULL; 4837 OSObject *pmsh = NULL; 4838 int i; 4839 4840 if (NULL == settings || 4841 NULL == func || 4842 NULL == handle) { 4843 return kIOReturnBadArgument; 4844 } 4845 4846 pmso = PMSettingObject::pmSettingObject( 4847 (IOPMrootDomain *) this, func, target, 4848 refcon, supportedPowerSources, settings, &pmsh); 4849 4850 if (!pmso) { 4851 *handle = NULL; 4852 return kIOReturnInternalError; 4853 } 4854 4855 PMSETTING_LOCK(); 4856 for (i = 0; settings[i]; i++) { 4857 OSSharedPtr<OSArray> newList; 4858 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i])); 4859 if (!list) { 4860 // New array of callbacks for this setting 4861 newList = OSArray::withCapacity(1); 4862 settingsCallbacks->setObject(settings[i], newList.get()); 4863 list = newList.get(); 4864 } 4865 4866 // Add caller to the callback list 4867 list->setObject(pmso); 4868 } 4869 PMSETTING_UNLOCK(); 4870 4871 // Return handle to the caller, the setting object is private. 4872 *handle = pmsh; 4873 4874 return kIOReturnSuccess; 4875 } 4876 4877 //****************************************************************************** 4878 // deregisterPMSettingObject (private) 4879 // 4880 // Only called from PMSettingObject. 4881 //****************************************************************************** 4882 4883 void 4884 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso ) 4885 { 4886 thread_t thisThread = current_thread(); 4887 PMSettingCallEntry *callEntry; 4888 OSSharedPtr<OSCollectionIterator> iter; 4889 OSSymbol *sym; 4890 OSArray *array; 4891 int index; 4892 bool wait; 4893 4894 PMSETTING_LOCK(); 4895 4896 pmso->disabled = true; 4897 4898 // Wait for all callout threads to finish. 4899 do { 4900 wait = false; 4901 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link) 4902 { 4903 if (callEntry->thread != thisThread) { 4904 wait = true; 4905 break; 4906 } 4907 } 4908 if (wait) { 4909 assert(NULL == pmso->waitThread); 4910 pmso->waitThread = thisThread; 4911 PMSETTING_WAIT(pmso); 4912 pmso->waitThread = NULL; 4913 } 4914 } while (wait); 4915 4916 // Search each PM settings array in the kernel. 4917 iter = OSCollectionIterator::withCollection(settingsCallbacks.get()); 4918 if (iter) { 4919 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) { 4920 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym)); 4921 index = array->getNextIndexOfObject(pmso, 0); 4922 if (-1 != index) { 4923 array->removeObject(index); 4924 } 4925 } 4926 } 4927 4928 PMSETTING_UNLOCK(); 4929 4930 pmso->release(); 4931 } 4932 4933 //****************************************************************************** 4934 // informCPUStateChange 4935 // 4936 // Call into PM CPU code so that CPU power savings may dynamically adjust for 4937 // running on battery, with the lid closed, etc. 4938 // 4939 // informCPUStateChange is a no-op on non x86 systems 4940 // only x86 has explicit support in the IntelCPUPowerManagement kext 4941 //****************************************************************************** 4942 4943 void 4944 IOPMrootDomain::informCPUStateChange( 4945 uint32_t type, 4946 uint32_t value ) 4947 { 4948 #if defined(__i386__) || defined(__x86_64__) 4949 4950 pmioctlVariableInfo_t varInfoStruct; 4951 int pmCPUret = 0; 4952 const char *varNameStr = NULL; 4953 int32_t *varIndex = NULL; 4954 4955 if (kInformAC == type) { 4956 varNameStr = kIOPMRootDomainBatPowerCString; 4957 varIndex = &idxPMCPULimitedPower; 4958 } else if (kInformLid == type) { 4959 varNameStr = kIOPMRootDomainLidCloseCString; 4960 varIndex = &idxPMCPUClamshell; 4961 } else { 4962 return; 4963 } 4964 4965 // Set the new value! 4966 // pmCPUControl will assign us a new ID if one doesn't exist yet 4967 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t)); 4968 varInfoStruct.varID = *varIndex; 4969 varInfoStruct.varType = vBool; 4970 varInfoStruct.varInitValue = value; 4971 varInfoStruct.varCurValue = value; 4972 strlcpy((char *)varInfoStruct.varName, 4973 (const char *)varNameStr, 4974 sizeof(varInfoStruct.varName)); 4975 4976 // Set! 4977 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct ); 4978 4979 // pmCPU only assigns numerical id's when a new varName is specified 4980 if ((0 == pmCPUret) 4981 && (*varIndex == kCPUUnknownIndex)) { 4982 // pmCPUControl has assigned us a new variable ID. 4983 // Let's re-read the structure we just SET to learn that ID. 4984 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct ); 4985 4986 if (0 == pmCPUret) { 4987 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower 4988 *varIndex = varInfoStruct.varID; 4989 } 4990 } 4991 4992 return; 4993 4994 #endif /* __i386__ || __x86_64__ */ 4995 } 4996 4997 // MARK: - 4998 // MARK: Deep Sleep Policy 4999 5000 #if HIBERNATION 5001 5002 //****************************************************************************** 5003 // evaluateSystemSleepPolicy 5004 //****************************************************************************** 5005 5006 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy" 5007 5008 // Sleep flags 5009 enum { 5010 kIOPMSleepFlagHibernate = 0x00000001, 5011 kIOPMSleepFlagSleepTimerEnable = 0x00000002 5012 }; 5013 5014 struct IOPMSystemSleepPolicyEntry { 5015 uint32_t factorMask; 5016 uint32_t factorBits; 5017 uint32_t sleepFlags; 5018 uint32_t wakeEvents; 5019 } __attribute__((packed)); 5020 5021 struct IOPMSystemSleepPolicyTable { 5022 uint32_t signature; 5023 uint16_t version; 5024 uint16_t entryCount; 5025 IOPMSystemSleepPolicyEntry entries[]; 5026 } __attribute__((packed)); 5027 5028 enum { 5029 kIOPMSleepAttributeHibernateSetup = 0x00000001, 5030 kIOPMSleepAttributeHibernateSleep = 0x00000002 5031 }; 5032 5033 static uint32_t 5034 getSleepTypeAttributes( uint32_t sleepType ) 5035 { 5036 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] = 5037 { 5038 /* invalid */ 0, 5039 /* abort */ 0, 5040 /* normal */ 0, 5041 /* safesleep */ kIOPMSleepAttributeHibernateSetup, 5042 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep, 5043 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep, 5044 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep, 5045 /* deepidle */ 0 5046 }; 5047 5048 if (sleepType >= kIOPMSleepTypeLast) { 5049 return 0; 5050 } 5051 5052 return sleepTypeAttributes[sleepType]; 5053 } 5054 5055 bool 5056 IOPMrootDomain::evaluateSystemSleepPolicy( 5057 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode ) 5058 { 5059 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x} 5060 5061 static const IONamedValue factorValues[] = { 5062 SLEEP_FACTOR( SleepTimerWake ), 5063 SLEEP_FACTOR( LidOpen ), 5064 SLEEP_FACTOR( ACPower ), 5065 SLEEP_FACTOR( BatteryLow ), 5066 SLEEP_FACTOR( StandbyNoDelay ), 5067 SLEEP_FACTOR( StandbyForced ), 5068 SLEEP_FACTOR( StandbyDisabled ), 5069 SLEEP_FACTOR( USBExternalDevice ), 5070 SLEEP_FACTOR( BluetoothHIDDevice ), 5071 SLEEP_FACTOR( ExternalMediaMounted ), 5072 SLEEP_FACTOR( ThunderboltDevice ), 5073 SLEEP_FACTOR( RTCAlarmScheduled ), 5074 SLEEP_FACTOR( MagicPacketWakeEnabled ), 5075 SLEEP_FACTOR( HibernateForced ), 5076 SLEEP_FACTOR( AutoPowerOffDisabled ), 5077 SLEEP_FACTOR( AutoPowerOffForced ), 5078 SLEEP_FACTOR( ExternalDisplay ), 5079 SLEEP_FACTOR( NetworkKeepAliveActive ), 5080 SLEEP_FACTOR( LocalUserActivity ), 5081 SLEEP_FACTOR( HibernateFailed ), 5082 SLEEP_FACTOR( ThermalWarning ), 5083 SLEEP_FACTOR( DisplayCaptured ), 5084 { 0, NULL } 5085 }; 5086 5087 const IOPMSystemSleepPolicyTable * pt; 5088 OSSharedPtr<OSObject> prop; 5089 OSData * policyData; 5090 uint64_t currentFactors = 0; 5091 char currentFactorsBuf[512]; 5092 uint32_t standbyDelay = 0; 5093 uint32_t powerOffDelay = 0; 5094 uint32_t powerOffTimer = 0; 5095 uint32_t standbyTimer = 0; 5096 uint32_t mismatch; 5097 bool standbyEnabled; 5098 bool powerOffEnabled; 5099 bool found = false; 5100 5101 // Get platform's sleep policy table 5102 if (!gSleepPolicyHandler) { 5103 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey); 5104 if (!prop) { 5105 goto done; 5106 } 5107 } 5108 5109 // Fetch additional settings 5110 standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay) 5111 && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue)); 5112 powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay) 5113 && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue)); 5114 if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) { 5115 powerOffTimer = powerOffDelay; 5116 } 5117 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) { 5118 standbyTimer = standbyDelay; 5119 } 5120 5121 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n", 5122 sleepPhase, standbyEnabled, standbyDelay, standbyTimer, 5123 powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode); 5124 5125 currentFactorsBuf[0] = 0; 5126 // pmset level overrides 5127 if ((*hibMode & kIOHibernateModeOn) == 0) { 5128 if (!gSleepPolicyHandler) { 5129 standbyEnabled = false; 5130 powerOffEnabled = false; 5131 } 5132 } else if (!(*hibMode & kIOHibernateModeSleep)) { 5133 // Force hibernate (i.e. mode 25) 5134 // If standby is enabled, force standy. 5135 // If poweroff is enabled, force poweroff. 5136 if (standbyEnabled) { 5137 currentFactors |= kIOPMSleepFactorStandbyForced; 5138 } else if (powerOffEnabled) { 5139 currentFactors |= kIOPMSleepFactorAutoPowerOffForced; 5140 } else { 5141 currentFactors |= kIOPMSleepFactorHibernateForced; 5142 } 5143 } 5144 5145 // Current factors based on environment and assertions 5146 if (sleepTimerMaintenance) { 5147 currentFactors |= kIOPMSleepFactorSleepTimerWake; 5148 } 5149 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) { 5150 currentFactors |= kIOPMSleepFactorSleepTimerWake; 5151 } 5152 if (!clamshellClosed) { 5153 currentFactors |= kIOPMSleepFactorLidOpen; 5154 } 5155 if (acAdaptorConnected) { 5156 currentFactors |= kIOPMSleepFactorACPower; 5157 } 5158 if (lowBatteryCondition) { 5159 hibernateMode = 0; 5160 getSleepOption(kIOHibernateModeKey, &hibernateMode); 5161 if ((hibernateMode & kIOHibernateModeOn) == 0) { 5162 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n"); 5163 } else { 5164 currentFactors |= kIOPMSleepFactorBatteryLow; 5165 } 5166 } 5167 if (!standbyDelay || !standbyTimer) { 5168 currentFactors |= kIOPMSleepFactorStandbyNoDelay; 5169 } 5170 if (standbyNixed || !standbyEnabled) { 5171 currentFactors |= kIOPMSleepFactorStandbyDisabled; 5172 } 5173 if (resetTimers) { 5174 currentFactors |= kIOPMSleepFactorLocalUserActivity; 5175 currentFactors &= ~kIOPMSleepFactorSleepTimerWake; 5176 } 5177 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) != 5178 kIOPMDriverAssertionLevelOff) { 5179 currentFactors |= kIOPMSleepFactorUSBExternalDevice; 5180 } 5181 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) != 5182 kIOPMDriverAssertionLevelOff) { 5183 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice; 5184 } 5185 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) != 5186 kIOPMDriverAssertionLevelOff) { 5187 currentFactors |= kIOPMSleepFactorExternalMediaMounted; 5188 } 5189 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) != 5190 kIOPMDriverAssertionLevelOff) { 5191 currentFactors |= kIOPMSleepFactorThunderboltDevice; 5192 } 5193 if (_scheduledAlarmMask != 0) { 5194 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled; 5195 } 5196 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) != 5197 kIOPMDriverAssertionLevelOff) { 5198 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled; 5199 } 5200 #define TCPKEEPALIVE 1 5201 #if TCPKEEPALIVE 5202 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) != 5203 kIOPMDriverAssertionLevelOff) { 5204 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive; 5205 } 5206 #endif 5207 if (!powerOffEnabled) { 5208 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled; 5209 } 5210 if (desktopMode) { 5211 currentFactors |= kIOPMSleepFactorExternalDisplay; 5212 } 5213 if (userWasActive) { 5214 currentFactors |= kIOPMSleepFactorLocalUserActivity; 5215 } 5216 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) { 5217 currentFactors |= kIOPMSleepFactorHibernateFailed; 5218 } 5219 if (thermalWarningState) { 5220 currentFactors |= kIOPMSleepFactorThermalWarning; 5221 } 5222 5223 for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) { 5224 uint32_t factor = 1 << factorBit; 5225 if (factor & currentFactors) { 5226 strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf)); 5227 strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf)); 5228 } 5229 } 5230 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf); 5231 5232 if (gSleepPolicyHandler) { 5233 uint32_t savedHibernateMode; 5234 IOReturn result; 5235 5236 if (!gSleepPolicyVars) { 5237 gSleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1); 5238 if (!gSleepPolicyVars) { 5239 goto done; 5240 } 5241 bzero(gSleepPolicyVars, sizeof(*gSleepPolicyVars)); 5242 } 5243 gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature; 5244 gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion; 5245 gSleepPolicyVars->currentCapability = _currentCapability; 5246 gSleepPolicyVars->highestCapability = _highestCapability; 5247 gSleepPolicyVars->sleepFactors = currentFactors; 5248 gSleepPolicyVars->sleepReason = lastSleepReason; 5249 gSleepPolicyVars->sleepPhase = sleepPhase; 5250 gSleepPolicyVars->standbyDelay = standbyDelay; 5251 gSleepPolicyVars->standbyTimer = standbyTimer; 5252 gSleepPolicyVars->poweroffDelay = powerOffDelay; 5253 gSleepPolicyVars->scheduledAlarms = _scheduledAlarmMask | _userScheduledAlarmMask; 5254 gSleepPolicyVars->poweroffTimer = powerOffTimer; 5255 5256 if (kIOPMSleepPhase0 == sleepPhase) { 5257 // preserve hibernateMode 5258 savedHibernateMode = gSleepPolicyVars->hibernateMode; 5259 gSleepPolicyVars->hibernateMode = *hibMode; 5260 } else if (kIOPMSleepPhase1 == sleepPhase) { 5261 // use original hibernateMode for phase2 5262 gSleepPolicyVars->hibernateMode = *hibMode; 5263 } 5264 5265 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params); 5266 5267 if (kIOPMSleepPhase0 == sleepPhase) { 5268 // restore hibernateMode 5269 gSleepPolicyVars->hibernateMode = savedHibernateMode; 5270 } 5271 5272 if ((result != kIOReturnSuccess) || 5273 (kIOPMSleepTypeInvalid == params->sleepType) || 5274 (params->sleepType >= kIOPMSleepTypeLast) || 5275 (kIOPMSystemSleepParametersVersion != params->version)) { 5276 MSG("sleep policy handler error\n"); 5277 goto done; 5278 } 5279 5280 if ((getSleepTypeAttributes(params->sleepType) & 5281 kIOPMSleepAttributeHibernateSetup) && 5282 ((*hibMode & kIOHibernateModeOn) == 0)) { 5283 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep); 5284 } 5285 5286 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n", 5287 params->version, params->sleepType, params->sleepFlags, 5288 params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer); 5289 found = true; 5290 goto done; 5291 } 5292 5293 // Policy table is meaningless without standby enabled 5294 if (!standbyEnabled) { 5295 goto done; 5296 } 5297 5298 // Validate the sleep policy table 5299 policyData = OSDynamicCast(OSData, prop.get()); 5300 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) { 5301 goto done; 5302 } 5303 5304 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy(); 5305 if ((pt->signature != kIOPMSystemSleepPolicySignature) || 5306 (pt->version != 1) || (0 == pt->entryCount)) { 5307 goto done; 5308 } 5309 5310 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) != 5311 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) { 5312 goto done; 5313 } 5314 5315 for (uint32_t i = 0; i < pt->entryCount; i++) { 5316 const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i]; 5317 mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask); 5318 5319 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n", 5320 entry->factorMask, entry->factorBits, 5321 entry->sleepFlags, entry->wakeEvents, mismatch); 5322 if (mismatch) { 5323 continue; 5324 } 5325 5326 DLOG("^ found match\n"); 5327 found = true; 5328 5329 params->version = kIOPMSystemSleepParametersVersion; 5330 params->reserved1 = 1; 5331 if (entry->sleepFlags & kIOPMSleepFlagHibernate) { 5332 params->sleepType = kIOPMSleepTypeStandby; 5333 } else { 5334 params->sleepType = kIOPMSleepTypeNormalSleep; 5335 } 5336 5337 params->ecWakeEvents = entry->wakeEvents; 5338 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) { 5339 if (kIOPMSleepPhase2 == sleepPhase) { 5340 clock_sec_t now_secs = gIOLastSleepTime.tv_sec; 5341 5342 if (!_standbyTimerResetSeconds || 5343 (now_secs <= _standbyTimerResetSeconds)) { 5344 // Reset standby timer adjustment 5345 _standbyTimerResetSeconds = now_secs; 5346 DLOG("standby delay %u, reset %u\n", 5347 standbyDelay, (uint32_t) _standbyTimerResetSeconds); 5348 } else if (standbyDelay) { 5349 // Shorten the standby delay timer 5350 clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds; 5351 if (standbyDelay > elapsed) { 5352 standbyDelay -= elapsed; 5353 } else { 5354 standbyDelay = 1; // must be > 0 5355 } 5356 DLOG("standby delay %u, elapsed %u\n", 5357 standbyDelay, (uint32_t) elapsed); 5358 } 5359 } 5360 params->ecWakeTimer = standbyDelay; 5361 } else if (kIOPMSleepPhase2 == sleepPhase) { 5362 // A sleep that does not enable the sleep timer will reset 5363 // the standby delay adjustment. 5364 _standbyTimerResetSeconds = 0; 5365 } 5366 break; 5367 } 5368 5369 done: 5370 return found; 5371 } 5372 5373 static IOPMSystemSleepParameters gEarlySystemSleepParams; 5374 5375 void 5376 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void ) 5377 { 5378 // Evaluate early (priority interest phase), before drivers sleep. 5379 5380 DLOG("%s\n", __FUNCTION__); 5381 removeProperty(kIOPMSystemSleepParametersKey); 5382 5383 // Full wake resets the standby timer delay adjustment 5384 if (_highestCapability & kIOPMSystemCapabilityGraphics) { 5385 _standbyTimerResetSeconds = 0; 5386 } 5387 5388 hibernateDisabled = false; 5389 hibernateMode = 0; 5390 getSleepOption(kIOHibernateModeKey, &hibernateMode); 5391 5392 // Save for late evaluation if sleep is aborted 5393 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams)); 5394 5395 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1, 5396 &hibernateMode)) { 5397 if (!hibernateRetry && 5398 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) & 5399 kIOPMSleepAttributeHibernateSetup) == 0)) { 5400 // skip hibernate setup 5401 hibernateDisabled = true; 5402 } 5403 } 5404 5405 // Publish IOPMSystemSleepType 5406 uint32_t sleepType = gEarlySystemSleepParams.sleepType; 5407 if (sleepType == kIOPMSleepTypeInvalid) { 5408 // no sleep policy 5409 sleepType = kIOPMSleepTypeNormalSleep; 5410 if (hibernateMode & kIOHibernateModeOn) { 5411 sleepType = (hibernateMode & kIOHibernateModeSleep) ? 5412 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate; 5413 } 5414 } else if ((sleepType == kIOPMSleepTypeStandby) && 5415 (gEarlySystemSleepParams.ecPoweroffTimer)) { 5416 // report the lowest possible sleep state 5417 sleepType = kIOPMSleepTypePowerOff; 5418 } 5419 5420 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32); 5421 } 5422 5423 void 5424 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void ) 5425 { 5426 IOPMSystemSleepParameters params; 5427 OSSharedPtr<OSData> paramsData; 5428 bool wakeNow; 5429 // Evaluate sleep policy after sleeping drivers but before platform sleep. 5430 5431 DLOG("%s\n", __FUNCTION__); 5432 5433 bzero(¶ms, sizeof(params)); 5434 wakeNow = false; 5435 if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) { 5436 if ((kIOPMSleepTypeStandby == params.sleepType) 5437 && gIOHibernateStandbyDisabled && gSleepPolicyVars 5438 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced) 5439 & gSleepPolicyVars->sleepFactors))) { 5440 standbyNixed = true; 5441 wakeNow = true; 5442 } 5443 if (wakeNow 5444 || ((hibernateDisabled || hibernateAborted) && 5445 (getSleepTypeAttributes(params.sleepType) & 5446 kIOPMSleepAttributeHibernateSetup))) { 5447 // Final evaluation picked a state requiring hibernation, 5448 // but hibernate isn't going to proceed. Arm a short sleep using 5449 // the early non-hibernate sleep parameters. 5450 bcopy(&gEarlySystemSleepParams, ¶ms, sizeof(params)); 5451 params.sleepType = kIOPMSleepTypeAbortedSleep; 5452 params.ecWakeTimer = 1; 5453 if (standbyNixed) { 5454 resetTimers = true; 5455 } else { 5456 // Set hibernateRetry flag to force hibernate setup on the 5457 // next sleep. 5458 hibernateRetry = true; 5459 } 5460 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n", 5461 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed); 5462 } else { 5463 hibernateRetry = false; 5464 } 5465 5466 if (kIOPMSleepTypeAbortedSleep != params.sleepType) { 5467 resetTimers = false; 5468 } 5469 5470 paramsData = OSData::withBytes(¶ms, sizeof(params)); 5471 if (paramsData) { 5472 setProperty(kIOPMSystemSleepParametersKey, paramsData.get()); 5473 } 5474 5475 if (getSleepTypeAttributes(params.sleepType) & 5476 kIOPMSleepAttributeHibernateSleep) { 5477 // Disable sleep to force hibernation 5478 gIOHibernateMode &= ~kIOHibernateModeSleep; 5479 } 5480 } 5481 } 5482 5483 bool 5484 IOPMrootDomain::getHibernateSettings( 5485 uint32_t * hibernateModePtr, 5486 uint32_t * hibernateFreeRatio, 5487 uint32_t * hibernateFreeTime ) 5488 { 5489 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly() 5490 // has updated the hibernateDisabled flag. 5491 5492 bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr); 5493 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio); 5494 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime); 5495 if (hibernateDisabled) { 5496 *hibernateModePtr = 0; 5497 } else if (gSleepPolicyHandler) { 5498 *hibernateModePtr = hibernateMode; 5499 } 5500 DLOG("hibernateMode 0x%x\n", *hibernateModePtr); 5501 return ok; 5502 } 5503 5504 bool 5505 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option ) 5506 { 5507 OSSharedPtr<OSObject> optionsProp; 5508 OSDictionary * optionsDict; 5509 OSSharedPtr<OSObject> obj; 5510 OSNumber * num; 5511 bool ok = false; 5512 5513 optionsProp = copyProperty(kRootDomainSleepOptionsKey); 5514 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get()); 5515 5516 if (optionsDict) { 5517 obj.reset(optionsDict->getObject(key), OSRetain); 5518 } 5519 if (!obj) { 5520 obj = copyProperty(key); 5521 } 5522 if (obj) { 5523 if ((num = OSDynamicCast(OSNumber, obj.get()))) { 5524 *option = num->unsigned32BitValue(); 5525 ok = true; 5526 } else if (OSDynamicCast(OSBoolean, obj.get())) { 5527 *option = (obj == kOSBooleanTrue) ? 1 : 0; 5528 ok = true; 5529 } 5530 } 5531 5532 return ok; 5533 } 5534 #endif /* HIBERNATION */ 5535 5536 IOReturn 5537 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer ) 5538 { 5539 #if HIBERNATION 5540 IOPMSystemSleepParameters params; 5541 uint32_t hibMode = 0; 5542 bool ok; 5543 5544 if (gIOPMWorkLoop->inGate() == false) { 5545 IOReturn ret = gIOPMWorkLoop->runAction( 5546 OSMemberFunctionCast(IOWorkLoop::Action, this, 5547 &IOPMrootDomain::getSystemSleepType), 5548 (OSObject *) this, 5549 (void *) sleepType, (void *) standbyTimer); 5550 return ret; 5551 } 5552 5553 getSleepOption(kIOHibernateModeKey, &hibMode); 5554 bzero(¶ms, sizeof(params)); 5555 5556 ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode); 5557 if (ok) { 5558 *sleepType = params.sleepType; 5559 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) && 5560 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) { 5561 DLOG("Standby delay is not set\n"); 5562 *standbyTimer = 0; 5563 } 5564 return kIOReturnSuccess; 5565 } 5566 #endif 5567 5568 return kIOReturnUnsupported; 5569 } 5570 5571 // MARK: - 5572 // MARK: Shutdown and Restart 5573 5574 //****************************************************************************** 5575 // handlePlatformHaltRestart 5576 // 5577 //****************************************************************************** 5578 5579 // Phases while performing shutdown/restart 5580 typedef enum { 5581 kNotifyDone = 0x00, 5582 kNotifyPriorityClients = 0x10, 5583 kNotifyPowerPlaneDrivers = 0x20, 5584 kNotifyHaltRestartAction = 0x30, 5585 kQuiescePM = 0x40, 5586 } shutdownPhase_t; 5587 5588 5589 struct HaltRestartApplierContext { 5590 IOPMrootDomain * RootDomain; 5591 unsigned long PowerState; 5592 IOPMPowerFlags PowerFlags; 5593 UInt32 MessageType; 5594 UInt32 Counter; 5595 const char * LogString; 5596 shutdownPhase_t phase; 5597 5598 IOServiceInterestHandler handler; 5599 } gHaltRestartCtx; 5600 5601 const char * 5602 shutdownPhase2String(shutdownPhase_t phase) 5603 { 5604 switch (phase) { 5605 case kNotifyDone: 5606 return "Notifications completed"; 5607 case kNotifyPriorityClients: 5608 return "Notifying priority clients"; 5609 case kNotifyPowerPlaneDrivers: 5610 return "Notifying power plane drivers"; 5611 case kNotifyHaltRestartAction: 5612 return "Notifying HaltRestart action handlers"; 5613 case kQuiescePM: 5614 return "Quiescing PM"; 5615 default: 5616 return "Unknown"; 5617 } 5618 } 5619 5620 static void 5621 platformHaltRestartApplier( OSObject * object, void * context ) 5622 { 5623 IOPowerStateChangeNotification notify; 5624 HaltRestartApplierContext * ctx; 5625 AbsoluteTime startTime, elapsedTime; 5626 uint32_t deltaTime; 5627 5628 ctx = (HaltRestartApplierContext *) context; 5629 5630 _IOServiceInterestNotifier * notifier; 5631 notifier = OSDynamicCast(_IOServiceInterestNotifier, object); 5632 memset(¬ify, 0, sizeof(notify)); 5633 notify.powerRef = (void *)(uintptr_t)ctx->Counter; 5634 notify.returnValue = 0; 5635 notify.stateNumber = ctx->PowerState; 5636 notify.stateFlags = ctx->PowerFlags; 5637 5638 if (notifier) { 5639 ctx->handler = notifier->handler; 5640 } 5641 5642 clock_get_uptime(&startTime); 5643 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)¬ify ); 5644 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime); 5645 5646 if ((deltaTime > kPMHaltTimeoutMS) && notifier) { 5647 LOG("%s handler %p took %u ms\n", 5648 ctx->LogString, OBFUSCATE(notifier->handler), deltaTime); 5649 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime); 5650 } 5651 5652 ctx->handler = NULL; 5653 ctx->Counter++; 5654 } 5655 5656 static void 5657 quiescePowerTreeCallback( void * target, void * param ) 5658 { 5659 IOLockLock(gPMHaltLock); 5660 gPMQuiesced = true; 5661 thread_wakeup(param); 5662 IOLockUnlock(gPMHaltLock); 5663 } 5664 5665 void 5666 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type ) 5667 { 5668 AbsoluteTime startTime, elapsedTime; 5669 uint32_t deltaTime; 5670 5671 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx)); 5672 gHaltRestartCtx.RootDomain = this; 5673 5674 clock_get_uptime(&startTime); 5675 switch (pe_type) { 5676 case kPEHaltCPU: 5677 case kPEUPSDelayHaltCPU: 5678 gHaltRestartCtx.PowerState = OFF_STATE; 5679 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff; 5680 gHaltRestartCtx.LogString = "PowerOff"; 5681 break; 5682 5683 case kPERestartCPU: 5684 gHaltRestartCtx.PowerState = RESTART_STATE; 5685 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart; 5686 gHaltRestartCtx.LogString = "Restart"; 5687 break; 5688 5689 case kPEPagingOff: 5690 gHaltRestartCtx.PowerState = ON_STATE; 5691 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff; 5692 gHaltRestartCtx.LogString = "PagingOff"; 5693 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff); 5694 #if HIBERNATION 5695 IOHibernateSystemRestart(); 5696 #endif 5697 break; 5698 5699 default: 5700 return; 5701 } 5702 5703 gHaltRestartCtx.phase = kNotifyPriorityClients; 5704 // Notify legacy clients 5705 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx); 5706 5707 // For normal shutdown, turn off File Server Mode. 5708 if (kPEHaltCPU == pe_type) { 5709 OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey); 5710 OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32); 5711 if (setting && num) { 5712 setPMSetting(setting.get(), num.get()); 5713 } 5714 } 5715 5716 if (kPEPagingOff != pe_type) { 5717 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers; 5718 // Notify in power tree order 5719 notifySystemShutdown(this, gHaltRestartCtx.MessageType); 5720 } 5721 5722 gHaltRestartCtx.phase = kNotifyHaltRestartAction; 5723 #if defined(XNU_TARGET_OS_OSX) 5724 IOCPURunPlatformHaltRestartActions(pe_type); 5725 #else /* !defined(XNU_TARGET_OS_OSX) */ 5726 if (kPEPagingOff != pe_type) { 5727 IOCPURunPlatformHaltRestartActions(pe_type); 5728 } 5729 #endif /* !defined(XNU_TARGET_OS_OSX) */ 5730 5731 // Wait for PM to quiesce 5732 if ((kPEPagingOff != pe_type) && gPMHaltLock) { 5733 gHaltRestartCtx.phase = kQuiescePM; 5734 AbsoluteTime quiesceTime = mach_absolute_time(); 5735 5736 IOLockLock(gPMHaltLock); 5737 gPMQuiesced = false; 5738 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) == 5739 kIOReturnSuccess) { 5740 while (!gPMQuiesced) { 5741 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT); 5742 } 5743 } 5744 IOLockUnlock(gPMHaltLock); 5745 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime); 5746 DLOG("PM quiesce took %u ms\n", deltaTime); 5747 halt_log_enter("Quiesce", NULL, elapsedTime); 5748 } 5749 gHaltRestartCtx.phase = kNotifyDone; 5750 5751 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime); 5752 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime); 5753 5754 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime); 5755 5756 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime); 5757 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime); 5758 5759 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) { 5760 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog); 5761 } 5762 5763 checkShutdownTimeout(); 5764 } 5765 5766 bool 5767 IOPMrootDomain::checkShutdownTimeout() 5768 { 5769 AbsoluteTime elapsedTime; 5770 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime); 5771 5772 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) { 5773 return true; 5774 } 5775 return false; 5776 } 5777 5778 void 5779 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs) 5780 { 5781 if (gHaltLog) { 5782 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) { 5783 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime); 5784 } 5785 panic("%s timed out in phase '%s'. Total %d ms:%s", 5786 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog); 5787 } else { 5788 panic("%s timed out in phase \'%s\'. Total %d ms", 5789 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs); 5790 } 5791 } 5792 5793 //****************************************************************************** 5794 // shutdownSystem 5795 // 5796 //****************************************************************************** 5797 5798 IOReturn 5799 IOPMrootDomain::shutdownSystem( void ) 5800 { 5801 return kIOReturnUnsupported; 5802 } 5803 5804 //****************************************************************************** 5805 // restartSystem 5806 // 5807 //****************************************************************************** 5808 5809 IOReturn 5810 IOPMrootDomain::restartSystem( void ) 5811 { 5812 return kIOReturnUnsupported; 5813 } 5814 5815 // MARK: - 5816 // MARK: System Capability 5817 5818 //****************************************************************************** 5819 // tagPowerPlaneService 5820 // 5821 // Running on PM work loop thread. 5822 //****************************************************************************** 5823 5824 void 5825 IOPMrootDomain::tagPowerPlaneService( 5826 IOService * service, 5827 IOPMActions * actions, 5828 IOPMPowerStateIndex maxPowerState ) 5829 { 5830 uint32_t flags = 0; 5831 5832 memset(actions, 0, sizeof(*actions)); 5833 actions->target = this; 5834 5835 if (service == this) { 5836 actions->actionPowerChangeStart = 5837 OSMemberFunctionCast( 5838 IOPMActionPowerChangeStart, this, 5839 &IOPMrootDomain::handleOurPowerChangeStart); 5840 5841 actions->actionPowerChangeDone = 5842 OSMemberFunctionCast( 5843 IOPMActionPowerChangeDone, this, 5844 &IOPMrootDomain::handleOurPowerChangeDone); 5845 5846 actions->actionPowerChangeOverride = 5847 OSMemberFunctionCast( 5848 IOPMActionPowerChangeOverride, this, 5849 &IOPMrootDomain::overrideOurPowerChange); 5850 return; 5851 } 5852 5853 #if DISPLAY_WRANGLER_PRESENT 5854 if (NULL != service->metaCast("IODisplayWrangler")) { 5855 // XXX should this really retain? 5856 wrangler.reset(service, OSRetain); 5857 wrangler->registerInterest(gIOGeneralInterest, 5858 &displayWranglerNotification, this, NULL); 5859 5860 // found the display wrangler, check for any display assertions already created 5861 if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) { 5862 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n"); 5863 wrangler->setIgnoreIdleTimer( true ); 5864 } 5865 flags |= kPMActionsFlagIsDisplayWrangler; 5866 } 5867 #endif /* DISPLAY_WRANGLER_PRESENT */ 5868 5869 if (service->propertyExists("IOPMStrictTreeOrder")) { 5870 flags |= kPMActionsFlagIsGraphicsDriver; 5871 } 5872 if (service->propertyExists("IOPMUnattendedWakePowerState")) { 5873 flags |= kPMActionsFlagIsAudioDriver; 5874 } 5875 5876 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey); 5877 if (prop) { 5878 OSNumber * num = OSDynamicCast(OSNumber, prop.get()); 5879 if (num) { 5880 actions->darkWakePowerState = num->unsigned32BitValue(); 5881 if (actions->darkWakePowerState < maxPowerState) { 5882 flags |= kPMActionsFlagHasDarkWakePowerState; 5883 } 5884 } 5885 } 5886 5887 // Find the power connection object that is a child of the PCI host 5888 // bridge, and has a graphics/audio device attached below. Mark the 5889 // power branch for delayed child notifications. 5890 5891 if (flags) { 5892 IORegistryEntry * child = service; 5893 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane); 5894 5895 while (child != this) { 5896 if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) { 5897 // Skip delaying notifications and clamping power on external graphics and audio devices. 5898 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags); 5899 flags = 0; 5900 break; 5901 } 5902 if ((parent == pciHostBridgeDriver) || 5903 (parent == this)) { 5904 if (OSDynamicCast(IOPowerConnection, child)) { 5905 IOPowerConnection * conn = (IOPowerConnection *) child; 5906 conn->delayChildNotification = true; 5907 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID()); 5908 } 5909 break; 5910 } 5911 child = parent; 5912 parent = child->getParentEntry(gIOPowerPlane); 5913 } 5914 } 5915 5916 if (flags) { 5917 DLOG("%s tag flags %x\n", service->getName(), flags); 5918 actions->flags |= flags; 5919 actions->actionPowerChangeOverride = 5920 OSMemberFunctionCast( 5921 IOPMActionPowerChangeOverride, this, 5922 &IOPMrootDomain::overridePowerChangeForService); 5923 5924 if (flags & kPMActionsFlagIsDisplayWrangler) { 5925 actions->actionActivityTickle = 5926 OSMemberFunctionCast( 5927 IOPMActionActivityTickle, this, 5928 &IOPMrootDomain::handleActivityTickleForDisplayWrangler); 5929 5930 actions->actionUpdatePowerClient = 5931 OSMemberFunctionCast( 5932 IOPMActionUpdatePowerClient, this, 5933 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler); 5934 } 5935 return; 5936 } 5937 5938 // Locate the first PCI host bridge for PMTrace. 5939 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) { 5940 IOService * provider = service->getProvider(); 5941 if (OSDynamicCast(IOPlatformDevice, provider) && 5942 provider->inPlane(gIODTPlane)) { 5943 pciHostBridgeDevice.reset(provider, OSNoRetain); 5944 pciHostBridgeDriver.reset(service, OSNoRetain); 5945 DLOG("PMTrace found PCI host bridge %s->%s\n", 5946 provider->getName(), service->getName()); 5947 } 5948 } 5949 5950 // Tag top-level PCI devices. The order of PMinit() call does not 5951 // change across boots and is used as the PCI bit number. 5952 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) { 5953 // Would prefer to check built-in property, but tagPowerPlaneService() 5954 // is called before pciDevice->registerService(). 5955 IORegistryEntry * parent = service->getParentEntry(gIODTPlane); 5956 if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) { 5957 int bit = pmTracer->recordTopLevelPCIDevice( service ); 5958 if (bit >= 0) { 5959 // Save the assigned bit for fast lookup. 5960 actions->flags |= (bit & kPMActionsPCIBitNumberMask); 5961 5962 actions->actionPowerChangeStart = 5963 OSMemberFunctionCast( 5964 IOPMActionPowerChangeStart, this, 5965 &IOPMrootDomain::handlePowerChangeStartForPCIDevice); 5966 5967 actions->actionPowerChangeDone = 5968 OSMemberFunctionCast( 5969 IOPMActionPowerChangeDone, this, 5970 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice); 5971 } 5972 } 5973 } 5974 } 5975 5976 //****************************************************************************** 5977 // PM actions for root domain 5978 //****************************************************************************** 5979 5980 void 5981 IOPMrootDomain::overrideOurPowerChange( 5982 IOService * service, 5983 IOPMActions * actions, 5984 const IOPMRequest * request, 5985 IOPMPowerStateIndex * inOutPowerState, 5986 IOPMPowerChangeFlags * inOutChangeFlags ) 5987 { 5988 uint32_t changeFlags = *inOutChangeFlags; 5989 uint32_t desiredPowerState = (uint32_t) *inOutPowerState; 5990 uint32_t currentPowerState = (uint32_t) getPowerState(); 5991 5992 if (request->getTag() == 0) { 5993 // Set a tag for any request that originates from IOServicePM 5994 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals); 5995 } 5996 5997 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n", 5998 getPowerStateString(currentPowerState), 5999 getPowerStateString(desiredPowerState), 6000 _currentCapability, changeFlags, 6001 request->getTag()); 6002 6003 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) { 6004 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT) 6005 *inOutChangeFlags |= kIOPMNotDone; 6006 return; 6007 } 6008 6009 if (changeFlags & kIOPMParentInitiated) { 6010 // Root parent is permanently pegged at max power, 6011 // a parent initiated power change is unexpected. 6012 *inOutChangeFlags |= kIOPMNotDone; 6013 return; 6014 } 6015 6016 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 6017 if (lowBatteryCondition && (desiredPowerState < currentPowerState)) { 6018 // Reject sleep requests when lowBatteryCondition is TRUE to 6019 // avoid racing with the impending system shutdown. 6020 *inOutChangeFlags |= kIOPMNotDone; 6021 return; 6022 } 6023 #endif 6024 6025 if (desiredPowerState < currentPowerState) { 6026 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) { 6027 // Root domain is dropping power state from ON->SLEEP. 6028 // If system is in full wake, first enter dark wake by 6029 // converting the power drop to a capability change. 6030 // Once in dark wake, transition to sleep state ASAP. 6031 6032 darkWakeToSleepASAP = true; 6033 6034 // Drop graphics and audio capability 6035 _desiredCapability &= ~( 6036 kIOPMSystemCapabilityGraphics | 6037 kIOPMSystemCapabilityAudio); 6038 6039 // Convert to capability change (ON->ON) 6040 *inOutPowerState = getRUN_STATE(); 6041 *inOutChangeFlags |= kIOPMSynchronize; 6042 6043 // Revert device desire from SLEEP to ON 6044 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride); 6045 } else { 6046 // System is already in dark wake, ok to drop power state. 6047 // Broadcast root power down to entire tree. 6048 *inOutChangeFlags |= kIOPMRootChangeDown; 6049 } 6050 } else if (desiredPowerState > currentPowerState) { 6051 if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) { 6052 // Broadcast power up when waking from sleep, but not for the 6053 // initial power change at boot by checking for cpu capability. 6054 *inOutChangeFlags |= kIOPMRootChangeUp; 6055 } 6056 } 6057 } 6058 6059 void 6060 IOPMrootDomain::handleOurPowerChangeStart( 6061 IOService * service, 6062 IOPMActions * actions, 6063 const IOPMRequest * request, 6064 IOPMPowerStateIndex newPowerState, 6065 IOPMPowerChangeFlags * inOutChangeFlags ) 6066 { 6067 IOPMRequestTag requestTag = request->getTag(); 6068 IOPMRequestTag sleepReason; 6069 6070 uint32_t changeFlags = *inOutChangeFlags; 6071 uint32_t currentPowerState = (uint32_t) getPowerState(); 6072 bool publishSleepReason = false; 6073 6074 // Check if request has a valid sleep reason 6075 sleepReason = REQUEST_TAG_TO_REASON(requestTag); 6076 if (sleepReason < kIOPMSleepReasonClamshell) { 6077 sleepReason = kIOPMSleepReasonIdle; 6078 } 6079 6080 _systemTransitionType = kSystemTransitionNone; 6081 _systemMessageClientMask = 0; 6082 capabilityLoss = false; 6083 toldPowerdCapWillChange = false; 6084 6085 // Emergency notifications may arrive after the initial sleep request 6086 // has been queued. Override the sleep reason so powerd and others can 6087 // treat this as an emergency sleep. 6088 if (lowBatteryCondition) { 6089 sleepReason = kIOPMSleepReasonLowPower; 6090 } else if (thermalEmergencyState) { 6091 sleepReason = kIOPMSleepReasonThermalEmergency; 6092 } 6093 6094 // 1. Explicit capability change. 6095 if (changeFlags & kIOPMSynchronize) { 6096 if (newPowerState == ON_STATE) { 6097 if (changeFlags & kIOPMSyncNoChildNotify) { 6098 _systemTransitionType = kSystemTransitionNewCapClient; 6099 } else { 6100 _systemTransitionType = kSystemTransitionCapability; 6101 } 6102 } 6103 } 6104 // 2. Going to sleep (cancellation still possible). 6105 else if (newPowerState < currentPowerState) { 6106 _systemTransitionType = kSystemTransitionSleep; 6107 } 6108 // 3. Woke from (idle or demand) sleep. 6109 else if (!systemBooting && 6110 (changeFlags & kIOPMSelfInitiated) && 6111 (newPowerState > currentPowerState)) { 6112 _systemTransitionType = kSystemTransitionWake; 6113 _desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork; 6114 6115 // Early exit from dark wake to full (e.g. LID open) 6116 if (kFullWakeReasonNone != fullWakeReason) { 6117 _desiredCapability |= ( 6118 kIOPMSystemCapabilityGraphics | 6119 kIOPMSystemCapabilityAudio); 6120 6121 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 6122 if (fullWakeReason == kFullWakeReasonLocalUser) { 6123 darkWakeExit = true; 6124 darkWakeToSleepASAP = false; 6125 setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ? 6126 kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser); 6127 } 6128 #endif 6129 } 6130 #if HIBERNATION 6131 IOHibernateSetWakeCapabilities(_desiredCapability); 6132 #endif 6133 } 6134 6135 // Update pending wake capability at the beginning of every 6136 // state transition (including synchronize). This will become 6137 // the current capability at the end of the transition. 6138 6139 if (kSystemTransitionSleep == _systemTransitionType) { 6140 _pendingCapability = 0; 6141 capabilityLoss = true; 6142 } else if (kSystemTransitionNewCapClient != _systemTransitionType) { 6143 _pendingCapability = _desiredCapability | 6144 kIOPMSystemCapabilityCPU | 6145 kIOPMSystemCapabilityNetwork; 6146 6147 if (_pendingCapability & kIOPMSystemCapabilityGraphics) { 6148 _pendingCapability |= kIOPMSystemCapabilityAudio; 6149 } 6150 6151 if ((kSystemTransitionCapability == _systemTransitionType) && 6152 (_pendingCapability == _currentCapability)) { 6153 // Cancel the PM state change. 6154 _systemTransitionType = kSystemTransitionNone; 6155 *inOutChangeFlags |= kIOPMNotDone; 6156 } 6157 if (__builtin_popcount(_pendingCapability) < 6158 __builtin_popcount(_currentCapability)) { 6159 capabilityLoss = true; 6160 } 6161 } 6162 6163 // 1. Capability change. 6164 if (kSystemTransitionCapability == _systemTransitionType) { 6165 // Dark to Full transition. 6166 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) { 6167 tracePoint( kIOPMTracePointDarkWakeExit ); 6168 6169 #if defined(XNU_TARGET_OS_OSX) 6170 // rdar://problem/65627936 6171 // When a dark->full wake promotion is scheduled before an ON->SLEEP 6172 // power state drop, invalidate any request to drop power state already 6173 // in the queue, including the override variant, unless full wake cannot 6174 // be sustained. Any power state drop queued after this SustainFullWake 6175 // request will not be affected. 6176 if (checkSystemCanSustainFullWake()) { 6177 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake); 6178 } 6179 #endif 6180 6181 willEnterFullWake(); 6182 } 6183 6184 // Full to Dark transition. 6185 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) { 6186 // Clear previous stats 6187 IOLockLock(pmStatsLock); 6188 if (pmStatsAppResponses) { 6189 pmStatsAppResponses = OSArray::withCapacity(5); 6190 } 6191 IOLockUnlock(pmStatsLock); 6192 6193 tracePoint( kIOPMTracePointDarkWakeEntry ); 6194 *inOutChangeFlags |= kIOPMSyncTellPowerDown; 6195 _systemMessageClientMask = kSystemMessageClientPowerd | 6196 kSystemMessageClientLegacyApp; 6197 6198 // rdar://15971327 6199 // Prevent user active transitions before notifying clients 6200 // that system will sleep. 6201 preventTransitionToUserActive(true); 6202 6203 IOService::setAdvisoryTickleEnable( false ); 6204 6205 // Publish the sleep reason for full to dark wake 6206 publishSleepReason = true; 6207 lastSleepReason = fullToDarkReason = sleepReason; 6208 6209 // Publish a UUID for the Sleep --> Wake cycle 6210 handlePublishSleepWakeUUID(true); 6211 if (sleepDelaysReport) { 6212 clock_get_uptime(&ts_sleepStart); 6213 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart); 6214 } 6215 6216 darkWakeExit = false; 6217 } 6218 } 6219 // 2. System sleep. 6220 else if (kSystemTransitionSleep == _systemTransitionType) { 6221 // Beginning of a system sleep transition. 6222 // Cancellation is still possible. 6223 tracePoint( kIOPMTracePointSleepStarted ); 6224 6225 _systemMessageClientMask = kSystemMessageClientAll; 6226 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) { 6227 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp; 6228 } 6229 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) { 6230 // Kernel priority clients are only notified on the initial 6231 // transition to full wake, so don't notify them unless system 6232 // has gained graphics capability since the last system wake. 6233 _systemMessageClientMask &= ~kSystemMessageClientKernel; 6234 } else { 6235 // System was in full wake, but the downwards power transition is driven 6236 // by a request that originates from IOServicePM, so it isn't tagged with 6237 // a valid system sleep reason. 6238 if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) { 6239 // Publish the same reason for full to dark 6240 sleepReason = fullToDarkReason; 6241 } 6242 } 6243 #if HIBERNATION 6244 gIOHibernateState = 0; 6245 #endif 6246 6247 // Record the reason for dark wake back to sleep 6248 // System may not have ever achieved full wake 6249 6250 publishSleepReason = true; 6251 lastSleepReason = sleepReason; 6252 if (sleepDelaysReport) { 6253 clock_get_uptime(&ts_sleepStart); 6254 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart); 6255 } 6256 } 6257 // 3. System wake. 6258 else if (kSystemTransitionWake == _systemTransitionType) { 6259 tracePoint( kIOPMTracePointWakeWillPowerOnClients ); 6260 // Clear stats about sleep 6261 6262 if (AOT_STATE == newPowerState) { 6263 _pendingCapability = 0; 6264 } 6265 6266 if (AOT_STATE == currentPowerState) { 6267 // Wake events are no longer accepted after waking to AOT_STATE. 6268 // Re-enable wake event acceptance to append wake events claimed 6269 // during the AOT to ON_STATE transition. 6270 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable); 6271 } 6272 6273 if (_pendingCapability & kIOPMSystemCapabilityGraphics) { 6274 willEnterFullWake(); 6275 } 6276 } 6277 6278 // The only location where the sleep reason is published. At this point 6279 // sleep can still be cancelled, but sleep reason should be published 6280 // early for logging purposes. 6281 6282 if (publishSleepReason) { 6283 static const char * IOPMSleepReasons[] = 6284 { 6285 kIOPMClamshellSleepKey, 6286 kIOPMPowerButtonSleepKey, 6287 kIOPMSoftwareSleepKey, 6288 kIOPMOSSwitchHibernationKey, 6289 kIOPMIdleSleepKey, 6290 kIOPMLowPowerSleepKey, 6291 kIOPMThermalEmergencySleepKey, 6292 kIOPMMaintenanceSleepKey, 6293 kIOPMSleepServiceExitKey, 6294 kIOPMDarkWakeThermalEmergencyKey, 6295 kIOPMNotificationWakeExitKey 6296 }; 6297 6298 // Record sleep cause in IORegistry 6299 uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell; 6300 if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) { 6301 DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]); 6302 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]); 6303 } 6304 } 6305 6306 if ((kSystemTransitionNone != _systemTransitionType) && 6307 (kSystemTransitionNewCapClient != _systemTransitionType)) { 6308 _systemStateGeneration++; 6309 systemDarkWake = false; 6310 6311 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n", 6312 getPowerStateString(currentPowerState), 6313 getPowerStateString((uint32_t) newPowerState), 6314 _currentCapability, _pendingCapability, 6315 *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask, 6316 requestTag); 6317 } 6318 6319 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) { 6320 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState)); 6321 } 6322 if (_aotNow && (ON_STATE == newPowerState)) { 6323 WAKEEVENT_LOCK(); 6324 aotShouldExit(false, true); 6325 WAKEEVENT_UNLOCK(); 6326 aotExit(false); 6327 } 6328 } 6329 6330 void 6331 IOPMrootDomain::handleOurPowerChangeDone( 6332 IOService * service, 6333 IOPMActions * actions, 6334 const IOPMRequest * request, 6335 IOPMPowerStateIndex oldPowerState, 6336 IOPMPowerChangeFlags changeFlags ) 6337 { 6338 if (kSystemTransitionNewCapClient == _systemTransitionType) { 6339 _systemTransitionType = kSystemTransitionNone; 6340 return; 6341 } 6342 6343 if (_systemTransitionType != kSystemTransitionNone) { 6344 uint32_t currentPowerState = (uint32_t) getPowerState(); 6345 6346 if (changeFlags & kIOPMNotDone) { 6347 // Power down was cancelled or vetoed. 6348 _pendingCapability = _currentCapability; 6349 lastSleepReason = 0; 6350 6351 // When sleep is cancelled or reverted, don't report 6352 // the target (lower) power state as the previous state. 6353 oldPowerState = currentPowerState; 6354 6355 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) && 6356 CAP_CURRENT(kIOPMSystemCapabilityCPU)) { 6357 #if defined(XNU_TARGET_OS_OSX) 6358 pmPowerStateQueue->submitPowerEvent( 6359 kPowerEventPolicyStimulus, 6360 (void *) kStimulusDarkWakeReentry, 6361 _systemStateGeneration ); 6362 #else /* !defined(XNU_TARGET_OS_OSX) */ 6363 // On embedded, there are no factors that can prolong a 6364 // "darkWake" when a power down is vetoed. We need to 6365 // promote to "fullWake" at least once so that factors 6366 // that prevent idle sleep can assert themselves if required 6367 pmPowerStateQueue->submitPowerEvent( 6368 kPowerEventPolicyStimulus, 6369 (void *) kStimulusDarkWakeActivityTickle); 6370 #endif /* !defined(XNU_TARGET_OS_OSX) */ 6371 } 6372 6373 // Revert device desire to max. 6374 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel); 6375 } else { 6376 // Send message on dark wake to full wake promotion. 6377 // tellChangeUp() handles the normal SLEEP->ON case. 6378 6379 if (kSystemTransitionCapability == _systemTransitionType) { 6380 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) { 6381 lastSleepReason = 0; // stop logging wrangler tickles 6382 tellClients(kIOMessageSystemHasPoweredOn); 6383 } 6384 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) { 6385 // Going dark, reset full wake state 6386 // userIsActive will be cleared by wrangler powering down 6387 fullWakeReason = kFullWakeReasonNone; 6388 6389 if (ts_sleepStart) { 6390 clock_get_uptime(&wake2DarkwakeDelay); 6391 SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart); 6392 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay); 6393 ts_sleepStart = 0; 6394 } 6395 } 6396 } 6397 6398 // Reset state after exiting from dark wake. 6399 6400 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) || 6401 CAP_LOSS(kIOPMSystemCapabilityCPU)) { 6402 darkWakeMaintenance = false; 6403 darkWakeToSleepASAP = false; 6404 pciCantSleepValid = false; 6405 darkWakeSleepService = false; 6406 6407 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) { 6408 // Remove the influence of display power assertion 6409 // before next system wake. 6410 if (wrangler) { 6411 wrangler->changePowerStateForRootDomain( 6412 kWranglerPowerStateMin ); 6413 } 6414 removeProperty(gIOPMUserTriggeredFullWakeKey.get()); 6415 } 6416 } 6417 6418 // Entered dark mode. 6419 6420 if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) && 6421 (_pendingCapability & kIOPMSystemCapabilityCPU)) { 6422 // Queue an evaluation of whether to remain in dark wake, 6423 // and for how long. This serves the purpose of draining 6424 // any assertions from the queue. 6425 6426 pmPowerStateQueue->submitPowerEvent( 6427 kPowerEventPolicyStimulus, 6428 (void *) kStimulusDarkWakeEntry, 6429 _systemStateGeneration ); 6430 } 6431 } 6432 6433 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n", 6434 getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState), 6435 _currentCapability, _pendingCapability, 6436 changeFlags, _systemStateGeneration, _systemMessageClientMask, 6437 request->getTag()); 6438 6439 if ((currentPowerState == ON_STATE) && pmAssertions) { 6440 pmAssertions->reportCPUBitAccounting(); 6441 } 6442 6443 if (_pendingCapability & kIOPMSystemCapabilityGraphics) { 6444 displayWakeCnt++; 6445 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 6446 if (clamshellExists && fullWakeThreadCall) { 6447 AbsoluteTime deadline; 6448 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline); 6449 thread_call_enter_delayed(fullWakeThreadCall, deadline); 6450 } 6451 #endif 6452 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) { 6453 darkWakeCnt++; 6454 } 6455 6456 // Update current system capability. 6457 if (_currentCapability != _pendingCapability) { 6458 _currentCapability = _pendingCapability; 6459 } 6460 6461 // Update highest system capability. 6462 6463 _highestCapability |= _currentCapability; 6464 6465 if (darkWakePostTickle && 6466 (kSystemTransitionWake == _systemTransitionType) && 6467 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) == 6468 kDarkWakeFlagPromotionLate) { 6469 darkWakePostTickle = false; 6470 reportUserInput(); 6471 } else if (darkWakeExit) { 6472 requestFullWake( kFullWakeReasonLocalUser ); 6473 } 6474 6475 // Reset tracepoint at completion of capability change, 6476 // completion of wake transition, and aborted sleep transition. 6477 6478 if ((_systemTransitionType == kSystemTransitionCapability) || 6479 (_systemTransitionType == kSystemTransitionWake) || 6480 ((_systemTransitionType == kSystemTransitionSleep) && 6481 (changeFlags & kIOPMNotDone))) { 6482 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64); 6483 tracePoint( kIOPMTracePointSystemUp ); 6484 } 6485 6486 _systemTransitionType = kSystemTransitionNone; 6487 _systemMessageClientMask = 0; 6488 toldPowerdCapWillChange = false; 6489 6490 darkWakeLogClamp = false; 6491 6492 if (lowBatteryCondition) { 6493 privateSleepSystem(kIOPMSleepReasonLowPower); 6494 } else if (thermalEmergencyState) { 6495 privateSleepSystem(kIOPMSleepReasonThermalEmergency); 6496 } else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) { 6497 // Request for full wake is removed while system is waking up to full wake 6498 DLOG("DisplayOn fullwake request is removed\n"); 6499 handleSetDisplayPowerOn(false); 6500 } 6501 6502 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) { 6503 pmPowerStateQueue->submitPowerEvent( 6504 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand ); 6505 } 6506 } 6507 } 6508 6509 //****************************************************************************** 6510 // PM actions for graphics and audio. 6511 //****************************************************************************** 6512 6513 void 6514 IOPMrootDomain::overridePowerChangeForService( 6515 IOService * service, 6516 IOPMActions * actions, 6517 const IOPMRequest * request, 6518 IOPMPowerStateIndex * inOutPowerState, 6519 IOPMPowerChangeFlags * inOutChangeFlags ) 6520 { 6521 uint32_t powerState = (uint32_t) *inOutPowerState; 6522 uint32_t changeFlags = (uint32_t) *inOutChangeFlags; 6523 const uint32_t actionFlags = actions->flags; 6524 6525 if (kSystemTransitionNone == _systemTransitionType) { 6526 // Not in midst of a system transition. 6527 // Do not set kPMActionsStatePowerClamped. 6528 } else if ((actions->state & kPMActionsStatePowerClamped) == 0) { 6529 bool enableClamp = false; 6530 6531 // For most drivers, enable the clamp during ON->Dark transition 6532 // which has the kIOPMSynchronize flag set in changeFlags. 6533 if ((actionFlags & kPMActionsFlagIsDisplayWrangler) && 6534 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) && 6535 (changeFlags & kIOPMSynchronize)) { 6536 enableClamp = true; 6537 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) && 6538 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) && 6539 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) && 6540 (changeFlags & kIOPMSynchronize)) { 6541 enableClamp = true; 6542 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) && 6543 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) && 6544 (changeFlags & kIOPMSynchronize)) { 6545 enableClamp = true; 6546 } else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) && 6547 (_systemTransitionType == kSystemTransitionSleep)) { 6548 // For graphics drivers, clamp power when entering 6549 // system sleep. Not when dropping to dark wake. 6550 enableClamp = true; 6551 } 6552 6553 if (enableClamp) { 6554 actions->state |= kPMActionsStatePowerClamped; 6555 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n", 6556 service->getName(), service->getRegistryEntryID(), 6557 _pendingCapability, powerState, changeFlags); 6558 } 6559 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) { 6560 bool disableClamp = false; 6561 6562 if ((actionFlags & ( 6563 kPMActionsFlagIsDisplayWrangler | 6564 kPMActionsFlagIsGraphicsDriver)) && 6565 (_pendingCapability & kIOPMSystemCapabilityGraphics)) { 6566 disableClamp = true; 6567 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) && 6568 (_pendingCapability & kIOPMSystemCapabilityAudio)) { 6569 disableClamp = true; 6570 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) && 6571 (_pendingCapability & kIOPMSystemCapabilityGraphics)) { 6572 disableClamp = true; 6573 } 6574 6575 if (disableClamp) { 6576 actions->state &= ~kPMActionsStatePowerClamped; 6577 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n", 6578 service->getName(), service->getRegistryEntryID(), 6579 _pendingCapability, powerState, changeFlags); 6580 } 6581 } 6582 6583 if (actions->state & kPMActionsStatePowerClamped) { 6584 uint32_t maxPowerState = 0; 6585 6586 // Determine the max power state allowed when clamp is enabled 6587 if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) { 6588 // Parent intiated power state changes 6589 if ((service->getPowerState() > maxPowerState) && 6590 (actionFlags & kPMActionsFlagIsDisplayWrangler)) { 6591 maxPowerState++; 6592 6593 // Remove lingering effects of any tickle before entering 6594 // dark wake. It will take a new tickle to return to full 6595 // wake, so the existing tickle state is useless. 6596 6597 if (changeFlags & kIOPMDomainDidChange) { 6598 *inOutChangeFlags |= kIOPMExpireIdleTimer; 6599 } 6600 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) { 6601 maxPowerState++; 6602 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) { 6603 maxPowerState = actions->darkWakePowerState; 6604 } 6605 } else { 6606 // Deny all self-initiated changes when power is limited. 6607 // Wrangler tickle should never defeat the limiter. 6608 maxPowerState = service->getPowerState(); 6609 } 6610 6611 if (powerState > maxPowerState) { 6612 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n", 6613 service->getName(), service->getRegistryEntryID(), 6614 powerState, maxPowerState, changeFlags); 6615 *inOutPowerState = maxPowerState; 6616 6617 if (darkWakePostTickle && 6618 (actionFlags & kPMActionsFlagIsDisplayWrangler) && 6619 (changeFlags & kIOPMDomainWillChange) && 6620 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == 6621 kDarkWakeFlagPromotionEarly)) { 6622 darkWakePostTickle = false; 6623 reportUserInput(); 6624 } 6625 } 6626 6627 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) { 6628 if (darkWakeLogClamp) { 6629 AbsoluteTime now; 6630 uint64_t nsec; 6631 6632 clock_get_uptime(&now); 6633 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 6634 absolutetime_to_nanoseconds(now, &nsec); 6635 DLOG("dark wake power clamped after %u ms\n", 6636 ((int)((nsec) / NSEC_PER_MSEC))); 6637 } 6638 darkWakePowerClamped = true; 6639 } 6640 } 6641 } 6642 6643 void 6644 IOPMrootDomain::handleActivityTickleForDisplayWrangler( 6645 IOService * service, 6646 IOPMActions * actions ) 6647 { 6648 #if DISPLAY_WRANGLER_PRESENT 6649 // Warning: Not running in PM work loop context - don't modify state !!! 6650 // Trap tickle directed to IODisplayWrangler while running with graphics 6651 // capability suppressed. 6652 6653 assert(service == wrangler); 6654 6655 clock_get_uptime(&userActivityTime); 6656 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle) 6657 || (lastSleepReason == kIOPMSleepReasonMaintenance) 6658 || (lastSleepReason == kIOPMSleepReasonSoftware)); 6659 if (aborting) { 6660 userActivityCount++; 6661 DLOG("display wrangler tickled1 %d lastSleepReason %d\n", 6662 userActivityCount, lastSleepReason); 6663 } 6664 6665 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) { 6666 DLOG("display wrangler tickled\n"); 6667 if (kIOLogPMRootDomain & gIOKitDebug) { 6668 OSReportWithBacktrace("Dark wake display tickle"); 6669 } 6670 if (pmPowerStateQueue) { 6671 pmPowerStateQueue->submitPowerEvent( 6672 kPowerEventPolicyStimulus, 6673 (void *) kStimulusDarkWakeActivityTickle, 6674 true /* set wake type */ ); 6675 } 6676 } 6677 #endif /* DISPLAY_WRANGLER_PRESENT */ 6678 } 6679 6680 void 6681 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler( 6682 IOService * service, 6683 IOPMActions * actions, 6684 const OSSymbol * powerClient, 6685 IOPMPowerStateIndex oldPowerState, 6686 IOPMPowerStateIndex newPowerState ) 6687 { 6688 #if DISPLAY_WRANGLER_PRESENT 6689 assert(service == wrangler); 6690 6691 // This function implements half of the user active detection 6692 // by monitoring changes to the display wrangler's device desire. 6693 // 6694 // User becomes active when either: 6695 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already 6696 // in max power state. This desire change in absence of a power state 6697 // change is detected within. This handles the case when user becomes 6698 // active while the display is already lit by setDisplayPowerOn(). 6699 // 6700 // 2. Power state change to max, and DeviceDesire is also at max. 6701 // Handled by displayWranglerNotification(). 6702 // 6703 // User becomes inactive when DeviceDesire drops to sleep state or below. 6704 6705 DLOG("wrangler %s (ps %u, %u->%u)\n", 6706 powerClient->getCStringNoCopy(), 6707 (uint32_t) service->getPowerState(), 6708 (uint32_t) oldPowerState, (uint32_t) newPowerState); 6709 6710 if (powerClient == gIOPMPowerClientDevice) { 6711 if ((newPowerState > oldPowerState) && 6712 (newPowerState == kWranglerPowerStateMax) && 6713 (service->getPowerState() == kWranglerPowerStateMax)) { 6714 evaluatePolicy( kStimulusEnterUserActiveState ); 6715 } else if ((newPowerState < oldPowerState) && 6716 (newPowerState <= kWranglerPowerStateSleep)) { 6717 evaluatePolicy( kStimulusLeaveUserActiveState ); 6718 } 6719 } 6720 6721 if (newPowerState <= kWranglerPowerStateSleep) { 6722 evaluatePolicy( kStimulusDisplayWranglerSleep ); 6723 } else if (newPowerState == kWranglerPowerStateMax) { 6724 evaluatePolicy( kStimulusDisplayWranglerWake ); 6725 } 6726 #endif /* DISPLAY_WRANGLER_PRESENT */ 6727 } 6728 6729 //****************************************************************************** 6730 // User active state management 6731 //****************************************************************************** 6732 6733 void 6734 IOPMrootDomain::preventTransitionToUserActive( bool prevent ) 6735 { 6736 #if DISPLAY_WRANGLER_PRESENT 6737 _preventUserActive = prevent; 6738 if (wrangler && !_preventUserActive) { 6739 // Allowing transition to user active, but the wrangler may have 6740 // already powered ON in case of sleep cancel/revert. Poll the 6741 // same conditions checked for in displayWranglerNotification() 6742 // to bring the user active state up to date. 6743 6744 if ((wrangler->getPowerState() == kWranglerPowerStateMax) && 6745 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) == 6746 kWranglerPowerStateMax)) { 6747 evaluatePolicy( kStimulusEnterUserActiveState ); 6748 } 6749 } 6750 #endif /* DISPLAY_WRANGLER_PRESENT */ 6751 } 6752 6753 //****************************************************************************** 6754 // Approve usage of delayed child notification by PM. 6755 //****************************************************************************** 6756 6757 bool 6758 IOPMrootDomain::shouldDelayChildNotification( 6759 IOService * service ) 6760 { 6761 if ((kFullWakeReasonNone == fullWakeReason) && 6762 (kSystemTransitionWake == _systemTransitionType)) { 6763 DLOG("%s: delay child notify\n", service->getName()); 6764 return true; 6765 } 6766 return false; 6767 } 6768 6769 //****************************************************************************** 6770 // PM actions for PCI device. 6771 //****************************************************************************** 6772 6773 void 6774 IOPMrootDomain::handlePowerChangeStartForPCIDevice( 6775 IOService * service, 6776 IOPMActions * actions, 6777 const IOPMRequest * request, 6778 IOPMPowerStateIndex powerState, 6779 IOPMPowerChangeFlags * inOutChangeFlags ) 6780 { 6781 pmTracer->tracePCIPowerChange( 6782 PMTraceWorker::kPowerChangeStart, 6783 service, *inOutChangeFlags, 6784 (actions->flags & kPMActionsPCIBitNumberMask)); 6785 } 6786 6787 void 6788 IOPMrootDomain::handlePowerChangeDoneForPCIDevice( 6789 IOService * service, 6790 IOPMActions * actions, 6791 const IOPMRequest * request, 6792 IOPMPowerStateIndex powerState, 6793 IOPMPowerChangeFlags changeFlags ) 6794 { 6795 pmTracer->tracePCIPowerChange( 6796 PMTraceWorker::kPowerChangeCompleted, 6797 service, changeFlags, 6798 (actions->flags & kPMActionsPCIBitNumberMask)); 6799 } 6800 6801 //****************************************************************************** 6802 // registerInterest 6803 // 6804 // Override IOService::registerInterest() for root domain clients. 6805 //****************************************************************************** 6806 6807 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier 6808 { 6809 friend class IOPMrootDomain; 6810 OSDeclareDefaultStructors(IOPMServiceInterestNotifier); 6811 6812 protected: 6813 uint32_t ackTimeoutCnt; 6814 uint32_t msgType; // Message pending ack 6815 uint32_t msgIndex; 6816 uint32_t maxMsgDelayMS; 6817 uint32_t maxAckDelayMS; 6818 uint64_t msgAbsTime; 6819 uint64_t uuid0; 6820 uint64_t uuid1; 6821 OSSharedPtr<const OSSymbol> identifier; 6822 OSSharedPtr<const OSSymbol> clientName; 6823 }; 6824 6825 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier) 6826 6827 OSSharedPtr<IONotifier> 6828 IOPMrootDomain::registerInterest( 6829 const OSSymbol * typeOfInterest, 6830 IOServiceInterestHandler handler, 6831 void * target, void * ref ) 6832 { 6833 IOPMServiceInterestNotifier* notifier; 6834 bool isSystemCapabilityClient; 6835 bool isKernelCapabilityClient; 6836 IOReturn rc = kIOReturnError; 6837 6838 isSystemCapabilityClient = typeOfInterest && 6839 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest); 6840 6841 isKernelCapabilityClient = typeOfInterest && 6842 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest); 6843 6844 if (isSystemCapabilityClient) { 6845 typeOfInterest = gIOAppPowerStateInterest; 6846 } 6847 6848 notifier = new IOPMServiceInterestNotifier; 6849 if (!notifier) { 6850 return NULL; 6851 } 6852 6853 if (notifier->init()) { 6854 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref); 6855 } 6856 if (rc != kIOReturnSuccess) { 6857 return NULL; 6858 } 6859 6860 notifier->ackTimeoutCnt = 0; 6861 6862 if (pmPowerStateQueue) { 6863 if (isSystemCapabilityClient) { 6864 notifier->retain(); 6865 if (pmPowerStateQueue->submitPowerEvent( 6866 kPowerEventRegisterSystemCapabilityClient, notifier) == false) { 6867 notifier->release(); 6868 } 6869 } 6870 6871 if (isKernelCapabilityClient) { 6872 notifier->retain(); 6873 if (pmPowerStateQueue->submitPowerEvent( 6874 kPowerEventRegisterKernelCapabilityClient, notifier) == false) { 6875 notifier->release(); 6876 } 6877 } 6878 } 6879 6880 OSSharedPtr<OSData> data; 6881 uint8_t *uuid = NULL; 6882 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler); 6883 if (kext) { 6884 data = kext->copyUUID(); 6885 } 6886 if (data && (data->getLength() == sizeof(uuid_t))) { 6887 uuid = (uint8_t *)(data->getBytesNoCopy()); 6888 6889 notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) | 6890 ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) | 6891 ((uint64_t)(uuid[6]) << 8) | (uuid[7]); 6892 notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) | 6893 ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) | 6894 ((uint64_t)(uuid[14]) << 8) | (uuid[15]); 6895 6896 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler); 6897 } 6898 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain); 6899 } 6900 6901 //****************************************************************************** 6902 // systemMessageFilter 6903 // 6904 //****************************************************************************** 6905 6906 bool 6907 IOPMrootDomain::systemMessageFilter( 6908 void * object, void * arg1, void * arg2, void * arg3 ) 6909 { 6910 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1; 6911 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange); 6912 bool isCapClient = false; 6913 bool allow = false; 6914 IOPMServiceInterestNotifier *notifier; 6915 6916 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object); 6917 6918 do { 6919 if ((kSystemTransitionNewCapClient == _systemTransitionType) && 6920 (!isCapMsg || !_joinedCapabilityClients || 6921 !_joinedCapabilityClients->containsObject((OSObject *) object))) { 6922 break; 6923 } 6924 6925 // Capability change message for app and kernel clients. 6926 6927 if (isCapMsg) { 6928 // Kernel clients 6929 if ((context->notifyType == kNotifyPriority) || 6930 (context->notifyType == kNotifyCapabilityChangePriority)) { 6931 isCapClient = true; 6932 } 6933 6934 // powerd's systemCapabilityNotifier 6935 if ((context->notifyType == kNotifyCapabilityChangeApps) && 6936 (object == (void *) systemCapabilityNotifier.get())) { 6937 isCapClient = true; 6938 } 6939 } 6940 6941 if (isCapClient) { 6942 IOPMSystemCapabilityChangeParameters * capArgs = 6943 (IOPMSystemCapabilityChangeParameters *) arg2; 6944 6945 if (kSystemTransitionNewCapClient == _systemTransitionType) { 6946 capArgs->fromCapabilities = 0; 6947 capArgs->toCapabilities = _currentCapability; 6948 capArgs->changeFlags = 0; 6949 } else { 6950 capArgs->fromCapabilities = _currentCapability; 6951 capArgs->toCapabilities = _pendingCapability; 6952 6953 if (context->isPreChange) { 6954 capArgs->changeFlags = kIOPMSystemCapabilityWillChange; 6955 } else { 6956 capArgs->changeFlags = kIOPMSystemCapabilityDidChange; 6957 } 6958 6959 if ((object == (void *) systemCapabilityNotifier.get()) && 6960 context->isPreChange) { 6961 toldPowerdCapWillChange = true; 6962 } 6963 } 6964 6965 // Capability change messages only go to the PM configd plugin. 6966 // Wait for response post-change if capabilitiy is increasing. 6967 // Wait for response pre-change if capability is decreasing. 6968 6969 if ((context->notifyType == kNotifyCapabilityChangeApps) && arg3 && 6970 ((capabilityLoss && context->isPreChange) || 6971 (!capabilityLoss && !context->isPreChange))) { 6972 // app has not replied yet, wait for it 6973 *((OSObject **) arg3) = kOSBooleanFalse; 6974 } 6975 6976 allow = true; 6977 break; 6978 } 6979 6980 // Capability client will always see kIOMessageCanSystemSleep, 6981 // even for demand sleep. It will also have a chance to veto 6982 // sleep one last time after all clients have responded to 6983 // kIOMessageSystemWillSleep 6984 6985 if ((kIOMessageCanSystemSleep == context->messageType) || 6986 (kIOMessageSystemWillNotSleep == context->messageType)) { 6987 if (object == (OSObject *) systemCapabilityNotifier.get()) { 6988 allow = true; 6989 break; 6990 } 6991 6992 // Not idle sleep, don't ask apps. 6993 if (context->changeFlags & kIOPMSkipAskPowerDown) { 6994 break; 6995 } 6996 } 6997 6998 if (kIOPMMessageLastCallBeforeSleep == context->messageType) { 6999 if ((object == (OSObject *) systemCapabilityNotifier.get()) && 7000 CAP_HIGHEST(kIOPMSystemCapabilityGraphics) && 7001 (fullToDarkReason == kIOPMSleepReasonIdle)) { 7002 allow = true; 7003 } 7004 break; 7005 } 7006 7007 // Reject capability change messages for legacy clients. 7008 // Reject legacy system sleep messages for capability client. 7009 7010 if (isCapMsg || (object == (OSObject *) systemCapabilityNotifier.get())) { 7011 break; 7012 } 7013 7014 // Filter system sleep messages. 7015 7016 if ((context->notifyType == kNotifyApps) && 7017 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) { 7018 allow = true; 7019 7020 if (notifier) { 7021 if (arg3) { 7022 if (notifier->ackTimeoutCnt >= 3) { 7023 *((OSObject **) arg3) = kOSBooleanFalse; 7024 } else { 7025 *((OSObject **) arg3) = kOSBooleanTrue; 7026 } 7027 } 7028 } 7029 } else if ((context->notifyType == kNotifyPriority) && 7030 (_systemMessageClientMask & kSystemMessageClientKernel)) { 7031 allow = true; 7032 } 7033 }while (false); 7034 7035 if (allow && isCapMsg && _joinedCapabilityClients) { 7036 _joinedCapabilityClients->removeObject((OSObject *) object); 7037 if (_joinedCapabilityClients->getCount() == 0) { 7038 DLOG("destroyed capability client set %p\n", 7039 OBFUSCATE(_joinedCapabilityClients.get())); 7040 _joinedCapabilityClients.reset(); 7041 } 7042 } 7043 if (notifier) { 7044 notifier->msgType = context->messageType; 7045 } 7046 7047 return allow; 7048 } 7049 7050 //****************************************************************************** 7051 // setMaintenanceWakeCalendar 7052 // 7053 //****************************************************************************** 7054 7055 IOReturn 7056 IOPMrootDomain::setMaintenanceWakeCalendar( 7057 const IOPMCalendarStruct * calendar ) 7058 { 7059 OSSharedPtr<OSData> data; 7060 IOReturn ret = 0; 7061 7062 if (!calendar) { 7063 return kIOReturnBadArgument; 7064 } 7065 7066 data = OSData::withBytes((void *) calendar, sizeof(*calendar)); 7067 if (!data) { 7068 return kIOReturnNoMemory; 7069 } 7070 7071 if (kPMCalendarTypeMaintenance == calendar->selector) { 7072 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get()); 7073 } else if (kPMCalendarTypeSleepService == calendar->selector) { 7074 ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get()); 7075 } 7076 7077 return ret; 7078 } 7079 7080 // MARK: - 7081 // MARK: Display Wrangler 7082 7083 //****************************************************************************** 7084 // displayWranglerNotification 7085 // 7086 // Handle the notification when the IODisplayWrangler changes power state. 7087 //****************************************************************************** 7088 7089 IOReturn 7090 IOPMrootDomain::displayWranglerNotification( 7091 void * target, void * refCon, 7092 UInt32 messageType, IOService * service, 7093 void * messageArgument, vm_size_t argSize ) 7094 { 7095 #if DISPLAY_WRANGLER_PRESENT 7096 IOPMPowerStateIndex displayPowerState; 7097 IOPowerStateChangeNotification * params = 7098 (IOPowerStateChangeNotification *) messageArgument; 7099 7100 if ((messageType != kIOMessageDeviceWillPowerOff) && 7101 (messageType != kIOMessageDeviceHasPoweredOn)) { 7102 return kIOReturnUnsupported; 7103 } 7104 7105 ASSERT_GATED(); 7106 if (!gRootDomain) { 7107 return kIOReturnUnsupported; 7108 } 7109 7110 displayPowerState = params->stateNumber; 7111 DLOG("wrangler %s ps %d\n", 7112 getIOMessageString(messageType), (uint32_t) displayPowerState); 7113 7114 switch (messageType) { 7115 case kIOMessageDeviceWillPowerOff: 7116 // Display wrangler has dropped power due to display idle 7117 // or force system sleep. 7118 // 7119 // 4 Display ON kWranglerPowerStateMax 7120 // 3 Display Dim kWranglerPowerStateDim 7121 // 2 Display Sleep kWranglerPowerStateSleep 7122 // 1 Not visible to user 7123 // 0 Not visible to user kWranglerPowerStateMin 7124 7125 if (displayPowerState <= kWranglerPowerStateSleep) { 7126 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep ); 7127 } 7128 break; 7129 7130 case kIOMessageDeviceHasPoweredOn: 7131 // Display wrangler has powered on due to user activity 7132 // or wake from sleep. 7133 7134 if (kWranglerPowerStateMax == displayPowerState) { 7135 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake ); 7136 7137 // See comment in handleUpdatePowerClientForDisplayWrangler 7138 if (service->getPowerStateForClient(gIOPMPowerClientDevice) == 7139 kWranglerPowerStateMax) { 7140 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState ); 7141 } 7142 } 7143 break; 7144 } 7145 #endif /* DISPLAY_WRANGLER_PRESENT */ 7146 return kIOReturnUnsupported; 7147 } 7148 7149 //****************************************************************************** 7150 // reportUserInput 7151 // 7152 //****************************************************************************** 7153 7154 void 7155 IOPMrootDomain::updateUserActivity( void ) 7156 { 7157 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 7158 clock_get_uptime(&userActivityTime); 7159 bool aborting = ((lastSleepReason == kIOPMSleepReasonSoftware) 7160 || (lastSleepReason == kIOPMSleepReasonIdle) 7161 || (lastSleepReason == kIOPMSleepReasonMaintenance)); 7162 if (aborting) { 7163 userActivityCount++; 7164 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason); 7165 } 7166 #endif 7167 } 7168 void 7169 IOPMrootDomain::reportUserInput( void ) 7170 { 7171 if (wrangler) { 7172 wrangler->activityTickle(0, 0); 7173 } 7174 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 7175 // Update user activity 7176 updateUserActivity(); 7177 7178 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) { 7179 // update user active abs time 7180 clock_get_uptime(&gUserActiveAbsTime); 7181 pmPowerStateQueue->submitPowerEvent( 7182 kPowerEventPolicyStimulus, 7183 (void *) kStimulusDarkWakeActivityTickle, 7184 true /* set wake type */ ); 7185 } 7186 #endif 7187 } 7188 7189 void 7190 IOPMrootDomain::requestUserActive(IOService *device, const char *reason) 7191 { 7192 #if DISPLAY_WRANGLER_PRESENT 7193 if (wrangler) { 7194 wrangler->activityTickle(0, 0); 7195 } 7196 #else 7197 if (!device) { 7198 DLOG("requestUserActive: device is null\n"); 7199 return; 7200 } 7201 OSSharedPtr<const OSSymbol> deviceName = device->copyName(); 7202 uint64_t registryID = device->getRegistryEntryID(); 7203 7204 if (!deviceName || !registryID) { 7205 DLOG("requestUserActive: no device name or registry entry\n"); 7206 return; 7207 } 7208 const char *name = deviceName->getCStringNoCopy(); 7209 char payload[128]; 7210 snprintf(payload, sizeof(payload), "%s:%s", name, reason); 7211 DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason); 7212 messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload)); 7213 #endif 7214 } 7215 7216 //****************************************************************************** 7217 // latchDisplayWranglerTickle 7218 //****************************************************************************** 7219 7220 bool 7221 IOPMrootDomain::latchDisplayWranglerTickle( bool latch ) 7222 { 7223 #if DISPLAY_WRANGLER_PRESENT 7224 if (latch) { 7225 if (!(_currentCapability & kIOPMSystemCapabilityGraphics) && 7226 !(_pendingCapability & kIOPMSystemCapabilityGraphics) && 7227 !checkSystemCanSustainFullWake()) { 7228 // Currently in dark wake, and not transitioning to full wake. 7229 // Full wake is unsustainable, so latch the tickle to prevent 7230 // the display from lighting up momentarily. 7231 wranglerTickled = true; 7232 } else { 7233 wranglerTickled = false; 7234 } 7235 } else if (wranglerTickled && checkSystemCanSustainFullWake()) { 7236 wranglerTickled = false; 7237 7238 pmPowerStateQueue->submitPowerEvent( 7239 kPowerEventPolicyStimulus, 7240 (void *) kStimulusDarkWakeActivityTickle ); 7241 } 7242 7243 return wranglerTickled; 7244 #else /* ! DISPLAY_WRANGLER_PRESENT */ 7245 return false; 7246 #endif /* ! DISPLAY_WRANGLER_PRESENT */ 7247 } 7248 7249 //****************************************************************************** 7250 // setDisplayPowerOn 7251 // 7252 // For root domain user client 7253 //****************************************************************************** 7254 7255 void 7256 IOPMrootDomain::setDisplayPowerOn( uint32_t options ) 7257 { 7258 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn, 7259 (void *) NULL, options ); 7260 } 7261 7262 // MARK: - 7263 // MARK: System PM Policy 7264 7265 //****************************************************************************** 7266 // checkSystemSleepAllowed 7267 // 7268 //****************************************************************************** 7269 7270 bool 7271 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options, 7272 uint32_t sleepReason ) 7273 { 7274 uint32_t err = 0; 7275 7276 // Conditions that prevent idle and demand system sleep. 7277 7278 do { 7279 if (userDisabledAllSleep) { 7280 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch 7281 break; 7282 } 7283 7284 if (systemBooting || systemShutdown || gWillShutdown) { 7285 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress 7286 break; 7287 } 7288 7289 if (options == 0) { 7290 break; 7291 } 7292 7293 // Conditions above pegs the system at full wake. 7294 // Conditions below prevent system sleep but does not prevent 7295 // dark wake, and must be called from gated context. 7296 7297 #if !CONFIG_SLEEP 7298 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep 7299 break; 7300 #endif 7301 7302 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) { 7303 break; // always sleep on low battery or when in thermal warning/emergency state 7304 } 7305 7306 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) { 7307 break; // always sleep on dark wake thermal emergencies 7308 } 7309 7310 if (preventSystemSleepList->getCount() != 0) { 7311 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp 7312 break; 7313 } 7314 7315 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) == 7316 kIOPMDriverAssertionLevelOn) { 7317 err = kPMCPUAssertion; // 5. CPU assertion 7318 break; 7319 } 7320 7321 if (pciCantSleepValid) { 7322 if (pciCantSleepFlag) { 7323 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached) 7324 } 7325 break; 7326 } else if (sleepSupportedPEFunction && 7327 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) { 7328 IOReturn ret; 7329 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport); 7330 ret = getPlatform()->callPlatformFunction( 7331 sleepSupportedPEFunction.get(), false, 7332 NULL, NULL, NULL, NULL); 7333 pciCantSleepValid = true; 7334 pciCantSleepFlag = false; 7335 if ((platformSleepSupport & kPCICantSleep) || 7336 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) { 7337 err = 6; // 6. PCI card does not support PM 7338 pciCantSleepFlag = true; 7339 break; 7340 } 7341 } 7342 }while (false); 7343 7344 if (err) { 7345 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err)); 7346 return false; 7347 } 7348 return true; 7349 } 7350 7351 bool 7352 IOPMrootDomain::checkSystemSleepEnabled( void ) 7353 { 7354 return checkSystemSleepAllowed(0, 0); 7355 } 7356 7357 bool 7358 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason ) 7359 { 7360 ASSERT_GATED(); 7361 return checkSystemSleepAllowed(1, sleepReason); 7362 } 7363 7364 //****************************************************************************** 7365 // checkSystemCanSustainFullWake 7366 //****************************************************************************** 7367 7368 bool 7369 IOPMrootDomain::checkSystemCanSustainFullWake( void ) 7370 { 7371 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) { 7372 // Low battery wake, or received a low battery notification 7373 // while system is awake. This condition will persist until 7374 // the following wake. 7375 return false; 7376 } 7377 7378 if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) { 7379 // Graphics state is unknown and external display might not be probed. 7380 // Do not incorporate state that requires graphics to be in max power 7381 // such as desktopMode or clamshellDisabled. 7382 7383 if (!acAdaptorConnected) { 7384 DLOG("full wake check: no AC\n"); 7385 return false; 7386 } 7387 } 7388 return true; 7389 } 7390 7391 //****************************************************************************** 7392 // mustHibernate 7393 //****************************************************************************** 7394 7395 #if HIBERNATION 7396 7397 bool 7398 IOPMrootDomain::mustHibernate( void ) 7399 { 7400 return lowBatteryCondition || thermalWarningState; 7401 } 7402 7403 #endif /* HIBERNATION */ 7404 7405 //****************************************************************************** 7406 // AOT 7407 //****************************************************************************** 7408 7409 // Tables for accumulated days in year by month, latter used for leap years 7410 7411 static const unsigned int daysbymonth[] = 7412 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; 7413 7414 static const unsigned int lydaysbymonth[] = 7415 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; 7416 7417 static int __unused 7418 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt) 7419 { 7420 const unsigned int * dbm = daysbymonth; 7421 clock_sec_t n, x, y, z; 7422 7423 // Calculate seconds, minutes and hours 7424 7425 n = secs % (24 * 3600); 7426 dt->second = n % 60; 7427 n /= 60; 7428 dt->minute = n % 60; 7429 dt->hour = (typeof(dt->hour))(n / 60); 7430 7431 // Calculate day of week 7432 7433 n = secs / (24 * 3600); 7434 // dt->dayWeek = (n + 4) % 7; 7435 7436 // Calculate year 7437 // Rebase from days since Unix epoch (1/1/1970) store in 'n', 7438 // to days since 1/1/1968 to start on 4 year cycle, beginning 7439 // on a leap year. 7440 7441 n += (366 + 365); 7442 7443 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days. 7444 // Valid before 2100, since 2100 is not a leap year. 7445 7446 x = n / 1461; // number of 4 year cycles 7447 y = n % 1461; // days into current 4 year cycle 7448 z = 1968 + (4 * x); 7449 7450 // Add in years in the current 4 year cycle 7451 7452 if (y >= 366) { 7453 y -= 366; // days after the leap year 7454 n = y % 365; // days into the current year 7455 z += (1 + y / 365); // years after the past 4-yr cycle 7456 } else { 7457 n = y; 7458 dbm = lydaysbymonth; 7459 } 7460 if (z > 2099) { 7461 return 0; 7462 } 7463 7464 dt->year = (typeof(dt->year))z; 7465 7466 // Adjust remaining days value to start at 1 7467 7468 n += 1; 7469 7470 // Calculate month 7471 7472 for (x = 1; (n > dbm[x]) && (x < 12); x++) { 7473 continue; 7474 } 7475 dt->month = (typeof(dt->month))x; 7476 7477 // Calculate day of month 7478 7479 dt->day = (typeof(dt->day))(n - dbm[x - 1]); 7480 7481 return 1; 7482 } 7483 7484 static clock_sec_t 7485 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt) 7486 { 7487 const unsigned int * dbm = daysbymonth; 7488 long y, secs, days; 7489 7490 if (dt->year < 1970 || dt->month > 12) { 7491 return 0; 7492 } 7493 7494 // Seconds elapsed in the current day 7495 7496 secs = dt->second + 60 * dt->minute + 3600 * dt->hour; 7497 7498 // Number of days from 1/1/70 to beginning of current year 7499 // Account for extra day every 4 years starting at 1973 7500 7501 y = dt->year - 1970; 7502 days = (y * 365) + ((y + 1) / 4); 7503 7504 // Change table if current year is a leap year 7505 7506 if ((dt->year % 4) == 0) { 7507 dbm = lydaysbymonth; 7508 } 7509 7510 // Add in days elapsed in the current year 7511 7512 days += (dt->day - 1) + dbm[dt->month - 1]; 7513 7514 // Add accumulated days to accumulated seconds 7515 7516 secs += 24 * 3600 * days; 7517 7518 return secs; 7519 } 7520 7521 unsigned long 7522 IOPMrootDomain::getRUN_STATE(void) 7523 { 7524 return _aotNow ? AOT_STATE : ON_STATE; 7525 } 7526 7527 bool 7528 IOPMrootDomain::isAOTMode() 7529 { 7530 return _aotNow; 7531 } 7532 7533 IOReturn 7534 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime) 7535 { 7536 clock_sec_t nowsecs, wakesecs; 7537 clock_usec_t nowmicrosecs, wakemicrosecs; 7538 uint64_t nowAbs, wakeAbs; 7539 7540 clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs); 7541 wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime); 7542 if (wakeAbs < nowAbs) { 7543 printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs); 7544 wakeAbs = nowAbs; 7545 } 7546 wakeAbs -= nowAbs; 7547 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs); 7548 7549 wakesecs += nowsecs; 7550 wakemicrosecs += nowmicrosecs; 7551 if (wakemicrosecs >= USEC_PER_SEC) { 7552 wakesecs++; 7553 wakemicrosecs -= USEC_PER_SEC; 7554 } 7555 if (wakemicrosecs >= (USEC_PER_SEC / 10)) { 7556 wakesecs++; 7557 } 7558 7559 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar); 7560 7561 if (_aotWakeTimeContinuous != wakeContinuousTime) { 7562 _aotWakeTimeContinuous = wakeContinuousTime; 7563 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar)); 7564 } 7565 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance; 7566 _aotWakeTimeUTC = wakesecs; 7567 7568 return kIOReturnSuccess; 7569 } 7570 7571 // assumes WAKEEVENT_LOCK 7572 bool 7573 IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software) 7574 { 7575 bool exitNow; 7576 const char * reason = ""; 7577 7578 if (software) { 7579 _aotExit = true; 7580 _aotMetrics->softwareRequestCount++; 7581 reason = "software request"; 7582 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) { 7583 _aotExit = true; 7584 reason = gWakeReasonString; 7585 } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) { 7586 _aotExit = true; 7587 _aotMetrics->noTimeSetCount++; 7588 reason = "flipbook expired"; 7589 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) { 7590 clock_sec_t sec; 7591 clock_usec_t usec; 7592 clock_get_calendar_microtime(&sec, &usec); 7593 if (_calendarWakeAlarmUTC <= sec) { 7594 _aotExit = true; 7595 _aotMetrics->rtcAlarmsCount++; 7596 reason = "user alarm"; 7597 } 7598 } 7599 exitNow = (_aotNow && _aotExit); 7600 if (exitNow) { 7601 _aotNow = false; 7602 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n", 7603 reason, 7604 _aotMetrics->sleepCount, 7605 _aotMetrics->possibleCount, 7606 _aotMetrics->confirmedPossibleCount, 7607 _aotMetrics->rejectedPossibleCount, 7608 _aotMetrics->expiredPossibleCount, 7609 _aotMetrics->noTimeSetCount, 7610 _aotMetrics->rtcAlarmsCount); 7611 } 7612 return exitNow; 7613 } 7614 7615 void 7616 IOPMrootDomain::aotExit(bool cps) 7617 { 7618 uint32_t savedMessageMask; 7619 7620 ASSERT_GATED(); 7621 _aotTasksSuspended = false; 7622 _aotReadyToFullWake = false; 7623 if (_aotTimerScheduled) { 7624 _aotTimerES->cancelTimeout(); 7625 _aotTimerScheduled = false; 7626 } 7627 updateTasksSuspend(); 7628 7629 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime; 7630 _aotLastWakeTime = 0; 7631 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) { 7632 WAKEEVENT_LOCK(); 7633 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0], 7634 gWakeReasonString, 7635 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount])); 7636 WAKEEVENT_UNLOCK(); 7637 } 7638 7639 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid; 7640 7641 // Preserve the message mask since a system wake transition 7642 // may have already started and initialized the mask. 7643 savedMessageMask = _systemMessageClientMask; 7644 _systemMessageClientMask = kSystemMessageClientLegacyApp; 7645 tellClients(kIOMessageSystemWillPowerOn); 7646 _systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp; 7647 7648 if (cps) { 7649 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit); 7650 } 7651 } 7652 7653 void 7654 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer) 7655 { 7656 bool exitNow; 7657 7658 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags); 7659 7660 WAKEEVENT_LOCK(); 7661 exitNow = aotShouldExit(false, false); 7662 if (timer != NULL) { 7663 _aotTimerScheduled = false; 7664 } 7665 WAKEEVENT_UNLOCK(); 7666 if (exitNow) { 7667 aotExit(true); 7668 } else { 7669 #if 0 7670 if (_aotLingerTime) { 7671 uint64_t deadline; 7672 IOLog("aot linger before sleep\n"); 7673 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline); 7674 clock_delay_until(deadline); 7675 } 7676 #endif 7677 privateSleepSystem(kIOPMSleepReasonSoftware); 7678 } 7679 } 7680 7681 //****************************************************************************** 7682 // adjustPowerState 7683 // 7684 // Conditions that affect our wake/sleep decision has changed. 7685 // If conditions dictate that the system must remain awake, clamp power 7686 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP 7687 // is TRUE, then remove the power clamp and allow the power state to drop 7688 // to SLEEP_STATE. 7689 //****************************************************************************** 7690 7691 void 7692 IOPMrootDomain::adjustPowerState( bool sleepASAP ) 7693 { 7694 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n", 7695 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled); 7696 7697 ASSERT_GATED(); 7698 7699 if (_aotNow) { 7700 bool exitNow; 7701 7702 if (AOT_STATE != getPowerState()) { 7703 return; 7704 } 7705 WAKEEVENT_LOCK(); 7706 exitNow = aotShouldExit(true, false); 7707 if (!exitNow 7708 && !_aotTimerScheduled 7709 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) { 7710 _aotTimerScheduled = true; 7711 if (_aotLingerTime) { 7712 _aotTimerES->setTimeout(_aotLingerTime); 7713 } else { 7714 _aotTimerES->setTimeout(800, kMillisecondScale); 7715 } 7716 } 7717 WAKEEVENT_UNLOCK(); 7718 if (exitNow) { 7719 aotExit(true); 7720 } else { 7721 _aotReadyToFullWake = true; 7722 if (!_aotTimerScheduled) { 7723 privateSleepSystem(kIOPMSleepReasonSoftware); 7724 } 7725 } 7726 return; 7727 } 7728 7729 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) { 7730 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState); 7731 } else if (sleepASAP) { 7732 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState); 7733 } 7734 } 7735 7736 void 7737 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn) 7738 { 7739 if (powerOn) { 7740 if (!checkSystemCanSustainFullWake()) { 7741 DLOG("System cannot sustain full wake\n"); 7742 return; 7743 } 7744 7745 // Force wrangler to max power state. If system is in dark wake 7746 // this alone won't raise the wrangler's power state. 7747 if (wrangler) { 7748 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax); 7749 } 7750 7751 // System in dark wake, always requesting full wake should 7752 // not have any bad side-effects, even if the request fails. 7753 7754 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) { 7755 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification); 7756 requestFullWake( kFullWakeReasonDisplayOn ); 7757 } 7758 } else { 7759 // Relenquish desire to power up display. 7760 // Must first transition to state 1 since wrangler doesn't 7761 // power off the displays at state 0. At state 0 the root 7762 // domain is removed from the wrangler's power client list. 7763 if (wrangler) { 7764 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1); 7765 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin); 7766 } 7767 } 7768 } 7769 7770 //****************************************************************************** 7771 // dispatchPowerEvent 7772 // 7773 // IOPMPowerStateQueue callback function. Running on PM work loop thread. 7774 //****************************************************************************** 7775 7776 void 7777 IOPMrootDomain::dispatchPowerEvent( 7778 uint32_t event, void * arg0, uint64_t arg1 ) 7779 { 7780 ASSERT_GATED(); 7781 7782 switch (event) { 7783 case kPowerEventFeatureChanged: 7784 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7785 messageClients(kIOPMMessageFeatureChange, this); 7786 break; 7787 7788 case kPowerEventReceivedPowerNotification: 7789 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7790 handlePowerNotification((UInt32)(uintptr_t) arg0 ); 7791 break; 7792 7793 case kPowerEventSystemBootCompleted: 7794 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7795 if (systemBooting) { 7796 systemBooting = false; 7797 7798 // read noidle setting from Device Tree 7799 OSSharedPtr<IORegistryEntry> defaults = IORegistryEntry::fromPath("IODeviceTree:/defaults"); 7800 if (defaults != NULL) { 7801 OSSharedPtr<OSObject> noIdleProp = defaults->copyProperty("no-idle"); 7802 OSData *data = OSDynamicCast(OSData, noIdleProp.get()); 7803 if ((data != NULL) && (data->getLength() == 4)) { 7804 gNoIdleFlag = *(uint32_t*)data->getBytesNoCopy(); 7805 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag); 7806 } 7807 } 7808 if (lowBatteryCondition || thermalEmergencyState) { 7809 if (lowBatteryCondition) { 7810 privateSleepSystem(kIOPMSleepReasonLowPower); 7811 } else { 7812 privateSleepSystem(kIOPMSleepReasonThermalEmergency); 7813 } 7814 // The rest is unnecessary since the system is expected 7815 // to sleep immediately. The following wake will update 7816 // everything. 7817 break; 7818 } 7819 7820 sleepWakeDebugMemAlloc(); 7821 saveFailureData2File(); 7822 7823 // If lid is closed, re-send lid closed notification 7824 // now that booting is complete. 7825 if (clamshellClosed) { 7826 handlePowerNotification(kLocalEvalClamshellCommand); 7827 } 7828 evaluatePolicy( kStimulusAllowSystemSleepChanged ); 7829 } 7830 break; 7831 7832 case kPowerEventSystemShutdown: 7833 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7834 if (kOSBooleanTrue == (OSBoolean *) arg0) { 7835 /* We set systemShutdown = true during shutdown 7836 * to prevent sleep at unexpected times while loginwindow is trying 7837 * to shutdown apps and while the OS is trying to transition to 7838 * complete power of. 7839 * 7840 * Set to true during shutdown, as soon as loginwindow shows 7841 * the "shutdown countdown dialog", through individual app 7842 * termination, and through black screen kernel shutdown. 7843 */ 7844 systemShutdown = true; 7845 } else { 7846 /* 7847 * A shutdown was initiated, but then the shutdown 7848 * was cancelled, clearing systemShutdown to false here. 7849 */ 7850 systemShutdown = false; 7851 } 7852 break; 7853 7854 case kPowerEventUserDisabledSleep: 7855 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7856 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0); 7857 break; 7858 7859 case kPowerEventRegisterSystemCapabilityClient: 7860 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7861 7862 // reset() handles the arg0 == nullptr case for us 7863 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain); 7864 /* intentional fall-through */ 7865 [[clang::fallthrough]]; 7866 7867 case kPowerEventRegisterKernelCapabilityClient: 7868 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7869 if (!_joinedCapabilityClients) { 7870 _joinedCapabilityClients = OSSet::withCapacity(8); 7871 } 7872 if (arg0) { 7873 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain); 7874 if (_joinedCapabilityClients) { 7875 _joinedCapabilityClients->setObject(notify.get()); 7876 synchronizePowerTree( kIOPMSyncNoChildNotify ); 7877 } 7878 } 7879 break; 7880 7881 case kPowerEventPolicyStimulus: 7882 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7883 if (arg0) { 7884 int stimulus = (int)(uintptr_t) arg0; 7885 evaluatePolicy(stimulus, (uint32_t) arg1); 7886 } 7887 break; 7888 7889 case kPowerEventAssertionCreate: 7890 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7891 if (pmAssertions) { 7892 pmAssertions->handleCreateAssertion((OSData *)arg0); 7893 } 7894 break; 7895 7896 7897 case kPowerEventAssertionRelease: 7898 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7899 if (pmAssertions) { 7900 pmAssertions->handleReleaseAssertion(arg1); 7901 } 7902 break; 7903 7904 case kPowerEventAssertionSetLevel: 7905 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7906 if (pmAssertions) { 7907 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0); 7908 } 7909 break; 7910 7911 case kPowerEventQueueSleepWakeUUID: 7912 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7913 handleQueueSleepWakeUUID((OSObject *)arg0); 7914 break; 7915 case kPowerEventPublishSleepWakeUUID: 7916 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7917 handlePublishSleepWakeUUID((bool)arg0); 7918 break; 7919 7920 case kPowerEventSetDisplayPowerOn: 7921 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7922 if (arg1 != 0) { 7923 displayPowerOnRequested = true; 7924 } else { 7925 displayPowerOnRequested = false; 7926 } 7927 handleSetDisplayPowerOn(displayPowerOnRequested); 7928 break; 7929 7930 case kPowerEventPublishWakeType: 7931 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7932 7933 // Don't replace wake type property if already set 7934 if ((arg0 == gIOPMWakeTypeUserKey) || 7935 !propertyExists(kIOPMRootDomainWakeTypeKey)) { 7936 const char * wakeType = NULL; 7937 7938 if (arg0 == gIOPMWakeTypeUserKey) { 7939 requestUserActive(this, "WakeTypeUser"); 7940 wakeType = kIOPMRootDomainWakeTypeUser; 7941 } else if (arg0 == gIOPMSettingDebugWakeRelativeKey) { 7942 requestUserActive(this, "WakeTypeAlarm"); 7943 wakeType = kIOPMRootDomainWakeTypeAlarm; 7944 } else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) { 7945 darkWakeSleepService = true; 7946 wakeType = kIOPMRootDomainWakeTypeSleepService; 7947 } else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) { 7948 wakeType = kIOPMRootDomainWakeTypeMaintenance; 7949 } 7950 7951 if (wakeType) { 7952 setProperty(kIOPMRootDomainWakeTypeKey, wakeType); 7953 } 7954 } 7955 break; 7956 7957 case kPowerEventAOTEvaluate: 7958 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1); 7959 if (_aotReadyToFullWake) { 7960 aotEvaluate(NULL); 7961 } 7962 break; 7963 } 7964 } 7965 7966 //****************************************************************************** 7967 // systemPowerEventOccurred 7968 // 7969 // The power controller is notifying us of a hardware-related power management 7970 // event that we must handle. 7971 // 7972 // systemPowerEventOccurred covers the same functionality that 7973 // receivePowerNotification does; it simply provides a richer API for conveying 7974 // more information. 7975 //****************************************************************************** 7976 7977 IOReturn 7978 IOPMrootDomain::systemPowerEventOccurred( 7979 const OSSymbol *event, 7980 uint32_t intValue) 7981 { 7982 IOReturn attempt = kIOReturnSuccess; 7983 OSSharedPtr<OSNumber> newNumber; 7984 7985 if (!event) { 7986 return kIOReturnBadArgument; 7987 } 7988 7989 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue)); 7990 if (!newNumber) { 7991 return kIOReturnInternalError; 7992 } 7993 7994 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get())); 7995 7996 return attempt; 7997 } 7998 7999 void 8000 IOPMrootDomain::setThermalState(OSObject *value) 8001 { 8002 OSNumber * num; 8003 8004 if (gIOPMWorkLoop->inGate() == false) { 8005 gIOPMWorkLoop->runAction( 8006 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState), 8007 (OSObject *)this, 8008 (void *)value); 8009 8010 return; 8011 } 8012 if (value && (num = OSDynamicCast(OSNumber, value))) { 8013 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) || 8014 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0; 8015 } 8016 } 8017 8018 IOReturn 8019 IOPMrootDomain::systemPowerEventOccurred( 8020 const OSSymbol *event, 8021 OSObject *value) 8022 { 8023 OSSharedPtr<OSDictionary> thermalsDict; 8024 bool shouldUpdate = true; 8025 8026 if (!event || !value) { 8027 return kIOReturnBadArgument; 8028 } 8029 8030 // LOCK 8031 // We reuse featuresDict Lock because it already exists and guards 8032 // the very infrequently used publish/remove feature mechanism; so there's zero rsk 8033 // of stepping on that lock. 8034 if (featuresDictLock) { 8035 IOLockLock(featuresDictLock); 8036 } 8037 8038 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey); 8039 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get()); 8040 8041 if (origThermalsDict) { 8042 thermalsDict = OSDictionary::withDictionary(origThermalsDict); 8043 } else { 8044 thermalsDict = OSDictionary::withCapacity(1); 8045 } 8046 8047 if (!thermalsDict) { 8048 shouldUpdate = false; 8049 goto exit; 8050 } 8051 8052 thermalsDict->setObject(event, value); 8053 8054 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get()); 8055 8056 exit: 8057 // UNLOCK 8058 if (featuresDictLock) { 8059 IOLockUnlock(featuresDictLock); 8060 } 8061 8062 if (shouldUpdate) { 8063 if (event && 8064 event->isEqualTo(kIOPMThermalLevelWarningKey)) { 8065 setThermalState(value); 8066 } 8067 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL); 8068 } 8069 8070 return kIOReturnSuccess; 8071 } 8072 8073 //****************************************************************************** 8074 // receivePowerNotification 8075 // 8076 // The power controller is notifying us of a hardware-related power management 8077 // event that we must handle. This may be a result of an 'environment' interrupt 8078 // from the power mgt micro. 8079 //****************************************************************************** 8080 8081 IOReturn 8082 IOPMrootDomain::receivePowerNotification( UInt32 msg ) 8083 { 8084 if (msg & kIOPMPowerButton) { 8085 uint32_t currentPhase = pmTracer->getTracePhase(); 8086 if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) { 8087 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase); 8088 swd_flags |= SWD_PWR_BTN_STACKSHOT; 8089 thread_call_enter(powerButtonDown); 8090 } else { 8091 DEBUG_LOG("power button pressed when system is up\n"); 8092 } 8093 } else if (msg & kIOPMPowerButtonUp) { 8094 if (swd_flags & SWD_PWR_BTN_STACKSHOT) { 8095 swd_flags &= ~SWD_PWR_BTN_STACKSHOT; 8096 thread_call_enter(powerButtonUp); 8097 } 8098 } else { 8099 pmPowerStateQueue->submitPowerEvent( 8100 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg ); 8101 } 8102 return kIOReturnSuccess; 8103 } 8104 8105 void 8106 IOPMrootDomain::handlePowerNotification( UInt32 msg ) 8107 { 8108 bool eval_clamshell = false; 8109 bool eval_clamshell_alarm = false; 8110 8111 ASSERT_GATED(); 8112 8113 /* 8114 * Local (IOPMrootDomain only) eval clamshell command 8115 */ 8116 if (msg & kLocalEvalClamshellCommand) { 8117 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) { 8118 eval_clamshell_alarm = true; 8119 8120 // reset isRTCAlarmWake. This evaluation should happen only once 8121 // on RTC/Alarm wake. Any clamshell events after wake should follow 8122 // the regular evaluation 8123 isRTCAlarmWake = false; 8124 } else { 8125 eval_clamshell = true; 8126 } 8127 } 8128 8129 /* 8130 * Overtemp 8131 */ 8132 if (msg & kIOPMOverTemp) { 8133 DLOG("Thermal overtemp message received!\n"); 8134 thermalEmergencyState = true; 8135 privateSleepSystem(kIOPMSleepReasonThermalEmergency); 8136 } 8137 8138 /* 8139 * Forward DW thermal notification to client, if system is not going to sleep 8140 */ 8141 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) { 8142 DLOG("DarkWake thermal limits message received!\n"); 8143 messageClients(kIOPMMessageDarkWakeThermalEmergency); 8144 } 8145 8146 /* 8147 * Sleep Now! 8148 */ 8149 if (msg & kIOPMSleepNow) { 8150 privateSleepSystem(kIOPMSleepReasonSoftware); 8151 } 8152 8153 /* 8154 * Power Emergency 8155 */ 8156 if (msg & kIOPMPowerEmergency) { 8157 DLOG("Low battery notification received\n"); 8158 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 8159 // Wait for the next low battery notification if the system state is 8160 // in transition. 8161 if ((_systemTransitionType == kSystemTransitionNone) && 8162 CAP_CURRENT(kIOPMSystemCapabilityCPU) && 8163 !systemBooting && !systemShutdown && !gWillShutdown) { 8164 // Setting lowBatteryCondition will prevent system sleep 8165 lowBatteryCondition = true; 8166 8167 // Notify userspace to initiate system shutdown 8168 messageClients(kIOPMMessageRequestSystemShutdown); 8169 } 8170 #else 8171 lowBatteryCondition = true; 8172 privateSleepSystem(kIOPMSleepReasonLowPower); 8173 #endif 8174 } 8175 8176 /* 8177 * Clamshell OPEN 8178 */ 8179 if (msg & kIOPMClamshellOpened) { 8180 DLOG("Clamshell opened\n"); 8181 // Received clamshel open message from clamshell controlling driver 8182 // Update our internal state and tell general interest clients 8183 clamshellClosed = false; 8184 clamshellExists = true; 8185 8186 // Don't issue a hid tickle when lid is open and polled on wake 8187 if (msg & kIOPMSetValue) { 8188 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open"); 8189 reportUserInput(); 8190 } 8191 8192 // Tell PMCPU 8193 informCPUStateChange(kInformLid, 0); 8194 8195 // Tell general interest clients 8196 sendClientClamshellNotification(); 8197 8198 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell) 8199 || (lastSleepReason == kIOPMSleepReasonIdle) 8200 || (lastSleepReason == kIOPMSleepReasonMaintenance)); 8201 if (aborting) { 8202 userActivityCount++; 8203 } 8204 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason); 8205 } 8206 8207 /* 8208 * Clamshell CLOSED 8209 * Send the clamshell interest notification since the lid is closing. 8210 */ 8211 if (msg & kIOPMClamshellClosed) { 8212 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) && 8213 clamshellClosed && clamshellExists) { 8214 DLOG("Ignoring redundant Clamshell close event\n"); 8215 } else { 8216 DLOG("Clamshell closed\n"); 8217 // Received clamshel open message from clamshell controlling driver 8218 // Update our internal state and tell general interest clients 8219 clamshellClosed = true; 8220 clamshellExists = true; 8221 8222 // Ignore all following clamshell close events until the clamshell 8223 // is opened or the system sleeps. When a clamshell close triggers 8224 // a system wake, the lid driver may send us two clamshell close 8225 // events, one for the clamshell close event itself, and a second 8226 // close event when the driver polls the lid state on wake. 8227 clamshellIgnoreClose = true; 8228 8229 // Tell PMCPU 8230 informCPUStateChange(kInformLid, 1); 8231 8232 // Tell general interest clients 8233 sendClientClamshellNotification(); 8234 8235 // And set eval_clamshell = so we can attempt 8236 eval_clamshell = true; 8237 } 8238 } 8239 8240 /* 8241 * Set Desktop mode (sent from graphics) 8242 * 8243 * -> reevaluate lid state 8244 */ 8245 if (msg & kIOPMSetDesktopMode) { 8246 desktopMode = (0 != (msg & kIOPMSetValue)); 8247 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue); 8248 DLOG("Desktop mode %d\n", desktopMode); 8249 8250 sendClientClamshellNotification(); 8251 8252 // Re-evaluate the lid state 8253 eval_clamshell = true; 8254 } 8255 8256 /* 8257 * AC Adaptor connected 8258 * 8259 * -> reevaluate lid state 8260 */ 8261 if (msg & kIOPMSetACAdaptorConnected) { 8262 acAdaptorConnected = (0 != (msg & kIOPMSetValue)); 8263 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue); 8264 8265 // Tell CPU PM 8266 informCPUStateChange(kInformAC, !acAdaptorConnected); 8267 8268 // Tell BSD if AC is connected 8269 // 0 == external power source; 1 == on battery 8270 post_sys_powersource(acAdaptorConnected ? 0:1); 8271 8272 sendClientClamshellNotification(); 8273 8274 // Re-evaluate the lid state 8275 eval_clamshell = true; 8276 8277 // Lack of AC may have latched a display wrangler tickle. 8278 // This mirrors the hardware's USB wake event latch, where a latched 8279 // USB wake event followed by an AC attach will trigger a full wake. 8280 latchDisplayWranglerTickle( false ); 8281 8282 #if HIBERNATION 8283 // AC presence will reset the standy timer delay adjustment. 8284 _standbyTimerResetSeconds = 0; 8285 #endif 8286 if (!userIsActive) { 8287 // Reset userActivityTime when power supply is changed(rdr 13789330) 8288 clock_get_uptime(&userActivityTime); 8289 } 8290 } 8291 8292 /* 8293 * Enable Clamshell (external display disappear) 8294 * 8295 * -> reevaluate lid state 8296 */ 8297 if (msg & kIOPMEnableClamshell) { 8298 DLOG("Clamshell enabled\n"); 8299 8300 // Re-evaluate the lid state 8301 // System should sleep on external display disappearance 8302 // in lid closed operation. 8303 if (true == clamshellDisabled) { 8304 eval_clamshell = true; 8305 8306 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 8307 // Also clear kClamshellSleepDisableInternal when graphics enables 8308 // the clamshell during a full wake. When graphics is behaving as 8309 // expected, this will allow clamshell close to be honored earlier 8310 // rather than waiting for the delayed evaluation. 8311 if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) && 8312 (CAP_PENDING(kIOPMSystemCapabilityGraphics) || 8313 CAP_CURRENT(kIOPMSystemCapabilityGraphics))) { 8314 setClamShellSleepDisable(false, kClamshellSleepDisableInternal); 8315 8316 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand 8317 // when timer expires which is harmless but useless. 8318 thread_call_cancel(fullWakeThreadCall); 8319 } 8320 #endif 8321 } 8322 8323 clamshellDisabled = false; 8324 sendClientClamshellNotification(); 8325 } 8326 8327 /* 8328 * Disable Clamshell (external display appeared) 8329 * We don't bother re-evaluating clamshell state. If the system is awake, 8330 * the lid is probably open. 8331 */ 8332 if (msg & kIOPMDisableClamshell) { 8333 DLOG("Clamshell disabled\n"); 8334 clamshellDisabled = true; 8335 sendClientClamshellNotification(); 8336 } 8337 8338 /* 8339 * Evaluate clamshell and SLEEP if appropriate 8340 */ 8341 if (eval_clamshell_alarm && clamshellClosed) { 8342 if (shouldSleepOnRTCAlarmWake()) { 8343 privateSleepSystem(kIOPMSleepReasonClamshell); 8344 } 8345 } else if (eval_clamshell && clamshellClosed) { 8346 if (shouldSleepOnClamshellClosed()) { 8347 privateSleepSystem(kIOPMSleepReasonClamshell); 8348 } else { 8349 evaluatePolicy( kStimulusDarkWakeEvaluate ); 8350 } 8351 } 8352 8353 if (msg & kIOPMProModeEngaged) { 8354 int newState = 1; 8355 DLOG("ProModeEngaged\n"); 8356 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState)); 8357 } 8358 8359 if (msg & kIOPMProModeDisengaged) { 8360 int newState = 0; 8361 DLOG("ProModeDisengaged\n"); 8362 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState)); 8363 } 8364 } 8365 8366 //****************************************************************************** 8367 // evaluatePolicy 8368 // 8369 // Evaluate root-domain policy in response to external changes. 8370 //****************************************************************************** 8371 8372 void 8373 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg ) 8374 { 8375 union { 8376 struct { 8377 int idleSleepEnabled : 1; 8378 int idleSleepDisabled : 1; 8379 int displaySleep : 1; 8380 int sleepDelayChanged : 1; 8381 int evaluateDarkWake : 1; 8382 int adjustPowerState : 1; 8383 int userBecameInactive : 1; 8384 int displaySleepEntry : 1; 8385 } bit; 8386 uint32_t u32; 8387 } flags; 8388 8389 8390 ASSERT_GATED(); 8391 flags.u32 = 0; 8392 8393 switch (stimulus) { 8394 case kStimulusDisplayWranglerSleep: 8395 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8396 if (!wranglerPowerOff) { 8397 // wrangler is in sleep state or lower 8398 flags.bit.displaySleep = true; 8399 } 8400 if (!wranglerAsleep) { 8401 // transition from wrangler wake to wrangler sleep 8402 flags.bit.displaySleepEntry = true; 8403 wranglerAsleep = true; 8404 } 8405 break; 8406 8407 case kStimulusDisplayWranglerWake: 8408 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8409 displayIdleForDemandSleep = false; 8410 wranglerPowerOff = false; 8411 wranglerAsleep = false; 8412 break; 8413 8414 case kStimulusEnterUserActiveState: 8415 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8416 if (_preventUserActive) { 8417 DLOG("user active dropped\n"); 8418 break; 8419 } 8420 if (!userIsActive) { 8421 userIsActive = true; 8422 userWasActive = true; 8423 clock_get_uptime(&gUserActiveAbsTime); 8424 8425 // Stay awake after dropping demand for display power on 8426 if (kFullWakeReasonDisplayOn == fullWakeReason) { 8427 fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser; 8428 DLOG("User activity while in notification wake\n"); 8429 changePowerStateWithOverrideTo( getRUN_STATE(), 0); 8430 } 8431 8432 kdebugTrace(kPMLogUserActiveState, 0, 1, 0); 8433 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue); 8434 messageClients(kIOPMMessageUserIsActiveChanged); 8435 } 8436 flags.bit.idleSleepDisabled = true; 8437 break; 8438 8439 case kStimulusLeaveUserActiveState: 8440 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8441 if (userIsActive) { 8442 clock_get_uptime(&gUserInactiveAbsTime); 8443 userIsActive = false; 8444 clock_get_uptime(&userBecameInactiveTime); 8445 flags.bit.userBecameInactive = true; 8446 8447 kdebugTrace(kPMLogUserActiveState, 0, 0, 0); 8448 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse); 8449 messageClients(kIOPMMessageUserIsActiveChanged); 8450 } 8451 break; 8452 8453 case kStimulusAggressivenessChanged: 8454 { 8455 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8456 unsigned long aggressiveValue; 8457 uint32_t minutesToIdleSleep = 0; 8458 uint32_t minutesToDisplayDim = 0; 8459 uint32_t minutesDelta = 0; 8460 8461 // Fetch latest display and system sleep slider values. 8462 aggressiveValue = 0; 8463 getAggressiveness(kPMMinutesToSleep, &aggressiveValue); 8464 minutesToIdleSleep = (uint32_t) aggressiveValue; 8465 8466 aggressiveValue = 0; 8467 getAggressiveness(kPMMinutesToDim, &aggressiveValue); 8468 minutesToDisplayDim = (uint32_t) aggressiveValue; 8469 DLOG("aggressiveness changed: system %u->%u, display %u\n", 8470 sleepSlider, minutesToIdleSleep, minutesToDisplayDim); 8471 8472 DLOG("idle time -> %d secs (ena %d)\n", 8473 idleSeconds, (minutesToIdleSleep != 0)); 8474 8475 // How long to wait before sleeping the system once 8476 // the displays turns off is indicated by 'extraSleepDelay'. 8477 8478 if (minutesToIdleSleep > minutesToDisplayDim) { 8479 minutesDelta = minutesToIdleSleep - minutesToDisplayDim; 8480 } else if (minutesToIdleSleep == minutesToDisplayDim) { 8481 minutesDelta = 1; 8482 } 8483 8484 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) { 8485 idleSleepEnabled = flags.bit.idleSleepEnabled = true; 8486 } 8487 8488 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) { 8489 flags.bit.idleSleepDisabled = true; 8490 idleSleepEnabled = false; 8491 } 8492 #if !defined(XNU_TARGET_OS_OSX) 8493 if (0x7fffffff == minutesToIdleSleep) { 8494 minutesToIdleSleep = idleSeconds; 8495 } 8496 #endif /* !defined(XNU_TARGET_OS_OSX) */ 8497 8498 if (((minutesDelta != extraSleepDelay) || 8499 (userActivityTime != userActivityTime_prev)) && 8500 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) { 8501 flags.bit.sleepDelayChanged = true; 8502 } 8503 8504 if (systemDarkWake && !darkWakeToSleepASAP && 8505 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) { 8506 // Reconsider decision to remain in dark wake 8507 flags.bit.evaluateDarkWake = true; 8508 } 8509 8510 sleepSlider = minutesToIdleSleep; 8511 extraSleepDelay = minutesDelta; 8512 userActivityTime_prev = userActivityTime; 8513 } break; 8514 8515 case kStimulusDemandSystemSleep: 8516 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8517 displayIdleForDemandSleep = true; 8518 if (wrangler && wranglerIdleSettings) { 8519 // Request wrangler idle only when demand sleep is triggered 8520 // from full wake. 8521 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) { 8522 wrangler->setProperties(wranglerIdleSettings.get()); 8523 DLOG("Requested wrangler idle\n"); 8524 } 8525 } 8526 // arg = sleepReason 8527 changePowerStateWithOverrideTo( SLEEP_STATE, arg ); 8528 break; 8529 8530 case kStimulusAllowSystemSleepChanged: 8531 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8532 flags.bit.adjustPowerState = true; 8533 break; 8534 8535 case kStimulusDarkWakeActivityTickle: 8536 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8537 // arg == true implies real and not self generated wrangler tickle. 8538 // Update wake type on PM work loop instead of the tickle thread to 8539 // eliminate the possibility of an early tickle clobbering the wake 8540 // type set by the platform driver. 8541 if (arg == true) { 8542 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity); 8543 } 8544 8545 if (!darkWakeExit) { 8546 if (latchDisplayWranglerTickle(true)) { 8547 DLOG("latched tickle\n"); 8548 break; 8549 } 8550 8551 darkWakeExit = true; 8552 DLOG("Requesting full wake due to dark wake activity tickle\n"); 8553 requestFullWake( kFullWakeReasonLocalUser ); 8554 } 8555 break; 8556 8557 case kStimulusDarkWakeEntry: 8558 case kStimulusDarkWakeReentry: 8559 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8560 // Any system transitions since the last dark wake transition 8561 // will invalid the stimulus. 8562 8563 if (arg == _systemStateGeneration) { 8564 DLOG("dark wake entry\n"); 8565 systemDarkWake = true; 8566 8567 // Keep wranglerPowerOff an invariant when wrangler is absent 8568 if (wrangler) { 8569 wranglerPowerOff = true; 8570 } 8571 8572 if (kStimulusDarkWakeEntry == stimulus) { 8573 clock_get_uptime(&userBecameInactiveTime); 8574 flags.bit.evaluateDarkWake = true; 8575 if (activitySinceSleep()) { 8576 DLOG("User activity recorded while going to darkwake\n"); 8577 reportUserInput(); 8578 } 8579 } 8580 8581 // Always accelerate disk spindown while in dark wake, 8582 // even if system does not support/allow sleep. 8583 8584 cancelIdleSleepTimer(); 8585 setQuickSpinDownTimeout(); 8586 } 8587 break; 8588 8589 case kStimulusDarkWakeEvaluate: 8590 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8591 if (systemDarkWake) { 8592 flags.bit.evaluateDarkWake = true; 8593 } 8594 break; 8595 8596 case kStimulusNoIdleSleepPreventers: 8597 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg); 8598 flags.bit.adjustPowerState = true; 8599 break; 8600 } /* switch(stimulus) */ 8601 8602 if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) { 8603 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n", 8604 darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected); 8605 if (darkWakeToSleepASAP || 8606 (clamshellClosed && !(desktopMode && acAdaptorConnected))) { 8607 uint32_t newSleepReason; 8608 8609 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) { 8610 // System was previously in full wake. Sleep reason from 8611 // full to dark already recorded in fullToDarkReason. 8612 8613 if (lowBatteryCondition) { 8614 newSleepReason = kIOPMSleepReasonLowPower; 8615 } else if (thermalEmergencyState) { 8616 newSleepReason = kIOPMSleepReasonThermalEmergency; 8617 } else { 8618 newSleepReason = fullToDarkReason; 8619 } 8620 } else { 8621 // In dark wake from system sleep. 8622 8623 if (darkWakeSleepService) { 8624 newSleepReason = kIOPMSleepReasonSleepServiceExit; 8625 } else { 8626 newSleepReason = kIOPMSleepReasonMaintenance; 8627 } 8628 } 8629 8630 if (checkSystemCanSleep(newSleepReason)) { 8631 privateSleepSystem(newSleepReason); 8632 } 8633 } else { // non-maintenance (network) dark wake 8634 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) { 8635 // Release power clamp, and wait for children idle. 8636 adjustPowerState(true); 8637 } else { 8638 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep); 8639 } 8640 } 8641 } 8642 8643 if (systemDarkWake) { 8644 // The rest are irrelevant while system is in dark wake. 8645 flags.u32 = 0; 8646 } 8647 8648 if ((flags.bit.displaySleepEntry) && 8649 (kFullWakeReasonDisplayOn == fullWakeReason)) { 8650 // kIOPMSleepReasonNotificationWakeExit 8651 DLOG("Display sleep while in notification wake\n"); 8652 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit); 8653 } 8654 8655 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) { 8656 bool cancelQuickSpindown = false; 8657 8658 if (flags.bit.sleepDelayChanged) { 8659 // Cancel existing idle sleep timer and quick disk spindown. 8660 // New settings will be applied by the idleSleepEnabled flag 8661 // handler below if idle sleep is enabled. 8662 8663 DLOG("extra sleep timer changed\n"); 8664 cancelIdleSleepTimer(); 8665 cancelQuickSpindown = true; 8666 } else { 8667 DLOG("user inactive\n"); 8668 } 8669 8670 if (!userIsActive && idleSleepEnabled) { 8671 startIdleSleepTimer(getTimeToIdleSleep()); 8672 } 8673 8674 if (cancelQuickSpindown) { 8675 restoreUserSpinDownTimeout(); 8676 } 8677 } 8678 8679 if (flags.bit.idleSleepEnabled) { 8680 DLOG("idle sleep timer enabled\n"); 8681 if (!wrangler) { 8682 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 8683 startIdleSleepTimer(getTimeToIdleSleep()); 8684 #else 8685 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled); 8686 startIdleSleepTimer( idleSeconds ); 8687 #endif 8688 } else { 8689 // Start idle timer if prefs now allow system sleep 8690 // and user is already inactive. Disk spindown is 8691 // accelerated upon timer expiration. 8692 8693 if (!userIsActive) { 8694 startIdleSleepTimer(getTimeToIdleSleep()); 8695 } 8696 } 8697 } 8698 8699 if (flags.bit.idleSleepDisabled) { 8700 DLOG("idle sleep timer disabled\n"); 8701 cancelIdleSleepTimer(); 8702 restoreUserSpinDownTimeout(); 8703 adjustPowerState(); 8704 } 8705 8706 if (flags.bit.adjustPowerState) { 8707 bool sleepASAP = false; 8708 8709 if (!systemBooting && (0 == idleSleepPreventersCount())) { 8710 if (!wrangler) { 8711 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy); 8712 if (idleSleepEnabled) { 8713 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 8714 if (!extraSleepDelay && !idleSleepTimerPending) { 8715 sleepASAP = true; 8716 } 8717 #else 8718 // stay awake for at least idleSeconds 8719 startIdleSleepTimer(idleSeconds); 8720 #endif 8721 } 8722 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake) { 8723 sleepASAP = true; 8724 } 8725 } 8726 8727 adjustPowerState(sleepASAP); 8728 } 8729 } 8730 8731 //****************************************************************************** 8732 8733 unsigned int 8734 IOPMrootDomain::idleSleepPreventersCount() 8735 { 8736 if (_aotMode) { 8737 unsigned int count __block; 8738 count = 0; 8739 preventIdleSleepList->iterateObjects(^bool (OSObject * obj) 8740 { 8741 count += (NULL == obj->metaCast("AppleARMBacklight")); 8742 return false; 8743 }); 8744 return count; 8745 } 8746 8747 return preventIdleSleepList->getCount(); 8748 } 8749 8750 8751 //****************************************************************************** 8752 // requestFullWake 8753 // 8754 // Request transition from dark wake to full wake 8755 //****************************************************************************** 8756 8757 void 8758 IOPMrootDomain::requestFullWake( FullWakeReason reason ) 8759 { 8760 uint32_t options = 0; 8761 IOService * pciRoot = NULL; 8762 bool promotion = false; 8763 8764 // System must be in dark wake and a valid reason for entering full wake 8765 if ((kFullWakeReasonNone == reason) || 8766 (kFullWakeReasonNone != fullWakeReason) || 8767 (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) { 8768 return; 8769 } 8770 8771 // Will clear reason upon exit from full wake 8772 fullWakeReason = reason; 8773 8774 _desiredCapability |= (kIOPMSystemCapabilityGraphics | 8775 kIOPMSystemCapabilityAudio); 8776 8777 if ((kSystemTransitionWake == _systemTransitionType) && 8778 !(_pendingCapability & kIOPMSystemCapabilityGraphics) && 8779 !darkWakePowerClamped) { 8780 // Promote to full wake while waking up to dark wake due to tickle. 8781 // PM will hold off notifying the graphics subsystem about system wake 8782 // as late as possible, so if a HID tickle does arrive, graphics can 8783 // power up from this same wake transition. Otherwise, the latency to 8784 // power up graphics on the following transition can be huge on certain 8785 // systems. However, once any power clamping has taken effect, it is 8786 // too late to promote the current dark wake transition to a full wake. 8787 _pendingCapability |= (kIOPMSystemCapabilityGraphics | 8788 kIOPMSystemCapabilityAudio); 8789 8790 // Tell the PCI parent of audio and graphics drivers to stop 8791 // delaying the child notifications. Same for root domain. 8792 pciRoot = pciHostBridgeDriver.get(); 8793 willEnterFullWake(); 8794 promotion = true; 8795 } 8796 8797 // Unsafe to cancel once graphics was powered. 8798 // If system woke from dark wake, the return to sleep can 8799 // be cancelled. "awake -> dark -> sleep" transition 8800 // can be cancelled also, during the "dark -> sleep" phase 8801 // *prior* to driver power down. 8802 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) || 8803 _pendingCapability == 0) { 8804 options |= kIOPMSyncCancelPowerDown; 8805 } 8806 8807 synchronizePowerTree(options, pciRoot); 8808 8809 if (kFullWakeReasonLocalUser == fullWakeReason) { 8810 // IOGraphics doesn't light the display even though graphics is 8811 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104) 8812 // So, do an explicit activity tickle 8813 if (wrangler) { 8814 wrangler->activityTickle(0, 0); 8815 } 8816 } 8817 8818 // Log a timestamp for the initial full wake request. 8819 // System may not always honor this full wake request. 8820 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) { 8821 AbsoluteTime now; 8822 uint64_t nsec; 8823 8824 clock_get_uptime(&now); 8825 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 8826 absolutetime_to_nanoseconds(now, &nsec); 8827 MSG("full wake %s (reason %u) %u ms\n", 8828 promotion ? "promotion" : "request", 8829 fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC))); 8830 } 8831 } 8832 8833 //****************************************************************************** 8834 // willEnterFullWake 8835 // 8836 // System will enter full wake from sleep, from dark wake, or from dark 8837 // wake promotion. This function aggregate things that are in common to 8838 // all three full wake transitions. 8839 // 8840 // Assumptions: fullWakeReason was updated 8841 //****************************************************************************** 8842 8843 void 8844 IOPMrootDomain::willEnterFullWake( void ) 8845 { 8846 hibernateRetry = false; 8847 sleepToStandby = false; 8848 standbyNixed = false; 8849 resetTimers = false; 8850 sleepTimerMaintenance = false; 8851 8852 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics)); 8853 8854 _systemMessageClientMask = kSystemMessageClientPowerd | 8855 kSystemMessageClientLegacyApp; 8856 8857 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) { 8858 // First time to attain full wake capability since the last wake 8859 _systemMessageClientMask |= kSystemMessageClientKernel; 8860 8861 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics 8862 setProperty(gIOPMUserTriggeredFullWakeKey.get(), 8863 (kFullWakeReasonLocalUser == fullWakeReason) ? 8864 kOSBooleanTrue : kOSBooleanFalse); 8865 } 8866 #if HIBERNATION 8867 IOHibernateSetWakeCapabilities(_pendingCapability); 8868 #endif 8869 8870 IOService::setAdvisoryTickleEnable( true ); 8871 tellClients(kIOMessageSystemWillPowerOn); 8872 preventTransitionToUserActive(false); 8873 } 8874 8875 //****************************************************************************** 8876 // fullWakeDelayedWork 8877 // 8878 // System has already entered full wake. Invoked by a delayed thread call. 8879 //****************************************************************************** 8880 8881 void 8882 IOPMrootDomain::fullWakeDelayedWork( void ) 8883 { 8884 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 8885 if (!gIOPMWorkLoop->inGate()) { 8886 gIOPMWorkLoop->runAction( 8887 OSMemberFunctionCast(IOWorkLoop::Action, this, 8888 &IOPMrootDomain::fullWakeDelayedWork), this); 8889 return; 8890 } 8891 8892 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n", 8893 _currentCapability, _pendingCapability, _highestCapability, 8894 clamshellDisabled, clamshellSleepDisableMask); 8895 8896 if (clamshellExists && 8897 CAP_CURRENT(kIOPMSystemCapabilityGraphics) && 8898 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) { 8899 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) { 8900 setClamShellSleepDisable(false, kClamshellSleepDisableInternal); 8901 } else { 8902 // Not the initial full wake after waking from sleep. 8903 // Evaluate the clamshell for rdar://problem/9157444. 8904 receivePowerNotification(kLocalEvalClamshellCommand); 8905 } 8906 } 8907 #endif 8908 } 8909 8910 //****************************************************************************** 8911 // evaluateAssertions 8912 // 8913 //****************************************************************************** 8914 8915 // Bitmask of all kernel assertions that prevent system idle sleep. 8916 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient. 8917 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \ 8918 (kIOPMDriverAssertionReservedBit7 | \ 8919 kIOPMDriverAssertionPreventSystemIdleSleepBit) 8920 8921 void 8922 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions) 8923 { 8924 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions; 8925 8926 messageClients(kIOPMMessageDriverAssertionsChanged); 8927 8928 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) { 8929 if (wrangler) { 8930 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false; 8931 8932 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value); 8933 wrangler->setIgnoreIdleTimer( value ); 8934 } 8935 } 8936 8937 if (changedBits & kIOPMDriverAssertionCPUBit) { 8938 if (_aotNow) { 8939 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions))); 8940 } 8941 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate); 8942 if (!assertOnWakeSecs && gIOLastWakeAbsTime) { 8943 AbsoluteTime now; 8944 clock_usec_t microsecs; 8945 clock_get_uptime(&now); 8946 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 8947 absolutetime_to_microtime(now, &assertOnWakeSecs, µsecs); 8948 if (assertOnWakeReport) { 8949 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs); 8950 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs); 8951 } 8952 } 8953 } 8954 8955 if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) { 8956 if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) { 8957 if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) { 8958 DLOG("PreventIdleSleep driver assertion raised\n"); 8959 bool ok = updatePreventIdleSleepList(this, true); 8960 if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) { 8961 // Cancel idle sleep if there is one in progress 8962 cancelIdlePowerDown(this); 8963 } 8964 } 8965 } else { 8966 DLOG("PreventIdleSleep driver assertion dropped\n"); 8967 updatePreventIdleSleepList(this, false); 8968 } 8969 } 8970 } 8971 8972 // MARK: - 8973 // MARK: Statistics 8974 8975 //****************************************************************************** 8976 // pmStats 8977 // 8978 //****************************************************************************** 8979 8980 void 8981 IOPMrootDomain::pmStatsRecordEvent( 8982 int eventIndex, 8983 AbsoluteTime timestamp) 8984 { 8985 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false; 8986 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false; 8987 uint64_t delta; 8988 uint64_t nsec; 8989 OSSharedPtr<OSData> publishPMStats; 8990 8991 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag); 8992 8993 absolutetime_to_nanoseconds(timestamp, &nsec); 8994 8995 switch (eventIndex) { 8996 case kIOPMStatsHibernateImageWrite: 8997 if (starting) { 8998 gPMStats.hibWrite.start = nsec; 8999 } else if (stopping) { 9000 gPMStats.hibWrite.stop = nsec; 9001 } 9002 9003 if (stopping) { 9004 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start; 9005 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC); 9006 } 9007 break; 9008 case kIOPMStatsHibernateImageRead: 9009 if (starting) { 9010 gPMStats.hibRead.start = nsec; 9011 } else if (stopping) { 9012 gPMStats.hibRead.stop = nsec; 9013 } 9014 9015 if (stopping) { 9016 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start; 9017 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC); 9018 9019 publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats)); 9020 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get()); 9021 bzero(&gPMStats, sizeof(gPMStats)); 9022 } 9023 break; 9024 } 9025 } 9026 9027 /* 9028 * Appends a record of the application response to 9029 * IOPMrootDomain::pmStatsAppResponses 9030 */ 9031 void 9032 IOPMrootDomain::pmStatsRecordApplicationResponse( 9033 const OSSymbol *response, 9034 const char *name, 9035 int messageType, 9036 uint32_t delay_ms, 9037 uint64_t id, 9038 OSObject *object, 9039 IOPMPowerStateIndex powerState, 9040 bool async) 9041 { 9042 OSSharedPtr<OSDictionary> responseDescription; 9043 OSSharedPtr<OSNumber> delayNum; 9044 OSSharedPtr<OSNumber> powerCaps; 9045 OSSharedPtr<OSNumber> pidNum; 9046 OSSharedPtr<OSNumber> msgNum; 9047 OSSharedPtr<const OSSymbol> appname; 9048 OSSharedPtr<const OSSymbol> sleep; 9049 OSSharedPtr<const OSSymbol> wake; 9050 IOPMServiceInterestNotifier *notify = NULL; 9051 9052 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) { 9053 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) { 9054 notify->ackTimeoutCnt++; 9055 } else { 9056 notify->ackTimeoutCnt = 0; 9057 } 9058 } 9059 9060 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) || 9061 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) { 9062 return; 9063 } 9064 9065 9066 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) { 9067 kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms); 9068 } else if (notify) { 9069 // User space app or kernel capability client 9070 if (id) { 9071 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms); 9072 } else { 9073 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms); 9074 } 9075 notify->msgType = 0; 9076 } 9077 9078 responseDescription = OSDictionary::withCapacity(5); 9079 if (responseDescription) { 9080 if (response) { 9081 responseDescription->setObject(_statsResponseTypeKey.get(), response); 9082 } 9083 9084 msgNum = OSNumber::withNumber(messageType, 32); 9085 if (msgNum) { 9086 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get()); 9087 } 9088 9089 if (!name && notify && notify->identifier) { 9090 name = notify->identifier->getCStringNoCopy(); 9091 } 9092 9093 if (name && (strlen(name) > 0)) { 9094 appname = OSSymbol::withCString(name); 9095 if (appname) { 9096 responseDescription->setObject(_statsNameKey.get(), appname.get()); 9097 } 9098 } 9099 9100 if (!id && notify) { 9101 id = notify->uuid0; 9102 } 9103 if (id != 0) { 9104 pidNum = OSNumber::withNumber(id, 64); 9105 if (pidNum) { 9106 responseDescription->setObject(_statsPIDKey.get(), pidNum.get()); 9107 } 9108 } 9109 9110 delayNum = OSNumber::withNumber(delay_ms, 32); 9111 if (delayNum) { 9112 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get()); 9113 } 9114 9115 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) { 9116 powerCaps = OSNumber::withNumber(powerState, 32); 9117 9118 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG) 9119 static const char * driverCallTypes[] = { 9120 [kDriverCallInformPreChange] = "powerStateWillChangeTo", 9121 [kDriverCallInformPostChange] = "powerStateDidChangeTo", 9122 [kDriverCallSetPowerState] = "setPowerState" 9123 }; 9124 9125 if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) { 9126 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n", 9127 name, id, driverCallTypes[messageType], (uint32_t) powerState, 9128 async ? "async " : "", delay_ms); 9129 } 9130 #endif 9131 } else { 9132 powerCaps = OSNumber::withNumber(_pendingCapability, 32); 9133 } 9134 if (powerCaps) { 9135 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get()); 9136 } 9137 9138 sleep = OSSymbol::withCString("Sleep"); 9139 wake = OSSymbol::withCString("Wake"); 9140 if (_systemTransitionType == kSystemTransitionSleep) { 9141 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get()); 9142 } else if (_systemTransitionType == kSystemTransitionWake) { 9143 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get()); 9144 } else if (_systemTransitionType == kSystemTransitionCapability) { 9145 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) { 9146 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get()); 9147 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) { 9148 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get()); 9149 } 9150 } 9151 9152 IOLockLock(pmStatsLock); 9153 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) { 9154 pmStatsAppResponses->setObject(responseDescription.get()); 9155 } 9156 IOLockUnlock(pmStatsLock); 9157 } 9158 9159 return; 9160 } 9161 9162 // MARK: - 9163 // MARK: PMTraceWorker 9164 9165 //****************************************************************************** 9166 // TracePoint support 9167 // 9168 //****************************************************************************** 9169 9170 #define kIOPMRegisterNVRAMTracePointHandlerKey \ 9171 "IOPMRegisterNVRAMTracePointHandler" 9172 9173 IOReturn 9174 IOPMrootDomain::callPlatformFunction( 9175 const OSSymbol * functionName, 9176 bool waitForFunction, 9177 void * param1, void * param2, 9178 void * param3, void * param4 ) 9179 { 9180 if (pmTracer && functionName && 9181 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) && 9182 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) { 9183 uint32_t tracePointPhases, tracePointPCI; 9184 uint64_t statusCode; 9185 9186 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1; 9187 pmTracer->tracePointTarget = (void *) param2; 9188 tracePointPCI = (uint32_t)(uintptr_t) param3; 9189 tracePointPhases = (uint32_t)(uintptr_t) param4; 9190 if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) { 9191 OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane ); 9192 if (node) { 9193 OSSharedPtr<OSObject> bootRomFailureProp; 9194 bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey); 9195 OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get()); 9196 uint32_t bootFailureCode; 9197 if (data && data->getLength() == sizeof(bootFailureCode)) { 9198 // Failure code from EFI/BootRom is a four byte structure 9199 memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode)); 9200 tracePointPCI = OSSwapBigToHostInt32(bootFailureCode); 9201 } 9202 } 9203 } 9204 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases; 9205 if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) { 9206 MSG("Sleep failure code 0x%08x 0x%08x\n", 9207 tracePointPCI, tracePointPhases); 9208 } 9209 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64); 9210 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 ); 9211 9212 return kIOReturnSuccess; 9213 } 9214 #if HIBERNATION 9215 else if (functionName && 9216 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) { 9217 if (gSleepPolicyHandler) { 9218 return kIOReturnExclusiveAccess; 9219 } 9220 if (!param1) { 9221 return kIOReturnBadArgument; 9222 } 9223 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1; 9224 gSleepPolicyTarget = (void *) param2; 9225 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue); 9226 return kIOReturnSuccess; 9227 } 9228 #endif 9229 9230 return super::callPlatformFunction( 9231 functionName, waitForFunction, param1, param2, param3, param4); 9232 } 9233 9234 void 9235 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id, 9236 uintptr_t param1, uintptr_t param2, uintptr_t param3) 9237 { 9238 uint32_t code = IODBG_POWER(event); 9239 uint64_t regId = id; 9240 if (regId == 0) { 9241 regId = getRegistryEntryID(); 9242 } 9243 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0); 9244 } 9245 9246 void 9247 IOPMrootDomain::tracePoint( uint8_t point ) 9248 { 9249 if (systemBooting) { 9250 return; 9251 } 9252 9253 if (kIOPMTracePointWakeCapabilityClients == point) { 9254 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable); 9255 } 9256 9257 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0); 9258 pmTracer->tracePoint(point); 9259 } 9260 9261 static void 9262 kext_log_putc(char c) 9263 { 9264 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) { 9265 return; 9266 } 9267 if (c == '(' || c == '[' || c == ' ') { 9268 c = 0; 9269 gKextNameEnd = true; 9270 } 9271 9272 gKextNameBuf[gKextNamePos++] = c; 9273 } 9274 9275 static int 9276 kext_log(const char *fmt, ...) 9277 { 9278 va_list listp; 9279 9280 va_start(listp, fmt); 9281 _doprnt(fmt, &listp, &kext_log_putc, 16); 9282 va_end(listp); 9283 9284 return 0; 9285 } 9286 9287 static OSPtr<const OSSymbol> 9288 copyKextIdentifierWithAddress(vm_address_t address) 9289 { 9290 OSSharedPtr<const OSSymbol> identifer; 9291 9292 IOLockLock(gHaltLogLock); 9293 9294 gKextNameEnd = false; 9295 gKextNamePos = 0; 9296 gKextNameBuf[0] = 0; 9297 9298 OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse); 9299 gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0; 9300 identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier); 9301 9302 IOLockUnlock(gHaltLogLock); 9303 9304 return identifer; 9305 } 9306 9307 // Caller serialized using PM workloop 9308 const char * 9309 IOPMrootDomain::getNotificationClientName(OSObject *object) 9310 { 9311 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object; 9312 const char *clientName = "UNKNOWN"; 9313 9314 if (!notifier->clientName) { 9315 // Check for user client 9316 if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) { 9317 OSNumber *clientID = NULL; 9318 messageClient(kIOMessageCopyClientID, object, &clientID); 9319 if (clientID) { 9320 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain); 9321 if (string) { 9322 notifier->clientName = OSSymbol::withString(string.get()); 9323 } 9324 clientID->release(); 9325 } 9326 } else if (notifier->identifier) { 9327 notifier->clientName.reset(notifier->identifier.get(), OSRetain); 9328 } 9329 } 9330 9331 if (notifier->clientName) { 9332 clientName = notifier->clientName->getCStringNoCopy(); 9333 } 9334 9335 return clientName; 9336 } 9337 9338 void 9339 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex) 9340 { 9341 IOPMServiceInterestNotifier *notifier; 9342 9343 if (systemBooting) { 9344 return; 9345 } 9346 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object); 9347 if (!notifier) { 9348 return; 9349 } 9350 9351 if (start) { 9352 pmTracer->traceDetail(notifier->uuid0 >> 32); 9353 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(), 9354 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1); 9355 9356 // Update notifier state used for response/ack logging 9357 notifier->msgIndex = msgIndex; 9358 notifier->msgAbsTime = timestamp; 9359 9360 if (msgIndex != UINT_MAX) { 9361 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier)); 9362 } else { 9363 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier)); 9364 } 9365 9366 assert(notifierObject == NULL); 9367 notifierThread = current_thread(); 9368 notifierObject.reset(notifier, OSRetain); 9369 } else { 9370 uint64_t nsec; 9371 uint32_t delayMS; 9372 9373 SUB_ABSOLUTETIME(×tamp, ¬ifier->msgAbsTime); 9374 absolutetime_to_nanoseconds(timestamp, &nsec); 9375 delayMS = (uint32_t)(nsec / 1000000ULL); 9376 if (delayMS > notifier->maxMsgDelayMS) { 9377 notifier->maxMsgDelayMS = delayMS; 9378 } 9379 9380 assert(notifierObject == notifier); 9381 notifierObject.reset(); 9382 notifierThread = NULL; 9383 } 9384 } 9385 9386 void 9387 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms) 9388 { 9389 if (systemBooting) { 9390 return; 9391 } 9392 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object); 9393 if (!notifier) { 9394 return; 9395 } 9396 9397 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0, 9398 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms); 9399 9400 DLOG("%s[%u] ack from %s took %d ms\n", 9401 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms); 9402 if (delay_ms > notifier->maxAckDelayMS) { 9403 notifier->maxAckDelayMS = delay_ms; 9404 } 9405 } 9406 9407 void 9408 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us) 9409 { 9410 if (systemBooting) { 9411 return; 9412 } 9413 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object); 9414 if (!notifier) { 9415 return; 9416 } 9417 9418 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0, 9419 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms); 9420 9421 if (ack_time_us == 0) { 9422 // Client work is done and ack will not be forthcoming 9423 DLOG("%s[%u] response from %s took %d ms\n", 9424 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms); 9425 } else { 9426 // Client needs more time and it must ack within ack_time_us 9427 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n", 9428 getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us); 9429 } 9430 } 9431 9432 void 9433 IOPMrootDomain::traceFilteredNotification(OSObject *object) 9434 { 9435 if ((kIOLogDebugPower & gIOKitDebug) == 0) { 9436 return; 9437 } 9438 if (systemBooting) { 9439 return; 9440 } 9441 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object); 9442 if (!notifier) { 9443 return; 9444 } 9445 9446 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier)); 9447 } 9448 9449 void 9450 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay) 9451 { 9452 if (!systemBooting) { 9453 uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff); 9454 pmTracer->traceDetail( detail ); 9455 kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay); 9456 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay); 9457 } 9458 } 9459 9460 void 9461 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result) 9462 { 9463 size_t reportSize; 9464 void **report = NULL; 9465 uint32_t bktCnt; 9466 uint32_t bktSize; 9467 uint32_t *clientCnt; 9468 9469 ASSERT_GATED(); 9470 9471 report = NULL; 9472 if (channel_id == kAssertDelayChID) { 9473 report = &assertOnWakeReport; 9474 bktCnt = kAssertDelayBcktCnt; 9475 bktSize = kAssertDelayBcktSize; 9476 clientCnt = &assertOnWakeClientCnt; 9477 } else if (channel_id == kSleepDelaysChID) { 9478 report = &sleepDelaysReport; 9479 bktCnt = kSleepDelaysBcktCnt; 9480 bktSize = kSleepDelaysBcktSize; 9481 clientCnt = &sleepDelaysClientCnt; 9482 } else { 9483 assert(false); 9484 return; 9485 } 9486 9487 switch (action) { 9488 case kIOReportEnable: 9489 9490 if (*report) { 9491 (*clientCnt)++; 9492 break; 9493 } 9494 9495 reportSize = HISTREPORT_BUFSIZE(bktCnt); 9496 *report = IOMalloc(reportSize); 9497 if (*report == NULL) { 9498 break; 9499 } 9500 bzero(*report, reportSize); 9501 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize, 9502 getRegistryEntryID(), channel_id, kIOReportCategoryPower); 9503 9504 if (channel_id == kAssertDelayChID) { 9505 assertOnWakeSecs = 0; 9506 } 9507 9508 break; 9509 9510 case kIOReportDisable: 9511 if (*clientCnt == 0) { 9512 break; 9513 } 9514 if (*clientCnt == 1) { 9515 IOFree(*report, HISTREPORT_BUFSIZE(bktCnt)); 9516 *report = NULL; 9517 } 9518 (*clientCnt)--; 9519 9520 if (channel_id == kAssertDelayChID) { 9521 assertOnWakeSecs = -1; // Invalid value to prevent updates 9522 } 9523 break; 9524 9525 case kIOReportGetDimensions: 9526 if (*report) { 9527 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result); 9528 } 9529 break; 9530 } 9531 9532 return; 9533 } 9534 9535 IOReturn 9536 IOPMrootDomain::configureReport(IOReportChannelList *channelList, 9537 IOReportConfigureAction action, 9538 void *result, 9539 void *destination) 9540 { 9541 unsigned cnt; 9542 uint64_t configAction = (uint64_t)action; 9543 9544 for (cnt = 0; cnt < channelList->nchannels; cnt++) { 9545 if ((channelList->channels[cnt].channel_id == kSleepCntChID) || 9546 (channelList->channels[cnt].channel_id == kDarkWkCntChID) || 9547 (channelList->channels[cnt].channel_id == kUserWkCntChID)) { 9548 if (action != kIOReportGetDimensions) { 9549 continue; 9550 } 9551 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result); 9552 } else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) || 9553 (channelList->channels[cnt].channel_id == kSleepDelaysChID)) { 9554 gIOPMWorkLoop->runAction( 9555 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated), 9556 (OSObject *)this, (void *)channelList->channels[cnt].channel_id, 9557 (void *)configAction, (void *)result); 9558 } 9559 } 9560 9561 return super::configureReport(channelList, action, result, destination); 9562 } 9563 9564 IOReturn 9565 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest) 9566 { 9567 uint32_t size2cpy; 9568 void *data2cpy; 9569 void **report; 9570 9571 ASSERT_GATED(); 9572 9573 report = NULL; 9574 if (ch_id == kAssertDelayChID) { 9575 report = &assertOnWakeReport; 9576 } else if (ch_id == kSleepDelaysChID) { 9577 report = &sleepDelaysReport; 9578 } else { 9579 assert(false); 9580 return kIOReturnBadArgument; 9581 } 9582 9583 if (*report == NULL) { 9584 return kIOReturnNotOpen; 9585 } 9586 9587 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy); 9588 if (size2cpy > (dest->getCapacity() - dest->getLength())) { 9589 return kIOReturnOverrun; 9590 } 9591 9592 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result); 9593 dest->appendBytes(data2cpy, size2cpy); 9594 9595 return kIOReturnSuccess; 9596 } 9597 9598 IOReturn 9599 IOPMrootDomain::updateReport(IOReportChannelList *channelList, 9600 IOReportUpdateAction action, 9601 void *result, 9602 void *destination) 9603 { 9604 uint32_t size2cpy; 9605 void *data2cpy; 9606 uint8_t buf[SIMPLEREPORT_BUFSIZE]; 9607 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination); 9608 unsigned cnt; 9609 uint64_t ch_id; 9610 9611 if (action != kIOReportCopyChannelData) { 9612 goto exit; 9613 } 9614 9615 for (cnt = 0; cnt < channelList->nchannels; cnt++) { 9616 ch_id = channelList->channels[cnt].channel_id; 9617 9618 if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) { 9619 gIOPMWorkLoop->runAction( 9620 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated), 9621 (OSObject *)this, (void *)ch_id, 9622 (void *)result, (void *)dest); 9623 continue; 9624 } else if ((ch_id == kSleepCntChID) || 9625 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) { 9626 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower); 9627 } else { 9628 continue; 9629 } 9630 9631 if (ch_id == kSleepCntChID) { 9632 SIMPLEREPORT_SETVALUE(buf, sleepCnt); 9633 } else if (ch_id == kDarkWkCntChID) { 9634 SIMPLEREPORT_SETVALUE(buf, darkWakeCnt); 9635 } else if (ch_id == kUserWkCntChID) { 9636 SIMPLEREPORT_SETVALUE(buf, displayWakeCnt); 9637 } 9638 9639 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy); 9640 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result); 9641 dest->appendBytes(data2cpy, size2cpy); 9642 } 9643 9644 exit: 9645 return super::updateReport(channelList, action, result, destination); 9646 } 9647 9648 9649 //****************************************************************************** 9650 // PMTraceWorker Class 9651 // 9652 //****************************************************************************** 9653 9654 #undef super 9655 #define super OSObject 9656 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject) 9657 9658 #define kPMBestGuessPCIDevicesCount 25 9659 #define kPMMaxRTCBitfieldSize 32 9660 9661 OSPtr<PMTraceWorker> 9662 PMTraceWorker::tracer(IOPMrootDomain * owner) 9663 { 9664 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>(); 9665 if (!me || !me->init()) { 9666 return NULL; 9667 } 9668 9669 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get())); 9670 9671 // Note that we cannot instantiate the PCI device -> bit mappings here, since 9672 // the IODeviceTree has not yet been created by IOPlatformExpert. We create 9673 // this dictionary lazily. 9674 me->owner = owner; 9675 me->pciDeviceBitMappings = NULL; 9676 me->pmTraceWorkerLock = IOLockAlloc(); 9677 me->tracePhase = kIOPMTracePointSystemUp; 9678 me->traceData32 = 0; 9679 me->loginWindowData = 0; 9680 me->coreDisplayData = 0; 9681 me->coreGraphicsData = 0; 9682 return me; 9683 } 9684 9685 void 9686 PMTraceWorker::RTC_TRACE(void) 9687 { 9688 if (tracePointHandler && tracePointTarget) { 9689 uint32_t wordA; 9690 9691 IOLockLock(pmTraceWorkerLock); 9692 wordA = (loginWindowData << 24) | (coreDisplayData << 16) | 9693 (coreGraphicsData << 8) | tracePhase; 9694 IOLockUnlock(pmTraceWorkerLock); 9695 9696 tracePointHandler( tracePointTarget, traceData32, wordA ); 9697 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA); 9698 } 9699 #if DEVELOPMENT || DEBUG 9700 if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) { 9701 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase); 9702 IOLock *l = IOLockAlloc(); 9703 IOLockLock(l); 9704 IOLockLock(l); 9705 } 9706 #endif 9707 } 9708 9709 int 9710 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice) 9711 { 9712 OSSharedPtr<const OSSymbol> deviceName; 9713 int index = -1; 9714 9715 IOLockLock(pmTraceWorkerLock); 9716 9717 if (!pciDeviceBitMappings) { 9718 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount); 9719 if (!pciDeviceBitMappings) { 9720 goto exit; 9721 } 9722 } 9723 9724 // Check for bitmask overflow. 9725 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) { 9726 goto exit; 9727 } 9728 9729 if ((deviceName = pciDevice->copyName()) && 9730 (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) && 9731 pciDeviceBitMappings->setObject(deviceName.get())) { 9732 index = pciDeviceBitMappings->getCount() - 1; 9733 _LOG("PMTrace PCI array: set object %s => %d\n", 9734 deviceName->getCStringNoCopy(), index); 9735 } 9736 9737 if (!addedToRegistry && (index >= 0)) { 9738 addedToRegistry = owner->setProperty("PCITopLevel", this); 9739 } 9740 9741 exit: 9742 IOLockUnlock(pmTraceWorkerLock); 9743 return index; 9744 } 9745 9746 bool 9747 PMTraceWorker::serialize(OSSerialize *s) const 9748 { 9749 bool ok = false; 9750 if (pciDeviceBitMappings) { 9751 IOLockLock(pmTraceWorkerLock); 9752 ok = pciDeviceBitMappings->serialize(s); 9753 IOLockUnlock(pmTraceWorkerLock); 9754 } 9755 return ok; 9756 } 9757 9758 void 9759 PMTraceWorker::tracePoint(uint8_t phase) 9760 { 9761 // clear trace detail when phase begins 9762 if (tracePhase != phase) { 9763 traceData32 = 0; 9764 } 9765 9766 tracePhase = phase; 9767 9768 DLOG("trace point 0x%02x\n", tracePhase); 9769 RTC_TRACE(); 9770 } 9771 9772 void 9773 PMTraceWorker::traceDetail(uint32_t detail) 9774 { 9775 if (detail == traceData32) { 9776 return; 9777 } 9778 traceData32 = detail; 9779 RTC_TRACE(); 9780 } 9781 9782 void 9783 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data) 9784 { 9785 switch (component) { 9786 case kIOPMLoginWindowProgress: 9787 loginWindowData = data & kIOPMLoginWindowProgressMask; 9788 break; 9789 case kIOPMCoreDisplayProgress: 9790 coreDisplayData = data & kIOPMCoreDisplayProgressMask; 9791 break; 9792 case kIOPMCoreGraphicsProgress: 9793 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask; 9794 break; 9795 default: 9796 return; 9797 } 9798 9799 DLOG("component trace point 0x%02x data 0x%08x\n", component, data); 9800 RTC_TRACE(); 9801 } 9802 9803 void 9804 PMTraceWorker::tracePCIPowerChange( 9805 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum) 9806 { 9807 uint32_t bitMask; 9808 uint32_t expectedFlag; 9809 9810 // Ignore PCI changes outside of system sleep/wake. 9811 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) && 9812 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) { 9813 return; 9814 } 9815 9816 // Only record the WillChange transition when going to sleep, 9817 // and the DidChange on the way up. 9818 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange); 9819 expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ? 9820 kIOPMDomainWillChange : kIOPMDomainDidChange; 9821 if (changeFlags != expectedFlag) { 9822 return; 9823 } 9824 9825 // Mark this device off in our bitfield 9826 if (bitNum < kPMMaxRTCBitfieldSize) { 9827 bitMask = (1 << bitNum); 9828 9829 if (kPowerChangeStart == type) { 9830 traceData32 |= bitMask; 9831 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n", 9832 service->getName(), bitNum, bitMask, traceData32); 9833 owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0); 9834 } else { 9835 traceData32 &= ~bitMask; 9836 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n", 9837 service->getName(), bitNum, bitMask, traceData32); 9838 owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0); 9839 } 9840 9841 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32); 9842 RTC_TRACE(); 9843 } 9844 } 9845 9846 uint64_t 9847 PMTraceWorker::getPMStatusCode() 9848 { 9849 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase); 9850 } 9851 9852 uint8_t 9853 PMTraceWorker::getTracePhase() 9854 { 9855 return tracePhase; 9856 } 9857 9858 uint32_t 9859 PMTraceWorker::getTraceData() 9860 { 9861 return traceData32; 9862 } 9863 9864 // MARK: - 9865 // MARK: PMHaltWorker 9866 9867 //****************************************************************************** 9868 // PMHaltWorker Class 9869 // 9870 //****************************************************************************** 9871 9872 PMHaltWorker * 9873 PMHaltWorker::worker( void ) 9874 { 9875 PMHaltWorker * me; 9876 IOThread thread; 9877 9878 do { 9879 me = OSTypeAlloc( PMHaltWorker ); 9880 if (!me || !me->init()) { 9881 break; 9882 } 9883 9884 me->lock = IOLockAlloc(); 9885 if (!me->lock) { 9886 break; 9887 } 9888 9889 DLOG("PMHaltWorker %p\n", OBFUSCATE(me)); 9890 me->retain(); // thread holds extra retain 9891 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) { 9892 me->release(); 9893 break; 9894 } 9895 thread_deallocate(thread); 9896 return me; 9897 } while (false); 9898 9899 if (me) { 9900 me->release(); 9901 } 9902 return NULL; 9903 } 9904 9905 void 9906 PMHaltWorker::free( void ) 9907 { 9908 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this)); 9909 if (lock) { 9910 IOLockFree(lock); 9911 lock = NULL; 9912 } 9913 return OSObject::free(); 9914 } 9915 9916 void 9917 PMHaltWorker::main( void * arg, wait_result_t waitResult ) 9918 { 9919 PMHaltWorker * me = (PMHaltWorker *) arg; 9920 9921 IOLockLock( gPMHaltLock ); 9922 gPMHaltBusyCount++; 9923 me->depth = gPMHaltDepth; 9924 IOLockUnlock( gPMHaltLock ); 9925 9926 while (me->depth >= 0) { 9927 PMHaltWorker::work( me ); 9928 9929 IOLockLock( gPMHaltLock ); 9930 if (++gPMHaltIdleCount >= gPMHaltBusyCount) { 9931 // This is the last thread to finish work on this level, 9932 // inform everyone to start working on next lower level. 9933 gPMHaltDepth--; 9934 me->depth = gPMHaltDepth; 9935 gPMHaltIdleCount = 0; 9936 thread_wakeup((event_t) &gPMHaltIdleCount); 9937 } else { 9938 // One or more threads are still working on this level, 9939 // this thread must wait. 9940 me->depth = gPMHaltDepth - 1; 9941 do { 9942 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT); 9943 } while (me->depth != gPMHaltDepth); 9944 } 9945 IOLockUnlock( gPMHaltLock ); 9946 } 9947 9948 // No more work to do, terminate thread 9949 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits); 9950 thread_wakeup( &gPMHaltDepth ); 9951 me->release(); 9952 } 9953 9954 void 9955 PMHaltWorker::work( PMHaltWorker * me ) 9956 { 9957 OSSharedPtr<IOService> service; 9958 OSSet * inner; 9959 AbsoluteTime startTime, elapsedTime; 9960 UInt32 deltaTime; 9961 bool timeout; 9962 9963 while (true) { 9964 timeout = false; 9965 9966 // Claim an unit of work from the shared pool 9967 IOLockLock( gPMHaltLock ); 9968 inner = (OSSet *)gPMHaltArray->getObject(me->depth); 9969 if (inner) { 9970 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain); 9971 if (service) { 9972 inner->removeObject(service.get()); 9973 } 9974 } 9975 IOLockUnlock( gPMHaltLock ); 9976 if (!service) { 9977 break; // no more work at this depth 9978 } 9979 clock_get_uptime(&startTime); 9980 9981 if (!service->isInactive() && 9982 service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) { 9983 IOLockLock(me->lock); 9984 me->startTime = startTime; 9985 me->service = service.get(); 9986 me->timeout = false; 9987 IOLockUnlock(me->lock); 9988 9989 service->systemWillShutdown( gPMHaltMessageType); 9990 9991 // Wait for driver acknowledgement 9992 IOLockLock(me->lock); 9993 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) { 9994 IOLockSleep(me->lock, me, THREAD_UNINT); 9995 } 9996 me->service = NULL; 9997 timeout = me->timeout; 9998 IOLockUnlock(me->lock); 9999 } 10000 10001 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime); 10002 if ((deltaTime > kPMHaltTimeoutMS) || timeout) { 10003 LOG("%s driver %s (0x%llx) took %u ms\n", 10004 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? 10005 "PowerOff" : "Restart", 10006 service->getName(), service->getRegistryEntryID(), 10007 (uint32_t) deltaTime ); 10008 halt_log_enter("PowerOff/Restart handler completed", 10009 OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown), 10010 elapsedTime); 10011 } 10012 10013 me->visits++; 10014 } 10015 } 10016 10017 void 10018 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now ) 10019 { 10020 UInt64 nano; 10021 AbsoluteTime startTime; 10022 AbsoluteTime endTime; 10023 10024 endTime = *now; 10025 10026 IOLockLock(me->lock); 10027 if (me->service && !me->timeout) { 10028 startTime = me->startTime; 10029 nano = 0; 10030 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) { 10031 SUB_ABSOLUTETIME(&endTime, &startTime); 10032 absolutetime_to_nanoseconds(endTime, &nano); 10033 } 10034 if (nano > 3000000000ULL) { 10035 me->timeout = true; 10036 10037 halt_log_enter("PowerOff/Restart still waiting on handler", 10038 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown), 10039 endTime); 10040 MSG("%s still waiting on %s\n", 10041 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart", 10042 me->service->getName()); 10043 } 10044 } 10045 IOLockUnlock(me->lock); 10046 } 10047 10048 //****************************************************************************** 10049 // acknowledgeSystemWillShutdown 10050 // 10051 // Acknowledgement from drivers that they have prepared for shutdown/restart. 10052 //****************************************************************************** 10053 10054 void 10055 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from ) 10056 { 10057 PMHaltWorker * worker; 10058 OSSharedPtr<OSObject> prop; 10059 10060 if (!from) { 10061 return; 10062 } 10063 10064 //DLOG("%s acknowledged\n", from->getName()); 10065 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get()); 10066 if (prop) { 10067 worker = (PMHaltWorker *) prop.get(); 10068 IOLockLock(worker->lock); 10069 from->removeProperty( gPMHaltClientAcknowledgeKey.get()); 10070 thread_wakeup((event_t) worker); 10071 IOLockUnlock(worker->lock); 10072 } else { 10073 DLOG("%s acknowledged without worker property\n", 10074 from->getName()); 10075 } 10076 } 10077 10078 10079 //****************************************************************************** 10080 // notifySystemShutdown 10081 // 10082 // Notify all objects in PM tree that system will shutdown or restart 10083 //****************************************************************************** 10084 10085 static void 10086 notifySystemShutdown( IOService * root, uint32_t messageType ) 10087 { 10088 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get()) 10089 OSSharedPtr<IORegistryIterator> iter; 10090 IORegistryEntry * entry; 10091 IOService * node; 10092 OSSet * inner; 10093 OSSharedPtr<OSSet> newInner; 10094 PMHaltWorker * workers[kPMHaltMaxWorkers]; 10095 AbsoluteTime deadline; 10096 unsigned int totalNodes = 0; 10097 unsigned int depth; 10098 unsigned int rootDepth; 10099 unsigned int numWorkers; 10100 unsigned int count; 10101 int waitResult; 10102 void * baseFunc; 10103 bool ok; 10104 10105 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType); 10106 10107 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown); 10108 10109 // Iterate the entire PM tree starting from root 10110 10111 rootDepth = root->getDepth( gIOPowerPlane ); 10112 if (!rootDepth) { 10113 goto done; 10114 } 10115 10116 // debug - for repeated test runs 10117 while (PMHaltWorker::metaClass->getInstanceCount()) { 10118 IOSleep(1); 10119 } 10120 10121 if (!gPMHaltArray) { 10122 gPMHaltArray = OSArray::withCapacity(40); 10123 if (!gPMHaltArray) { 10124 goto done; 10125 } 10126 } else { // debug 10127 gPMHaltArray->flushCollection(); 10128 } 10129 10130 if (!gPMHaltLock) { 10131 gPMHaltLock = IOLockAlloc(); 10132 if (!gPMHaltLock) { 10133 goto done; 10134 } 10135 } 10136 10137 if (!gPMHaltClientAcknowledgeKey) { 10138 gPMHaltClientAcknowledgeKey = 10139 OSSymbol::withCStringNoCopy("PMShutdown"); 10140 if (!gPMHaltClientAcknowledgeKey) { 10141 goto done; 10142 } 10143 } 10144 10145 gPMHaltMessageType = messageType; 10146 10147 // Depth-first walk of PM plane 10148 10149 iter = IORegistryIterator::iterateOver( 10150 root, gIOPowerPlane, kIORegistryIterateRecursively); 10151 10152 if (iter) { 10153 while ((entry = iter->getNextObject())) { 10154 node = OSDynamicCast(IOService, entry); 10155 if (!node) { 10156 continue; 10157 } 10158 10159 if (baseFunc == 10160 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) { 10161 continue; 10162 } 10163 10164 depth = node->getDepth( gIOPowerPlane ); 10165 if (depth <= rootDepth) { 10166 continue; 10167 } 10168 10169 ok = false; 10170 10171 // adjust to zero based depth 10172 depth -= (rootDepth + 1); 10173 10174 // gPMHaltArray is an array of containers, each container 10175 // refers to nodes with the same depth. 10176 10177 count = gPMHaltArray->getCount(); 10178 while (depth >= count) { 10179 // expand array and insert placeholders 10180 gPMHaltArray->setObject(PLACEHOLDER); 10181 count++; 10182 } 10183 count = gPMHaltArray->getCount(); 10184 if (depth < count) { 10185 inner = (OSSet *)gPMHaltArray->getObject(depth); 10186 if (inner == PLACEHOLDER) { 10187 newInner = OSSet::withCapacity(40); 10188 if (newInner) { 10189 gPMHaltArray->replaceObject(depth, newInner.get()); 10190 inner = newInner.get(); 10191 } 10192 } 10193 10194 // PM nodes that appear more than once in the tree will have 10195 // the same depth, OSSet will refuse to add the node twice. 10196 if (inner) { 10197 ok = inner->setObject(node); 10198 } 10199 } 10200 if (!ok) { 10201 DLOG("Skipped PM node %s\n", node->getName()); 10202 } 10203 } 10204 } 10205 10206 // debug only 10207 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) { 10208 count = 0; 10209 if (inner != PLACEHOLDER) { 10210 count = inner->getCount(); 10211 } 10212 DLOG("Nodes at depth %u = %u\n", i, count); 10213 } 10214 10215 // strip placeholders (not all depths are populated) 10216 numWorkers = 0; 10217 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) { 10218 if (inner == PLACEHOLDER) { 10219 gPMHaltArray->removeObject(i); 10220 continue; 10221 } 10222 count = inner->getCount(); 10223 if (count > numWorkers) { 10224 numWorkers = count; 10225 } 10226 totalNodes += count; 10227 i++; 10228 } 10229 10230 if (gPMHaltArray->getCount() == 0 || !numWorkers) { 10231 goto done; 10232 } 10233 10234 gPMHaltBusyCount = 0; 10235 gPMHaltIdleCount = 0; 10236 gPMHaltDepth = gPMHaltArray->getCount() - 1; 10237 10238 // Create multiple workers (and threads) 10239 10240 if (numWorkers > kPMHaltMaxWorkers) { 10241 numWorkers = kPMHaltMaxWorkers; 10242 } 10243 10244 DLOG("PM nodes %u, maxDepth %u, workers %u\n", 10245 totalNodes, gPMHaltArray->getCount(), numWorkers); 10246 10247 for (unsigned int i = 0; i < numWorkers; i++) { 10248 workers[i] = PMHaltWorker::worker(); 10249 } 10250 10251 // Wait for workers to exhaust all available work 10252 10253 IOLockLock(gPMHaltLock); 10254 while (gPMHaltDepth >= 0) { 10255 clock_interval_to_deadline(1000, kMillisecondScale, &deadline); 10256 10257 waitResult = IOLockSleepDeadline( 10258 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT); 10259 if (THREAD_TIMED_OUT == waitResult) { 10260 AbsoluteTime now; 10261 clock_get_uptime(&now); 10262 10263 IOLockUnlock(gPMHaltLock); 10264 for (unsigned int i = 0; i < numWorkers; i++) { 10265 if (workers[i]) { 10266 PMHaltWorker::checkTimeout(workers[i], &now); 10267 } 10268 } 10269 IOLockLock(gPMHaltLock); 10270 } 10271 } 10272 IOLockUnlock(gPMHaltLock); 10273 10274 // Release all workers 10275 10276 for (unsigned int i = 0; i < numWorkers; i++) { 10277 if (workers[i]) { 10278 workers[i]->release(); 10279 } 10280 // worker also retained by it's own thread 10281 } 10282 10283 done: 10284 DLOG("%s done\n", __FUNCTION__); 10285 return; 10286 } 10287 10288 // MARK: - 10289 // MARK: Kernel Assertion 10290 10291 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10292 10293 IOPMDriverAssertionID 10294 IOPMrootDomain::createPMAssertion( 10295 IOPMDriverAssertionType whichAssertionBits, 10296 IOPMDriverAssertionLevel assertionLevel, 10297 IOService *ownerService, 10298 const char *ownerDescription) 10299 { 10300 IOReturn ret; 10301 IOPMDriverAssertionID newAssertion; 10302 10303 if (!pmAssertions) { 10304 return 0; 10305 } 10306 10307 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion); 10308 10309 if (kIOReturnSuccess == ret) { 10310 return newAssertion; 10311 } else { 10312 return 0; 10313 } 10314 } 10315 10316 IOReturn 10317 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion) 10318 { 10319 if (!pmAssertions) { 10320 return kIOReturnInternalError; 10321 } 10322 10323 return pmAssertions->releaseAssertion(releaseAssertion); 10324 } 10325 10326 10327 IOReturn 10328 IOPMrootDomain::setPMAssertionLevel( 10329 IOPMDriverAssertionID assertionID, 10330 IOPMDriverAssertionLevel assertionLevel) 10331 { 10332 return pmAssertions->setAssertionLevel(assertionID, assertionLevel); 10333 } 10334 10335 IOPMDriverAssertionLevel 10336 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion) 10337 { 10338 IOPMDriverAssertionType sysLevels; 10339 10340 if (!pmAssertions || whichAssertion == 0) { 10341 return kIOPMDriverAssertionLevelOff; 10342 } 10343 10344 sysLevels = pmAssertions->getActivatedAssertions(); 10345 10346 // Check that every bit set in argument 'whichAssertion' is asserted 10347 // in the aggregate bits. 10348 if ((sysLevels & whichAssertion) == whichAssertion) { 10349 return kIOPMDriverAssertionLevelOn; 10350 } else { 10351 return kIOPMDriverAssertionLevelOff; 10352 } 10353 } 10354 10355 IOReturn 10356 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels) 10357 { 10358 if (!pmAssertions) { 10359 return kIOReturnNotFound; 10360 } 10361 10362 return pmAssertions->setUserAssertionLevels(inLevels); 10363 } 10364 10365 bool 10366 IOPMrootDomain::serializeProperties( OSSerialize * s ) const 10367 { 10368 if (pmAssertions) { 10369 pmAssertions->publishProperties(); 10370 } 10371 return IOService::serializeProperties(s); 10372 } 10373 10374 OSSharedPtr<OSObject> 10375 IOPMrootDomain::copyProperty( const char * aKey) const 10376 { 10377 OSSharedPtr<OSObject> obj; 10378 obj = IOService::copyProperty(aKey); 10379 10380 if (obj) { 10381 return obj; 10382 } 10383 10384 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey, 10385 sizeof(kIOPMSleepWakeWdogRebootKey))) { 10386 if (swd_flags & SWD_BOOT_BY_SW_WDOG) { 10387 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain); 10388 } else { 10389 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain); 10390 } 10391 } 10392 10393 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey, 10394 sizeof(kIOPMSleepWakeWdogLogsValidKey))) { 10395 if (swd_flags & SWD_VALID_LOGS) { 10396 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain); 10397 } else { 10398 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain); 10399 } 10400 } 10401 10402 /* 10403 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey' 10404 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be 10405 * issued by DisplayWrangler on darkwake. 10406 */ 10407 if (!strcmp(aKey, "DesktopMode")) { 10408 if (desktopMode) { 10409 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain); 10410 } else { 10411 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain); 10412 } 10413 } 10414 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) { 10415 if (displayIdleForDemandSleep) { 10416 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain); 10417 } else { 10418 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain); 10419 } 10420 } 10421 10422 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) { 10423 OSSharedPtr<OSArray> array; 10424 WAKEEVENT_LOCK(); 10425 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) { 10426 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection(); 10427 if (collection) { 10428 array = OSDynamicPtrCast<OSArray>(collection); 10429 } 10430 } 10431 WAKEEVENT_UNLOCK(); 10432 return os::move(array); 10433 } 10434 10435 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) { 10436 OSSharedPtr<OSArray> array; 10437 IOLockLock(pmStatsLock); 10438 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) { 10439 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection(); 10440 if (collection) { 10441 array = OSDynamicPtrCast<OSArray>(collection); 10442 } 10443 } 10444 IOLockUnlock(pmStatsLock); 10445 return os::move(array); 10446 } 10447 10448 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) { 10449 OSArray *idleSleepList = NULL; 10450 gRootDomain->copySleepPreventersList(&idleSleepList, NULL); 10451 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain); 10452 } 10453 10454 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) { 10455 OSArray *systemSleepList = NULL; 10456 gRootDomain->copySleepPreventersList(NULL, &systemSleepList); 10457 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain); 10458 } 10459 10460 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) { 10461 OSArray *idleSleepList = NULL; 10462 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL); 10463 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain); 10464 } 10465 10466 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) { 10467 OSArray *systemSleepList = NULL; 10468 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList); 10469 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain); 10470 } 10471 return NULL; 10472 } 10473 10474 // MARK: - 10475 // MARK: Wake Event Reporting 10476 10477 void 10478 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize ) 10479 { 10480 WAKEEVENT_LOCK(); 10481 strlcpy(outBuf, gWakeReasonString, bufSize); 10482 WAKEEVENT_UNLOCK(); 10483 } 10484 10485 void 10486 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize ) 10487 { 10488 WAKEEVENT_LOCK(); 10489 strlcpy(outBuf, gShutdownReasonString, bufSize); 10490 WAKEEVENT_UNLOCK(); 10491 } 10492 10493 //****************************************************************************** 10494 // acceptSystemWakeEvents 10495 // 10496 // Private control for the acceptance of driver wake event claims. 10497 //****************************************************************************** 10498 10499 void 10500 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control ) 10501 { 10502 bool logWakeReason = false; 10503 10504 WAKEEVENT_LOCK(); 10505 switch (control) { 10506 case kAcceptSystemWakeEvents_Enable: 10507 assert(_acceptSystemWakeEvents == false); 10508 if (!_systemWakeEventsArray) { 10509 _systemWakeEventsArray = OSArray::withCapacity(4); 10510 } 10511 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL); 10512 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) { 10513 gWakeReasonString[0] = '\0'; 10514 if (_systemWakeEventsArray) { 10515 _systemWakeEventsArray->flushCollection(); 10516 } 10517 } 10518 10519 // Remove stale WakeType property before system sleep 10520 removeProperty(kIOPMRootDomainWakeTypeKey); 10521 removeProperty(kIOPMRootDomainWakeReasonKey); 10522 break; 10523 10524 case kAcceptSystemWakeEvents_Disable: 10525 _acceptSystemWakeEvents = false; 10526 #if defined(XNU_TARGET_OS_OSX) 10527 logWakeReason = (gWakeReasonString[0] != '\0'); 10528 #else /* !defined(XNU_TARGET_OS_OSX) */ 10529 logWakeReason = gWakeReasonSysctlRegistered; 10530 #if DEVELOPMENT 10531 static int panic_allowed = -1; 10532 10533 if ((panic_allowed == -1) && 10534 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) { 10535 panic_allowed = 0; 10536 } 10537 10538 if (panic_allowed) { 10539 size_t i = 0; 10540 // Panic if wake reason is null or empty 10541 for (i = 0; (i < strlen(gWakeReasonString)); i++) { 10542 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) { 10543 break; 10544 } 10545 } 10546 if (i >= strlen(gWakeReasonString)) { 10547 panic("Wake reason is empty\n"); 10548 } 10549 } 10550 #endif /* DEVELOPMENT */ 10551 #endif /* !defined(XNU_TARGET_OS_OSX) */ 10552 10553 // publish kIOPMRootDomainWakeReasonKey if not already set 10554 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) { 10555 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString); 10556 } 10557 break; 10558 10559 case kAcceptSystemWakeEvents_Reenable: 10560 assert(_acceptSystemWakeEvents == false); 10561 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL); 10562 removeProperty(kIOPMRootDomainWakeReasonKey); 10563 break; 10564 } 10565 WAKEEVENT_UNLOCK(); 10566 10567 if (logWakeReason) { 10568 MSG("system wake events: %s\n", gWakeReasonString); 10569 } 10570 } 10571 10572 //****************************************************************************** 10573 // claimSystemWakeEvent 10574 // 10575 // For a driver to claim a device is the source/conduit of a system wake event. 10576 //****************************************************************************** 10577 10578 void 10579 IOPMrootDomain::claimSystemWakeEvent( 10580 IOService * device, 10581 IOOptionBits flags, 10582 const char * reason, 10583 OSObject * details ) 10584 { 10585 OSSharedPtr<const OSSymbol> deviceName; 10586 OSSharedPtr<OSNumber> deviceRegId; 10587 OSSharedPtr<OSNumber> claimTime; 10588 OSSharedPtr<OSData> flagsData; 10589 OSSharedPtr<OSString> reasonString; 10590 OSSharedPtr<OSDictionary> dict; 10591 uint64_t timestamp; 10592 bool addWakeReason; 10593 10594 if (!device || !reason) { 10595 return; 10596 } 10597 10598 pmEventTimeStamp(×tamp); 10599 10600 IOOptionBits aotFlags = 0; 10601 bool needAOTEvaluate = FALSE; 10602 10603 if (kIOPMAOTModeAddEventFlags & _aotMode) { 10604 if (!strcmp("hold", reason) 10605 || !strcmp("help", reason) 10606 || !strcmp("menu", reason) 10607 || !strcmp("stockholm", reason) 10608 || !strcmp("ringer", reason) 10609 || !strcmp("ringerab", reason) 10610 || !strcmp("smc0", reason) 10611 || !strcmp("AOP.RTPWakeupAP", reason) 10612 || !strcmp("BT.OutboxNotEmpty", reason) 10613 || !strcmp("WL.OutboxNotEmpty", reason)) { 10614 flags |= kIOPMWakeEventAOTExit; 10615 } 10616 } 10617 10618 #if DEVELOPMENT || DEBUG 10619 if (_aotLingerTime && !strcmp("rtc", reason)) { 10620 flags |= kIOPMWakeEventAOTPossibleExit; 10621 } 10622 #endif /* DEVELOPMENT || DEBUG */ 10623 10624 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT 10625 // Publishing the WakeType is serialized by the PM work loop 10626 if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) { 10627 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType, 10628 (void *) _nextScheduledAlarmType.get()); 10629 } 10630 10631 // Workaround for the missing wake HID event 10632 if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) { 10633 if (!strcmp("trackpadkeyboard", reason)) { 10634 pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType, 10635 (void *) gIOPMWakeTypeUserKey.get()); 10636 } 10637 } 10638 #endif 10639 10640 deviceName = device->copyName(gIOServicePlane); 10641 deviceRegId = OSNumber::withNumber(device->getRegistryEntryID(), 64); 10642 claimTime = OSNumber::withNumber(timestamp, 64); 10643 flagsData = OSData::withBytes(&flags, sizeof(flags)); 10644 reasonString = OSString::withCString(reason); 10645 dict = OSDictionary::withCapacity(5 + (details ? 1 : 0)); 10646 if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) { 10647 goto done; 10648 } 10649 10650 dict->setObject(gIONameKey, deviceName.get()); 10651 dict->setObject(gIORegistryEntryIDKey, deviceRegId.get()); 10652 dict->setObject(kIOPMWakeEventTimeKey, claimTime.get()); 10653 dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get()); 10654 dict->setObject(kIOPMWakeEventReasonKey, reasonString.get()); 10655 if (details) { 10656 dict->setObject(kIOPMWakeEventDetailsKey, details); 10657 } 10658 10659 WAKEEVENT_LOCK(); 10660 addWakeReason = _acceptSystemWakeEvents; 10661 if (_aotMode) { 10662 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake); 10663 } 10664 aotFlags = (kIOPMWakeEventAOTFlags & flags); 10665 aotFlags = (aotFlags & ~_aotPendingFlags); 10666 needAOTEvaluate = false; 10667 if (_aotNow && aotFlags) { 10668 if (kIOPMWakeEventAOTPossibleExit & flags) { 10669 _aotMetrics->possibleCount++; 10670 } 10671 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) { 10672 _aotMetrics->confirmedPossibleCount++; 10673 } 10674 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) { 10675 _aotMetrics->rejectedPossibleCount++; 10676 } 10677 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) { 10678 _aotMetrics->expiredPossibleCount++; 10679 } 10680 10681 _aotPendingFlags |= aotFlags; 10682 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags)); 10683 needAOTEvaluate = _aotReadyToFullWake; 10684 } 10685 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n", 10686 reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(), 10687 _aotNow, pmTracer->getTracePhase(), addWakeReason); 10688 10689 if (!gWakeReasonSysctlRegistered) { 10690 // Lazy registration until the platform driver stops registering 10691 // the same name. 10692 gWakeReasonSysctlRegistered = true; 10693 #if !defined(XNU_TARGET_OS_OSX) 10694 sysctl_register_oid(&sysctl__kern_wakereason); 10695 #endif /* !defined(XNU_TARGET_OS_OSX) */ 10696 } 10697 if (addWakeReason) { 10698 _systemWakeEventsArray->setObject(dict.get()); 10699 if (gWakeReasonString[0] != '\0') { 10700 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString)); 10701 } 10702 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString)); 10703 } 10704 10705 WAKEEVENT_UNLOCK(); 10706 if (needAOTEvaluate) { 10707 // Call aotEvaluate() on PM work loop since it may call 10708 // aotExit() which accesses PM state. 10709 pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate); 10710 } 10711 10712 done: 10713 return; 10714 } 10715 10716 //****************************************************************************** 10717 // claimSystemBootEvent 10718 // 10719 // For a driver to claim a device is the source/conduit of a system boot event. 10720 //****************************************************************************** 10721 10722 void 10723 IOPMrootDomain::claimSystemBootEvent( 10724 IOService * device, 10725 IOOptionBits flags, 10726 const char * reason, 10727 __unused OSObject * details ) 10728 { 10729 if (!device || !reason) { 10730 return; 10731 } 10732 10733 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags); 10734 WAKEEVENT_LOCK(); 10735 if (!gBootReasonSysctlRegistered) { 10736 // Lazy sysctl registration after setting gBootReasonString 10737 strlcat(gBootReasonString, reason, sizeof(gBootReasonString)); 10738 sysctl_register_oid(&sysctl__kern_bootreason); 10739 gBootReasonSysctlRegistered = true; 10740 } 10741 WAKEEVENT_UNLOCK(); 10742 } 10743 10744 //****************************************************************************** 10745 // claimSystemShutdownEvent 10746 // 10747 // For drivers to claim a system shutdown event on the ensuing boot. 10748 //****************************************************************************** 10749 10750 void 10751 IOPMrootDomain::claimSystemShutdownEvent( 10752 IOService * device, 10753 IOOptionBits flags, 10754 const char * reason, 10755 __unused OSObject * details ) 10756 { 10757 if (!device || !reason) { 10758 return; 10759 } 10760 10761 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags); 10762 WAKEEVENT_LOCK(); 10763 if (gShutdownReasonString[0] != '\0') { 10764 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString)); 10765 } 10766 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString)); 10767 10768 if (!gShutdownReasonSysctlRegistered) { 10769 sysctl_register_oid(&sysctl__kern_shutdownreason); 10770 gShutdownReasonSysctlRegistered = true; 10771 } 10772 WAKEEVENT_UNLOCK(); 10773 } 10774 10775 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10776 10777 // MARK: - 10778 // MARK: PMSettingHandle 10779 10780 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject ) 10781 10782 void 10783 PMSettingHandle::free( void ) 10784 { 10785 if (pmso) { 10786 pmso->clientHandleFreed(); 10787 pmso->release(); 10788 pmso = NULL; 10789 } 10790 10791 OSObject::free(); 10792 } 10793 10794 // MARK: - 10795 // MARK: PMSettingObject 10796 10797 #undef super 10798 #define super OSObject 10799 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject ) 10800 10801 /* 10802 * Static constructor/initializer for PMSettingObject 10803 */ 10804 PMSettingObject *PMSettingObject::pmSettingObject( 10805 IOPMrootDomain * parent_arg, 10806 IOPMSettingControllerCallback handler_arg, 10807 OSObject * target_arg, 10808 uintptr_t refcon_arg, 10809 uint32_t supportedPowerSources, 10810 const OSSymbol * settings[], 10811 OSObject * *handle_obj) 10812 { 10813 uint32_t settingCount = 0; 10814 PMSettingObject *pmso = NULL; 10815 PMSettingHandle *pmsh = NULL; 10816 10817 if (!parent_arg || !handler_arg || !settings || !handle_obj) { 10818 return NULL; 10819 } 10820 10821 // count OSSymbol entries in NULL terminated settings array 10822 while (settings[settingCount]) { 10823 settingCount++; 10824 } 10825 if (0 == settingCount) { 10826 return NULL; 10827 } 10828 10829 pmso = new PMSettingObject; 10830 if (!pmso || !pmso->init()) { 10831 goto fail; 10832 } 10833 10834 pmsh = new PMSettingHandle; 10835 if (!pmsh || !pmsh->init()) { 10836 goto fail; 10837 } 10838 10839 queue_init(&pmso->calloutQueue); 10840 pmso->parent = parent_arg; 10841 pmso->func = handler_arg; 10842 pmso->target = target_arg; 10843 pmso->refcon = refcon_arg; 10844 pmso->settingCount = settingCount; 10845 10846 pmso->retain(); // handle holds a retain on pmso 10847 pmsh->pmso = pmso; 10848 pmso->pmsh = pmsh; 10849 10850 pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount); 10851 if (pmso->publishedFeatureID) { 10852 for (unsigned int i = 0; i < settingCount; i++) { 10853 // Since there is now at least one listener to this setting, publish 10854 // PM root domain support for it. 10855 parent_arg->publishPMSetting( settings[i], 10856 supportedPowerSources, &pmso->publishedFeatureID[i] ); 10857 } 10858 } 10859 10860 *handle_obj = pmsh; 10861 return pmso; 10862 10863 fail: 10864 if (pmso) { 10865 pmso->release(); 10866 } 10867 if (pmsh) { 10868 pmsh->release(); 10869 } 10870 return NULL; 10871 } 10872 10873 void 10874 PMSettingObject::free( void ) 10875 { 10876 if (publishedFeatureID) { 10877 for (uint32_t i = 0; i < settingCount; i++) { 10878 if (publishedFeatureID[i]) { 10879 parent->removePublishedFeature( publishedFeatureID[i] ); 10880 } 10881 } 10882 10883 IOFree(publishedFeatureID, sizeof(uint32_t) * settingCount); 10884 } 10885 10886 super::free(); 10887 } 10888 10889 IOReturn 10890 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object ) 10891 { 10892 return (*func)(target, type, object, refcon); 10893 } 10894 10895 void 10896 PMSettingObject::clientHandleFreed( void ) 10897 { 10898 parent->deregisterPMSettingObject(this); 10899 } 10900 10901 // MARK: - 10902 // MARK: PMAssertionsTracker 10903 10904 //********************************************************************************* 10905 //********************************************************************************* 10906 //********************************************************************************* 10907 // class PMAssertionsTracker Implementation 10908 10909 #define kAssertUniqueIDStart 500 10910 10911 PMAssertionsTracker * 10912 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain ) 10913 { 10914 PMAssertionsTracker *me; 10915 10916 me = new PMAssertionsTracker; 10917 if (!me || !me->init()) { 10918 if (me) { 10919 me->release(); 10920 } 10921 return NULL; 10922 } 10923 10924 me->owner = rootDomain; 10925 me->issuingUniqueID = kAssertUniqueIDStart; 10926 me->assertionsArray = OSArray::withCapacity(5); 10927 me->assertionsKernel = 0; 10928 me->assertionsUser = 0; 10929 me->assertionsCombined = 0; 10930 me->assertionsArrayLock = IOLockAlloc(); 10931 me->tabulateProducerCount = me->tabulateConsumerCount = 0; 10932 10933 assert(me->assertionsArray); 10934 assert(me->assertionsArrayLock); 10935 10936 return me; 10937 } 10938 10939 /* tabulate 10940 * - Update assertionsKernel to reflect the state of all 10941 * assertions in the kernel. 10942 * - Update assertionsCombined to reflect both kernel & user space. 10943 */ 10944 void 10945 PMAssertionsTracker::tabulate(void) 10946 { 10947 int i; 10948 int count; 10949 PMAssertStruct *_a = NULL; 10950 OSData *_d = NULL; 10951 10952 IOPMDriverAssertionType oldKernel = assertionsKernel; 10953 IOPMDriverAssertionType oldCombined = assertionsCombined; 10954 10955 ASSERT_GATED(); 10956 10957 assertionsKernel = 0; 10958 assertionsCombined = 0; 10959 10960 if (!assertionsArray) { 10961 return; 10962 } 10963 10964 if ((count = assertionsArray->getCount())) { 10965 for (i = 0; i < count; i++) { 10966 _d = OSDynamicCast(OSData, assertionsArray->getObject(i)); 10967 if (_d) { 10968 _a = (PMAssertStruct *)_d->getBytesNoCopy(); 10969 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) { 10970 assertionsKernel |= _a->assertionBits; 10971 } 10972 } 10973 } 10974 } 10975 10976 tabulateProducerCount++; 10977 assertionsCombined = assertionsKernel | assertionsUser; 10978 10979 if ((assertionsKernel != oldKernel) || 10980 (assertionsCombined != oldCombined)) { 10981 owner->evaluateAssertions(assertionsCombined, oldCombined); 10982 } 10983 } 10984 10985 void 10986 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct ) 10987 { 10988 AbsoluteTime now; 10989 uint64_t nsec; 10990 10991 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) || 10992 (assertStruct->assertCPUStartTime == 0)) { 10993 return; 10994 } 10995 10996 now = mach_absolute_time(); 10997 SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime); 10998 absolutetime_to_nanoseconds(now, &nsec); 10999 assertStruct->assertCPUDuration += nsec; 11000 assertStruct->assertCPUStartTime = 0; 11001 11002 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) { 11003 maxAssertCPUDuration = assertStruct->assertCPUDuration; 11004 maxAssertCPUEntryId = assertStruct->registryEntryID; 11005 } 11006 } 11007 11008 void 11009 PMAssertionsTracker::reportCPUBitAccounting( void ) 11010 { 11011 PMAssertStruct *_a; 11012 OSData *_d; 11013 int i, count; 11014 AbsoluteTime now; 11015 uint64_t nsec; 11016 11017 ASSERT_GATED(); 11018 11019 // Account for drivers that are still holding the CPU assertion 11020 if (assertionsKernel & kIOPMDriverAssertionCPUBit) { 11021 now = mach_absolute_time(); 11022 if ((count = assertionsArray->getCount())) { 11023 for (i = 0; i < count; i++) { 11024 _d = OSDynamicCast(OSData, assertionsArray->getObject(i)); 11025 if (_d) { 11026 _a = (PMAssertStruct *)_d->getBytesNoCopy(); 11027 if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) && 11028 (_a->level == kIOPMDriverAssertionLevelOn) && 11029 (_a->assertCPUStartTime != 0)) { 11030 // Don't modify PMAssertStruct, leave that 11031 // for updateCPUBitAccounting() 11032 SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime); 11033 absolutetime_to_nanoseconds(now, &nsec); 11034 nsec += _a->assertCPUDuration; 11035 if (nsec > maxAssertCPUDuration) { 11036 maxAssertCPUDuration = nsec; 11037 maxAssertCPUEntryId = _a->registryEntryID; 11038 } 11039 } 11040 } 11041 } 11042 } 11043 } 11044 11045 if (maxAssertCPUDuration) { 11046 DLOG("cpu assertion held for %llu ms by 0x%llx\n", 11047 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId); 11048 } 11049 11050 maxAssertCPUDuration = 0; 11051 maxAssertCPUEntryId = 0; 11052 } 11053 11054 void 11055 PMAssertionsTracker::publishProperties( void ) 11056 { 11057 OSSharedPtr<OSArray> assertionsSummary; 11058 11059 if (tabulateConsumerCount != tabulateProducerCount) { 11060 IOLockLock(assertionsArrayLock); 11061 11062 tabulateConsumerCount = tabulateProducerCount; 11063 11064 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed" 11065 */ 11066 assertionsSummary = copyAssertionsArray(); 11067 if (assertionsSummary) { 11068 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get()); 11069 } else { 11070 owner->removeProperty(kIOPMAssertionsDriverDetailedKey); 11071 } 11072 11073 /* Publish the IOPMrootDomain property "DriverPMAssertions" 11074 */ 11075 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64); 11076 11077 IOLockUnlock(assertionsArrayLock); 11078 } 11079 } 11080 11081 PMAssertionsTracker::PMAssertStruct * 11082 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index) 11083 { 11084 PMAssertStruct *_a = NULL; 11085 OSData *_d = NULL; 11086 int found = -1; 11087 int count = 0; 11088 int i = 0; 11089 11090 if (assertionsArray 11091 && (count = assertionsArray->getCount())) { 11092 for (i = 0; i < count; i++) { 11093 _d = OSDynamicCast(OSData, assertionsArray->getObject(i)); 11094 if (_d) { 11095 _a = (PMAssertStruct *)_d->getBytesNoCopy(); 11096 if (_a && (_id == _a->id)) { 11097 found = i; 11098 break; 11099 } 11100 } 11101 } 11102 } 11103 11104 if (-1 == found) { 11105 return NULL; 11106 } else { 11107 if (index) { 11108 *index = found; 11109 } 11110 return _a; 11111 } 11112 } 11113 11114 /* PMAssertionsTracker::handleCreateAssertion 11115 * Perform assertion work on the PM workloop. Do not call directly. 11116 */ 11117 IOReturn 11118 PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion) 11119 { 11120 PMAssertStruct *assertStruct; 11121 11122 ASSERT_GATED(); 11123 11124 if (newAssertion) { 11125 IOLockLock(assertionsArrayLock); 11126 assertStruct = (PMAssertStruct *) newAssertion->getBytesNoCopy(); 11127 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) && 11128 (assertStruct->level == kIOPMDriverAssertionLevelOn)) { 11129 assertStruct->assertCPUStartTime = mach_absolute_time(); 11130 } 11131 assertionsArray->setObject(newAssertion); 11132 IOLockUnlock(assertionsArrayLock); 11133 newAssertion->release(); 11134 11135 tabulate(); 11136 } 11137 return kIOReturnSuccess; 11138 } 11139 11140 /* PMAssertionsTracker::createAssertion 11141 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if 11142 * appropiate. 11143 */ 11144 IOReturn 11145 PMAssertionsTracker::createAssertion( 11146 IOPMDriverAssertionType which, 11147 IOPMDriverAssertionLevel level, 11148 IOService *serviceID, 11149 const char *whoItIs, 11150 IOPMDriverAssertionID *outID) 11151 { 11152 OSSharedPtr<OSData> dataStore; 11153 PMAssertStruct track; 11154 11155 // Warning: trillions and trillions of created assertions may overflow the unique ID. 11156 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID); 11157 track.level = level; 11158 track.assertionBits = which; 11159 11160 // NB: ownerString is explicitly managed by PMAssertStruct 11161 // it will be released in `handleReleaseAssertion' below 11162 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr; 11163 track.ownerService = serviceID; 11164 track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0; 11165 track.modifiedTime = 0; 11166 pmEventTimeStamp(&track.createdTime); 11167 track.assertCPUStartTime = 0; 11168 track.assertCPUDuration = 0; 11169 11170 dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct)); 11171 if (!dataStore) { 11172 if (track.ownerString) { 11173 track.ownerString->release(); 11174 track.ownerString = NULL; 11175 } 11176 return kIOReturnNoMemory; 11177 } 11178 11179 *outID = track.id; 11180 11181 if (owner && owner->pmPowerStateQueue) { 11182 // queue action is responsible for releasing dataStore 11183 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach()); 11184 } 11185 11186 return kIOReturnSuccess; 11187 } 11188 11189 /* PMAssertionsTracker::handleReleaseAssertion 11190 * Runs in PM workloop. Do not call directly. 11191 */ 11192 IOReturn 11193 PMAssertionsTracker::handleReleaseAssertion( 11194 IOPMDriverAssertionID _id) 11195 { 11196 ASSERT_GATED(); 11197 11198 int index; 11199 PMAssertStruct *assertStruct = detailsForID(_id, &index); 11200 11201 if (!assertStruct) { 11202 return kIOReturnNotFound; 11203 } 11204 11205 IOLockLock(assertionsArrayLock); 11206 11207 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) && 11208 (assertStruct->level == kIOPMDriverAssertionLevelOn)) { 11209 updateCPUBitAccounting(assertStruct); 11210 } 11211 11212 if (assertStruct->ownerString) { 11213 assertStruct->ownerString->release(); 11214 assertStruct->ownerString = NULL; 11215 } 11216 11217 assertionsArray->removeObject(index); 11218 IOLockUnlock(assertionsArrayLock); 11219 11220 tabulate(); 11221 return kIOReturnSuccess; 11222 } 11223 11224 /* PMAssertionsTracker::releaseAssertion 11225 * Releases an assertion and affects system behavior if appropiate. 11226 * Actual work happens on PM workloop. 11227 */ 11228 IOReturn 11229 PMAssertionsTracker::releaseAssertion( 11230 IOPMDriverAssertionID _id) 11231 { 11232 if (owner && owner->pmPowerStateQueue) { 11233 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id); 11234 } 11235 return kIOReturnSuccess; 11236 } 11237 11238 /* PMAssertionsTracker::handleSetAssertionLevel 11239 * Runs in PM workloop. Do not call directly. 11240 */ 11241 IOReturn 11242 PMAssertionsTracker::handleSetAssertionLevel( 11243 IOPMDriverAssertionID _id, 11244 IOPMDriverAssertionLevel _level) 11245 { 11246 PMAssertStruct *assertStruct = detailsForID(_id, NULL); 11247 11248 ASSERT_GATED(); 11249 11250 if (!assertStruct) { 11251 return kIOReturnNotFound; 11252 } 11253 11254 IOLockLock(assertionsArrayLock); 11255 pmEventTimeStamp(&assertStruct->modifiedTime); 11256 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) && 11257 (assertStruct->level != _level)) { 11258 if (_level == kIOPMDriverAssertionLevelOn) { 11259 assertStruct->assertCPUStartTime = mach_absolute_time(); 11260 } else { 11261 updateCPUBitAccounting(assertStruct); 11262 } 11263 } 11264 assertStruct->level = _level; 11265 IOLockUnlock(assertionsArrayLock); 11266 11267 tabulate(); 11268 return kIOReturnSuccess; 11269 } 11270 11271 /* PMAssertionsTracker::setAssertionLevel 11272 */ 11273 IOReturn 11274 PMAssertionsTracker::setAssertionLevel( 11275 IOPMDriverAssertionID _id, 11276 IOPMDriverAssertionLevel _level) 11277 { 11278 if (owner && owner->pmPowerStateQueue) { 11279 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel, 11280 (void *)(uintptr_t)_level, _id); 11281 } 11282 11283 return kIOReturnSuccess; 11284 } 11285 11286 IOReturn 11287 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0) 11288 { 11289 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0; 11290 11291 ASSERT_GATED(); 11292 11293 if (new_user_levels != assertionsUser) { 11294 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels); 11295 assertionsUser = new_user_levels; 11296 } 11297 11298 tabulate(); 11299 return kIOReturnSuccess; 11300 } 11301 11302 IOReturn 11303 PMAssertionsTracker::setUserAssertionLevels( 11304 IOPMDriverAssertionType new_user_levels) 11305 { 11306 if (gIOPMWorkLoop) { 11307 gIOPMWorkLoop->runAction( 11308 OSMemberFunctionCast( 11309 IOWorkLoop::Action, 11310 this, 11311 &PMAssertionsTracker::handleSetUserAssertionLevels), 11312 this, 11313 (void *) &new_user_levels, NULL, NULL, NULL); 11314 } 11315 11316 return kIOReturnSuccess; 11317 } 11318 11319 11320 OSSharedPtr<OSArray> 11321 PMAssertionsTracker::copyAssertionsArray(void) 11322 { 11323 int count; 11324 int i; 11325 OSSharedPtr<OSArray> outArray = NULL; 11326 11327 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) { 11328 goto exit; 11329 } 11330 outArray = OSArray::withCapacity(count); 11331 if (!outArray) { 11332 goto exit; 11333 } 11334 11335 for (i = 0; i < count; i++) { 11336 PMAssertStruct *_a = NULL; 11337 OSData *_d = NULL; 11338 OSSharedPtr<OSDictionary> details; 11339 11340 _d = OSDynamicCast(OSData, assertionsArray->getObject(i)); 11341 if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy())) { 11342 OSSharedPtr<OSNumber> _n; 11343 11344 details = OSDictionary::withCapacity(7); 11345 if (!details) { 11346 continue; 11347 } 11348 11349 outArray->setObject(details.get()); 11350 11351 _n = OSNumber::withNumber(_a->id, 64); 11352 if (_n) { 11353 details->setObject(kIOPMDriverAssertionIDKey, _n.get()); 11354 } 11355 _n = OSNumber::withNumber(_a->createdTime, 64); 11356 if (_n) { 11357 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get()); 11358 } 11359 _n = OSNumber::withNumber(_a->modifiedTime, 64); 11360 if (_n) { 11361 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get()); 11362 } 11363 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64); 11364 if (_n) { 11365 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get()); 11366 } 11367 _n = OSNumber::withNumber(_a->level, 64); 11368 if (_n) { 11369 details->setObject(kIOPMDriverAssertionLevelKey, _n.get()); 11370 } 11371 _n = OSNumber::withNumber(_a->assertionBits, 64); 11372 if (_n) { 11373 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get()); 11374 } 11375 11376 if (_a->ownerString) { 11377 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString); 11378 } 11379 } 11380 } 11381 11382 exit: 11383 return os::move(outArray); 11384 } 11385 11386 IOPMDriverAssertionType 11387 PMAssertionsTracker::getActivatedAssertions(void) 11388 { 11389 return assertionsCombined; 11390 } 11391 11392 IOPMDriverAssertionLevel 11393 PMAssertionsTracker::getAssertionLevel( 11394 IOPMDriverAssertionType type) 11395 { 11396 // FIXME: unused and also wrong 11397 if (type && ((type & assertionsKernel) == assertionsKernel)) { 11398 return kIOPMDriverAssertionLevelOn; 11399 } else { 11400 return kIOPMDriverAssertionLevelOff; 11401 } 11402 } 11403 11404 //********************************************************************************* 11405 //********************************************************************************* 11406 //********************************************************************************* 11407 11408 11409 static void 11410 pmEventTimeStamp(uint64_t *recordTS) 11411 { 11412 clock_sec_t tsec; 11413 clock_usec_t tusec; 11414 11415 if (!recordTS) { 11416 return; 11417 } 11418 11419 // We assume tsec fits into 32 bits; 32 bits holds enough 11420 // seconds for 136 years since the epoch in 1970. 11421 clock_get_calendar_microtime(&tsec, &tusec); 11422 11423 11424 // Pack the sec & microsec calendar time into a uint64_t, for fun. 11425 *recordTS = 0; 11426 *recordTS |= (uint32_t)tusec; 11427 *recordTS |= ((uint64_t)tsec << 32); 11428 11429 return; 11430 } 11431 11432 // MARK: - 11433 // MARK: IORootParent 11434 11435 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 11436 11437 OSDefineMetaClassAndFinalStructors(IORootParent, IOService) 11438 11439 // The reason that root domain needs a root parent is to facilitate demand 11440 // sleep, since a power change from the root parent cannot be vetoed. 11441 // 11442 // The above statement is no longer true since root domain now performs 11443 // demand sleep using overrides. But root parent remains to avoid changing 11444 // the power tree stacking. Root parent is parked at the max power state. 11445 11446 11447 static IOPMPowerState patriarchPowerStates[2] = 11448 { 11449 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11450 {1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11451 }; 11452 11453 void 11454 IORootParent::initialize( void ) 11455 { 11456 11457 gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey); 11458 gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey); 11459 gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey); 11460 gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey); 11461 gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey); 11462 gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey); 11463 gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey); 11464 gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey); 11465 gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey); 11466 gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey); 11467 gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey); 11468 gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey); 11469 gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey); 11470 gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey); 11471 gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey); 11472 gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey); 11473 gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey); 11474 gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey); 11475 gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey); 11476 gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey); 11477 gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey); 11478 gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey); 11479 gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey); 11480 gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey); 11481 gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey); 11482 gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey); 11483 gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey); 11484 gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey); 11485 gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey); 11486 gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey); 11487 gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey); 11488 gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey); 11489 gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey); 11490 gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey); 11491 gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey); 11492 gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey); 11493 gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey); 11494 gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey); 11495 gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey); 11496 gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey); 11497 gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey); 11498 gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey); 11499 gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey); 11500 gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey); 11501 } 11502 11503 bool 11504 IORootParent::start( IOService * nub ) 11505 { 11506 IOService::start(nub); 11507 attachToParent( getRegistryRoot(), gIOPowerPlane ); 11508 PMinit(); 11509 registerPowerDriver(this, patriarchPowerStates, 2); 11510 makeUsable(); 11511 return true; 11512 } 11513 11514 void 11515 IORootParent::shutDownSystem( void ) 11516 { 11517 } 11518 11519 void 11520 IORootParent::restartSystem( void ) 11521 { 11522 } 11523 11524 void 11525 IORootParent::sleepSystem( void ) 11526 { 11527 } 11528 11529 void 11530 IORootParent::dozeSystem( void ) 11531 { 11532 } 11533 11534 void 11535 IORootParent::sleepToDoze( void ) 11536 { 11537 } 11538 11539 void 11540 IORootParent::wakeSystem( void ) 11541 { 11542 } 11543 11544 OSSharedPtr<OSObject> 11545 IORootParent::copyProperty( const char * aKey) const 11546 { 11547 return IOService::copyProperty(aKey); 11548 } 11549 11550 uint32_t 11551 IOPMrootDomain::getWatchdogTimeout() 11552 { 11553 if (gSwdSleepWakeTimeout) { 11554 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout; 11555 } 11556 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) || 11557 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) { 11558 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT; 11559 } else { 11560 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT; 11561 } 11562 } 11563 11564 11565 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION) 11566 IOReturn 11567 IOPMrootDomain::restartWithStackshot() 11568 { 11569 takeStackshot(true); 11570 11571 return kIOReturnSuccess; 11572 } 11573 11574 void 11575 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger) 11576 { 11577 takeStackshot(wdogTrigger); 11578 } 11579 11580 void 11581 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description) 11582 { 11583 switch (tracePhase) { 11584 case kIOPMTracePointSleepStarted: 11585 *phaseString = "kIOPMTracePointSleepStarted"; 11586 *description = "starting sleep"; 11587 break; 11588 11589 case kIOPMTracePointSleepApplications: 11590 *phaseString = "kIOPMTracePointSleepApplications"; 11591 *description = "notifying applications"; 11592 break; 11593 11594 case kIOPMTracePointSleepPriorityClients: 11595 *phaseString = "kIOPMTracePointSleepPriorityClients"; 11596 *description = "notifying clients about upcoming system capability changes"; 11597 break; 11598 11599 case kIOPMTracePointSleepWillChangeInterests: 11600 *phaseString = "kIOPMTracePointSleepWillChangeInterests"; 11601 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes"; 11602 break; 11603 11604 case kIOPMTracePointSleepPowerPlaneDrivers: 11605 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers"; 11606 *description = "calling power state change callbacks"; 11607 break; 11608 11609 case kIOPMTracePointSleepDidChangeInterests: 11610 *phaseString = "kIOPMTracePointSleepDidChangeInterests"; 11611 *description = "calling rootDomain's clients about rootDomain's state changes"; 11612 break; 11613 11614 case kIOPMTracePointSleepCapabilityClients: 11615 *phaseString = "kIOPMTracePointSleepCapabilityClients"; 11616 *description = "notifying clients about current system capabilities"; 11617 break; 11618 11619 case kIOPMTracePointSleepPlatformActions: 11620 *phaseString = "kIOPMTracePointSleepPlatformActions"; 11621 *description = "calling Quiesce/Sleep action callbacks"; 11622 break; 11623 11624 case kIOPMTracePointSleepCPUs: 11625 { 11626 *phaseString = "kIOPMTracePointSleepCPUs"; 11627 #if defined(__i386__) || defined(__x86_64__) 11628 /* 11629 * We cannot use the getCPUNumber() method to get the cpu number, since 11630 * that cpu number is unrelated to the cpu number we need (we need the cpu 11631 * number as enumerated by the scheduler, NOT the CPU number enumerated 11632 * by ACPIPlatform as the CPUs are enumerated in MADT order). 11633 * Instead, pass the Mach processor pointer associated with the current 11634 * shutdown target so its associated cpu_id can be used in 11635 * processor_to_datastring. 11636 */ 11637 if (currentShutdownTarget != NULL && 11638 currentShutdownTarget->getMachProcessor() != NULL) { 11639 const char *sbuf = processor_to_datastring("halting all non-boot CPUs", 11640 currentShutdownTarget->getMachProcessor()); 11641 *description = sbuf; 11642 } else { 11643 *description = "halting all non-boot CPUs"; 11644 } 11645 #else 11646 *description = "halting all non-boot CPUs"; 11647 #endif 11648 break; 11649 } 11650 case kIOPMTracePointSleepPlatformDriver: 11651 *phaseString = "kIOPMTracePointSleepPlatformDriver"; 11652 *description = "executing platform specific code"; 11653 break; 11654 11655 case kIOPMTracePointHibernate: 11656 *phaseString = "kIOPMTracePointHibernate"; 11657 *description = "writing the hibernation image"; 11658 break; 11659 11660 case kIOPMTracePointSystemSleep: 11661 *phaseString = "kIOPMTracePointSystemSleep"; 11662 *description = "in EFI/Bootrom after last point of entry to sleep"; 11663 break; 11664 11665 case kIOPMTracePointWakePlatformDriver: 11666 *phaseString = "kIOPMTracePointWakePlatformDriver"; 11667 *description = "executing platform specific code"; 11668 break; 11669 11670 11671 case kIOPMTracePointWakePlatformActions: 11672 *phaseString = "kIOPMTracePointWakePlatformActions"; 11673 *description = "calling Wake action callbacks"; 11674 break; 11675 11676 case kIOPMTracePointWakeCPUs: 11677 *phaseString = "kIOPMTracePointWakeCPUs"; 11678 *description = "starting non-boot CPUs"; 11679 break; 11680 11681 case kIOPMTracePointWakeWillPowerOnClients: 11682 *phaseString = "kIOPMTracePointWakeWillPowerOnClients"; 11683 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients"; 11684 break; 11685 11686 case kIOPMTracePointWakeWillChangeInterests: 11687 *phaseString = "kIOPMTracePointWakeWillChangeInterests"; 11688 *description = "calling rootDomain's clients about upcoming rootDomain's state changes"; 11689 break; 11690 11691 case kIOPMTracePointWakeDidChangeInterests: 11692 *phaseString = "kIOPMTracePointWakeDidChangeInterests"; 11693 *description = "calling rootDomain's clients about completed rootDomain's state changes"; 11694 break; 11695 11696 case kIOPMTracePointWakePowerPlaneDrivers: 11697 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers"; 11698 *description = "calling power state change callbacks"; 11699 break; 11700 11701 case kIOPMTracePointWakeCapabilityClients: 11702 *phaseString = "kIOPMTracePointWakeCapabilityClients"; 11703 *description = "informing clients about current system capabilities"; 11704 break; 11705 11706 case kIOPMTracePointWakeApplications: 11707 *phaseString = "kIOPMTracePointWakeApplications"; 11708 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients"; 11709 break; 11710 11711 case kIOPMTracePointDarkWakeEntry: 11712 *phaseString = "kIOPMTracePointDarkWakeEntry"; 11713 *description = "entering darkwake on way to sleep"; 11714 break; 11715 11716 case kIOPMTracePointDarkWakeExit: 11717 *phaseString = "kIOPMTracePointDarkWakeExit"; 11718 *description = "entering fullwake from darkwake"; 11719 break; 11720 11721 default: 11722 *phaseString = NULL; 11723 *description = NULL; 11724 } 11725 } 11726 11727 void 11728 IOPMrootDomain::saveFailureData2File() 11729 { 11730 unsigned int len = 0; 11731 char failureStr[512]; 11732 errno_t error; 11733 char *outbuf; 11734 OSNumber *statusCode; 11735 uint64_t pmStatusCode = 0; 11736 uint32_t phaseData = 0; 11737 uint32_t phaseDetail = 0; 11738 bool efiFailure = false; 11739 11740 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey); 11741 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get()); 11742 if (statusCode) { 11743 pmStatusCode = statusCode->unsigned64BitValue(); 11744 phaseData = pmStatusCode & 0xFFFFFFFF; 11745 phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF; 11746 if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) { 11747 LOG("Sleep Wake failure in EFI\n"); 11748 efiFailure = true; 11749 failureStr[0] = 0; 11750 snprintf(failureStr, sizeof(failureStr), "Sleep Wake failure in EFI\n\nFailure code:: 0x%08x 0x%08x\n\nPlease IGNORE the below stackshot\n", phaseDetail, phaseData); 11751 len = (typeof(len))strnlen(failureStr, sizeof(failureStr)); 11752 } 11753 } 11754 11755 if (!efiFailure) { 11756 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) { 11757 swd_flags |= SWD_BOOT_BY_SW_WDOG; 11758 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic); 11759 // dump panic will handle saving nvram data 11760 return; 11761 } 11762 11763 /* Keeping this around for capturing data during power 11764 * button press */ 11765 11766 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) { 11767 DLOG("No sleep wake failure string\n"); 11768 return; 11769 } 11770 if (len == 0) { 11771 DLOG("Ignoring zero byte SleepWake failure string\n"); 11772 goto exit; 11773 } 11774 11775 // if PMStatus code is zero, delete stackshot and return 11776 if (statusCode) { 11777 if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) { 11778 // there was no sleep wake failure 11779 // this can happen if delete stackshot was called 11780 // before take stackshot completed. Let us delete any 11781 // sleep wake failure data in nvram 11782 DLOG("Deleting stackshot on successful wake\n"); 11783 deleteStackshot(); 11784 return; 11785 } 11786 } 11787 11788 if (len > sizeof(failureStr)) { 11789 len = sizeof(failureStr); 11790 } 11791 failureStr[0] = 0; 11792 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len); 11793 } 11794 if (failureStr[0] != 0) { 11795 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len); 11796 if (error) { 11797 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error); 11798 } else { 11799 DLOG("Saved SleepWake failure string to file.\n"); 11800 } 11801 } 11802 11803 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) { 11804 goto exit; 11805 } 11806 11807 if (swd_buffer) { 11808 unsigned int len = 0; 11809 errno_t error; 11810 char nvram_var_name_buffer[20]; 11811 unsigned int concat_len = 0; 11812 swd_hdr *hdr = NULL; 11813 11814 11815 hdr = (swd_hdr *)swd_buffer; 11816 outbuf = (char *)hdr + hdr->spindump_offset; 11817 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset); 11818 11819 for (int i = 0; i < 8; i++) { 11820 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1); 11821 if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) { 11822 LOG("No SleepWake blob to read beyond chunk %d\n", i); 11823 break; 11824 } 11825 if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) { 11826 PERemoveNVRAMProperty(nvram_var_name_buffer); 11827 LOG("Could not read the property :-(\n"); 11828 break; 11829 } 11830 PERemoveNVRAMProperty(nvram_var_name_buffer); 11831 concat_len += len; 11832 } 11833 LOG("Concatenated length for the SWD blob %d\n", concat_len); 11834 11835 if (concat_len) { 11836 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len); 11837 if (error) { 11838 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error); 11839 } else { 11840 LOG("Saved SleepWake zipped data to file.\n"); 11841 } 11842 } else { 11843 // There is a sleep wake failure string but no stackshot 11844 // Write a placeholder stacks file so that swd runs 11845 snprintf(outbuf, 20, "%s", "No stackshot data\n"); 11846 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20); 11847 if (error) { 11848 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error); 11849 } else { 11850 LOG("Saved SleepWake zipped data to file.\n"); 11851 } 11852 } 11853 } else { 11854 LOG("No buffer allocated to save failure stackshot\n"); 11855 } 11856 11857 11858 gRootDomain->swd_lock = 0; 11859 exit: 11860 PERemoveNVRAMProperty(kIOSleepWakeFailureString); 11861 return; 11862 } 11863 11864 11865 void 11866 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen) 11867 { 11868 OSSharedPtr<IORegistryIterator> iter; 11869 OSSharedPtr<const OSSymbol> kextName = NULL; 11870 IORegistryEntry * entry; 11871 IOService * node; 11872 bool nodeFound = false; 11873 11874 const void * callMethod = NULL; 11875 const char * objectName = NULL; 11876 uint32_t timeout = getWatchdogTimeout(); 11877 const char * phaseString = NULL; 11878 const char * phaseDescription = NULL; 11879 11880 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get()); 11881 uint32_t tracePhase = pmTracer->getTracePhase(); 11882 11883 *thread = NULL; 11884 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) { 11885 snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout); 11886 } else { 11887 snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout); 11888 } 11889 tracePhase2String(tracePhase, &phaseString, &phaseDescription); 11890 11891 if (notifierThread) { 11892 if (notifier && (notifier->identifier)) { 11893 objectName = notifier->identifier->getCStringNoCopy(); 11894 } 11895 *thread = notifierThread; 11896 } else { 11897 iter = IORegistryIterator::iterateOver( 11898 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively); 11899 11900 if (iter) { 11901 while ((entry = iter->getNextObject())) { 11902 node = OSDynamicCast(IOService, entry); 11903 if (!node) { 11904 continue; 11905 } 11906 if (OSDynamicCast(IOPowerConnection, node)) { 11907 continue; 11908 } 11909 11910 if (node->getBlockingDriverCall(thread, &callMethod)) { 11911 nodeFound = true; 11912 break; 11913 } 11914 } 11915 } 11916 if (nodeFound) { 11917 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod); 11918 if (kextName) { 11919 objectName = kextName->getCStringNoCopy(); 11920 } 11921 } 11922 } 11923 if (phaseDescription) { 11924 strlcat(failureStr, " while ", strLen); 11925 strlcat(failureStr, phaseDescription, strLen); 11926 strlcat(failureStr, ".", strLen); 11927 } 11928 if (objectName) { 11929 strlcat(failureStr, " Suspected bundle: ", strLen); 11930 strlcat(failureStr, objectName, strLen); 11931 strlcat(failureStr, ".", strLen); 11932 } 11933 if (*thread) { 11934 char threadName[40]; 11935 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread)); 11936 strlcat(failureStr, threadName, strLen); 11937 } 11938 11939 DLOG("%s\n", failureStr); 11940 } 11941 11942 struct swd_stackshot_compressed_data { 11943 z_output_func zoutput; 11944 size_t zipped; 11945 uint64_t totalbytes; 11946 uint64_t lastpercent; 11947 IOReturn error; 11948 unsigned outremain; 11949 unsigned outlen; 11950 unsigned writes; 11951 Bytef * outbuf; 11952 }; 11953 struct swd_stackshot_compressed_data swd_zip_var = { }; 11954 11955 static void * 11956 swd_zs_alloc(void *__unused ref, u_int items, u_int size) 11957 { 11958 void *result; 11959 LOG("Alloc in zipping %d items of size %d\n", items, size); 11960 11961 result = (void *)(swd_zs_zmem + swd_zs_zoffset); 11962 swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc 11963 LOG("Offset %zu\n", swd_zs_zoffset); 11964 return result; 11965 } 11966 11967 static int 11968 swd_zinput(z_streamp strm, Bytef *buf, unsigned size) 11969 { 11970 unsigned len; 11971 11972 len = strm->avail_in; 11973 11974 if (len > size) { 11975 len = size; 11976 } 11977 if (len == 0) { 11978 return 0; 11979 } 11980 11981 if (strm->next_in != (Bytef *) strm) { 11982 memcpy(buf, strm->next_in, len); 11983 } else { 11984 bzero(buf, len); 11985 } 11986 11987 strm->adler = z_crc32(strm->adler, buf, len); 11988 11989 strm->avail_in -= len; 11990 strm->next_in += len; 11991 strm->total_in += len; 11992 11993 return (int)len; 11994 } 11995 11996 static int 11997 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len) 11998 { 11999 unsigned int i = 0; 12000 // if outlen > max size don't add to the buffer 12001 assert(buf != NULL); 12002 if (strm && buf) { 12003 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) { 12004 LOG("No space to GZIP... not writing to NVRAM\n"); 12005 return len; 12006 } 12007 } 12008 for (i = 0; i < len; i++) { 12009 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i); 12010 } 12011 swd_zip_var.outlen += len; 12012 return len; 12013 } 12014 12015 static void 12016 swd_zs_free(void * __unused ref, void * __unused ptr) 12017 { 12018 } 12019 12020 static int 12021 swd_compress(char *inPtr, char *outPtr, size_t numBytes) 12022 { 12023 int wbits = 12; 12024 int memlevel = 3; 12025 12026 if (((unsigned int) numBytes) != numBytes) { 12027 return 0; 12028 } 12029 12030 if (!swd_zs.zalloc) { 12031 swd_zs.zalloc = swd_zs_alloc; 12032 swd_zs.zfree = swd_zs_free; 12033 if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) { 12034 // allocation failed 12035 bzero(&swd_zs, sizeof(swd_zs)); 12036 // swd_zs_zoffset = 0; 12037 } else { 12038 LOG("PMRD inited the zlib allocation routines\n"); 12039 } 12040 } 12041 12042 swd_zip_var.zipped = 0; 12043 swd_zip_var.totalbytes = 0; // should this be the max that we have? 12044 swd_zip_var.lastpercent = 0; 12045 swd_zip_var.error = kIOReturnSuccess; 12046 swd_zip_var.outremain = 0; 12047 swd_zip_var.outlen = 0; 12048 swd_zip_var.writes = 0; 12049 swd_zip_var.outbuf = (Bytef *)outPtr; 12050 12051 swd_zip_var.totalbytes = numBytes; 12052 12053 swd_zs.avail_in = 0; 12054 swd_zs.next_in = NULL; 12055 swd_zs.avail_out = 0; 12056 swd_zs.next_out = NULL; 12057 12058 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput); 12059 12060 z_stream *zs; 12061 int zr; 12062 zs = &swd_zs; 12063 12064 while (swd_zip_var.error >= 0) { 12065 if (!zs->avail_in) { 12066 zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */ 12067 zs->avail_in = (unsigned int) numBytes; 12068 } 12069 if (!zs->avail_out) { 12070 zs->next_out = (Bytef *)zs; 12071 zs->avail_out = UINT32_MAX; 12072 } 12073 zr = deflate(zs, Z_NO_FLUSH); 12074 if (Z_STREAM_END == zr) { 12075 break; 12076 } 12077 if (zr != Z_OK) { 12078 LOG("ZERR %d\n", zr); 12079 swd_zip_var.error = zr; 12080 } else { 12081 if (zs->total_in == numBytes) { 12082 break; 12083 } 12084 } 12085 } 12086 12087 //now flush the stream 12088 while (swd_zip_var.error >= 0) { 12089 if (!zs->avail_out) { 12090 zs->next_out = (Bytef *)zs; 12091 zs->avail_out = UINT32_MAX; 12092 } 12093 zr = deflate(zs, Z_FINISH); 12094 if (Z_STREAM_END == zr) { 12095 break; 12096 } 12097 if (zr != Z_OK) { 12098 LOG("ZERR %d\n", zr); 12099 swd_zip_var.error = zr; 12100 } else { 12101 if (zs->total_in == numBytes) { 12102 LOG("Total output size %d\n", swd_zip_var.outlen); 12103 break; 12104 } 12105 } 12106 } 12107 12108 return swd_zip_var.outlen; 12109 } 12110 12111 void 12112 IOPMrootDomain::deleteStackshot() 12113 { 12114 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) { 12115 // takeStackshot hasn't completed 12116 return; 12117 } 12118 LOG("Deleting any sleepwake failure data in nvram\n"); 12119 12120 PERemoveNVRAMProperty(kIOSleepWakeFailureString); 12121 char nvram_var_name_buf[20]; 12122 for (int i = 0; i < 8; i++) { 12123 snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1); 12124 if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) { 12125 LOG("Removing %s returned false\n", nvram_var_name_buf); 12126 } 12127 } 12128 // force NVRAM sync 12129 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) { 12130 DLOG("Failed to force nvram sync\n"); 12131 } 12132 gRootDomain->swd_lock = 0; 12133 } 12134 12135 void 12136 IOPMrootDomain::takeStackshot(bool wdogTrigger) 12137 { 12138 swd_hdr * hdr = NULL; 12139 int cnt = 0; 12140 int max_cnt = 2; 12141 pid_t pid = 0; 12142 kern_return_t kr = KERN_SUCCESS; 12143 uint64_t flags; 12144 12145 char * dstAddr; 12146 uint32_t size; 12147 uint32_t bytesRemaining; 12148 unsigned bytesWritten = 0; 12149 12150 char failureStr[512]; 12151 thread_t thread = NULL; 12152 const char * swfPanic = "swfPanic"; 12153 12154 uint32_t bufSize; 12155 int success = 0; 12156 12157 #if defined(__i386__) || defined(__x86_64__) 12158 const bool concise = false; 12159 #else 12160 const bool concise = true; 12161 #endif 12162 12163 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) { 12164 return; 12165 } 12166 12167 failureStr[0] = 0; 12168 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) { 12169 return; 12170 } 12171 12172 if (wdogTrigger) { 12173 getFailureData(&thread, failureStr, sizeof(failureStr)); 12174 12175 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) { 12176 goto skip_stackshot; 12177 } 12178 } else { 12179 AbsoluteTime now; 12180 uint64_t nsec; 12181 clock_get_uptime(&now); 12182 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime); 12183 absolutetime_to_nanoseconds(now, &nsec); 12184 snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC))); 12185 } 12186 12187 if (swd_buffer == NULL) { 12188 sleepWakeDebugMemAlloc(); 12189 if (swd_buffer == NULL) { 12190 return; 12191 } 12192 } 12193 hdr = (swd_hdr *)swd_buffer; 12194 bufSize = hdr->alloc_size; 12195 12196 dstAddr = (char*)hdr + hdr->spindump_offset; 12197 flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO; 12198 /* If not wdogTrigger only take kernel tasks stackshot 12199 */ 12200 if (wdogTrigger) { 12201 pid = -1; 12202 } else { 12203 pid = 0; 12204 } 12205 12206 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS 12207 * If we run out of space, take stackshot with only kernel task 12208 */ 12209 while (success == 0 && cnt < max_cnt) { 12210 bytesRemaining = bufSize - hdr->spindump_offset; 12211 cnt++; 12212 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining); 12213 12214 size = bytesRemaining; 12215 kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten); 12216 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n", 12217 kr, pid, size, flags, bytesWritten); 12218 if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) { 12219 if (pid == -1) { 12220 pid = 0; 12221 } else { 12222 LOG("Insufficient buffer size for only kernel task\n"); 12223 break; 12224 } 12225 } 12226 if (kr == KERN_SUCCESS) { 12227 if (bytesWritten == 0) { 12228 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags); 12229 continue; 12230 } 12231 bytesRemaining -= bytesWritten; 12232 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset); 12233 12234 memset(hdr->reason, 0x20, sizeof(hdr->reason)); 12235 12236 // Compress stackshot and save to NVRAM 12237 { 12238 char *outbuf = (char *)swd_compressed_buffer; 12239 int outlen = 0; 12240 int num_chunks = 0; 12241 int max_chunks = 0; 12242 int leftover = 0; 12243 char nvram_var_name_buffer[20]; 12244 12245 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten); 12246 12247 if (outlen) { 12248 max_chunks = outlen / (2096 - 200); 12249 leftover = outlen % (2096 - 200); 12250 12251 if (max_chunks < 8) { 12252 for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) { 12253 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1); 12254 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) { 12255 LOG("Failed to update NVRAM %d\n", num_chunks); 12256 break; 12257 } 12258 } 12259 if (leftover) { 12260 snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1); 12261 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) { 12262 LOG("Failed to update NVRAM with leftovers\n"); 12263 } 12264 } 12265 success = 1; 12266 LOG("Successfully saved stackshot to NVRAM\n"); 12267 } else { 12268 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen); 12269 if (pid == -1) { 12270 pid = 0; 12271 } else { 12272 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen); 12273 break; 12274 } 12275 } 12276 } 12277 } 12278 } 12279 } 12280 12281 if (failureStr[0]) { 12282 // append sleep-wake failure code 12283 char traceCode[80]; 12284 snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n", 12285 pmTracer->getTraceData(), pmTracer->getTracePhase()); 12286 strlcat(failureStr, traceCode, sizeof(failureStr)); 12287 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) { 12288 DLOG("Failed to write SleepWake failure string\n"); 12289 } 12290 } 12291 12292 // force NVRAM sync 12293 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) { 12294 DLOG("Failed to force nvram sync\n"); 12295 } 12296 12297 skip_stackshot: 12298 if (wdogTrigger) { 12299 if (PEGetCoprocessorVersion() < kCoprocessorVersion2) { 12300 if (swd_flags & SWD_BOOT_BY_SW_WDOG) { 12301 // If current boot is due to this watch dog trigger restart in previous boot, 12302 // then don't trigger again until at least 1 successful sleep & wake. 12303 if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) { 12304 LOG("Shutting down due to repeated Sleep/Wake failures\n"); 12305 if (!tasksSuspended) { 12306 tasksSuspended = TRUE; 12307 updateTasksSuspend(); 12308 } 12309 PEHaltRestart(kPEHaltCPU); 12310 return; 12311 } 12312 } 12313 if (gSwdPanic == 0) { 12314 LOG("Calling panic prevented by swd_panic boot-args. Calling restart"); 12315 if (!tasksSuspended) { 12316 tasksSuspended = TRUE; 12317 updateTasksSuspend(); 12318 } 12319 PEHaltRestart(kPERestartCPU); 12320 } 12321 } 12322 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) { 12323 DLOG("Failed to write SleepWake failure panic key\n"); 12324 } 12325 #if defined(__x86_64__) 12326 if (thread) { 12327 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr); 12328 } else 12329 #endif /* defined(__x86_64__) */ 12330 { 12331 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr); 12332 } 12333 } else { 12334 gRootDomain->swd_lock = 0; 12335 return; 12336 } 12337 } 12338 12339 void 12340 IOPMrootDomain::sleepWakeDebugMemAlloc() 12341 { 12342 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE; 12343 12344 swd_hdr *hdr = NULL; 12345 void *bufPtr = NULL; 12346 12347 OSSharedPtr<IOBufferMemoryDescriptor> memDesc; 12348 12349 12350 if (kIOSleepWakeWdogOff & gIOKitDebug) { 12351 return; 12352 } 12353 12354 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) { 12355 return; 12356 } 12357 12358 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions( 12359 kernel_task, kIODirectionIn | kIOMemoryMapperNone, 12360 size); 12361 if (memDesc == NULL) { 12362 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n"); 12363 goto exit; 12364 } 12365 12366 bufPtr = memDesc->getBytesNoCopy(); 12367 12368 // Carve out memory for zlib routines 12369 swd_zs_zmem = (vm_offset_t)bufPtr; 12370 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE; 12371 12372 // Carve out memory for compressed stackshots 12373 swd_compressed_buffer = bufPtr; 12374 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE; 12375 12376 // Remaining is used for holding stackshot 12377 hdr = (swd_hdr *)bufPtr; 12378 memset(hdr, 0, sizeof(swd_hdr)); 12379 12380 hdr->signature = SWD_HDR_SIGNATURE; 12381 hdr->alloc_size = SWD_STACKSHOT_SIZE; 12382 12383 hdr->spindump_offset = sizeof(swd_hdr); 12384 swd_buffer = (void *)hdr; 12385 swd_memDesc = os::move(memDesc); 12386 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset); 12387 12388 exit: 12389 gRootDomain->swd_lock = 0; 12390 } 12391 12392 void 12393 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc() 12394 { 12395 #if UNUSED 12396 vm_size_t size = SWD_SPINDUMP_SIZE; 12397 12398 swd_hdr *hdr = NULL; 12399 12400 OSSharedPtr<IOBufferMemoryDescriptor> memDesc; 12401 12402 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) { 12403 return; 12404 } 12405 12406 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions( 12407 kernel_task, kIODirectionIn | kIOMemoryMapperNone, 12408 SWD_SPINDUMP_SIZE); 12409 12410 if (memDesc == NULL) { 12411 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n"); 12412 goto exit; 12413 } 12414 12415 12416 hdr = (swd_hdr *)memDesc->getBytesNoCopy(); 12417 memset(hdr, 0, sizeof(swd_hdr)); 12418 12419 hdr->signature = SWD_HDR_SIGNATURE; 12420 hdr->alloc_size = size; 12421 12422 hdr->spindump_offset = sizeof(swd_hdr); 12423 swd_spindump_buffer = (void *)hdr; 12424 swd_spindump_memDesc = os::move(memDesc); 12425 12426 exit: 12427 gRootDomain->swd_lock = 0; 12428 #endif /* UNUSED */ 12429 } 12430 12431 void 12432 IOPMrootDomain::sleepWakeDebugEnableWdog() 12433 { 12434 } 12435 12436 bool 12437 IOPMrootDomain::sleepWakeDebugIsWdogEnabled() 12438 { 12439 return !systemBooting && !systemShutdown && !gWillShutdown; 12440 } 12441 12442 void 12443 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile() 12444 { 12445 swd_hdr *hdr = NULL; 12446 errno_t error = EIO; 12447 12448 if (swd_spindump_buffer && gSpinDumpBufferFull) { 12449 hdr = (swd_hdr *)swd_spindump_buffer; 12450 12451 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump", 12452 (char*)hdr + hdr->spindump_offset, hdr->spindump_size); 12453 12454 if (error) { 12455 return; 12456 } 12457 12458 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump", 12459 (char*)hdr + offsetof(swd_hdr, UUID), 12460 sizeof(swd_hdr) - offsetof(swd_hdr, UUID)); 12461 12462 gSpinDumpBufferFull = false; 12463 } 12464 } 12465 12466 errno_t 12467 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len) 12468 { 12469 struct vnode *vp = NULL; 12470 vfs_context_t ctx = vfs_context_create(vfs_context_current()); 12471 kauth_cred_t cred = vfs_context_ucred(ctx); 12472 struct vnode_attr va; 12473 errno_t error = EIO; 12474 12475 if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW), 12476 S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) { 12477 LOG("Failed to open the file %s\n", name); 12478 swd_flags |= SWD_FILEOP_ERROR; 12479 goto exit; 12480 } 12481 VATTR_INIT(&va); 12482 VATTR_WANTED(&va, va_nlink); 12483 /* Don't dump to non-regular files or files with links. */ 12484 if (vp->v_type != VREG || 12485 vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) { 12486 LOG("Bailing as this is not a regular file\n"); 12487 swd_flags |= SWD_FILEOP_ERROR; 12488 goto exit; 12489 } 12490 VATTR_INIT(&va); 12491 VATTR_SET(&va, va_data_size, 0); 12492 vnode_setattr(vp, &va, ctx); 12493 12494 12495 if (buf != NULL) { 12496 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0, 12497 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx)); 12498 if (error != 0) { 12499 LOG("Failed to save sleep wake log. err 0x%x\n", error); 12500 swd_flags |= SWD_FILEOP_ERROR; 12501 } else { 12502 DLOG("Saved %d bytes to file %s\n", len, name); 12503 } 12504 } 12505 12506 exit: 12507 if (vp) { 12508 vnode_close(vp, FWRITE, ctx); 12509 } 12510 if (ctx) { 12511 vfs_context_rele(ctx); 12512 } 12513 12514 return error; 12515 } 12516 12517 #else /* defined(__i386__) || defined(__x86_64__) */ 12518 12519 void 12520 IOPMrootDomain::sleepWakeDebugTrig(bool restart) 12521 { 12522 if (restart) { 12523 if (gSwdPanic == 0) { 12524 return; 12525 } 12526 panic("Sleep/Wake hang detected"); 12527 return; 12528 } 12529 } 12530 12531 void 12532 IOPMrootDomain::takeStackshot(bool restart) 12533 { 12534 #pragma unused(restart) 12535 } 12536 12537 void 12538 IOPMrootDomain::deleteStackshot() 12539 { 12540 } 12541 12542 void 12543 IOPMrootDomain::sleepWakeDebugMemAlloc() 12544 { 12545 } 12546 12547 void 12548 IOPMrootDomain::saveFailureData2File() 12549 { 12550 } 12551 12552 void 12553 IOPMrootDomain::sleepWakeDebugEnableWdog() 12554 { 12555 } 12556 12557 bool 12558 IOPMrootDomain::sleepWakeDebugIsWdogEnabled() 12559 { 12560 return false; 12561 } 12562 12563 void 12564 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile() 12565 { 12566 } 12567 12568 errno_t 12569 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len) 12570 { 12571 return 0; 12572 } 12573 12574 #endif /* defined(__i386__) || defined(__x86_64__) */ 12575 12576