2 * Copyright (c) 1998-2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #define IOKIT_ENABLE_SHARED_PTR
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 <IOKit/IOUserServer.h>
58 #include "IOKitKernelInternal.h"
60 #include <IOKit/IOHibernatePrivate.h>
61 #endif /* HIBERNATION */
62 #include <console/video_console.h>
63 #include <sys/syslog.h>
64 #include <sys/sysctl.h>
65 #include <sys/vnode.h>
66 #include <sys/vnode_internal.h>
67 #include <sys/fcntl.h>
69 #include <pexpert/protos.h>
70 #include <AssertMacros.h>
73 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
74 #include "IOServicePMPrivate.h"
76 #include <libkern/zlib.h>
77 #include <os/cpp_util.h>
78 #include <libkern/c++/OSBoundedArrayRef.h>
81 #include <mach/shared_region.h>
82 #include <kern/clock.h>
85 #if defined(__i386__) || defined(__x86_64__)
87 #include "IOPMrootDomainInternal.h"
88 const char *processor_to_datastring(const char *prefix
, processor_t target_processor
);
92 #define kIOPMrootDomainClass "IOPMrootDomain"
93 #define LOG_PREFIX "PMRD: "
97 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
100 do { kprintf(LOG_PREFIX x); } while (false)
102 #if DEVELOPMENT || DEBUG
103 #define DEBUG_LOG(x...) do { \
104 if (kIOLogPMRootDomain & gIOKitDebug) \
105 kprintf(LOG_PREFIX x); \
106 os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
109 #define DEBUG_LOG(x...)
112 #define DLOG(x...) do { \
113 if (kIOLogPMRootDomain & gIOKitDebug) \
114 kprintf(LOG_PREFIX x); \
116 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
119 #define DMSG(x...) do { \
120 if (kIOLogPMRootDomain & gIOKitDebug) { \
121 kprintf(LOG_PREFIX x); \
128 #define CHECK_THREAD_CONTEXT
129 #ifdef CHECK_THREAD_CONTEXT
130 static IOWorkLoop
* gIOPMWorkLoop
= NULL
;
131 #define ASSERT_GATED() \
133 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
134 panic("RootDomain: not inside PM gate"); \
138 #define ASSERT_GATED()
139 #endif /* CHECK_THREAD_CONTEXT */
141 #define CAP_LOSS(c) \
142 (((_pendingCapability & (c)) == 0) && \
143 ((_currentCapability & (c)) != 0))
145 #define CAP_GAIN(c) \
146 (((_currentCapability & (c)) == 0) && \
147 ((_pendingCapability & (c)) != 0))
149 #define CAP_CHANGE(c) \
150 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
152 #define CAP_CURRENT(c) \
153 ((_currentCapability & (c)) != 0)
155 #define CAP_HIGHEST(c) \
156 ((_highestCapability & (c)) != 0)
158 #define CAP_PENDING(c) \
159 ((_pendingCapability & (c)) != 0)
161 // rdar://problem/9157444
162 #if defined(__i386__) || defined(__x86_64__)
163 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
166 // Event types for IOPMPowerStateQueue::submitPowerEvent()
168 kPowerEventFeatureChanged
= 1, // 1
169 kPowerEventReceivedPowerNotification
, // 2
170 kPowerEventSystemBootCompleted
, // 3
171 kPowerEventSystemShutdown
, // 4
172 kPowerEventUserDisabledSleep
, // 5
173 kPowerEventRegisterSystemCapabilityClient
, // 6
174 kPowerEventRegisterKernelCapabilityClient
, // 7
175 kPowerEventPolicyStimulus
, // 8
176 kPowerEventAssertionCreate
, // 9
177 kPowerEventAssertionRelease
, // 10
178 kPowerEventAssertionSetLevel
, // 11
179 kPowerEventQueueSleepWakeUUID
, // 12
180 kPowerEventPublishSleepWakeUUID
, // 13
181 kPowerEventSetDisplayPowerOn
, // 14
182 kPowerEventPublishWakeType
, // 15
183 kPowerEventAOTEvaluate
// 16
186 // For evaluatePolicy()
187 // List of stimuli that affects the root domain policy.
189 kStimulusDisplayWranglerSleep
, // 0
190 kStimulusDisplayWranglerWake
, // 1
191 kStimulusAggressivenessChanged
, // 2
192 kStimulusDemandSystemSleep
, // 3
193 kStimulusAllowSystemSleepChanged
, // 4
194 kStimulusDarkWakeActivityTickle
, // 5
195 kStimulusDarkWakeEntry
, // 6
196 kStimulusDarkWakeReentry
, // 7
197 kStimulusDarkWakeEvaluate
, // 8
198 kStimulusNoIdleSleepPreventers
, // 9
199 kStimulusEnterUserActiveState
, // 10
200 kStimulusLeaveUserActiveState
// 11
203 // Internal power state change reasons
204 // Must be less than kIOPMSleepReasonClamshell=101
206 kCPSReasonNone
= 0, // 0
209 kCPSReasonIdleSleepPrevent
, // 3
210 kCPSReasonIdleSleepAllow
, // 4
211 kCPSReasonPowerOverride
, // 5
212 kCPSReasonPowerDownCancel
, // 6
213 kCPSReasonAOTExit
, // 7
214 kCPSReasonAdjustPowerState
, // 8
215 kCPSReasonDarkWakeCannotSleep
, // 9
216 kCPSReasonIdleSleepEnabled
, // 10
217 kCPSReasonEvaluatePolicy
, // 11
218 kCPSReasonSustainFullWake
, // 12
219 kCPSReasonPMInternals
= (kIOPMSleepReasonClamshell
- 1)
223 IOReturn
OSKextSystemSleepOrWake( UInt32
);
225 extern "C" ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
);
226 extern "C" addr64_t
kvtophys(vm_offset_t va
);
227 extern "C" boolean_t
kdp_has_polled_corefile();
229 static void idleSleepTimerExpired( thread_call_param_t
, thread_call_param_t
);
230 static void notifySystemShutdown( IOService
* root
, uint32_t messageType
);
231 static void handleAggressivesFunction( thread_call_param_t
, thread_call_param_t
);
232 static void pmEventTimeStamp(uint64_t *recordTS
);
233 static void powerButtonUpCallout( thread_call_param_t
, thread_call_param_t
);
234 static void powerButtonDownCallout( thread_call_param_t
, thread_call_param_t
);
235 static OSPtr
<const OSSymbol
> copyKextIdentifierWithAddress(vm_address_t address
);
237 static int IOPMConvertSecondsToCalendar(clock_sec_t secs
, IOPMCalendarStruct
* dt
);
238 static clock_sec_t
IOPMConvertCalendarToSeconds(const IOPMCalendarStruct
* dt
);
239 #define YMDTF "%04d/%02d/%d %02d:%02d:%02d"
240 #define YMDT(cal) ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
242 // "IOPMSetSleepSupported" callPlatformFunction name
243 static OSSharedPtr
<const OSSymbol
> sleepSupportedPEFunction
;
244 static OSSharedPtr
<const OSSymbol
> sleepMessagePEFunction
;
245 static OSSharedPtr
<const OSSymbol
> gIOPMWakeTypeUserKey
;
247 static OSSharedPtr
<const OSSymbol
> gIOPMPSExternalConnectedKey
;
248 static OSSharedPtr
<const OSSymbol
> gIOPMPSExternalChargeCapableKey
;
249 static OSSharedPtr
<const OSSymbol
> gIOPMPSBatteryInstalledKey
;
250 static OSSharedPtr
<const OSSymbol
> gIOPMPSIsChargingKey
;
251 static OSSharedPtr
<const OSSymbol
> gIOPMPSAtWarnLevelKey
;
252 static OSSharedPtr
<const OSSymbol
> gIOPMPSAtCriticalLevelKey
;
253 static OSSharedPtr
<const OSSymbol
> gIOPMPSCurrentCapacityKey
;
254 static OSSharedPtr
<const OSSymbol
> gIOPMPSMaxCapacityKey
;
255 static OSSharedPtr
<const OSSymbol
> gIOPMPSDesignCapacityKey
;
256 static OSSharedPtr
<const OSSymbol
> gIOPMPSTimeRemainingKey
;
257 static OSSharedPtr
<const OSSymbol
> gIOPMPSAmperageKey
;
258 static OSSharedPtr
<const OSSymbol
> gIOPMPSVoltageKey
;
259 static OSSharedPtr
<const OSSymbol
> gIOPMPSCycleCountKey
;
260 static OSSharedPtr
<const OSSymbol
> gIOPMPSMaxErrKey
;
261 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterInfoKey
;
262 static OSSharedPtr
<const OSSymbol
> gIOPMPSLocationKey
;
263 static OSSharedPtr
<const OSSymbol
> gIOPMPSErrorConditionKey
;
264 static OSSharedPtr
<const OSSymbol
> gIOPMPSManufacturerKey
;
265 static OSSharedPtr
<const OSSymbol
> gIOPMPSManufactureDateKey
;
266 static OSSharedPtr
<const OSSymbol
> gIOPMPSModelKey
;
267 static OSSharedPtr
<const OSSymbol
> gIOPMPSSerialKey
;
268 static OSSharedPtr
<const OSSymbol
> gIOPMPSLegacyBatteryInfoKey
;
269 static OSSharedPtr
<const OSSymbol
> gIOPMPSBatteryHealthKey
;
270 static OSSharedPtr
<const OSSymbol
> gIOPMPSHealthConfidenceKey
;
271 static OSSharedPtr
<const OSSymbol
> gIOPMPSCapacityEstimatedKey
;
272 static OSSharedPtr
<const OSSymbol
> gIOPMPSBatteryChargeStatusKey
;
273 static OSSharedPtr
<const OSSymbol
> gIOPMPSBatteryTemperatureKey
;
274 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsKey
;
275 static OSSharedPtr
<const OSSymbol
> gIOPMPSChargerConfigurationKey
;
276 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsIDKey
;
277 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsWattsKey
;
278 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsRevisionKey
;
279 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsSerialNumberKey
;
280 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsFamilyKey
;
281 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsAmperageKey
;
282 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsDescriptionKey
;
283 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsPMUConfigurationKey
;
284 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsSourceIDKey
;
285 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsErrorFlagsKey
;
286 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsSharedSourceKey
;
287 static OSSharedPtr
<const OSSymbol
> gIOPMPSAdapterDetailsCloakedKey
;
288 static OSSharedPtr
<const OSSymbol
> gIOPMPSInvalidWakeSecondsKey
;
289 static OSSharedPtr
<const OSSymbol
> gIOPMPSPostChargeWaitSecondsKey
;
290 static OSSharedPtr
<const OSSymbol
> gIOPMPSPostDishargeWaitSecondsKey
;
292 #define kIOSleepSupportedKey "IOSleepSupported"
293 #define kIOPMSystemCapabilitiesKey "System Capabilities"
294 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
296 #define kIORequestWranglerIdleKey "IORequestIdle"
297 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
299 #define kIOSleepWakeFailureString "SleepWakeFailureString"
300 #define kIOEFIBootRomFailureKey "wake-failure"
301 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
303 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
304 | kIOPMSupportedOnBatt \
305 | kIOPMSupportedOnUPS)
307 #define kLocalEvalClamshellCommand (1 << 15)
308 #define kIdleSleepRetryInterval (3 * 60)
310 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
313 kWranglerPowerStateMin
= 0,
314 kWranglerPowerStateSleep
= 2,
315 kWranglerPowerStateDim
= 3,
316 kWranglerPowerStateMax
= 4
329 getPowerStateString( uint32_t state
)
331 #define POWER_STATE(x) {(uint32_t) x, #x}
333 static const IONamedValue powerStates
[] = {
334 POWER_STATE( OFF_STATE
),
335 POWER_STATE( RESTART_STATE
),
336 POWER_STATE( SLEEP_STATE
),
337 POWER_STATE( AOT_STATE
),
338 POWER_STATE( ON_STATE
),
341 return IOFindNameForValue(state
, powerStates
);
344 #define ON_POWER kIOPMPowerOn
345 #define RESTART_POWER kIOPMRestart
346 #define SLEEP_POWER kIOPMAuxPowerOn
348 static IOPMPowerState
349 ourPowerStates
[NUM_POWER_STATES
] =
352 .capabilityFlags
= 0,
353 .outputPowerCharacter
= 0,
354 .inputPowerRequirement
= 0 },
356 .capabilityFlags
= kIOPMRestartCapability
,
357 .outputPowerCharacter
= kIOPMRestart
,
358 .inputPowerRequirement
= RESTART_POWER
},
360 .capabilityFlags
= kIOPMSleepCapability
,
361 .outputPowerCharacter
= kIOPMSleep
,
362 .inputPowerRequirement
= SLEEP_POWER
},
364 .capabilityFlags
= kIOPMAOTCapability
,
365 .outputPowerCharacter
= kIOPMAOTPower
,
366 .inputPowerRequirement
= ON_POWER
},
368 .capabilityFlags
= kIOPMPowerOn
,
369 .outputPowerCharacter
= kIOPMPowerOn
,
370 .inputPowerRequirement
= ON_POWER
},
373 #define kIOPMRootDomainWakeTypeSleepService "SleepService"
374 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
375 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
376 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
377 #define kIOPMRootDomainWakeTypeUser "User"
378 #define kIOPMRootDomainWakeTypeAlarm "Alarm"
379 #define kIOPMRootDomainWakeTypeNetwork "Network"
380 #define kIOPMRootDomainWakeTypeHIDActivity "HID Activity"
381 #define kIOPMRootDomainWakeTypeNotification "Notification"
382 #define kIOPMRootDomainWakeTypeHibernateError "HibernateError"
384 // Special interest that entitles the interested client from receiving
385 // all system messages. Only used by powerd.
387 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
389 // Entitlement required for root domain clients
390 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
392 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
393 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
398 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
399 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
401 #define kAggressivesMinValue 1
404 getAggressivenessTypeString( uint32_t type
)
406 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
408 static const IONamedValue aggressivenessTypes
[] = {
409 AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness
),
410 AGGRESSIVENESS_TYPE( kPMMinutesToDim
),
411 AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown
),
412 AGGRESSIVENESS_TYPE( kPMMinutesToSleep
),
413 AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings
),
414 AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed
),
415 AGGRESSIVENESS_TYPE( kPMPowerSource
),
416 AGGRESSIVENESS_TYPE( kPMMotionSensor
),
417 AGGRESSIVENESS_TYPE( kPMLastAggressivenessType
),
420 return IOFindNameForValue(type
, aggressivenessTypes
);
424 kAggressivesStateBusy
= 0x01,
425 kAggressivesStateQuickSpindown
= 0x02
428 struct AggressivesRecord
{
434 struct AggressivesRequest
{
439 OSSharedPtr
<IOService
> service
;
440 AggressivesRecord record
;
445 kAggressivesRequestTypeService
= 1,
446 kAggressivesRequestTypeRecord
450 kAggressivesOptionSynchronous
= 0x00000001,
451 kAggressivesOptionQuickSpindownEnable
= 0x00000100,
452 kAggressivesOptionQuickSpindownDisable
= 0x00000200,
453 kAggressivesOptionQuickSpindownMask
= 0x00000300
457 kAggressivesRecordFlagModified
= 0x00000001,
458 kAggressivesRecordFlagMinValue
= 0x00000002
461 // System Sleep Preventers
464 kPMUserDisabledAllSleep
= 1,
465 kPMSystemRestartBootingInProgress
,
466 kPMConfigPreventSystemSleep
,
467 kPMChildPreventSystemSleep
,
473 getSystemSleepPreventerString( uint32_t preventer
)
475 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
476 static const IONamedValue systemSleepPreventers
[] = {
477 SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep
),
478 SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress
),
479 SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep
),
480 SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep
),
481 SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion
),
482 SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported
),
485 return IOFindNameForValue(preventer
, systemSleepPreventers
);
490 kDarkWakeFlagPromotionNone
= 0x0000,
491 kDarkWakeFlagPromotionEarly
= 0x0001, // promote before gfx clamp
492 kDarkWakeFlagPromotionLate
= 0x0002, // promote after gfx clamp
493 kDarkWakeFlagPromotionMask
= 0x0003,
494 kDarkWakeFlagAlarmIsDark
= 0x0100,
495 kDarkWakeFlagAudioNotSuppressed
= 0x0200,
496 kDarkWakeFlagUserWakeWorkaround
= 0x1000
500 // The workaround for 9157444 is enabled at compile time using the
501 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
503 kClamshell_WAR_38378787
= 0x00000001,
504 kClamshell_WAR_47715679
= 0x00000002,
505 kClamshell_WAR_58009435
= 0x00000004
508 // acceptSystemWakeEvents()
510 kAcceptSystemWakeEvents_Disable
= 0,
511 kAcceptSystemWakeEvents_Enable
,
512 kAcceptSystemWakeEvents_Reenable
515 static IOPMrootDomain
* gRootDomain
;
516 static IORootParent
* gPatriarch
;
517 static IONotifier
* gSysPowerDownNotifier
= NULL
;
518 static UInt32 gSleepOrShutdownPending
= 0;
519 static UInt32 gWillShutdown
= 0;
520 static UInt32 gPagingOff
= 0;
521 static UInt32 gSleepWakeUUIDIsSet
= false;
522 static uint32_t gAggressivesState
= 0;
523 uint32_t gHaltTimeMaxLog
;
524 uint32_t gHaltTimeMaxPanic
;
525 IOLock
* gHaltLogLock
;
526 static char * gHaltLog
;
527 enum { kHaltLogSize
= 2048 };
528 static size_t gHaltLogPos
;
529 static uint64_t gHaltStartTime
;
530 static char gKextNameBuf
[64];
531 static size_t gKextNamePos
;
532 static bool gKextNameEnd
;
534 uuid_string_t bootsessionuuid_string
;
536 #if defined(XNU_TARGET_OS_OSX)
537 #if DISPLAY_WRANGLER_PRESENT
538 static uint32_t gDarkWakeFlags
= kDarkWakeFlagPromotionNone
;
540 // Enable temporary full wake promotion workarounds
541 static uint32_t gDarkWakeFlags
= kDarkWakeFlagUserWakeWorkaround
;
543 // Enable full wake promotion workarounds
544 static uint32_t gDarkWakeFlags
= kDarkWakeFlagUserWakeWorkaround
;
546 #else /* !defined(XNU_TARGET_OS_OSX) */
547 static uint32_t gDarkWakeFlags
= kDarkWakeFlagPromotionEarly
;
548 #endif /* !defined(XNU_TARGET_OS_OSX) */
550 static uint32_t gNoIdleFlag
= 0;
551 static uint32_t gSwdPanic
= 1;
552 static uint32_t gSwdSleepTimeout
= 0;
553 static uint32_t gSwdWakeTimeout
= 0;
554 static uint32_t gSwdSleepWakeTimeout
= 0;
555 static PMStatsStruct gPMStats
;
556 #if DEVELOPMENT || DEBUG
557 static uint32_t swd_panic_phase
;
560 static uint32_t gClamshellFlags
= 0
561 #if defined(__i386__) || defined(__x86_64__)
562 | kClamshell_WAR_58009435
568 #if defined(__arm64__)
570 defaultSleepPolicyHandler(void *ctx
, const IOPMSystemSleepPolicyVariables
*vars
, IOPMSystemSleepParameters
*params
)
572 uint32_t sleepType
= kIOPMSleepTypeDeepIdle
;
574 assert(vars
->signature
== kIOPMSystemSleepPolicySignature
);
575 assert(vars
->version
== kIOPMSystemSleepPolicyVersion
);
577 // Hibernation enabled and either user forced hibernate or low battery sleep
578 if ((vars
->hibernateMode
& kIOHibernateModeOn
) &&
579 (((vars
->hibernateMode
& kIOHibernateModeSleep
) == 0) ||
580 (vars
->sleepFactors
& kIOPMSleepFactorBatteryLow
))) {
581 sleepType
= kIOPMSleepTypeHibernate
;
583 params
->version
= kIOPMSystemSleepParametersVersion
;
584 params
->sleepType
= sleepType
;
585 return kIOReturnSuccess
;
587 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler
= &defaultSleepPolicyHandler
;
588 #else /* defined(__arm64__) */
589 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler
= NULL
;
590 #endif /* defined(__arm64__) */
592 static IOPMSystemSleepPolicyVariables
* gSleepPolicyVars
= NULL
;
593 static void * gSleepPolicyTarget
;
596 struct timeval gIOLastSleepTime
;
597 struct timeval gIOLastWakeTime
;
598 AbsoluteTime gIOLastWakeAbsTime
;
599 AbsoluteTime gIOLastSleepAbsTime
;
601 struct timeval gIOLastUserSleepTime
;
603 static char gWakeReasonString
[128];
604 static char gBootReasonString
[80];
605 static char gShutdownReasonString
[80];
606 static bool gWakeReasonSysctlRegistered
= false;
607 static bool gBootReasonSysctlRegistered
= false;
608 static bool gShutdownReasonSysctlRegistered
= false;
609 static bool gWillShutdownSysctlRegistered
= false;
610 static AbsoluteTime gUserActiveAbsTime
;
611 static AbsoluteTime gUserInactiveAbsTime
;
613 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
614 static bool gSpinDumpBufferFull
= false;
618 vm_offset_t swd_zs_zmem
;
619 //size_t swd_zs_zsize;
620 size_t swd_zs_zoffset
;
621 #if defined(__i386__) || defined(__x86_64__)
622 IOCPU
*currentShutdownTarget
= NULL
;
625 static unsigned int gPMHaltBusyCount
;
626 static unsigned int gPMHaltIdleCount
;
627 static int gPMHaltDepth
;
628 static uint32_t gPMHaltMessageType
;
629 static IOLock
* gPMHaltLock
= NULL
;
630 static OSSharedPtr
<OSArray
> gPMHaltArray
;
631 static OSSharedPtr
<const OSSymbol
> gPMHaltClientAcknowledgeKey
;
632 static bool gPMQuiesced
;
634 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
635 #define kCPUUnknownIndex 9999999
642 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponseTimedOut
;
643 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponseCancel
;
644 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponseSlow
;
645 OSSharedPtr
<const OSSymbol
> gIOPMStatsResponsePrompt
;
646 OSSharedPtr
<const OSSymbol
> gIOPMStatsDriverPSChangeSlow
;
648 #define kBadPMFeatureID 0
652 * Opaque handle passed to clients of registerPMSettingController()
654 class PMSettingHandle
: public OSObject
656 OSDeclareFinalStructors( PMSettingHandle
);
657 friend class PMSettingObject
;
660 PMSettingObject
*pmso
;
661 void free(void) APPLE_KEXT_OVERRIDE
;
666 * Internal object to track each PM setting controller
668 class PMSettingObject
: public OSObject
670 OSDeclareFinalStructors( PMSettingObject
);
671 friend class IOPMrootDomain
;
674 queue_head_t calloutQueue
;
676 IOPMrootDomain
*parent
;
677 PMSettingHandle
*pmsh
;
678 IOPMSettingControllerCallback func
;
681 uint32_t *publishedFeatureID
;
682 uint32_t settingCount
;
685 void free(void) APPLE_KEXT_OVERRIDE
;
688 static PMSettingObject
*pmSettingObject(
689 IOPMrootDomain
*parent_arg
,
690 IOPMSettingControllerCallback handler_arg
,
691 OSObject
*target_arg
,
692 uintptr_t refcon_arg
,
693 uint32_t supportedPowerSources
,
694 const OSSymbol
*settings
[],
695 OSObject
**handle_obj
);
697 IOReturn
dispatchPMSetting(const OSSymbol
*type
, OSObject
*object
);
698 void clientHandleFreed(void);
701 struct PMSettingCallEntry
{
706 #define PMSETTING_LOCK() IOLockLock(settingsCtrlLock)
707 #define PMSETTING_UNLOCK() IOLockUnlock(settingsCtrlLock)
708 #define PMSETTING_WAIT(p) IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
709 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
713 * Internal helper object for logging trace points to RTC
714 * IOPMrootDomain and only IOPMrootDomain should instantiate
715 * exactly one of these.
718 typedef void (*IOPMTracePointHandler
)(
719 void * target
, uint32_t code
, uint32_t data
);
721 class PMTraceWorker
: public OSObject
723 OSDeclareDefaultStructors(PMTraceWorker
);
725 typedef enum { kPowerChangeStart
, kPowerChangeCompleted
} change_t
;
727 static OSPtr
<PMTraceWorker
> tracer( IOPMrootDomain
* );
728 void tracePCIPowerChange(change_t
, IOService
*, uint32_t, uint32_t);
729 void tracePoint(uint8_t phase
);
730 void traceDetail(uint32_t detail
);
731 void traceComponentWakeProgress(uint32_t component
, uint32_t data
);
732 int recordTopLevelPCIDevice(IOService
*);
733 void RTC_TRACE(void);
734 virtual bool serialize(OSSerialize
*s
) const APPLE_KEXT_OVERRIDE
;
736 IOPMTracePointHandler tracePointHandler
;
737 void * tracePointTarget
;
738 uint64_t getPMStatusCode();
739 uint8_t getTracePhase();
740 uint32_t getTraceData();
742 IOPMrootDomain
*owner
;
743 IOLock
*pmTraceWorkerLock
;
744 OSSharedPtr
<OSArray
> pciDeviceBitMappings
;
746 uint8_t addedToRegistry
;
748 uint32_t traceData32
;
749 uint8_t loginWindowData
;
750 uint8_t coreDisplayData
;
751 uint8_t coreGraphicsData
;
755 * PMAssertionsTracker
756 * Tracks kernel and user space PM assertions
758 class PMAssertionsTracker
: public OSObject
760 OSDeclareFinalStructors(PMAssertionsTracker
);
762 static PMAssertionsTracker
*pmAssertionsTracker( IOPMrootDomain
* );
764 IOReturn
createAssertion(IOPMDriverAssertionType
, IOPMDriverAssertionLevel
, IOService
*, const char *, IOPMDriverAssertionID
*);
765 IOReturn
releaseAssertion(IOPMDriverAssertionID
);
766 IOReturn
setAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
);
767 IOReturn
setUserAssertionLevels(IOPMDriverAssertionType
);
769 OSSharedPtr
<OSArray
> copyAssertionsArray(void);
770 IOPMDriverAssertionType
getActivatedAssertions(void);
771 IOPMDriverAssertionLevel
getAssertionLevel(IOPMDriverAssertionType
);
773 IOReturn
handleCreateAssertion(OSData
*);
774 IOReturn
handleReleaseAssertion(IOPMDriverAssertionID
);
775 IOReturn
handleSetAssertionLevel(IOPMDriverAssertionID
, IOPMDriverAssertionLevel
);
776 IOReturn
handleSetUserAssertionLevels(void * arg0
);
777 void publishProperties(void);
778 void reportCPUBitAccounting(void);
782 * this should be treated as POD, as it's byte-copied around
783 * and we cannot rely on d'tor firing at the right time
786 IOPMDriverAssertionID id
;
787 IOPMDriverAssertionType assertionBits
;
788 uint64_t createdTime
;
789 uint64_t modifiedTime
;
790 const OSSymbol
*ownerString
;
791 IOService
*ownerService
;
792 uint64_t registryEntryID
;
793 IOPMDriverAssertionLevel level
;
794 uint64_t assertCPUStartTime
;
795 uint64_t assertCPUDuration
;
798 uint32_t tabulateProducerCount
;
799 uint32_t tabulateConsumerCount
;
801 uint64_t maxAssertCPUDuration
;
802 uint64_t maxAssertCPUEntryId
;
804 PMAssertStruct
*detailsForID(IOPMDriverAssertionID
, int *);
806 void updateCPUBitAccounting(PMAssertStruct
* assertStruct
);
808 IOPMrootDomain
*owner
;
809 OSSharedPtr
<OSArray
> assertionsArray
;
810 IOLock
*assertionsArrayLock
;
811 IOPMDriverAssertionID issuingUniqueID
__attribute__((aligned(8)));/* aligned for atomic access */
812 IOPMDriverAssertionType assertionsKernel
;
813 IOPMDriverAssertionType assertionsUser
;
814 IOPMDriverAssertionType assertionsCombined
;
817 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker
, OSObject
);
821 * Internal helper object for Shutdown/Restart notifications.
823 #define kPMHaltMaxWorkers 8
824 #define kPMHaltTimeoutMS 100
826 class PMHaltWorker
: public OSObject
828 OSDeclareFinalStructors( PMHaltWorker
);
831 IOService
* service
;// service being worked on
832 AbsoluteTime startTime
; // time when work started
833 int depth
; // work on nubs at this PM-tree depth
834 int visits
; // number of nodes visited (debug)
836 bool timeout
;// service took too long
838 static PMHaltWorker
* worker( void );
839 static void main( void * arg
, wait_result_t waitResult
);
840 static void work( PMHaltWorker
* me
);
841 static void checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
);
842 virtual void free( void ) APPLE_KEXT_OVERRIDE
;
845 OSDefineMetaClassAndFinalStructors( PMHaltWorker
, OSObject
)
848 #define super IOService
849 OSDefineMetaClassAndFinalStructors(IOPMrootDomain
, IOService
)
852 IOPMRootDomainGetWillShutdown(void)
854 return gWillShutdown
!= 0;
858 IOPMRootDomainWillShutdown(void)
860 if (OSCompareAndSwap(0, 1, &gWillShutdown
)) {
861 IOService::willShutdown();
862 for (int i
= 0; i
< 100; i
++) {
863 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending
)) {
871 extern "C" IONotifier
*
872 registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
874 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
).detach();
877 extern "C" IONotifier
*
878 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
880 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
).detach();
884 acknowledgeSleepWakeNotification(void * PMrefcon
)
886 return gRootDomain
->allowPowerChange((unsigned long)PMrefcon
);
890 vetoSleepWakeNotification(void * PMrefcon
)
892 return gRootDomain
->cancelPowerChange((unsigned long)PMrefcon
);
896 rootDomainRestart( void )
898 return gRootDomain
->restartSystem();
902 rootDomainShutdown( void )
904 return gRootDomain
->shutdownSystem();
908 halt_log_putc(char c
)
910 if (gHaltLogPos
>= (kHaltLogSize
- 2)) {
913 gHaltLog
[gHaltLogPos
++] = c
;
917 _doprnt_log(const char *fmt
,
923 halt_log(const char *fmt
, ...)
927 va_start(listp
, fmt
);
928 _doprnt_log(fmt
, &listp
, &halt_log_putc
, 16);
935 halt_log_enter(const char * what
, const void * pc
, uint64_t time
)
937 uint64_t nano
, millis
;
942 absolutetime_to_nanoseconds(time
, &nano
);
943 millis
= nano
/ NSEC_PER_MSEC
;
948 IOLockLock(gHaltLogLock
);
950 halt_log("%s: %qd ms @ 0x%lx, ", what
, millis
, VM_KERNEL_UNSLIDE(pc
));
951 OSKext::printKextsInBacktrace((vm_offset_t
*) &pc
, 1, &halt_log
,
952 OSKext::kPrintKextsLock
| OSKext::kPrintKextsUnslide
| OSKext::kPrintKextsTerse
);
954 halt_log("%s: %qd ms\n", what
, millis
);
957 gHaltLog
[gHaltLogPos
] = 0;
958 IOLockUnlock(gHaltLogLock
);
961 extern uint32_t gFSState
;
964 IOSystemShutdownNotification(int stage
)
968 if (kIOSystemShutdownNotificationStageRootUnmount
== stage
) {
969 #if defined(XNU_TARGET_OS_OSX)
970 uint64_t nano
, millis
;
971 startTime
= mach_absolute_time();
972 IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC
);
973 absolutetime_to_nanoseconds(mach_absolute_time() - startTime
, &nano
);
974 millis
= nano
/ NSEC_PER_MSEC
;
975 if (gHaltTimeMaxLog
&& (millis
>= gHaltTimeMaxLog
)) {
976 printf("waitQuiet() for unmount %qd ms\n", millis
);
978 #endif /* defined(XNU_TARGET_OS_OSX) */
982 if (kIOSystemShutdownNotificationTerminateDEXTs
== stage
) {
983 uint64_t nano
, millis
;
984 startTime
= mach_absolute_time();
985 IOServicePH::systemHalt();
986 absolutetime_to_nanoseconds(mach_absolute_time() - startTime
, &nano
);
987 millis
= nano
/ NSEC_PER_MSEC
;
988 if (true || (gHaltTimeMaxLog
&& (millis
>= gHaltTimeMaxLog
))) {
989 printf("IOServicePH::systemHalt took %qd ms\n", millis
);
994 assert(kIOSystemShutdownNotificationStageProcessExit
== stage
);
996 IOLockLock(gHaltLogLock
);
998 gHaltLog
= IONew(char, kHaltLogSize
);
999 gHaltStartTime
= mach_absolute_time();
1001 halt_log_putc('\n');
1004 IOLockUnlock(gHaltLogLock
);
1006 startTime
= mach_absolute_time();
1007 IOPMRootDomainWillShutdown();
1008 halt_log_enter("IOPMRootDomainWillShutdown", NULL
, mach_absolute_time() - startTime
);
1010 startTime
= mach_absolute_time();
1011 IOHibernateSystemPostWake(true);
1012 halt_log_enter("IOHibernateSystemPostWake", NULL
, mach_absolute_time() - startTime
);
1014 if (OSCompareAndSwap(0, 1, &gPagingOff
)) {
1015 gRootDomain
->handlePlatformHaltRestart(kPEPagingOff
);
1019 extern "C" int sync_internal(void);
1022 * A device is always in the highest power state which satisfies its driver,
1023 * its policy-maker, and any power children it has, but within the constraint
1024 * of the power state provided by its parent. The driver expresses its desire by
1025 * calling changePowerStateTo(), the policy-maker expresses its desire by calling
1026 * changePowerStateToPriv(), and the children express their desires by calling
1027 * requestPowerDomainState().
1029 * The Root Power Domain owns the policy for idle and demand sleep for the system.
1030 * It is a power-managed IOService just like the others in the system.
1031 * It implements several power states which map to what we see as Sleep and On.
1033 * The sleep policy is as follows:
1034 * 1. Sleep is prevented if the case is open so that nobody will think the machine
1035 * is off and plug/unplug cards.
1036 * 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1037 * 3. System cannot Sleep if some object in the tree is in a power state marked
1038 * kIOPMPreventSystemSleep.
1040 * These three conditions are enforced using the "driver clamp" by calling
1041 * changePowerStateTo(). For example, if the case is opened,
1042 * changePowerStateTo(ON_STATE) is called to hold the system on regardless
1043 * of the desires of the children of the root or the state of the other clamp.
1045 * Demand Sleep is initiated by pressing the front panel power button, closing
1046 * the clamshell, or selecting the menu item. In this case the root's parent
1047 * actually initiates the power state change so that the root domain has no
1048 * choice and does not give applications the opportunity to veto the change.
1050 * Idle Sleep occurs if no objects in the tree are in a state marked
1051 * kIOPMPreventIdleSleep. When this is true, the root's children are not holding
1052 * the root on, so it sets the "policy-maker clamp" by calling
1053 * changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1054 * This timer is set for the difference between the sleep timeout slider and the
1055 * display dim timeout slider. When the timer expires, it releases its clamp and
1056 * now nothing is holding it awake, so it falls asleep.
1058 * Demand sleep is prevented when the system is booting. When preferences are
1059 * transmitted by the loginwindow at the end of boot, a flag is cleared,
1060 * and this allows subsequent Demand Sleep.
1063 //******************************************************************************
1066 IOPMrootDomain::construct( void )
1068 IOPMrootDomain
*root
;
1070 root
= new IOPMrootDomain
;
1078 //******************************************************************************
1079 // updateConsoleUsersCallout
1081 //******************************************************************************
1084 updateConsoleUsersCallout(thread_call_param_t p0
, thread_call_param_t p1
)
1086 IOPMrootDomain
* rootDomain
= (IOPMrootDomain
*) p0
;
1087 rootDomain
->updateConsoleUsers();
1091 IOPMrootDomain::updateConsoleUsers(void)
1093 IOService::updateConsoleUsers(NULL
, kIOMessageSystemHasPoweredOn
);
1094 if (tasksSuspended
) {
1095 tasksSuspended
= FALSE
;
1096 updateTasksSuspend();
1101 IOPMrootDomain::updateTasksSuspend(void)
1105 newSuspend
= (tasksSuspended
|| _aotTasksSuspended
);
1106 if (newSuspend
== tasksSuspendState
) {
1109 tasksSuspendState
= newSuspend
;
1110 tasks_system_suspend(newSuspend
);
1113 //******************************************************************************
1116 disk_sync_callout( thread_call_param_t p0
, thread_call_param_t p1
)
1118 IOPMrootDomain
* rootDomain
= (IOPMrootDomain
*) p0
;
1119 uint32_t notifyRef
= (uint32_t)(uintptr_t) p1
;
1120 uint32_t powerState
= rootDomain
->getPowerState();
1122 DLOG("disk_sync_callout ps=%u\n", powerState
);
1124 if (ON_STATE
== powerState
) {
1128 // Block sleep until trim issued on previous wake path is completed.
1129 IOHibernateSystemPostWake(true);
1134 IOHibernateSystemPostWake(false);
1136 rootDomain
->sleepWakeDebugSaveSpinDumpFile();
1140 rootDomain
->allowPowerChange(notifyRef
);
1141 DLOG("disk_sync_callout finish\n");
1144 //******************************************************************************
1146 computeDeltaTimeMS( const AbsoluteTime
* startTime
, AbsoluteTime
* elapsedTime
)
1148 AbsoluteTime endTime
;
1151 clock_get_uptime(&endTime
);
1152 if (CMP_ABSOLUTETIME(&endTime
, startTime
) <= 0) {
1155 SUB_ABSOLUTETIME(&endTime
, startTime
);
1156 absolutetime_to_nanoseconds(endTime
, &nano
);
1157 *elapsedTime
= endTime
;
1160 return (UInt32
)(nano
/ NSEC_PER_MSEC
);
1163 //******************************************************************************
1166 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1168 struct timeval
*swt
= (struct timeval
*)arg1
;
1169 struct proc
*p
= req
->p
;
1171 if (p
== kernproc
) {
1172 return sysctl_io_opaque(req
, swt
, sizeof(*swt
), NULL
);
1173 } else if (proc_is64bit(p
)) {
1174 struct user64_timeval t
= {};
1175 t
.tv_sec
= swt
->tv_sec
;
1176 t
.tv_usec
= swt
->tv_usec
;
1177 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
);
1179 struct user32_timeval t
= {};
1180 t
.tv_sec
= (typeof(t
.tv_sec
))swt
->tv_sec
;
1181 t
.tv_usec
= swt
->tv_usec
;
1182 return sysctl_io_opaque(req
, &t
, sizeof(t
), NULL
);
1186 static SYSCTL_PROC(_kern
, OID_AUTO
, sleeptime
,
1187 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1188 &gIOLastUserSleepTime
, 0, sysctl_sleepwaketime
, "S,timeval", "");
1190 static SYSCTL_PROC(_kern
, OID_AUTO
, waketime
,
1191 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1192 &gIOLastWakeTime
, 0, sysctl_sleepwaketime
, "S,timeval", "");
1194 SYSCTL_QUAD(_kern
, OID_AUTO
, wake_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gIOLastWakeAbsTime
, "");
1195 SYSCTL_QUAD(_kern
, OID_AUTO
, sleep_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gIOLastSleepAbsTime
, "");
1196 SYSCTL_QUAD(_kern
, OID_AUTO
, useractive_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gUserActiveAbsTime
, "");
1197 SYSCTL_QUAD(_kern
, OID_AUTO
, userinactive_abs_time
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &gUserInactiveAbsTime
, "");
1200 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1202 int new_value
, changed
, error
;
1204 if (!gWillShutdownSysctlRegistered
) {
1208 error
= sysctl_io_number(req
, gWillShutdown
, sizeof(int), &new_value
, &changed
);
1210 if (!gWillShutdown
&& (new_value
== 1)) {
1211 IOPMRootDomainWillShutdown();
1219 static SYSCTL_PROC(_kern
, OID_AUTO
, willshutdown
,
1220 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1221 NULL
, 0, sysctl_willshutdown
, "I", "");
1223 #if defined(XNU_TARGET_OS_OSX)
1226 sysctl_progressmeterenable
1227 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1230 int new_value
, changed
;
1232 error
= sysctl_io_number(req
, vc_progressmeter_enable
, sizeof(int), &new_value
, &changed
);
1235 vc_enable_progressmeter(new_value
);
1242 sysctl_progressmeter
1243 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1246 int new_value
, changed
;
1248 error
= sysctl_io_number(req
, vc_progressmeter_value
, sizeof(int), &new_value
, &changed
);
1251 vc_set_progressmeter(new_value
);
1257 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeterenable
,
1258 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1259 NULL
, 0, sysctl_progressmeterenable
, "I", "");
1261 static SYSCTL_PROC(_kern
, OID_AUTO
, progressmeter
,
1262 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1263 NULL
, 0, sysctl_progressmeter
, "I", "");
1265 #endif /* defined(XNU_TARGET_OS_OSX) */
1270 sysctl_consoleoptions
1271 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1276 error
= sysctl_io_number(req
, vc_user_options
.options
, sizeof(uint32_t), &new_value
, &changed
);
1279 vc_user_options
.options
= new_value
;
1285 static SYSCTL_PROC(_kern
, OID_AUTO
, consoleoptions
,
1286 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1287 NULL
, 0, sysctl_consoleoptions
, "I", "");
1291 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1293 return sysctl_io_opaque(req
, &vc_user_options
, sizeof(vc_user_options
), NULL
);
1296 static SYSCTL_PROC(_kern
, OID_AUTO
, progressoptions
,
1297 CTLTYPE_STRUCT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1298 NULL
, 0, sysctl_progressoptions
, "S,vc_progress_user_options", "");
1302 sysctl_wakereason SYSCTL_HANDLER_ARGS
1304 char wr
[sizeof(gWakeReasonString
)];
1307 if (gRootDomain
&& gWakeReasonSysctlRegistered
) {
1308 gRootDomain
->copyWakeReasonString(wr
, sizeof(wr
));
1313 return sysctl_io_string(req
, wr
, 0, 0, NULL
);
1316 SYSCTL_PROC(_kern
, OID_AUTO
, wakereason
,
1317 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1318 NULL
, 0, sysctl_wakereason
, "A", "wakereason");
1321 sysctl_bootreason SYSCTL_HANDLER_ARGS
1323 if (!os_atomic_load(&gBootReasonSysctlRegistered
, acquire
)) {
1327 return sysctl_io_string(req
, gBootReasonString
, 0, 0, NULL
);
1330 SYSCTL_PROC(_kern
, OID_AUTO
, bootreason
,
1331 CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1332 NULL
, 0, sysctl_bootreason
, "A", "");
1335 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1337 char sr
[sizeof(gShutdownReasonString
)];
1340 if (gRootDomain
&& gShutdownReasonSysctlRegistered
) {
1341 gRootDomain
->copyShutdownReasonString(sr
, sizeof(sr
));
1346 return sysctl_io_string(req
, sr
, 0, 0, NULL
);
1349 SYSCTL_PROC(_kern
, OID_AUTO
, shutdownreason
,
1350 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1351 NULL
, 0, sysctl_shutdownreason
, "A", "shutdownreason");
1354 sysctl_targettype SYSCTL_HANDLER_ARGS
1357 OSSharedPtr
<OSObject
> obj
;
1362 root
= IOService::getServiceRoot();
1363 if (root
&& (obj
= root
->copyProperty(gIODTTargetTypeKey
))) {
1364 if ((data
= OSDynamicCast(OSData
, obj
.get()))) {
1365 strlcpy(tt
, (const char *) data
->getBytesNoCopy(), sizeof(tt
));
1368 return sysctl_io_string(req
, tt
, 0, 0, NULL
);
1371 SYSCTL_PROC(_hw
, OID_AUTO
, targettype
,
1372 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1373 NULL
, 0, sysctl_targettype
, "A", "targettype");
1375 static SYSCTL_INT(_debug
, OID_AUTO
, noidle
, CTLFLAG_RW
, &gNoIdleFlag
, 0, "");
1376 static SYSCTL_INT(_debug
, OID_AUTO
, swd_sleep_timeout
, CTLFLAG_RW
, &gSwdSleepTimeout
, 0, "");
1377 static SYSCTL_INT(_debug
, OID_AUTO
, swd_wake_timeout
, CTLFLAG_RW
, &gSwdWakeTimeout
, 0, "");
1378 static SYSCTL_INT(_debug
, OID_AUTO
, swd_timeout
, CTLFLAG_RW
, &gSwdSleepWakeTimeout
, 0, "");
1379 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic
, CTLFLAG_RW
, &gSwdPanic
, 0, "");
1380 #if DEVELOPMENT || DEBUG
1381 static SYSCTL_INT(_debug
, OID_AUTO
, swd_panic_phase
, CTLFLAG_RW
, &swd_panic_phase
, 0, "");
1382 #if defined(XNU_TARGET_OS_OSX)
1383 static SYSCTL_INT(_debug
, OID_AUTO
, clamshell
, CTLFLAG_RW
, &gClamshellFlags
, 0, "");
1384 static SYSCTL_INT(_debug
, OID_AUTO
, darkwake
, CTLFLAG_RW
, &gDarkWakeFlags
, 0, "");
1385 #endif /* defined(XNU_TARGET_OS_OSX) */
1386 #endif /* DEVELOPMENT || DEBUG */
1388 //******************************************************************************
1392 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1394 if (NULL
== gRootDomain
) {
1397 if (NULL
== gRootDomain
->_aotMetrics
) {
1400 return sysctl_io_opaque(req
, gRootDomain
->_aotMetrics
, sizeof(IOPMAOTMetrics
), NULL
);
1403 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmetrics
,
1404 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1405 NULL
, 0, sysctl_aotmetrics
, "S,IOPMAOTMetrics", "");
1409 update_aotmode(uint32_t mode
)
1413 if (!gIOPMWorkLoop
) {
1416 result
= gIOPMWorkLoop
->runActionBlock(^IOReturn (void) {
1417 unsigned int oldCount
;
1419 if (mode
&& !gRootDomain
->_aotMetrics
) {
1420 gRootDomain
->_aotMetrics
= IONewZero(IOPMAOTMetrics
, 1);
1421 if (!gRootDomain
->_aotMetrics
) {
1426 oldCount
= gRootDomain
->idleSleepPreventersCount();
1427 gRootDomain
->_aotMode
= (mode
& kIOPMAOTModeMask
);
1428 gRootDomain
->updatePreventIdleSleepListInternal(NULL
, false, oldCount
);
1436 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1441 if (NULL
== gRootDomain
) {
1444 error
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
);
1445 if (changed
&& gIOPMWorkLoop
) {
1446 error
= update_aotmode(new_value
);
1452 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmodebits
,
1453 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1454 NULL
, 0, sysctl_aotmodebits
, "I", "");
1458 (__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1463 if (NULL
== gRootDomain
) {
1466 error
= sysctl_io_number(req
, gRootDomain
->_aotMode
, sizeof(uint32_t), &new_value
, &changed
);
1467 if (changed
&& gIOPMWorkLoop
) {
1469 new_value
= kIOPMAOTModeDefault
; // & ~kIOPMAOTModeRespectTimers;
1471 error
= update_aotmode(new_value
);
1477 static SYSCTL_PROC(_kern
, OID_AUTO
, aotmode
,
1478 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
1479 NULL
, 0, sysctl_aotmode
, "I", "");
1481 //******************************************************************************
1483 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoWakeCalendarKey
;
1484 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoWakeSecondsKey
;
1485 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoPowerCalendarKey
;
1486 static OSSharedPtr
<const OSSymbol
> gIOPMSettingAutoPowerSecondsKey
;
1487 static OSSharedPtr
<const OSSymbol
> gIOPMSettingDebugWakeRelativeKey
;
1488 static OSSharedPtr
<const OSSymbol
> gIOPMSettingDebugPowerRelativeKey
;
1489 static OSSharedPtr
<const OSSymbol
> gIOPMSettingMaintenanceWakeCalendarKey
;
1490 static OSSharedPtr
<const OSSymbol
> gIOPMSettingSleepServiceWakeCalendarKey
;
1491 static OSSharedPtr
<const OSSymbol
> gIOPMSettingSilentRunningKey
;
1492 static OSSharedPtr
<const OSSymbol
> gIOPMUserTriggeredFullWakeKey
;
1493 static OSSharedPtr
<const OSSymbol
> gIOPMUserIsActiveKey
;
1494 static OSSharedPtr
<const OSSymbol
> gIOPMSettingLowLatencyAudioModeKey
;
1496 //******************************************************************************
1499 //******************************************************************************
1501 #define kRootDomainSettingsCount 20
1502 #define kRootDomainNoPublishSettingsCount 4
1505 IOPMrootDomain::start( IOService
* nub
)
1507 OSSharedPtr
<OSIterator
> psIterator
;
1508 OSSharedPtr
<OSDictionary
> tmpDict
;
1513 gIOPMSettingAutoWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
);
1514 gIOPMSettingAutoWakeSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
);
1515 gIOPMSettingAutoPowerCalendarKey
= OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
);
1516 gIOPMSettingAutoPowerSecondsKey
= OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
);
1517 gIOPMSettingDebugWakeRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
);
1518 gIOPMSettingDebugPowerRelativeKey
= OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
);
1519 gIOPMSettingMaintenanceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey
);
1520 gIOPMSettingSleepServiceWakeCalendarKey
= OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey
);
1521 gIOPMSettingSilentRunningKey
= OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey
);
1522 gIOPMUserTriggeredFullWakeKey
= OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey
);
1523 gIOPMUserIsActiveKey
= OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey
);
1524 gIOPMSettingLowLatencyAudioModeKey
= OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey
);
1526 gIOPMStatsResponseTimedOut
= OSSymbol::withCString(kIOPMStatsResponseTimedOut
);
1527 gIOPMStatsResponseCancel
= OSSymbol::withCString(kIOPMStatsResponseCancel
);
1528 gIOPMStatsResponseSlow
= OSSymbol::withCString(kIOPMStatsResponseSlow
);
1529 gIOPMStatsResponsePrompt
= OSSymbol::withCString(kIOPMStatsResponsePrompt
);
1530 gIOPMStatsDriverPSChangeSlow
= OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow
);
1532 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
1533 sleepMessagePEFunction
= OSSymbol::withCString("IOPMSystemSleepMessage");
1534 gIOPMWakeTypeUserKey
= OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser
);
1536 OSSharedPtr
<const OSSymbol
> settingsArr
[kRootDomainSettingsCount
] =
1538 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
1539 gIOPMSettingAutoWakeSecondsKey
,
1540 gIOPMSettingAutoPowerSecondsKey
,
1541 gIOPMSettingAutoWakeCalendarKey
,
1542 gIOPMSettingAutoPowerCalendarKey
,
1543 gIOPMSettingDebugWakeRelativeKey
,
1544 gIOPMSettingDebugPowerRelativeKey
,
1545 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
1546 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
1547 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
1548 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
1549 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
),
1550 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey
),
1551 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey
),
1552 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey
),
1553 OSSymbol::withCString(kIOPMStateConsoleShutdown
),
1554 OSSymbol::withCString(kIOPMSettingProModeControl
),
1555 OSSymbol::withCString(kIOPMSettingProModeDefer
),
1556 gIOPMSettingSilentRunningKey
,
1557 gIOPMSettingLowLatencyAudioModeKey
,
1560 OSSharedPtr
<const OSSymbol
> noPublishSettingsArr
[kRootDomainNoPublishSettingsCount
] =
1562 OSSymbol::withCString(kIOPMSettingProModeControl
),
1563 OSSymbol::withCString(kIOPMSettingProModeDefer
),
1564 gIOPMSettingSilentRunningKey
,
1565 gIOPMSettingLowLatencyAudioModeKey
,
1568 #if DEVELOPMENT || DEBUG
1569 #if defined(XNU_TARGET_OS_OSX)
1570 PE_parse_boot_argn("darkwake", &gDarkWakeFlags
, sizeof(gDarkWakeFlags
));
1571 PE_parse_boot_argn("clamshell", &gClamshellFlags
, sizeof(gClamshellFlags
));
1572 #endif /* defined(XNU_TARGET_OS_OSX) */
1573 #endif /* DEVELOPMENT || DEBUG */
1575 PE_parse_boot_argn("noidle", &gNoIdleFlag
, sizeof(gNoIdleFlag
));
1576 PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout
, sizeof(gSwdSleepTimeout
));
1577 PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout
, sizeof(gSwdWakeTimeout
));
1578 PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout
, sizeof(gSwdSleepWakeTimeout
));
1579 PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic
, sizeof(gHaltTimeMaxPanic
));
1580 PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog
, sizeof(gHaltTimeMaxLog
));
1582 queue_init(&aggressivesQueue
);
1583 aggressivesThreadCall
= thread_call_allocate(handleAggressivesFunction
, this);
1584 aggressivesData
= OSData::withCapacity(
1585 sizeof(AggressivesRecord
) * (kPMLastAggressivenessType
+ 4));
1587 featuresDictLock
= IOLockAlloc();
1588 settingsCtrlLock
= IOLockAlloc();
1589 wakeEventLock
= IOLockAlloc();
1590 gHaltLogLock
= IOLockAlloc();
1591 setPMRootDomain(this);
1593 extraSleepTimer
= thread_call_allocate(
1594 idleSleepTimerExpired
,
1595 (thread_call_param_t
) this);
1597 powerButtonDown
= thread_call_allocate(
1598 powerButtonDownCallout
,
1599 (thread_call_param_t
) this);
1601 powerButtonUp
= thread_call_allocate(
1602 powerButtonUpCallout
,
1603 (thread_call_param_t
) this);
1605 diskSyncCalloutEntry
= thread_call_allocate(
1607 (thread_call_param_t
) this);
1608 updateConsoleUsersEntry
= thread_call_allocate(
1609 &updateConsoleUsersCallout
,
1610 (thread_call_param_t
) this);
1612 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1613 fullWakeThreadCall
= thread_call_allocate_with_options(
1614 OSMemberFunctionCast(thread_call_func_t
, this,
1615 &IOPMrootDomain::fullWakeDelayedWork
),
1616 (thread_call_param_t
) this, THREAD_CALL_PRIORITY_KERNEL
,
1617 THREAD_CALL_OPTIONS_ONCE
);
1620 setProperty(kIOSleepSupportedKey
, true);
1622 bzero(&gPMStats
, sizeof(gPMStats
));
1624 pmTracer
= PMTraceWorker::tracer(this);
1626 pmAssertions
= PMAssertionsTracker::pmAssertionsTracker(this);
1628 userDisabledAllSleep
= false;
1629 systemBooting
= true;
1630 idleSleepEnabled
= false;
1632 idleSleepTimerPending
= false;
1634 clamshellClosed
= false;
1635 clamshellExists
= false;
1636 #if DISPLAY_WRANGLER_PRESENT
1637 clamshellDisabled
= true;
1639 clamshellDisabled
= false;
1641 clamshellIgnoreClose
= false;
1642 acAdaptorConnected
= true;
1643 clamshellSleepDisableMask
= 0;
1644 gWakeReasonString
[0] = '\0';
1646 // Initialize to user active.
1647 // Will never transition to user inactive w/o wrangler.
1648 fullWakeReason
= kFullWakeReasonLocalUser
;
1649 userIsActive
= userWasActive
= true;
1650 clock_get_uptime(&gUserActiveAbsTime
);
1651 setProperty(gIOPMUserIsActiveKey
.get(), kOSBooleanTrue
);
1653 // Set the default system capabilities at boot.
1654 _currentCapability
= kIOPMSystemCapabilityCPU
|
1655 kIOPMSystemCapabilityGraphics
|
1656 kIOPMSystemCapabilityAudio
|
1657 kIOPMSystemCapabilityNetwork
;
1659 _pendingCapability
= _currentCapability
;
1660 _desiredCapability
= _currentCapability
;
1661 _highestCapability
= _currentCapability
;
1662 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
1664 queuedSleepWakeUUIDString
= NULL
;
1665 initializeBootSessionUUID();
1666 pmStatsAppResponses
= OSArray::withCapacity(5);
1667 _statsNameKey
= OSSymbol::withCString(kIOPMStatsNameKey
);
1668 _statsPIDKey
= OSSymbol::withCString(kIOPMStatsPIDKey
);
1669 _statsTimeMSKey
= OSSymbol::withCString(kIOPMStatsTimeMSKey
);
1670 _statsResponseTypeKey
= OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey
);
1671 _statsMessageTypeKey
= OSSymbol::withCString(kIOPMStatsMessageTypeKey
);
1672 _statsPowerCapsKey
= OSSymbol::withCString(kIOPMStatsPowerCapabilityKey
);
1673 assertOnWakeSecs
= -1;// Invalid value to prevent updates
1675 pmStatsLock
= IOLockAlloc();
1676 idxPMCPUClamshell
= kCPUUnknownIndex
;
1677 idxPMCPULimitedPower
= kCPUUnknownIndex
;
1679 tmpDict
= OSDictionary::withCapacity(1);
1680 setProperty(kRootDomainSupportedFeatures
, tmpDict
.get());
1682 // Set a default "SystemPowerProfileOverrideDict" for platform
1683 // drivers without any overrides.
1684 if (!propertyExists(kIOPMSystemDefaultOverrideKey
)) {
1685 tmpDict
= OSDictionary::withCapacity(1);
1686 setProperty(kIOPMSystemDefaultOverrideKey
, tmpDict
.get());
1689 settingsCallbacks
= OSDictionary::withCapacity(1);
1691 // Create a list of the valid PM settings that we'll relay to
1692 // interested clients in setProperties() => setPMSetting()
1693 allowedPMSettings
= OSArray::withObjects(
1694 (const OSObject
**)settingsArr
,
1695 kRootDomainSettingsCount
,
1698 // List of PM settings that should not automatically publish itself
1699 // as a feature when registered by a listener.
1700 noPublishPMSettings
= OSArray::withObjects(
1701 (const OSObject
**)noPublishSettingsArr
,
1702 kRootDomainNoPublishSettingsCount
,
1705 fPMSettingsDict
= OSDictionary::withCapacity(5);
1706 preventIdleSleepList
= OSSet::withCapacity(8);
1707 preventSystemSleepList
= OSSet::withCapacity(2);
1709 PMinit(); // creates gIOPMWorkLoop
1710 gIOPMWorkLoop
= getIOPMWorkloop();
1712 // Create IOPMPowerStateQueue used to queue external power
1713 // events, and to handle those events on the PM work loop.
1714 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(
1715 this, OSMemberFunctionCast(IOEventSource::Action
, this,
1716 &IOPMrootDomain::dispatchPowerEvent
));
1717 gIOPMWorkLoop
->addEventSource(pmPowerStateQueue
);
1720 _aotTimerES
= IOTimerEventSource::timerEventSource(this,
1721 OSMemberFunctionCast(IOTimerEventSource::Action
,
1722 this, &IOPMrootDomain::aotEvaluate
));
1723 gIOPMWorkLoop
->addEventSource(_aotTimerES
.get());
1725 // create our power parent
1726 gPatriarch
= new IORootParent
;
1728 gPatriarch
->attach(this);
1729 gPatriarch
->start(this);
1730 gPatriarch
->addPowerChild(this);
1732 registerPowerDriver(this, ourPowerStates
, NUM_POWER_STATES
);
1733 changePowerStateWithTagToPriv(ON_STATE
, kCPSReasonInit
);
1735 // install power change handler
1736 gSysPowerDownNotifier
= registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, NULL
);
1738 #if DISPLAY_WRANGLER_PRESENT
1739 wranglerIdleSettings
= OSDictionary::withCapacity(1);
1740 OSSharedPtr
<OSNumber
> wranglerIdlePeriod
= OSNumber::withNumber(kDefaultWranglerIdlePeriod
, 32);
1742 if (wranglerIdleSettings
&& wranglerIdlePeriod
) {
1743 wranglerIdleSettings
->setObject(kIORequestWranglerIdleKey
,
1744 wranglerIdlePeriod
.get());
1747 #endif /* DISPLAY_WRANGLER_PRESENT */
1749 lowLatencyAudioNotifierDict
= OSDictionary::withCapacity(2);
1750 lowLatencyAudioNotifyStateSym
= OSSymbol::withCString("LowLatencyAudioNotifyState");
1751 lowLatencyAudioNotifyTimestampSym
= OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1752 lowLatencyAudioNotifyStateVal
= OSNumber::withNumber(0ull, 32);
1753 lowLatencyAudioNotifyTimestampVal
= OSNumber::withNumber(0ull, 64);
1755 if (lowLatencyAudioNotifierDict
&& lowLatencyAudioNotifyStateSym
&& lowLatencyAudioNotifyTimestampSym
&&
1756 lowLatencyAudioNotifyStateVal
&& lowLatencyAudioNotifyTimestampVal
) {
1757 lowLatencyAudioNotifierDict
->setObject(lowLatencyAudioNotifyStateSym
.get(), lowLatencyAudioNotifyStateVal
.get());
1758 lowLatencyAudioNotifierDict
->setObject(lowLatencyAudioNotifyTimestampSym
.get(), lowLatencyAudioNotifyTimestampVal
.get());
1761 OSSharedPtr
<const OSSymbol
> ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
1762 setProperty(gIOUserClientClassKey
, const_cast<OSObject
*>(static_cast<const OSObject
*>(ucClassName
.get())));
1764 // IOBacklightDisplay can take a long time to load at boot, or it may
1765 // not load at all if you're booting with clamshell closed. We publish
1766 // 'DisplayDims' here redundantly to get it published early and at all.
1767 OSSharedPtr
<OSDictionary
> matching
;
1768 matching
= serviceMatching("IOPMPowerSource");
1769 psIterator
= getMatchingServices(matching
.get());
1771 if (psIterator
&& psIterator
->getNextObject()) {
1772 // There's at least one battery on the system, so we publish
1773 // 'DisplayDims' support for the LCD.
1774 publishFeature("DisplayDims");
1777 // read swd_panic boot-arg
1778 PE_parse_boot_argn("swd_panic", &gSwdPanic
, sizeof(gSwdPanic
));
1779 gWillShutdownSysctlRegistered
= true;
1782 #if defined(__arm64__)
1783 #endif /* defined(__arm64__) */
1784 IOHibernateSystemInit(this);
1787 registerService(); // let clients find us
1792 //******************************************************************************
1795 // Receive a setProperty call
1796 // The "System Boot" property means the system is completely booted.
1797 //******************************************************************************
1800 IOPMrootDomain::setProperties( OSObject
* props_obj
)
1802 IOReturn return_value
= kIOReturnSuccess
;
1803 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
1804 OSBoolean
*b
= NULL
;
1806 const OSSymbol
*key
= NULL
;
1807 OSObject
*obj
= NULL
;
1808 OSSharedPtr
<OSCollectionIterator
> iter
;
1811 return kIOReturnBadArgument
;
1814 bool clientEntitled
= false;
1816 OSSharedPtr
<OSObject
> obj
= IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty
);
1817 clientEntitled
= (obj
== kOSBooleanTrue
);
1820 if (!clientEntitled
) {
1821 const char * errorSuffix
= NULL
;
1823 // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1824 // That API can set 6 possible keys that are checked below.
1825 if ((dict
->getCount() == 1) &&
1826 (dict
->getObject(gIOPMSettingAutoWakeSecondsKey
.get()) ||
1827 dict
->getObject(gIOPMSettingAutoPowerSecondsKey
.get()) ||
1828 dict
->getObject(gIOPMSettingAutoWakeCalendarKey
.get()) ||
1829 dict
->getObject(gIOPMSettingAutoPowerCalendarKey
.get()) ||
1830 dict
->getObject(gIOPMSettingDebugWakeRelativeKey
.get()) ||
1831 dict
->getObject(gIOPMSettingDebugPowerRelativeKey
.get()))) {
1832 return_value
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
1833 if (return_value
!= kIOReturnSuccess
) {
1834 errorSuffix
= "privileged";
1837 return_value
= kIOReturnNotPermitted
;
1838 errorSuffix
= "entitled";
1841 if (return_value
!= kIOReturnSuccess
) {
1842 OSSharedPtr
<OSString
> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain
);
1843 DLOG("%s failed, process %s is not %s\n", __func__
,
1844 procName
? procName
->getCStringNoCopy() : "", errorSuffix
);
1845 return return_value
;
1849 OSSharedPtr
<const OSSymbol
> publish_simulated_battery_string
= OSSymbol::withCString("SoftwareSimulatedBatteries");
1850 OSSharedPtr
<const OSSymbol
> boot_complete_string
= OSSymbol::withCString("System Boot Complete");
1851 OSSharedPtr
<const OSSymbol
> sys_shutdown_string
= OSSymbol::withCString("System Shutdown");
1852 OSSharedPtr
<const OSSymbol
> stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
1853 OSSharedPtr
<const OSSymbol
> battery_warning_disabled_string
= OSSymbol::withCString("BatteryWarningsDisabled");
1854 OSSharedPtr
<const OSSymbol
> idle_seconds_string
= OSSymbol::withCString("System Idle Seconds");
1855 OSSharedPtr
<const OSSymbol
> sleepdisabled_string
= OSSymbol::withCString("SleepDisabled");
1856 OSSharedPtr
<const OSSymbol
> ondeck_sleepwake_uuid_string
= OSSymbol::withCString(kIOPMSleepWakeUUIDKey
);
1857 OSSharedPtr
<const OSSymbol
> loginwindow_progress_string
= OSSymbol::withCString(kIOPMLoginWindowProgressKey
);
1858 OSSharedPtr
<const OSSymbol
> coredisplay_progress_string
= OSSymbol::withCString(kIOPMCoreDisplayProgressKey
);
1859 OSSharedPtr
<const OSSymbol
> coregraphics_progress_string
= OSSymbol::withCString(kIOPMCoreGraphicsProgressKey
);
1860 #if DEBUG || DEVELOPMENT
1861 OSSharedPtr
<const OSSymbol
> clamshell_close_string
= OSSymbol::withCString("IOPMTestClamshellClose");
1862 OSSharedPtr
<const OSSymbol
> clamshell_open_string
= OSSymbol::withCString("IOPMTestClamshellOpen");
1863 OSSharedPtr
<const OSSymbol
> ac_detach_string
= OSSymbol::withCString("IOPMTestACDetach");
1864 OSSharedPtr
<const OSSymbol
> ac_attach_string
= OSSymbol::withCString("IOPMTestACAttach");
1865 OSSharedPtr
<const OSSymbol
> desktopmode_set_string
= OSSymbol::withCString("IOPMTestDesktopModeSet");
1866 OSSharedPtr
<const OSSymbol
> desktopmode_remove_string
= OSSymbol::withCString("IOPMTestDesktopModeRemove");
1870 OSSharedPtr
<const OSSymbol
> hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
1871 OSSharedPtr
<const OSSymbol
> hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
1872 OSSharedPtr
<const OSSymbol
> hibernatefilemin_string
= OSSymbol::withCString(kIOHibernateFileMinSizeKey
);
1873 OSSharedPtr
<const OSSymbol
> hibernatefilemax_string
= OSSymbol::withCString(kIOHibernateFileMaxSizeKey
);
1874 OSSharedPtr
<const OSSymbol
> hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
1875 OSSharedPtr
<const OSSymbol
> hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
1878 iter
= OSCollectionIterator::withCollection(dict
);
1880 return_value
= kIOReturnNoMemory
;
1884 while ((key
= (const OSSymbol
*) iter
->getNextObject()) &&
1885 (obj
= dict
->getObject(key
))) {
1886 if (key
->isEqualTo(publish_simulated_battery_string
.get())) {
1887 if (OSDynamicCast(OSBoolean
, obj
)) {
1888 publishResource(key
, kOSBooleanTrue
);
1890 } else if (key
->isEqualTo(idle_seconds_string
.get())) {
1891 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1892 setProperty(key
, n
);
1893 idleSeconds
= n
->unsigned32BitValue();
1895 } else if (key
->isEqualTo(boot_complete_string
.get())) {
1896 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemBootCompleted
);
1897 } else if (key
->isEqualTo(sys_shutdown_string
.get())) {
1898 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1899 pmPowerStateQueue
->submitPowerEvent(kPowerEventSystemShutdown
, (void *) b
);
1901 } else if (key
->isEqualTo(battery_warning_disabled_string
.get())) {
1902 setProperty(key
, obj
);
1905 else if (key
->isEqualTo(hibernatemode_string
.get()) ||
1906 key
->isEqualTo(hibernatefilemin_string
.get()) ||
1907 key
->isEqualTo(hibernatefilemax_string
.get()) ||
1908 key
->isEqualTo(hibernatefreeratio_string
.get()) ||
1909 key
->isEqualTo(hibernatefreetime_string
.get())) {
1910 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1911 setProperty(key
, n
);
1913 } else if (key
->isEqualTo(hibernatefile_string
.get())) {
1914 OSString
* str
= OSDynamicCast(OSString
, obj
);
1916 setProperty(key
, str
);
1920 else if (key
->isEqualTo(sleepdisabled_string
.get())) {
1921 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1922 setProperty(key
, b
);
1923 pmPowerStateQueue
->submitPowerEvent(kPowerEventUserDisabledSleep
, (void *) b
);
1925 } else if (key
->isEqualTo(ondeck_sleepwake_uuid_string
.get())) {
1927 pmPowerStateQueue
->submitPowerEvent(kPowerEventQueueSleepWakeUUID
, (void *)obj
);
1928 } else if (key
->isEqualTo(loginwindow_progress_string
.get())) {
1929 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1930 uint32_t data
= n
->unsigned32BitValue();
1931 pmTracer
->traceComponentWakeProgress(kIOPMLoginWindowProgress
, data
);
1932 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMLoginWindowProgress
, data
);
1934 } else if (key
->isEqualTo(coredisplay_progress_string
.get())) {
1935 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1936 uint32_t data
= n
->unsigned32BitValue();
1937 pmTracer
->traceComponentWakeProgress(kIOPMCoreDisplayProgress
, data
);
1938 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreDisplayProgress
, data
);
1940 } else if (key
->isEqualTo(coregraphics_progress_string
.get())) {
1941 if (pmTracer
&& (n
= OSDynamicCast(OSNumber
, obj
))) {
1942 uint32_t data
= n
->unsigned32BitValue();
1943 pmTracer
->traceComponentWakeProgress(kIOPMCoreGraphicsProgress
, data
);
1944 kdebugTrace(kPMLogComponentWakeProgress
, 0, kIOPMCoreGraphicsProgress
, data
);
1946 } else if (key
->isEqualTo(kIOPMDeepSleepEnabledKey
) ||
1947 key
->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey
) ||
1948 key
->isEqualTo(kIOPMAutoPowerOffEnabledKey
) ||
1949 key
->isEqualTo(stall_halt_string
.get())) {
1950 if ((b
= OSDynamicCast(OSBoolean
, obj
))) {
1951 setProperty(key
, b
);
1953 } else if (key
->isEqualTo(kIOPMDeepSleepDelayKey
) ||
1954 key
->isEqualTo(kIOPMDeepSleepTimerKey
) ||
1955 key
->isEqualTo(kIOPMAutoPowerOffDelayKey
) ||
1956 key
->isEqualTo(kIOPMAutoPowerOffTimerKey
)) {
1957 if ((n
= OSDynamicCast(OSNumber
, obj
))) {
1958 setProperty(key
, n
);
1960 } else if (key
->isEqualTo(kIOPMUserWakeAlarmScheduledKey
)) {
1961 if (kOSBooleanTrue
== obj
) {
1962 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_userScheduledAlarmMask
);
1964 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_userScheduledAlarmMask
);
1966 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask
);
1968 #if DEBUG || DEVELOPMENT
1969 else if (key
->isEqualTo(clamshell_close_string
.get())) {
1970 DLOG("SetProperties: setting clamshell close\n");
1971 UInt32 msg
= kIOPMClamshellClosed
;
1972 pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
);
1973 } else if (key
->isEqualTo(clamshell_open_string
.get())) {
1974 DLOG("SetProperties: setting clamshell open\n");
1975 UInt32 msg
= kIOPMClamshellOpened
;
1976 pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
);
1977 } else if (key
->isEqualTo(ac_detach_string
.get())) {
1978 DLOG("SetProperties: setting ac detach\n");
1979 UInt32 msg
= kIOPMSetACAdaptorConnected
;
1980 pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
);
1981 } else if (key
->isEqualTo(ac_attach_string
.get())) {
1982 DLOG("SetProperties: setting ac attach\n");
1983 UInt32 msg
= kIOPMSetACAdaptorConnected
| kIOPMSetValue
;
1984 pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
);
1985 } else if (key
->isEqualTo(desktopmode_set_string
.get())) {
1986 DLOG("SetProperties: setting desktopmode");
1987 UInt32 msg
= kIOPMSetDesktopMode
| kIOPMSetValue
;
1988 pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
);
1989 } else if (key
->isEqualTo(desktopmode_remove_string
.get())) {
1990 DLOG("SetProperties: removing desktopmode\n");
1991 UInt32 msg
= kIOPMSetDesktopMode
;
1992 pmPowerStateQueue
->submitPowerEvent(kPowerEventReceivedPowerNotification
, (void *)(uintptr_t)msg
);
1995 // Relay our allowed PM settings onto our registered PM clients
1996 else if ((allowedPMSettings
->getNextIndexOfObject(key
, 0) != (unsigned int) -1)) {
1997 return_value
= setPMSetting(key
, obj
);
1998 if (kIOReturnSuccess
!= return_value
) {
2002 DLOG("setProperties(%s) not handled\n", key
->getCStringNoCopy());
2007 return return_value
;
2011 // MARK: Aggressiveness
2013 //******************************************************************************
2014 // setAggressiveness
2016 // Override IOService::setAggressiveness()
2017 //******************************************************************************
2020 IOPMrootDomain::setAggressiveness(
2022 unsigned long value
)
2024 return setAggressiveness( type
, value
, 0 );
2028 * Private setAggressiveness() with an internal options argument.
2031 IOPMrootDomain::setAggressiveness(
2033 unsigned long value
,
2034 IOOptionBits options
)
2036 AggressivesRequest
* entry
;
2037 AggressivesRequest
* request
;
2040 if ((type
> UINT_MAX
) || (value
> UINT_MAX
)) {
2041 return kIOReturnBadArgument
;
2044 if (type
== kPMMinutesToDim
|| type
== kPMMinutesToSleep
) {
2045 DLOG("setAggressiveness(%x) %s = %u\n",
2046 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
2048 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2049 (uint32_t) options
, getAggressivenessTypeString((uint32_t) type
), (uint32_t) value
);
2052 request
= IONew(AggressivesRequest
, 1);
2054 return kIOReturnNoMemory
;
2057 memset(request
, 0, sizeof(*request
));
2058 request
->options
= options
;
2059 request
->dataType
= kAggressivesRequestTypeRecord
;
2060 request
->data
.record
.type
= (uint32_t) type
;
2061 request
->data
.record
.value
= (uint32_t) value
;
2065 // Update disk quick spindown flag used by getAggressiveness().
2066 // Never merge requests with quick spindown flags set.
2068 if (options
& kAggressivesOptionQuickSpindownEnable
) {
2069 gAggressivesState
|= kAggressivesStateQuickSpindown
;
2070 } else if (options
& kAggressivesOptionQuickSpindownDisable
) {
2071 gAggressivesState
&= ~kAggressivesStateQuickSpindown
;
2073 // Coalesce requests with identical aggressives types.
2074 // Deal with callers that calls us too "aggressively".
2076 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
2078 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
2079 (entry
->data
.record
.type
== type
) &&
2080 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
2081 entry
->data
.record
.value
= (uint32_t) value
;
2089 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2092 AGGRESSIVES_UNLOCK();
2095 IODelete(request
, AggressivesRequest
, 1);
2098 if (options
& kAggressivesOptionSynchronous
) {
2099 handleAggressivesRequests(); // not truly synchronous
2101 thread_call_enter(aggressivesThreadCall
);
2104 return kIOReturnSuccess
;
2107 //******************************************************************************
2108 // getAggressiveness
2110 // Override IOService::setAggressiveness()
2111 // Fetch the aggressiveness factor with the given type.
2112 //******************************************************************************
2115 IOPMrootDomain::getAggressiveness(
2117 unsigned long * outLevel
)
2122 if (!outLevel
|| (type
> UINT_MAX
)) {
2123 return kIOReturnBadArgument
;
2128 // Disk quick spindown in effect, report value = 1
2130 if ((gAggressivesState
& kAggressivesStateQuickSpindown
) &&
2131 (type
== kPMMinutesToSpinDown
)) {
2132 value
= kAggressivesMinValue
;
2136 // Consult the pending request queue.
2139 AggressivesRequest
* entry
;
2141 queue_iterate(&aggressivesQueue
, entry
, AggressivesRequest
*, chain
)
2143 if ((entry
->dataType
== kAggressivesRequestTypeRecord
) &&
2144 (entry
->data
.record
.type
== type
) &&
2145 ((entry
->options
& kAggressivesOptionQuickSpindownMask
) == 0)) {
2146 value
= entry
->data
.record
.value
;
2153 // Consult the backend records.
2155 if (!source
&& aggressivesData
) {
2156 AggressivesRecord
* record
;
2159 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2160 record
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2162 for (i
= 0; i
< count
; i
++, record
++) {
2163 if (record
->type
== type
) {
2164 value
= record
->value
;
2171 AGGRESSIVES_UNLOCK();
2174 *outLevel
= (unsigned long) value
;
2175 return kIOReturnSuccess
;
2177 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type
);
2178 *outLevel
= 0; // default return = 0, driver may not check for error
2179 return kIOReturnInvalid
;
2183 //******************************************************************************
2184 // joinAggressiveness
2186 // Request from IOService to join future aggressiveness broadcasts.
2187 //******************************************************************************
2190 IOPMrootDomain::joinAggressiveness(
2191 IOService
* service
)
2193 AggressivesRequest
* request
;
2195 if (!service
|| (service
== this)) {
2196 return kIOReturnBadArgument
;
2199 DEBUG_LOG("joinAggressiveness %s %p\n", service
->getName(), OBFUSCATE(service
));
2201 request
= IONew(AggressivesRequest
, 1);
2203 return kIOReturnNoMemory
;
2206 memset(request
, 0, sizeof(*request
));
2207 request
->dataType
= kAggressivesRequestTypeService
;
2208 request
->data
.service
.reset(service
, OSRetain
); // released by synchronizeAggressives()
2211 queue_enter(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2212 AGGRESSIVES_UNLOCK();
2214 thread_call_enter(aggressivesThreadCall
);
2216 return kIOReturnSuccess
;
2219 //******************************************************************************
2220 // handleAggressivesRequests
2222 // Backend thread processes all incoming aggressiveness requests in the queue.
2223 //******************************************************************************
2226 handleAggressivesFunction(
2227 thread_call_param_t param1
,
2228 thread_call_param_t param2
)
2231 ((IOPMrootDomain
*) param1
)->handleAggressivesRequests();
2236 IOPMrootDomain::handleAggressivesRequests( void )
2238 AggressivesRecord
* start
;
2239 AggressivesRecord
* record
;
2240 AggressivesRequest
* request
;
2241 queue_head_t joinedQueue
;
2245 bool pingSelf
= false;
2249 if ((gAggressivesState
& kAggressivesStateBusy
) || !aggressivesData
||
2250 queue_empty(&aggressivesQueue
)) {
2254 gAggressivesState
|= kAggressivesStateBusy
;
2255 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2256 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2260 queue_init(&joinedQueue
);
2263 // Remove request from the incoming queue in FIFO order.
2264 queue_remove_first(&aggressivesQueue
, request
, AggressivesRequest
*, chain
);
2265 switch (request
->dataType
) {
2266 case kAggressivesRequestTypeRecord
:
2267 // Update existing record if found.
2269 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2270 if (record
->type
== request
->data
.record
.type
) {
2273 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2274 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2276 record
->flags
|= (kAggressivesRecordFlagMinValue
|
2277 kAggressivesRecordFlagModified
);
2278 DLOG("disk spindown accelerated, was %u min\n",
2281 } else if (request
->options
& kAggressivesOptionQuickSpindownDisable
) {
2282 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2284 record
->flags
|= kAggressivesRecordFlagModified
;
2285 record
->flags
&= ~kAggressivesRecordFlagMinValue
;
2286 DLOG("disk spindown restored to %u min\n",
2289 } else if (record
->value
!= request
->data
.record
.value
) {
2290 record
->value
= request
->data
.record
.value
;
2291 if ((record
->flags
& kAggressivesRecordFlagMinValue
) == 0) {
2293 record
->flags
|= kAggressivesRecordFlagModified
;
2300 // No matching record, append a new record.
2302 ((request
->options
& kAggressivesOptionQuickSpindownDisable
) == 0)) {
2303 AggressivesRecord newRecord
;
2305 newRecord
.flags
= kAggressivesRecordFlagModified
;
2306 newRecord
.type
= request
->data
.record
.type
;
2307 newRecord
.value
= request
->data
.record
.value
;
2308 if (request
->options
& kAggressivesOptionQuickSpindownEnable
) {
2309 newRecord
.flags
|= kAggressivesRecordFlagMinValue
;
2310 DLOG("disk spindown accelerated\n");
2313 aggressivesData
->appendBytes(&newRecord
, sizeof(newRecord
));
2315 // OSData may have switched to another (larger) buffer.
2316 count
= aggressivesData
->getLength() / sizeof(AggressivesRecord
);
2317 start
= (AggressivesRecord
*) aggressivesData
->getBytesNoCopy();
2321 // Finished processing the request, release it.
2322 IODelete(request
, AggressivesRequest
, 1);
2325 case kAggressivesRequestTypeService
:
2326 // synchronizeAggressives() will free request.
2327 queue_enter(&joinedQueue
, request
, AggressivesRequest
*, chain
);
2331 panic("bad aggressives request type %x\n", request
->dataType
);
2334 } while (!queue_empty(&aggressivesQueue
));
2336 // Release the lock to perform work, with busy flag set.
2337 if (!queue_empty(&joinedQueue
) || broadcast
) {
2338 AGGRESSIVES_UNLOCK();
2339 if (!queue_empty(&joinedQueue
)) {
2340 synchronizeAggressives(&joinedQueue
, start
, count
);
2343 broadcastAggressives(start
, count
);
2348 // Remove the modified flag from all records.
2349 for (i
= 0, record
= start
; i
< count
; i
++, record
++) {
2350 if ((record
->flags
& kAggressivesRecordFlagModified
) &&
2351 ((record
->type
== kPMMinutesToDim
) ||
2352 (record
->type
== kPMMinutesToSleep
))) {
2356 record
->flags
&= ~kAggressivesRecordFlagModified
;
2359 // Check the incoming queue again since new entries may have been
2360 // added while lock was released above.
2361 } while (!queue_empty(&aggressivesQueue
));
2363 gAggressivesState
&= ~kAggressivesStateBusy
;
2366 AGGRESSIVES_UNLOCK();
2368 // Root domain is interested in system and display sleep slider changes.
2369 // Submit a power event to handle those changes on the PM work loop.
2371 if (pingSelf
&& pmPowerStateQueue
) {
2372 pmPowerStateQueue
->submitPowerEvent(
2373 kPowerEventPolicyStimulus
,
2374 (void *) kStimulusAggressivenessChanged
);
2378 //******************************************************************************
2379 // synchronizeAggressives
2381 // Push all known aggressiveness records to one or more IOService.
2382 //******************************************************************************
2385 IOPMrootDomain::synchronizeAggressives(
2386 queue_head_t
* joinedQueue
,
2387 const AggressivesRecord
* array
,
2390 OSSharedPtr
<IOService
> service
;
2391 AggressivesRequest
* request
;
2392 const AggressivesRecord
* record
;
2393 IOPMDriverCallEntry callEntry
;
2397 while (!queue_empty(joinedQueue
)) {
2398 queue_remove_first(joinedQueue
, request
, AggressivesRequest
*, chain
);
2399 if (request
->dataType
== kAggressivesRequestTypeService
) {
2400 // retained by joinAggressiveness(), so take ownership
2401 service
= os::move(request
->data
.service
);
2406 IODelete(request
, AggressivesRequest
, 1);
2410 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2411 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2412 value
= record
->value
;
2413 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2414 value
= kAggressivesMinValue
;
2417 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2418 record
->type
, value
, service
->getName());
2419 service
->setAggressiveness(record
->type
, value
);
2421 service
->deassertPMDriverCall(&callEntry
);
2427 //******************************************************************************
2428 // broadcastAggressives
2430 // Traverse PM tree and call setAggressiveness() for records that have changed.
2431 //******************************************************************************
2434 IOPMrootDomain::broadcastAggressives(
2435 const AggressivesRecord
* array
,
2438 OSSharedPtr
<IORegistryIterator
> iter
;
2439 IORegistryEntry
*entry
;
2440 OSSharedPtr
<IORegistryEntry
> child
;
2441 IOPowerConnection
*connect
;
2443 const AggressivesRecord
*record
;
2444 IOPMDriverCallEntry callEntry
;
2448 iter
= IORegistryIterator::iterateOver(
2449 this, gIOPowerPlane
, kIORegistryIterateRecursively
);
2452 // !! reset the iterator
2454 while ((entry
= iter
->getNextObject())) {
2455 connect
= OSDynamicCast(IOPowerConnection
, entry
);
2456 if (!connect
|| !connect
->getReadyFlag()) {
2460 child
= connect
->copyChildEntry(gIOPowerPlane
);
2462 if ((service
= OSDynamicCast(IOService
, child
.get()))) {
2463 if (service
->assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetAggressive
)) {
2464 for (i
= 0, record
= array
; i
< count
; i
++, record
++) {
2465 if (record
->flags
& kAggressivesRecordFlagModified
) {
2466 value
= record
->value
;
2467 if (record
->flags
& kAggressivesRecordFlagMinValue
) {
2468 value
= kAggressivesMinValue
;
2470 _LOG("broadcastAggressives %x = %u to %s\n",
2471 record
->type
, value
, service
->getName());
2472 service
->setAggressiveness(record
->type
, value
);
2475 service
->deassertPMDriverCall(&callEntry
);
2480 }while (!entry
&& !iter
->isValid());
2484 //*****************************************
2485 // stackshot on power button press
2486 // ***************************************
2488 powerButtonDownCallout(thread_call_param_t us
, thread_call_param_t
)
2490 /* Power button pressed during wake
2493 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2494 ((IOPMrootDomain
*)us
)->takeStackshot(false);
2498 powerButtonUpCallout(thread_call_param_t us
, thread_call_param_t
)
2500 /* Power button released.
2501 * Delete any stackshot data
2503 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2504 ((IOPMrootDomain
*)us
)->deleteStackshot();
2506 //*************************************************************************
2510 // MARK: System Sleep
2512 //******************************************************************************
2513 // startIdleSleepTimer
2515 //******************************************************************************
2518 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds
)
2520 AbsoluteTime deadline
;
2524 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag
);
2528 clock_interval_to_deadline(inSeconds
, kSecondScale
, &deadline
);
2529 thread_call_enter_delayed(extraSleepTimer
, deadline
);
2530 idleSleepTimerPending
= true;
2532 thread_call_enter(extraSleepTimer
);
2534 DLOG("idle timer set for %u seconds\n", inSeconds
);
2537 //******************************************************************************
2538 // cancelIdleSleepTimer
2540 //******************************************************************************
2543 IOPMrootDomain::cancelIdleSleepTimer( void )
2546 if (idleSleepTimerPending
) {
2547 DLOG("idle timer cancelled\n");
2548 thread_call_cancel(extraSleepTimer
);
2549 idleSleepTimerPending
= false;
2551 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
2553 clock_usec_t microsecs
;
2554 clock_get_uptime(&now
);
2555 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
2556 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
2557 if (assertOnWakeReport
) {
2558 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
2559 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
2565 //******************************************************************************
2566 // idleSleepTimerExpired
2568 //******************************************************************************
2571 idleSleepTimerExpired(
2572 thread_call_param_t us
, thread_call_param_t
)
2574 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
2577 //******************************************************************************
2578 // handleSleepTimerExpiration
2580 // The time between the sleep idle timeout and the next longest one has elapsed.
2581 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2582 //******************************************************************************
2585 IOPMrootDomain::handleSleepTimerExpiration( void )
2587 if (!gIOPMWorkLoop
->inGate()) {
2588 gIOPMWorkLoop
->runAction(
2589 OSMemberFunctionCast(IOWorkLoop::Action
, this,
2590 &IOPMrootDomain::handleSleepTimerExpiration
),
2595 DLOG("sleep timer expired\n");
2598 idleSleepTimerPending
= false;
2599 setQuickSpinDownTimeout();
2600 adjustPowerState(true);
2603 //******************************************************************************
2604 // getTimeToIdleSleep
2606 // Returns number of seconds left before going into idle sleep.
2607 // Caller has to make sure that idle sleep is allowed at the time of calling
2609 //******************************************************************************
2612 IOPMrootDomain::getTimeToIdleSleep( void )
2614 AbsoluteTime now
, lastActivityTime
;
2616 uint32_t minutesSinceUserInactive
= 0;
2617 uint32_t sleepDelay
= 0;
2619 if (!idleSleepEnabled
) {
2623 if (userActivityTime
) {
2624 lastActivityTime
= userActivityTime
;
2626 lastActivityTime
= userBecameInactiveTime
;
2629 // Ignore any lastActivityTime that predates the last system wake.
2630 // The goal is to avoid a sudden idle sleep right after a dark wake
2631 // due to sleepDelay=0 computed below. The alternative 60s minimum
2632 // timeout should be large enough to allow dark wake to complete,
2633 // at which point the idle timer will be promptly cancelled.
2634 clock_get_uptime(&now
);
2635 if ((CMP_ABSOLUTETIME(&lastActivityTime
, &gIOLastWakeAbsTime
) >= 0) &&
2636 (CMP_ABSOLUTETIME(&now
, &lastActivityTime
) > 0)) {
2637 SUB_ABSOLUTETIME(&now
, &lastActivityTime
);
2638 absolutetime_to_nanoseconds(now
, &nanos
);
2639 minutesSinceUserInactive
= nanos
/ (60000000000ULL);
2641 if (minutesSinceUserInactive
>= sleepSlider
) {
2644 sleepDelay
= sleepSlider
- minutesSinceUserInactive
;
2647 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2648 lastActivityTime
, now
, gIOLastWakeAbsTime
);
2649 sleepDelay
= sleepSlider
;
2652 DLOG("user inactive %u min, time to idle sleep %u min\n",
2653 minutesSinceUserInactive
, sleepDelay
);
2655 return sleepDelay
* 60;
2658 //******************************************************************************
2659 // setQuickSpinDownTimeout
2661 //******************************************************************************
2664 IOPMrootDomain::setQuickSpinDownTimeout( void )
2668 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownEnable
);
2671 //******************************************************************************
2672 // restoreUserSpinDownTimeout
2674 //******************************************************************************
2677 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2681 kPMMinutesToSpinDown
, 0, kAggressivesOptionQuickSpindownDisable
);
2684 //******************************************************************************
2687 //******************************************************************************
2691 IOPMrootDomain::sleepSystem( void )
2693 return sleepSystemOptions(NULL
);
2698 IOPMrootDomain::sleepSystemOptions( OSDictionary
*options
)
2700 OSObject
*obj
= NULL
;
2701 OSString
*reason
= NULL
;
2702 /* sleepSystem is a public function, and may be called by any kernel driver.
2703 * And that's bad - drivers should sleep the system by calling
2704 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2706 * Note that user space app calls to IOPMSleepSystem() will also travel
2707 * this code path and thus be correctly identified as software sleeps.
2710 if (options
&& options
->getObject("OSSwitch")) {
2711 // Log specific sleep cause for OS Switch hibernation
2712 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate
);
2715 if (options
&& (obj
= options
->getObject("Sleep Reason"))) {
2716 reason
= OSDynamicCast(OSString
, obj
);
2717 if (reason
&& reason
->isEqualTo(kIOPMDarkWakeThermalEmergencyKey
)) {
2718 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency
);
2720 if (reason
&& reason
->isEqualTo(kIOPMNotificationWakeExitKey
)) {
2721 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit
);
2725 return privateSleepSystem( kIOPMSleepReasonSoftware
);
2730 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason
)
2732 /* Called from both gated and non-gated context */
2734 if (!checkSystemSleepEnabled() || !pmPowerStateQueue
) {
2735 return kIOReturnNotPermitted
;
2738 pmPowerStateQueue
->submitPowerEvent(
2739 kPowerEventPolicyStimulus
,
2740 (void *) kStimulusDemandSystemSleep
,
2743 return kIOReturnSuccess
;
2746 //******************************************************************************
2749 // This overrides powerChangeDone in IOService.
2750 //******************************************************************************
2752 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState
)
2754 #if !__i386__ && !__x86_64__
2755 uint64_t timeSinceReset
= 0;
2758 unsigned long newState
;
2760 clock_usec_t microsecs
;
2761 uint32_t lastDebugWakeSeconds
;
2762 clock_sec_t adjWakeTime
;
2763 IOPMCalendarStruct nowCalendar
;
2766 newState
= getPowerState();
2767 DLOG("PowerChangeDone: %s->%s\n",
2768 getPowerStateString((uint32_t) previousPowerState
), getPowerStateString((uint32_t) getPowerState()));
2770 if (previousPowerState
== newState
) {
2774 notifierThread
= current_thread();
2775 switch (getPowerState()) {
2777 if (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
) {
2780 PEGetUTCTimeOfDay(&secs
, µsecs
);
2783 if ((kIOPMAOTModeRespectTimers
& _aotMode
) && (_calendarWakeAlarmUTC
< _aotWakeTimeUTC
)) {
2784 IOLog("use _calendarWakeAlarmUTC\n");
2785 adjWakeTime
= _calendarWakeAlarmUTC
;
2786 } else if (_aotExit
|| (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
)) {
2787 IOLog("accelerate _aotWakeTime for exit\n");
2789 } else if (kIOPMDriverAssertionLevelOn
== getPMAssertionLevel(kIOPMDriverAssertionCPUBit
)) {
2790 IOLog("accelerate _aotWakeTime for assertion\n");
2794 IOPMConvertSecondsToCalendar(adjWakeTime
, &_aotWakeTimeCalendar
);
2797 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2798 IOLog("aotSleep at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2800 IOReturn __unused ret
= setMaintenanceWakeCalendar(&_aotWakeTimeCalendar
);
2801 assert(kIOReturnSuccess
== ret
);
2803 if (_aotLastWakeTime
) {
2804 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
2805 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
2806 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
2808 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
2811 _aotPendingFlags
&= ~kIOPMWakeEventAOTPerCycleFlags
;
2812 if (_aotTimerScheduled
) {
2813 _aotTimerES
->cancelTimeout();
2814 _aotTimerScheduled
= false;
2816 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable
);
2818 // re-enable this timer for next sleep
2819 cancelIdleSleepTimer();
2821 if (clamshellExists
) {
2822 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2823 if (gClamshellFlags
& kClamshell_WAR_58009435
) {
2824 // Disable clamshell sleep until system has completed full wake.
2825 // This prevents a system sleep request (due to a clamshell close)
2826 // from being queued until the end of system full wake - even if
2827 // other clamshell disable bits outside of our control is wrong.
2828 setClamShellSleepDisable(true, kClamshellSleepDisableInternal
);
2832 // Log the last known clamshell state before system sleep
2833 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2834 clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
,
2835 desktopMode
, acAdaptorConnected
);
2838 clock_get_calendar_absolute_and_microtime(&secs
, µsecs
, &now
);
2840 gIOLastSleepTime
.tv_sec
= secs
;
2841 gIOLastSleepTime
.tv_usec
= microsecs
;
2842 if (!_aotLastWakeTime
) {
2843 gIOLastUserSleepTime
= gIOLastSleepTime
;
2846 gIOLastWakeTime
.tv_sec
= 0;
2847 gIOLastWakeTime
.tv_usec
= 0;
2848 gIOLastSleepAbsTime
= now
;
2850 if (wake2DarkwakeDelay
&& sleepDelaysReport
) {
2851 clock_sec_t wake2DarkwakeSecs
, darkwake2SleepSecs
;
2852 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2854 SUB_ABSOLUTETIME(&now
, &ts_sleepStart
);
2855 absolutetime_to_microtime(now
, &darkwake2SleepSecs
, µsecs
);
2856 absolutetime_to_microtime(wake2DarkwakeDelay
, &wake2DarkwakeSecs
, µsecs
);
2857 HISTREPORT_TALLYVALUE(sleepDelaysReport
,
2858 (int64_t)(wake2DarkwakeSecs
+ darkwake2SleepSecs
));
2860 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs
, (unsigned long)darkwake2SleepSecs
);
2861 wake2DarkwakeDelay
= 0;
2864 LOG("System %sSleep\n", gIOHibernateState
? "Safe" : "");
2866 IOHibernateSystemHasSlept();
2868 evaluateSystemSleepPolicyFinal();
2870 LOG("System Sleep\n");
2872 if (thermalWarningState
) {
2873 OSSharedPtr
<const OSSymbol
> event
= OSSymbol::withCString(kIOPMThermalLevelWarningKey
);
2875 systemPowerEventOccurred(event
.get(), kIOPMThermalLevelUnknown
);
2878 assertOnWakeSecs
= 0;
2879 lowBatteryCondition
= false;
2880 thermalEmergencyState
= false;
2882 #if DEVELOPMENT || DEBUG
2883 extern int g_should_log_clock_adjustments
;
2884 if (g_should_log_clock_adjustments
) {
2885 clock_sec_t secs
= 0;
2886 clock_usec_t microsecs
= 0;
2887 uint64_t now_b
= mach_absolute_time();
2891 PEGetUTCTimeOfDay(&secs
, µsecs
);
2893 uint64_t now_a
= mach_absolute_time();
2894 os_log(OS_LOG_DEFAULT
, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2895 __func__
, (unsigned long)secs
, microsecs
, now_b
, now_a
);
2899 getPlatform()->sleepKernel();
2901 // The CPU(s) are off at this point,
2902 // Code will resume execution here upon wake.
2904 clock_get_uptime(&gIOLastWakeAbsTime
);
2905 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime
);
2906 _highestCapability
= 0;
2909 IOHibernateSystemWake();
2912 // sleep transition complete
2913 gSleepOrShutdownPending
= 0;
2915 // trip the reset of the calendar clock
2916 clock_wakeup_calendar();
2917 clock_get_calendar_microtime(&secs
, µsecs
);
2918 gIOLastWakeTime
.tv_sec
= secs
;
2919 gIOLastWakeTime
.tv_usec
= microsecs
;
2922 if (_aotWakeTimeCalendar
.selector
!= kPMCalendarTypeInvalid
) {
2923 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
2926 PEGetUTCTimeOfDay(&secs
, µsecs
);
2927 IOPMConvertSecondsToCalendar(secs
, &nowCalendar
);
2928 IOLog("aotWake at " YMDTF
" sched: " YMDTF
"\n", YMDT(&nowCalendar
), YMDT(&_aotWakeTimeCalendar
));
2929 _aotMetrics
->sleepCount
++;
2930 _aotLastWakeTime
= gIOLastWakeAbsTime
;
2931 if (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
) {
2932 _aotMetrics
->kernelSleepTime
[_aotMetrics
->sleepCount
- 1]
2933 = (((uint64_t) gIOLastSleepTime
.tv_sec
) << 10) + (gIOLastSleepTime
.tv_usec
/ 1000);
2934 _aotMetrics
->kernelWakeTime
[_aotMetrics
->sleepCount
- 1]
2935 = (((uint64_t) gIOLastWakeTime
.tv_sec
) << 10) + (gIOLastWakeTime
.tv_usec
/ 1000);
2939 if (_aotWakeTimeUTC
<= secs
) {
2940 _aotTestTime
= _aotTestTime
+ _aotTestInterval
;
2942 setWakeTime(_aotTestTime
);
2947 LOG("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
2950 lastSleepReason
= 0;
2952 lastDebugWakeSeconds
= _debugWakeSeconds
;
2953 _debugWakeSeconds
= 0;
2954 _scheduledAlarmMask
= 0;
2955 _nextScheduledAlarmType
= NULL
;
2957 darkWakeExit
= false;
2958 darkWakePowerClamped
= false;
2959 darkWakePostTickle
= false;
2960 darkWakeHibernateError
= false;
2961 darkWakeToSleepASAP
= true;
2962 darkWakeLogClamp
= true;
2963 sleepTimerMaintenance
= false;
2964 sleepToStandby
= false;
2965 wranglerTickled
= false;
2966 userWasActive
= false;
2967 isRTCAlarmWake
= false;
2968 clamshellIgnoreClose
= false;
2969 fullWakeReason
= kFullWakeReasonNone
;
2971 #if defined(__i386__) || defined(__x86_64__)
2972 kdebugTrace(kPMLogSystemWake
, 0, 0, 0);
2974 OSSharedPtr
<OSObject
> wakeTypeProp
= copyProperty(kIOPMRootDomainWakeTypeKey
);
2975 OSSharedPtr
<OSObject
> wakeReasonProp
= copyProperty(kIOPMRootDomainWakeReasonKey
);
2976 OSString
* wakeType
= OSDynamicCast(OSString
, wakeTypeProp
.get());
2977 OSString
* wakeReason
= OSDynamicCast(OSString
, wakeReasonProp
.get());
2979 if (wakeReason
&& (wakeReason
->getLength() >= 2) &&
2980 gWakeReasonString
[0] == '\0') {
2982 // Until the platform driver can claim its wake reasons
2983 strlcat(gWakeReasonString
, wakeReason
->getCStringNoCopy(),
2984 sizeof(gWakeReasonString
));
2985 if (!gWakeReasonSysctlRegistered
) {
2986 gWakeReasonSysctlRegistered
= true;
2991 if (wakeType
&& wakeType
->isEqualTo(kIOPMrootDomainWakeTypeLowBattery
)) {
2992 lowBatteryCondition
= true;
2993 darkWakeMaintenance
= true;
2996 OSSharedPtr
<OSObject
> hibOptionsProp
= copyProperty(kIOHibernateOptionsKey
);
2997 OSNumber
* hibOptions
= OSDynamicCast( OSNumber
, hibOptionsProp
.get());
2998 if (hibernateAborted
|| ((hibOptions
&&
2999 !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)))) {
3000 // Hibernate aborted, or EFI brought up graphics
3001 darkWakeExit
= true;
3002 if (hibernateAborted
) {
3003 DLOG("Hibernation aborted\n");
3005 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions
->unsigned32BitValue());
3010 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeUser
) ||
3011 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
))) {
3012 // User wake or RTC alarm
3013 darkWakeExit
= true;
3014 if (wakeType
->isEqualTo(kIOPMRootDomainWakeTypeAlarm
)) {
3015 isRTCAlarmWake
= true;
3017 } else if (wakeType
&&
3018 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer
)) {
3019 // SMC standby timer trumps SleepX
3020 darkWakeMaintenance
= true;
3021 sleepTimerMaintenance
= true;
3022 } else if ((lastDebugWakeSeconds
!= 0) &&
3023 ((gDarkWakeFlags
& kDarkWakeFlagAlarmIsDark
) == 0)) {
3024 // SleepX before maintenance
3025 darkWakeExit
= true;
3026 } else if (wakeType
&&
3027 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeMaintenance
)) {
3028 darkWakeMaintenance
= true;
3029 } else if (wakeType
&&
3030 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeSleepService
)) {
3031 darkWakeMaintenance
= true;
3032 darkWakeSleepService
= true;
3034 if (kIOHibernateStateWakingFromHibernate
== gIOHibernateState
) {
3035 sleepToStandby
= true;
3038 } else if (wakeType
&&
3039 wakeType
->isEqualTo(kIOPMRootDomainWakeTypeHibernateError
)) {
3040 darkWakeMaintenance
= true;
3041 darkWakeHibernateError
= true;
3043 // Unidentified wake source, resume to full wake if debug
3044 // alarm is pending.
3046 if (lastDebugWakeSeconds
&&
3047 (!wakeReason
|| wakeReason
->isEqualTo(""))) {
3048 darkWakeExit
= true;
3054 darkWakeToSleepASAP
= false;
3055 fullWakeReason
= kFullWakeReasonLocalUser
;
3057 } else if (displayPowerOnRequested
&& checkSystemCanSustainFullWake()) {
3058 handleSetDisplayPowerOn(true);
3059 } else if (!darkWakeMaintenance
) {
3060 // Early/late tickle for non-maintenance wake.
3061 if ((gDarkWakeFlags
& kDarkWakeFlagPromotionMask
) != kDarkWakeFlagPromotionNone
) {
3062 darkWakePostTickle
= true;
3065 #else /* !__i386__ && !__x86_64__ */
3066 timeSinceReset
= ml_get_time_since_reset();
3067 kdebugTrace(kPMLogSystemWake
, 0, (uintptr_t)(timeSinceReset
>> 32), (uintptr_t) timeSinceReset
);
3069 if ((gDarkWakeFlags
& kDarkWakeFlagPromotionMask
) == kDarkWakeFlagPromotionEarly
) {
3070 wranglerTickled
= true;
3071 fullWakeReason
= kFullWakeReasonLocalUser
;
3072 requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3073 } else if ((lastDebugWakeSeconds
!= 0) && !(gDarkWakeFlags
& kDarkWakeFlagAlarmIsDark
)) {
3074 isRTCAlarmWake
= true;
3075 fullWakeReason
= kFullWakeReasonLocalUser
;
3076 requestUserActive(this, "RTC debug alarm");
3079 OSSharedPtr
<OSObject
> hibOptionsProp
= copyProperty(kIOHibernateOptionsKey
);
3080 OSNumber
* hibOptions
= OSDynamicCast(OSNumber
, hibOptionsProp
.get());
3081 if (hibOptions
&& !(hibOptions
->unsigned32BitValue() & kIOHibernateOptionDarkWake
)) {
3082 fullWakeReason
= kFullWakeReasonLocalUser
;
3083 requestUserActive(this, "hibernate user wake");
3088 // stay awake for at least 30 seconds
3089 startIdleSleepTimer(30);
3093 thread_call_enter(updateConsoleUsersEntry
);
3095 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake
);
3098 #if !__i386__ && !__x86_64__
3102 DLOG("Force re-evaluating aggressiveness\n");
3103 /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3104 pmPowerStateQueue
->submitPowerEvent(
3105 kPowerEventPolicyStimulus
,
3106 (void *) kStimulusNoIdleSleepPreventers
);
3108 // After changing to ON_STATE, invalidate any previously queued
3109 // request to change to a state less than ON_STATE. This isn't
3110 // necessary for AOT_STATE or if the device has only one running
3111 // state since the changePowerStateToPriv() issued at the tail
3112 // end of SLEEP_STATE case should take care of that.
3113 if (getPowerState() == ON_STATE
) {
3114 changePowerStateWithTagToPriv(ON_STATE
, kCPSReasonWake
);
3118 #endif /* !__i386__ && !__x86_64__ */
3120 notifierThread
= NULL
;
3123 //******************************************************************************
3124 // requestPowerDomainState
3126 // Extend implementation in IOService. Running on PM work loop thread.
3127 //******************************************************************************
3130 IOPMrootDomain::requestPowerDomainState(
3131 IOPMPowerFlags childDesire
,
3132 IOPowerConnection
* childConnection
,
3133 unsigned long specification
)
3135 // Idle and system sleep prevention flags affects driver desire.
3136 // Children desire are irrelevant so they are cleared.
3138 return super::requestPowerDomainState(0, childConnection
, specification
);
3143 makeSleepPreventersListLog(const OSSharedPtr
<OSSet
> &preventers
, char *buf
, size_t buf_size
)
3145 if (!preventers
->getCount()) {
3149 char *buf_iter
= buf
+ strlen(buf
);
3150 char *buf_end
= buf
+ buf_size
;
3152 OSSharedPtr
<OSCollectionIterator
> iterator
= OSCollectionIterator::withCollection(preventers
.get());
3153 OSObject
*obj
= NULL
;
3155 while ((obj
= iterator
->getNextObject())) {
3156 IOService
*srv
= OSDynamicCast(IOService
, obj
);
3157 if (buf_iter
< buf_end
) {
3158 buf_iter
+= snprintf(buf_iter
, buf_end
- buf_iter
, " %s", srv
->getName());
3160 DLOG("Print buffer exhausted for sleep preventers list\n");
3166 //******************************************************************************
3167 // updatePreventIdleSleepList
3169 // Called by IOService on PM work loop.
3170 // Returns true if PM policy recognized the driver's desire to prevent idle
3171 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3172 //******************************************************************************
3175 IOPMrootDomain::updatePreventIdleSleepList(
3176 IOService
* service
, bool addNotRemove
)
3178 unsigned int oldCount
;
3180 oldCount
= idleSleepPreventersCount();
3181 return updatePreventIdleSleepListInternal(service
, addNotRemove
, oldCount
);
3185 IOPMrootDomain::updatePreventIdleSleepListInternal(
3186 IOService
* service
, bool addNotRemove
, unsigned int oldCount
)
3188 unsigned int newCount
;
3192 #if defined(XNU_TARGET_OS_OSX)
3193 // Only the display wrangler and no-idle-sleep kernel assertions
3194 // can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3195 // reported by drivers in their power state table is ignored.
3196 if (service
&& (service
!= wrangler
) && (service
!= this)) {
3203 preventIdleSleepList
->setObject(service
);
3204 DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3205 service
->getName(), preventIdleSleepList
->getCount());
3206 } else if (preventIdleSleepList
->member(service
)) {
3207 preventIdleSleepList
->removeObject(service
);
3208 DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3209 service
->getName(), preventIdleSleepList
->getCount());
3212 if (preventIdleSleepList
->getCount()) {
3213 char buf
[256] = "Idle Sleep Preventers:";
3214 makeSleepPreventersListLog(preventIdleSleepList
, buf
, sizeof(buf
));
3219 newCount
= idleSleepPreventersCount();
3221 if ((oldCount
== 0) && (newCount
!= 0)) {
3222 // Driver added to empty prevent list.
3223 // Update the driver desire to prevent idle sleep.
3224 // Driver desire does not prevent demand sleep.
3226 changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent
);
3227 } else if ((oldCount
!= 0) && (newCount
== 0)) {
3228 // Last driver removed from prevent list.
3229 // Drop the driver clamp to allow idle sleep.
3231 changePowerStateWithTagTo(SLEEP_STATE
, kCPSReasonIdleSleepAllow
);
3232 evaluatePolicy( kStimulusNoIdleSleepPreventers
);
3234 messageClient(kIOPMMessageIdleSleepPreventers
, systemCapabilityNotifier
.get(),
3235 &newCount
, sizeof(newCount
));
3237 #if defined(XNU_TARGET_OS_OSX)
3238 if (addNotRemove
&& (service
== wrangler
) && !checkSystemCanSustainFullWake()) {
3239 DLOG("Cannot cancel idle sleep\n");
3240 return false; // do not idle-cancel
3247 //******************************************************************************
3249 //******************************************************************************
3252 IOPMrootDomain::startSpinDump(uint32_t spindumpKind
)
3254 messageClients(kIOPMMessageLaunchBootSpinDump
, (void *)(uintptr_t)spindumpKind
);
3257 //******************************************************************************
3258 // preventSystemSleepListUpdate
3260 // Called by IOService on PM work loop.
3261 //******************************************************************************
3264 IOPMrootDomain::updatePreventSystemSleepList(
3265 IOService
* service
, bool addNotRemove
)
3267 unsigned int oldCount
, newCount
;
3270 if (this == service
) {
3274 oldCount
= preventSystemSleepList
->getCount();
3276 preventSystemSleepList
->setObject(service
);
3277 DLOG("Added %s to system sleep preventers list (Total %u)\n",
3278 service
->getName(), preventSystemSleepList
->getCount());
3279 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
3281 clock_usec_t microsecs
;
3282 clock_get_uptime(&now
);
3283 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
3284 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
3285 if (assertOnWakeReport
) {
3286 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
3287 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
3290 } else if (preventSystemSleepList
->member(service
)) {
3291 preventSystemSleepList
->removeObject(service
);
3292 DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3293 service
->getName(), preventSystemSleepList
->getCount());
3295 if ((oldCount
!= 0) && (preventSystemSleepList
->getCount() == 0)) {
3296 // Lost all system sleep preventers.
3297 // Send stimulus if system sleep was blocked, and is in dark wake.
3298 evaluatePolicy( kStimulusDarkWakeEvaluate
);
3302 newCount
= preventSystemSleepList
->getCount();
3304 char buf
[256] = "System Sleep Preventers:";
3305 makeSleepPreventersListLog(preventSystemSleepList
, buf
, sizeof(buf
));
3309 messageClient(kIOPMMessageSystemSleepPreventers
, systemCapabilityNotifier
.get(),
3310 &newCount
, sizeof(newCount
));
3314 IOPMrootDomain::copySleepPreventersList(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3316 OSSharedPtr
<OSCollectionIterator
> iterator
;
3317 OSObject
*object
= NULL
;
3318 OSSharedPtr
<OSArray
> array
;
3320 if (!gIOPMWorkLoop
->inGate()) {
3321 gIOPMWorkLoop
->runAction(
3322 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3323 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList
),
3324 this, (void *)idleSleepList
, (void *)systemSleepList
);
3328 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3329 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
.get());
3330 array
= OSArray::withCapacity(5);
3332 if (iterator
&& array
) {
3333 while ((object
= iterator
->getNextObject())) {
3334 IOService
*service
= OSDynamicCast(IOService
, object
);
3336 OSSharedPtr
<const OSSymbol
> name
= service
->copyName();
3338 array
->setObject(name
.get());
3343 *idleSleepList
= array
.detach();
3346 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3347 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
.get());
3348 array
= OSArray::withCapacity(5);
3350 if (iterator
&& array
) {
3351 while ((object
= iterator
->getNextObject())) {
3352 IOService
*service
= OSDynamicCast(IOService
, object
);
3354 OSSharedPtr
<const OSSymbol
> name
= service
->copyName();
3356 array
->setObject(name
.get());
3361 *systemSleepList
= array
.detach();
3366 IOPMrootDomain::copySleepPreventersListWithID(OSArray
**idleSleepList
, OSArray
**systemSleepList
)
3368 OSSharedPtr
<OSCollectionIterator
> iterator
;
3369 OSObject
*object
= NULL
;
3370 OSSharedPtr
<OSArray
> array
;
3372 if (!gIOPMWorkLoop
->inGate()) {
3373 gIOPMWorkLoop
->runAction(
3374 OSMemberFunctionCast(IOWorkLoop::Action
, this,
3375 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID
),
3376 this, (void *)idleSleepList
, (void *)systemSleepList
);
3380 if (idleSleepList
&& preventIdleSleepList
&& (preventIdleSleepList
->getCount() != 0)) {
3381 iterator
= OSCollectionIterator::withCollection(preventIdleSleepList
.get());
3382 array
= OSArray::withCapacity(5);
3384 if (iterator
&& array
) {
3385 while ((object
= iterator
->getNextObject())) {
3386 IOService
*service
= OSDynamicCast(IOService
, object
);
3388 OSSharedPtr
<OSDictionary
> dict
= OSDictionary::withCapacity(2);
3389 OSSharedPtr
<const OSSymbol
> name
= service
->copyName();
3390 OSSharedPtr
<OSNumber
> id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3391 if (dict
&& name
&& id
) {
3392 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
.get());
3393 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, name
.get());
3394 array
->setObject(dict
.get());
3399 *idleSleepList
= array
.detach();
3402 if (systemSleepList
&& preventSystemSleepList
&& (preventSystemSleepList
->getCount() != 0)) {
3403 iterator
= OSCollectionIterator::withCollection(preventSystemSleepList
.get());
3404 array
= OSArray::withCapacity(5);
3406 if (iterator
&& array
) {
3407 while ((object
= iterator
->getNextObject())) {
3408 IOService
*service
= OSDynamicCast(IOService
, object
);
3410 OSSharedPtr
<OSDictionary
> dict
= OSDictionary::withCapacity(2);
3411 OSSharedPtr
<const OSSymbol
> name
= service
->copyName();
3412 OSSharedPtr
<OSNumber
> id
= OSNumber::withNumber(service
->getRegistryEntryID(), 64);
3413 if (dict
&& name
&& id
) {
3414 dict
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, id
.get());
3415 dict
->setObject(kIOPMDriverAssertionOwnerStringKey
, name
.get());
3416 array
->setObject(dict
.get());
3421 *systemSleepList
= array
.detach();
3425 //******************************************************************************
3428 // Override the superclass implementation to send a different message type.
3429 //******************************************************************************
3432 IOPMrootDomain::tellChangeDown( unsigned long stateNum
)
3434 DLOG("tellChangeDown %s->%s\n",
3435 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3437 if (SLEEP_STATE
== stateNum
) {
3438 // Legacy apps were already told in the full->dark transition
3439 if (!ignoreTellChangeDown
) {
3440 tracePoint( kIOPMTracePointSleepApplications
);
3442 tracePoint( kIOPMTracePointSleepPriorityClients
);
3446 if (!ignoreTellChangeDown
) {
3447 userActivityAtSleep
= userActivityCount
;
3448 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep
);
3450 if (SLEEP_STATE
== stateNum
) {
3451 hibernateAborted
= false;
3453 // Direct callout into OSKext so it can disable kext unloads
3454 // during sleep/wake to prevent deadlocks.
3455 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep
);
3457 IOService::updateConsoleUsers(NULL
, kIOMessageSystemWillSleep
);
3459 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3460 // But tellClientsWithResponse() must be called for both.
3461 ignoreTellChangeDown
= true;
3465 return super::tellClientsWithResponse( kIOMessageSystemWillSleep
);
3468 //******************************************************************************
3471 // Override the superclass implementation to send a different message type.
3472 // This must be idle sleep since we don't ask during any other power change.
3473 //******************************************************************************
3476 IOPMrootDomain::askChangeDown( unsigned long stateNum
)
3478 DLOG("askChangeDown %s->%s\n",
3479 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3481 // Don't log for dark wake entry
3482 if (kSystemTransitionSleep
== _systemTransitionType
) {
3483 tracePoint( kIOPMTracePointSleepApplications
);
3486 return super::tellClientsWithResponse( kIOMessageCanSystemSleep
);
3489 //******************************************************************************
3490 // askChangeDownDone
3492 // An opportunity for root domain to cancel the power transition,
3493 // possibily due to an assertion created by powerd in response to
3494 // kIOMessageCanSystemSleep.
3497 // full -> dark wake transition
3498 // 1. Notify apps and powerd with kIOMessageCanSystemSleep
3499 // 2. askChangeDownDone()
3500 // dark -> sleep transition
3501 // 1. Notify powerd with kIOMessageCanSystemSleep
3502 // 2. askChangeDownDone()
3505 // full -> dark wake transition
3506 // 1. Notify powerd with kIOMessageCanSystemSleep
3507 // 2. askChangeDownDone()
3508 // dark -> sleep transition
3509 // 1. Notify powerd with kIOMessageCanSystemSleep
3510 // 2. askChangeDownDone()
3511 //******************************************************************************
3514 IOPMrootDomain::askChangeDownDone(
3515 IOPMPowerChangeFlags
* inOutChangeFlags
, bool * cancel
)
3517 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3518 *inOutChangeFlags
, *cancel
,
3519 _systemTransitionType
,
3520 _currentCapability
, _pendingCapability
);
3522 if ((false == *cancel
) && (kSystemTransitionSleep
== _systemTransitionType
)) {
3523 // Dark->Sleep transition.
3524 // Check if there are any deny sleep assertions.
3525 // lastSleepReason already set by handleOurPowerChangeStart()
3527 if (!checkSystemCanSleep(lastSleepReason
)) {
3528 // Cancel dark wake to sleep transition.
3529 // Must re-scan assertions upon entering dark wake.
3532 DLOG("cancel dark->sleep\n");
3534 if (_aotMode
&& (kPMCalendarTypeInvalid
!= _aotWakeTimeCalendar
.selector
)) {
3535 uint64_t now
= mach_continuous_time();
3536 if (((now
+ _aotWakePreWindow
) >= _aotWakeTimeContinuous
)
3537 && (now
< (_aotWakeTimeContinuous
+ _aotWakePostWindow
))) {
3539 IOLog("AOT wake window cancel: %qd, %qd\n", now
, _aotWakeTimeContinuous
);
3545 //******************************************************************************
3546 // systemDidNotSleep
3548 // Work common to both canceled or aborted sleep.
3549 //******************************************************************************
3552 IOPMrootDomain::systemDidNotSleep( void )
3554 // reset console lock state
3555 thread_call_enter(updateConsoleUsersEntry
);
3557 if (idleSleepEnabled
) {
3559 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3560 startIdleSleepTimer(kIdleSleepRetryInterval
);
3562 startIdleSleepTimer(idleSeconds
);
3564 } else if (!userIsActive
) {
3565 // Manually start the idle sleep timer besides waiting for
3566 // the user to become inactive.
3567 startIdleSleepTimer(kIdleSleepRetryInterval
);
3571 preventTransitionToUserActive(false);
3572 IOService::setAdvisoryTickleEnable( true );
3574 // After idle revert and cancel, send a did-change message to powerd
3575 // to balance the previous will-change message. Kernel clients do not
3576 // need this since sleep cannot be canceled once they are notified.
3578 if (toldPowerdCapWillChange
&& systemCapabilityNotifier
&&
3579 (_pendingCapability
!= _currentCapability
) &&
3580 ((_systemMessageClientMask
& kSystemMessageClientPowerd
) != 0)) {
3581 // Differs from a real capability gain change where notifyRef != 0,
3582 // but it is zero here since no response is expected.
3584 IOPMSystemCapabilityChangeParameters params
;
3586 bzero(¶ms
, sizeof(params
));
3587 params
.fromCapabilities
= _pendingCapability
;
3588 params
.toCapabilities
= _currentCapability
;
3589 params
.changeFlags
= kIOPMSystemCapabilityDidChange
;
3591 DLOG("MESG cap %x->%x did change\n",
3592 params
.fromCapabilities
, params
.toCapabilities
);
3593 messageClient(kIOMessageSystemCapabilityChange
, systemCapabilityNotifier
.get(),
3594 ¶ms
, sizeof(params
));
3598 //******************************************************************************
3601 // Notify registered applications and kernel clients that we are not dropping
3604 // We override the superclass implementation so we can send a different message
3605 // type to the client or application being notified.
3607 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3608 //******************************************************************************
3611 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum
)
3613 DLOG("tellNoChangeDown %s->%s\n",
3614 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3616 // Sleep canceled, clear the sleep trace point.
3617 tracePoint(kIOPMTracePointSystemUp
);
3619 systemDidNotSleep();
3620 return tellClients( kIOMessageSystemWillNotSleep
);
3623 //******************************************************************************
3626 // Notify registered applications and kernel clients that we are raising power.
3628 // We override the superclass implementation so we can send a different message
3629 // type to the client or application being notified.
3630 //******************************************************************************
3633 IOPMrootDomain::tellChangeUp( unsigned long stateNum
)
3635 DLOG("tellChangeUp %s->%s\n",
3636 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum
));
3638 ignoreTellChangeDown
= false;
3640 if (stateNum
== ON_STATE
) {
3641 // Direct callout into OSKext so it can disable kext unloads
3642 // during sleep/wake to prevent deadlocks.
3643 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
3645 // Notify platform that sleep was cancelled or resumed.
3646 getPlatform()->callPlatformFunction(
3647 sleepMessagePEFunction
.get(), false,
3648 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn
,
3651 if (getPowerState() == ON_STATE
) {
3652 // Sleep was cancelled by idle cancel or revert
3653 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
3654 // rdar://problem/50363791
3655 // If system is in dark wake and sleep is cancelled, do not
3656 // send SystemWillPowerOn/HasPoweredOn messages to kernel
3657 // priority clients. They haven't yet seen a SystemWillSleep
3658 // message before the cancellation. So make sure the kernel
3659 // client bit is cleared in _systemMessageClientMask before
3660 // invoking the tellClients() below. This bit may have been
3661 // set by handleOurPowerChangeStart() anticipating a successful
3662 // sleep and setting the filter mask ahead of time allows the
3663 // SystemWillSleep message to go through.
3664 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
3667 systemDidNotSleep();
3668 tellClients( kIOMessageSystemWillPowerOn
);
3671 tracePoint( kIOPMTracePointWakeApplications
);
3672 tellClients( kIOMessageSystemHasPoweredOn
);
3676 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3677 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3678 ((params)->fromCapabilities & (flag)) && \
3679 (((params)->toCapabilities & (flag)) == 0))
3681 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3682 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3683 ((params)->toCapabilities & (flag)) && \
3684 (((params)->fromCapabilities & (flag)) == 0))
3686 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3687 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3688 ((params)->fromCapabilities & (flag)) && \
3689 (((params)->toCapabilities & (flag)) == 0))
3691 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3692 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3693 ((params)->toCapabilities & (flag)) && \
3694 (((params)->fromCapabilities & (flag)) == 0))
3696 //******************************************************************************
3697 // sysPowerDownHandler
3699 // Perform a vfs sync before system sleep.
3700 //******************************************************************************
3703 IOPMrootDomain::sysPowerDownHandler(
3704 void * target
, void * refCon
,
3705 UInt32 messageType
, IOService
* service
,
3706 void * messageArgs
, vm_size_t argSize
)
3708 static UInt32 lastSystemMessageType
= 0;
3711 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType
));
3713 // rdar://problem/50363791
3714 // Sanity check to make sure the SystemWill/Has message types are
3715 // received in the expected order for all kernel priority clients.
3716 if (messageType
== kIOMessageSystemWillSleep
||
3717 messageType
== kIOMessageSystemWillPowerOn
||
3718 messageType
== kIOMessageSystemHasPoweredOn
) {
3719 switch (messageType
) {
3720 case kIOMessageSystemWillPowerOn
:
3721 assert(lastSystemMessageType
== kIOMessageSystemWillSleep
);
3723 case kIOMessageSystemHasPoweredOn
:
3724 assert(lastSystemMessageType
== kIOMessageSystemWillPowerOn
);
3728 lastSystemMessageType
= messageType
;
3732 return kIOReturnUnsupported
;
3735 if (messageType
== kIOMessageSystemCapabilityChange
) {
3736 IOPMSystemCapabilityChangeParameters
* params
=
3737 (IOPMSystemCapabilityChangeParameters
*) messageArgs
;
3739 // Interested applications have been notified of an impending power
3740 // change and have acked (when applicable).
3741 // This is our chance to save whatever state we can before powering
3743 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3746 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3747 params
->fromCapabilities
, params
->toCapabilities
,
3748 params
->changeFlags
);
3750 if (CAP_WILL_CHANGE_TO_OFF(params
, kIOPMSystemCapabilityCPU
)) {
3751 // We will ack within 20 seconds
3752 params
->maxWaitForReply
= 20 * 1000 * 1000;
3755 gRootDomain
->evaluateSystemSleepPolicyEarly();
3757 // add in time we could spend freeing pages
3758 if (gRootDomain
->hibernateMode
&& !gRootDomain
->hibernateDisabled
) {
3759 params
->maxWaitForReply
= kCapabilityClientMaxWait
;
3761 DLOG("sysPowerDownHandler max wait %d s\n",
3762 (int) (params
->maxWaitForReply
/ 1000 / 1000));
3765 // Notify platform that sleep has begun, after the early
3766 // sleep policy evaluation.
3767 getPlatform()->callPlatformFunction(
3768 sleepMessagePEFunction
.get(), false,
3769 (void *)(uintptr_t) kIOMessageSystemWillSleep
,
3772 if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
)) {
3773 // Purposely delay the ack and hope that shutdown occurs quickly.
3774 // Another option is not to schedule the thread and wait for
3776 AbsoluteTime deadline
;
3777 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
3778 thread_call_enter1_delayed(
3779 gRootDomain
->diskSyncCalloutEntry
,
3780 (thread_call_param_t
)(uintptr_t) params
->notifyRef
,
3784 gRootDomain
->diskSyncCalloutEntry
,
3785 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3789 else if (CAP_DID_CHANGE_TO_ON(params
, kIOPMSystemCapabilityCPU
)) {
3790 // We will ack within 110 seconds
3791 params
->maxWaitForReply
= 110 * 1000 * 1000;
3794 gRootDomain
->diskSyncCalloutEntry
,
3795 (thread_call_param_t
)(uintptr_t) params
->notifyRef
);
3798 ret
= kIOReturnSuccess
;
3804 //******************************************************************************
3805 // handleQueueSleepWakeUUID
3807 // Called from IOPMrootDomain when we're initiating a sleep,
3808 // or indirectly from PM configd when PM decides to clear the UUID.
3809 // PM clears the UUID several minutes after successful wake from sleep,
3810 // so that we might associate App spindumps with the immediately previous
3813 // @param obj has a retain on it. We're responsible for releasing that retain.
3814 //******************************************************************************
3817 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject
*obj
)
3819 OSSharedPtr
<OSString
> str
;
3821 if (kOSBooleanFalse
== obj
) {
3822 handlePublishSleepWakeUUID(false);
3824 str
.reset(OSDynamicCast(OSString
, obj
), OSNoRetain
);
3826 // This branch caches the UUID for an upcoming sleep/wake
3827 queuedSleepWakeUUIDString
= str
;
3828 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString
->getCStringNoCopy());
3832 //******************************************************************************
3833 // handlePublishSleepWakeUUID
3835 // Called from IOPMrootDomain when we're initiating a sleep,
3836 // or indirectly from PM configd when PM decides to clear the UUID.
3837 // PM clears the UUID several minutes after successful wake from sleep,
3838 // so that we might associate App spindumps with the immediately previous
3840 //******************************************************************************
3843 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish
)
3848 * Clear the current UUID
3850 if (gSleepWakeUUIDIsSet
) {
3851 DLOG("SleepWake UUID cleared\n");
3853 gSleepWakeUUIDIsSet
= false;
3855 removeProperty(kIOPMSleepWakeUUIDKey
);
3856 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDCleared
);
3860 * Optionally, publish a new UUID
3862 if (queuedSleepWakeUUIDString
&& shouldPublish
) {
3863 OSSharedPtr
<OSString
> publishThisUUID
;
3865 publishThisUUID
= queuedSleepWakeUUIDString
;
3867 if (publishThisUUID
) {
3868 setProperty(kIOPMSleepWakeUUIDKey
, publishThisUUID
.get());
3871 gSleepWakeUUIDIsSet
= true;
3872 messageClients(kIOPMMessageSleepWakeUUIDChange
, kIOPMMessageSleepWakeUUIDSet
);
3874 queuedSleepWakeUUIDString
.reset();
3878 //******************************************************************************
3879 // IOPMGetSleepWakeUUIDKey
3881 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3882 // To get the full key -- a C string -- the buffer must large enough for
3883 // the end-of-string character.
3884 // The key is expected to be an UUID string
3885 //******************************************************************************
3888 IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
)
3890 if (!gSleepWakeUUIDIsSet
) {
3894 if (buffer
!= NULL
) {
3895 OSSharedPtr
<OSString
> string
=
3896 OSDynamicPtrCast
<OSString
>(gRootDomain
->copyProperty(kIOPMSleepWakeUUIDKey
));
3901 strlcpy(buffer
, string
->getCStringNoCopy(), buf_len
);
3908 //******************************************************************************
3909 // lowLatencyAudioNotify
3911 // Used to send an update about low latency audio activity to interested
3912 // clients. To keep the overhead minimal the OSDictionary used here
3913 // is initialized at boot.
3914 //******************************************************************************
3917 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time
, boolean_t state
)
3919 if (lowLatencyAudioNotifierDict
&& lowLatencyAudioNotifyStateSym
&& lowLatencyAudioNotifyTimestampSym
&&
3920 lowLatencyAudioNotifyStateVal
&& lowLatencyAudioNotifyTimestampVal
) {
3921 lowLatencyAudioNotifyTimestampVal
->setValue(time
);
3922 lowLatencyAudioNotifyStateVal
->setValue(state
);
3923 setPMSetting(gIOPMSettingLowLatencyAudioModeKey
.get(), lowLatencyAudioNotifierDict
.get());
3925 DLOG("LowLatencyAudioNotify error\n");
3930 //******************************************************************************
3931 // IOPMrootDomainRTNotifier
3933 // Used by performance controller to update the timestamp and state associated
3934 // with low latency audio activity in the system.
3935 //******************************************************************************
3938 IOPMrootDomainRTNotifier(uint64_t time
, boolean_t state
)
3940 gRootDomain
->lowLatencyAudioNotify(time
, state
);
3944 //******************************************************************************
3945 // initializeBootSessionUUID
3947 // Initialize the boot session uuid at boot up and sets it into registry.
3948 //******************************************************************************
3951 IOPMrootDomain::initializeBootSessionUUID(void)
3954 uuid_string_t new_uuid_string
;
3956 uuid_generate(new_uuid
);
3957 uuid_unparse_upper(new_uuid
, new_uuid_string
);
3958 memcpy(bootsessionuuid_string
, new_uuid_string
, sizeof(uuid_string_t
));
3960 setProperty(kIOPMBootSessionUUIDKey
, new_uuid_string
);
3963 //******************************************************************************
3964 // Root domain uses the private and tagged changePowerState methods for
3965 // tracking and logging purposes.
3966 //******************************************************************************
3968 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
3971 nextRequestTag( IOPMRequestTag tag
)
3973 static SInt16 msb16
= 1;
3974 uint16_t id
= OSAddAtomic16(1, &msb16
);
3975 return ((uint32_t)id
<< 16) | REQUEST_TAG_TO_REASON(tag
);
3978 // TODO: remove this shim function and exported symbol
3980 IOPMrootDomain::changePowerStateTo( unsigned long ordinal
)
3982 return changePowerStateWithTagTo(ordinal
, kCPSReasonNone
);
3985 // TODO: remove this shim function and exported symbol
3987 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal
)
3989 return changePowerStateWithTagToPriv(ordinal
, kCPSReasonNone
);
3993 IOPMrootDomain::changePowerStateWithOverrideTo(
3994 IOPMPowerStateIndex ordinal
, IOPMRequestTag reason
)
3996 uint32_t tag
= nextRequestTag(reason
);
3997 DLOG("%s(%s, %x)\n", __FUNCTION__
, getPowerStateString((uint32_t) ordinal
), tag
);
3999 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
4000 return kIOReturnUnsupported
;
4003 return super::changePowerStateWithOverrideTo(ordinal
, tag
);
4007 IOPMrootDomain::changePowerStateWithTagTo(
4008 IOPMPowerStateIndex ordinal
, IOPMRequestTag reason
)
4010 uint32_t tag
= nextRequestTag(reason
);
4011 DLOG("%s(%s, %x)\n", __FUNCTION__
, getPowerStateString((uint32_t) ordinal
), tag
);
4013 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
4014 return kIOReturnUnsupported
;
4017 return super::changePowerStateWithTagTo(ordinal
, tag
);
4021 IOPMrootDomain::changePowerStateWithTagToPriv(
4022 IOPMPowerStateIndex ordinal
, IOPMRequestTag reason
)
4024 uint32_t tag
= nextRequestTag(reason
);
4025 DLOG("%s(%s, %x)\n", __FUNCTION__
, getPowerStateString((uint32_t) ordinal
), tag
);
4027 if ((ordinal
!= ON_STATE
) && (ordinal
!= AOT_STATE
) && (ordinal
!= SLEEP_STATE
)) {
4028 return kIOReturnUnsupported
;
4031 return super::changePowerStateWithTagToPriv(ordinal
, tag
);
4034 //******************************************************************************
4037 //******************************************************************************
4040 IOPMrootDomain::activitySinceSleep(void)
4042 return userActivityCount
!= userActivityAtSleep
;
4046 IOPMrootDomain::abortHibernation(void)
4049 // don't allow hibernation to be aborted on ARM due to user activity
4050 // since once ApplePMGR decides we're hibernating, we can't turn back
4051 // see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4054 bool ret
= activitySinceSleep();
4056 if (ret
&& !hibernateAborted
&& checkSystemCanSustainFullWake()) {
4057 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount
, userActivityAtSleep
);
4058 hibernateAborted
= true;
4065 hibernate_should_abort(void)
4068 return gRootDomain
->abortHibernation();
4074 //******************************************************************************
4075 // willNotifyPowerChildren
4077 // Called after all interested drivers have all acknowledged the power change,
4078 // but before any power children is informed. Dispatched though a thread call,
4079 // so it is safe to perform work that might block on a sleeping disk. PM state
4080 // machine (not thread) will block w/o timeout until this function returns.
4081 //******************************************************************************
4084 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState
)
4086 OSSharedPtr
<OSDictionary
> dict
;
4087 OSSharedPtr
<OSNumber
> secs
;
4089 if (SLEEP_STATE
== newPowerState
) {
4090 notifierThread
= current_thread();
4091 if (!tasksSuspended
) {
4092 AbsoluteTime deadline
;
4093 tasksSuspended
= TRUE
;
4094 updateTasksSuspend();
4096 clock_interval_to_deadline(10, kSecondScale
, &deadline
);
4097 #if defined(XNU_TARGET_OS_OSX)
4098 vm_pageout_wait(AbsoluteTime_to_scalar(&deadline
));
4099 #endif /* defined(XNU_TARGET_OS_OSX) */
4102 _aotReadyToFullWake
= false;
4104 if (_aotLingerTime
) {
4106 IOLog("aot linger no return\n");
4107 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
4108 clock_delay_until(deadline
);
4113 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
4115 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
4117 } else if (!_aotNow
&& !_debugWakeSeconds
) {
4120 _aotPendingFlags
= 0;
4121 _aotTasksSuspended
= true;
4122 _aotLastWakeTime
= 0;
4123 bzero(_aotMetrics
, sizeof(IOPMAOTMetrics
));
4124 if (kIOPMAOTModeCycle
& _aotMode
) {
4125 clock_interval_to_absolutetime_interval(60, kSecondScale
, &_aotTestInterval
);
4126 _aotTestTime
= mach_continuous_time() + _aotTestInterval
;
4127 setWakeTime(_aotTestTime
);
4129 uint32_t lingerSecs
;
4130 if (!PE_parse_boot_argn("aotlinger", &lingerSecs
, sizeof(lingerSecs
))) {
4133 clock_interval_to_absolutetime_interval(lingerSecs
, kSecondScale
, &_aotLingerTime
);
4134 clock_interval_to_absolutetime_interval(2000, kMillisecondScale
, &_aotWakePreWindow
);
4135 clock_interval_to_absolutetime_interval(1100, kMillisecondScale
, &_aotWakePostWindow
);
4139 IOHibernateSystemSleep();
4140 IOHibernateIOKitSleep();
4142 if (gRootDomain
->activitySinceSleep()) {
4143 dict
= OSDictionary::withCapacity(1);
4144 secs
= OSNumber::withNumber(1, 32);
4147 dict
->setObject(gIOPMSettingDebugWakeRelativeKey
.get(), secs
.get());
4148 gRootDomain
->setProperties(dict
.get());
4149 MSG("Reverting sleep with relative wake\n");
4153 notifierThread
= NULL
;
4157 //******************************************************************************
4158 // willTellSystemCapabilityDidChange
4160 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4161 // domain is raising its power state, immediately after notifying interested
4162 // drivers and power children.
4163 //******************************************************************************
4166 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4168 if ((_systemTransitionType
== kSystemTransitionWake
) &&
4169 !CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
4170 // After powering up drivers, dark->full promotion on the current wake
4171 // transition is no longer possible. That is because the next machine
4172 // state will issue the system capability change messages.
4173 // The darkWakePowerClamped flag may already be set if the system has
4174 // at least one driver that was power clamped due to dark wake.
4175 // This function sets the darkWakePowerClamped flag in case there
4176 // is no power-clamped driver in the system.
4178 // Last opportunity to exit dark wake using:
4179 // requestFullWake( kFullWakeReasonLocalUser );
4181 if (!darkWakePowerClamped
) {
4182 if (darkWakeLogClamp
) {
4186 clock_get_uptime(&now
);
4187 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
4188 absolutetime_to_nanoseconds(now
, &nsec
);
4189 DLOG("dark wake promotion disabled at %u ms\n",
4190 ((int)((nsec
) / NSEC_PER_MSEC
)));
4192 darkWakePowerClamped
= true;
4197 //******************************************************************************
4198 // sleepOnClamshellClosed
4200 // contains the logic to determine if the system should sleep when the clamshell
4202 //******************************************************************************
4205 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4207 if (!clamshellExists
) {
4211 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4212 clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, desktopMode
, acAdaptorConnected
);
4214 return !clamshellDisabled
&& !(desktopMode
&& acAdaptorConnected
) && !clamshellSleepDisableMask
;
4218 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4220 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4221 // closed && battery
4222 if (!clamshellExists
) {
4226 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4227 clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, desktopMode
, acAdaptorConnected
);
4229 return !acAdaptorConnected
&& !clamshellSleepDisableMask
;
4233 IOPMrootDomain::sendClientClamshellNotification( void )
4235 /* Only broadcast clamshell alert if clamshell exists. */
4236 if (!clamshellExists
) {
4240 setProperty(kAppleClamshellStateKey
,
4241 clamshellClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
4243 setProperty(kAppleClamshellCausesSleepKey
,
4244 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
4246 /* Argument to message is a bitfiel of
4247 * ( kClamshellStateBit | kClamshellSleepBit )
4249 messageClients(kIOPMMessageClamshellStateChange
,
4250 (void *)(uintptr_t) ((clamshellClosed
? kClamshellStateBit
: 0)
4251 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)));
4254 //******************************************************************************
4255 // getSleepSupported
4258 //******************************************************************************
4261 IOPMrootDomain::getSleepSupported( void )
4263 return platformSleepSupport
;
4266 //******************************************************************************
4267 // setSleepSupported
4270 //******************************************************************************
4273 IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
4275 DLOG("setSleepSupported(%x)\n", (uint32_t) flags
);
4276 OSBitOrAtomic(flags
, &platformSleepSupport
);
4279 //******************************************************************************
4280 // setClamShellSleepDisable
4282 //******************************************************************************
4285 IOPMrootDomain::setClamShellSleepDisable( bool disable
, uint32_t bitmask
)
4289 // User client calls this in non-gated context
4290 if (gIOPMWorkLoop
->inGate() == false) {
4291 gIOPMWorkLoop
->runAction(
4292 OSMemberFunctionCast(IOWorkLoop::Action
, this,
4293 &IOPMrootDomain::setClamShellSleepDisable
),
4295 (void *) disable
, (void *)(uintptr_t) bitmask
);
4299 oldMask
= clamshellSleepDisableMask
;
4301 clamshellSleepDisableMask
|= bitmask
;
4303 clamshellSleepDisableMask
&= ~bitmask
;
4305 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask
, clamshellSleepDisableMask
);
4307 if (clamshellExists
&& clamshellClosed
&&
4308 (clamshellSleepDisableMask
!= oldMask
) &&
4309 (clamshellSleepDisableMask
== 0)) {
4310 handlePowerNotification(kLocalEvalClamshellCommand
);
4314 //******************************************************************************
4318 //******************************************************************************
4321 IOPMrootDomain::wakeFromDoze( void )
4323 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4326 //******************************************************************************
4329 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4330 // should be a dark wake or a full wake. Both Maintenance and SleepService
4331 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4332 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4333 // PMSettings are ignored.
4335 // Caller serialized using settingsCtrlLock.
4336 //******************************************************************************
4339 IOPMrootDomain::recordRTCAlarm(
4340 const OSSymbol
*type
,
4343 uint32_t previousAlarmMask
= _scheduledAlarmMask
;
4345 if (type
== gIOPMSettingDebugWakeRelativeKey
) {
4346 OSNumber
* n
= OSDynamicCast(OSNumber
, object
);
4348 // Debug wake has highest scheduling priority so it overrides any
4349 // pre-existing alarm.
4350 uint32_t debugSecs
= n
->unsigned32BitValue();
4351 _nextScheduledAlarmType
.reset(type
, OSRetain
);
4352 _nextScheduledAlarmUTC
= debugSecs
;
4354 _debugWakeSeconds
= debugSecs
;
4355 OSBitOrAtomic(kIOPMAlarmBitDebugWake
, &_scheduledAlarmMask
);
4356 DLOG("next alarm (%s) in %u secs\n",
4357 type
->getCStringNoCopy(), debugSecs
);
4359 } else if ((type
== gIOPMSettingAutoWakeCalendarKey
.get()) ||
4360 (type
== gIOPMSettingMaintenanceWakeCalendarKey
.get()) ||
4361 (type
== gIOPMSettingSleepServiceWakeCalendarKey
.get())) {
4362 OSData
* data
= OSDynamicCast(OSData
, object
);
4363 if (data
&& (data
->getLength() == sizeof(IOPMCalendarStruct
))) {
4364 const IOPMCalendarStruct
* cs
;
4365 bool replaceNextAlarm
= false;
4368 cs
= (const IOPMCalendarStruct
*) data
->getBytesNoCopy();
4369 secs
= IOPMConvertCalendarToSeconds(cs
);
4370 DLOG("%s " YMDTF
"\n", type
->getCStringNoCopy(), YMDT(cs
));
4372 // Update the next scheduled alarm type
4373 if ((_nextScheduledAlarmType
== NULL
) ||
4374 ((_nextScheduledAlarmType
!= gIOPMSettingDebugWakeRelativeKey
) &&
4375 (secs
< _nextScheduledAlarmUTC
))) {
4376 replaceNextAlarm
= true;
4379 if (type
== gIOPMSettingAutoWakeCalendarKey
.get()) {
4381 _calendarWakeAlarmUTC
= IOPMConvertCalendarToSeconds(cs
);
4382 OSBitOrAtomic(kIOPMAlarmBitCalendarWake
, &_scheduledAlarmMask
);
4384 // TODO: can this else-block be removed?
4385 _calendarWakeAlarmUTC
= 0;
4386 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake
, &_scheduledAlarmMask
);
4389 if (type
== gIOPMSettingMaintenanceWakeCalendarKey
.get()) {
4390 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake
, &_scheduledAlarmMask
);
4392 if (type
== gIOPMSettingSleepServiceWakeCalendarKey
.get()) {
4393 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake
, &_scheduledAlarmMask
);
4396 if (replaceNextAlarm
) {
4397 _nextScheduledAlarmType
.reset(type
, OSRetain
);
4398 _nextScheduledAlarmUTC
= secs
;
4399 DLOG("next alarm (%s) " YMDTF
"\n", type
->getCStringNoCopy(), YMDT(cs
));
4404 if (_scheduledAlarmMask
!= previousAlarmMask
) {
4405 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask
);
4412 //******************************************************************************
4415 // Adds a new feature to the supported features dictionary
4416 //******************************************************************************
4419 IOPMrootDomain::publishFeature( const char * feature
)
4421 publishFeature(feature
, kRD_AllPowerSources
, NULL
);
4424 //******************************************************************************
4425 // publishFeature (with supported power source specified)
4427 // Adds a new feature to the supported features dictionary
4428 //******************************************************************************
4431 IOPMrootDomain::publishFeature(
4432 const char *feature
,
4433 uint32_t supportedWhere
,
4434 uint32_t *uniqueFeatureID
)
4436 static uint16_t next_feature_id
= 500;
4438 OSSharedPtr
<OSNumber
> new_feature_data
;
4439 OSNumber
*existing_feature
= NULL
;
4440 OSArray
*existing_feature_arr_raw
= NULL
;
4441 OSSharedPtr
<OSArray
> existing_feature_arr
;
4442 OSObject
*osObj
= NULL
;
4443 uint32_t feature_value
= 0;
4445 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
4447 if (!supportedWhere
) {
4448 // Feature isn't supported anywhere!
4452 if (next_feature_id
> 5000) {
4453 // Far, far too many features!
4457 if (featuresDictLock
) {
4458 IOLockLock(featuresDictLock
);
4461 OSSharedPtr
<OSObject
> origFeaturesProp
= copyProperty(kRootDomainSupportedFeatures
);
4462 OSDictionary
*origFeatures
= OSDynamicCast(OSDictionary
, origFeaturesProp
.get());
4463 OSSharedPtr
<OSDictionary
> features
;
4465 // Create new features dict if necessary
4467 features
= OSDictionary::withDictionary(origFeatures
);
4469 features
= OSDictionary::withCapacity(1);
4472 // Create OSNumber to track new feature
4474 next_feature_id
+= 1;
4475 if (uniqueFeatureID
) {
4476 // We don't really mind if the calling kext didn't give us a place
4477 // to stash their unique id. Many kexts don't plan to unload, and thus
4478 // have no need to remove themselves later.
4479 *uniqueFeatureID
= next_feature_id
;
4482 feature_value
= (uint32_t)next_feature_id
;
4483 feature_value
<<= 16;
4484 feature_value
+= supportedWhere
;
4486 new_feature_data
= OSNumber::withNumber(
4487 (unsigned long long)feature_value
, 32);
4489 // Does features object already exist?
4490 if ((osObj
= features
->getObject(feature
))) {
4491 if ((existing_feature
= OSDynamicCast(OSNumber
, osObj
))) {
4492 // We need to create an OSArray to hold the now 2 elements.
4493 existing_feature_arr
= OSArray::withObjects(
4494 (const OSObject
**)&existing_feature
, 1, 2);
4495 } else if ((existing_feature_arr_raw
= OSDynamicCast(OSArray
, osObj
))) {
4496 // Add object to existing array
4497 existing_feature_arr
= OSArray::withArray(
4498 existing_feature_arr_raw
,
4499 existing_feature_arr_raw
->getCount() + 1);
4502 if (existing_feature_arr
) {
4503 existing_feature_arr
->setObject(new_feature_data
.get());
4504 features
->setObject(feature
, existing_feature_arr
.get());
4507 // The easy case: no previously existing features listed. We simply
4508 // set the OSNumber at key 'feature' and we're on our way.
4509 features
->setObject(feature
, new_feature_data
.get());
4512 setProperty(kRootDomainSupportedFeatures
, features
.get());
4514 if (featuresDictLock
) {
4515 IOLockUnlock(featuresDictLock
);
4518 // Notify EnergySaver and all those in user space so they might
4519 // re-populate their feature specific UI
4520 if (pmPowerStateQueue
) {
4521 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4525 //******************************************************************************
4526 // removePublishedFeature
4528 // Removes previously published feature
4529 //******************************************************************************
4532 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
4534 IOReturn ret
= kIOReturnError
;
4535 uint32_t feature_value
= 0;
4536 uint16_t feature_id
= 0;
4537 bool madeAChange
= false;
4539 OSSymbol
*dictKey
= NULL
;
4540 OSSharedPtr
<OSCollectionIterator
> dictIterator
;
4541 OSArray
*arrayMember
= NULL
;
4542 OSNumber
*numberMember
= NULL
;
4543 OSObject
*osObj
= NULL
;
4544 OSNumber
*osNum
= NULL
;
4545 OSSharedPtr
<OSArray
> arrayMemberCopy
;
4547 if (kBadPMFeatureID
== removeFeatureID
) {
4548 return kIOReturnNotFound
;
4551 if (featuresDictLock
) {
4552 IOLockLock(featuresDictLock
);
4555 OSSharedPtr
<OSObject
> origFeaturesProp
= copyProperty(kRootDomainSupportedFeatures
);
4556 OSDictionary
*origFeatures
= OSDynamicCast(OSDictionary
, origFeaturesProp
.get());
4557 OSSharedPtr
<OSDictionary
> features
;
4560 // Any modifications to the dictionary are made to the copy to prevent
4561 // races & crashes with userland clients. Dictionary updated
4562 // automically later.
4563 features
= OSDictionary::withDictionary(origFeatures
);
4566 ret
= kIOReturnNotFound
;
4570 // We iterate 'features' dictionary looking for an entry tagged
4571 // with 'removeFeatureID'. If found, we remove it from our tracking
4572 // structures and notify the OS via a general interest message.
4574 dictIterator
= OSCollectionIterator::withCollection(features
.get());
4575 if (!dictIterator
) {
4579 while ((dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject()))) {
4580 osObj
= features
->getObject(dictKey
);
4582 // Each Feature is either tracked by an OSNumber
4583 if (osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
))) {
4584 feature_value
= numberMember
->unsigned32BitValue();
4585 feature_id
= (uint16_t)(feature_value
>> 16);
4587 if (feature_id
== (uint16_t)removeFeatureID
) {
4589 features
->removeObject(dictKey
);
4594 // Or tracked by an OSArray of OSNumbers
4595 } else if (osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
))) {
4596 unsigned int arrayCount
= arrayMember
->getCount();
4598 for (unsigned int i
= 0; i
< arrayCount
; i
++) {
4599 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
4604 feature_value
= osNum
->unsigned32BitValue();
4605 feature_id
= (uint16_t)(feature_value
>> 16);
4607 if (feature_id
== (uint16_t)removeFeatureID
) {
4609 if (1 == arrayCount
) {
4610 // If the array only contains one element, remove
4612 features
->removeObject(dictKey
);
4614 // Otherwise remove the element from a copy of the array.
4615 arrayMemberCopy
= OSArray::withArray(arrayMember
);
4616 if (arrayMemberCopy
) {
4617 arrayMemberCopy
->removeObject(i
);
4618 features
->setObject(dictKey
, arrayMemberCopy
.get());
4630 ret
= kIOReturnSuccess
;
4632 setProperty(kRootDomainSupportedFeatures
, features
.get());
4634 // Notify EnergySaver and all those in user space so they might
4635 // re-populate their feature specific UI
4636 if (pmPowerStateQueue
) {
4637 pmPowerStateQueue
->submitPowerEvent( kPowerEventFeatureChanged
);
4640 ret
= kIOReturnNotFound
;
4644 if (featuresDictLock
) {
4645 IOLockUnlock(featuresDictLock
);
4650 //******************************************************************************
4651 // publishPMSetting (private)
4653 // Should only be called by PMSettingObject to publish a PM Setting as a
4654 // supported feature.
4655 //******************************************************************************
4658 IOPMrootDomain::publishPMSetting(
4659 const OSSymbol
* feature
, uint32_t where
, uint32_t * featureID
)
4661 if (noPublishPMSettings
&&
4662 (noPublishPMSettings
->getNextIndexOfObject(feature
, 0) != (unsigned int)-1)) {
4663 // Setting found in noPublishPMSettings array
4664 *featureID
= kBadPMFeatureID
;
4669 feature
->getCStringNoCopy(), where
, featureID
);
4672 //******************************************************************************
4673 // setPMSetting (private)
4675 // Internal helper to relay PM settings changes from user space to individual
4676 // drivers. Should be called only by IOPMrootDomain::setProperties.
4677 //******************************************************************************
4680 IOPMrootDomain::setPMSetting(
4681 const OSSymbol
*type
,
4684 PMSettingCallEntry
*entries
= NULL
;
4685 OSSharedPtr
<OSArray
> chosen
;
4686 const OSArray
*array
;
4687 PMSettingObject
*pmso
;
4688 thread_t thisThread
;
4689 int i
, j
, count
, capacity
;
4694 return kIOReturnBadArgument
;
4699 // Update settings dict so changes are visible from copyPMSetting().
4700 fPMSettingsDict
->setObject(type
, object
);
4702 // Prep all PMSetting objects with the given 'type' for callout.
4703 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(type
));
4704 if (!array
|| ((capacity
= array
->getCount()) == 0)) {
4708 // Array to retain PMSetting objects targeted for callout.
4709 chosen
= OSArray::withCapacity(capacity
);
4711 goto unlock_exit
; // error
4713 entries
= IONew(PMSettingCallEntry
, capacity
);
4715 goto unlock_exit
; // error
4717 memset(entries
, 0, sizeof(PMSettingCallEntry
) * capacity
);
4719 thisThread
= current_thread();
4721 for (i
= 0, j
= 0; i
< capacity
; i
++) {
4722 pmso
= (PMSettingObject
*) array
->getObject(i
);
4723 if (pmso
->disabled
) {
4726 entries
[j
].thread
= thisThread
;
4727 queue_enter(&pmso
->calloutQueue
, &entries
[j
], PMSettingCallEntry
*, link
);
4728 chosen
->setObject(pmso
);
4738 // Call each pmso in the chosen array.
4739 for (i
= 0; i
< count
; i
++) {
4740 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4741 ret
= pmso
->dispatchPMSetting(type
, object
);
4742 if (ret
== kIOReturnSuccess
) {
4743 // At least one setting handler was successful
4745 #if DEVELOPMENT || DEBUG
4747 // Log the handler and kext that failed
4748 OSSharedPtr
<const OSSymbol
> kextName
= copyKextIdentifierWithAddress((vm_address_t
) pmso
->func
);
4750 DLOG("PMSetting(%s) error 0x%x from %s\n",
4751 type
->getCStringNoCopy(), ret
, kextName
->getCStringNoCopy());
4758 for (i
= 0; i
< count
; i
++) {
4759 pmso
= (PMSettingObject
*) chosen
->getObject(i
);
4760 queue_remove(&pmso
->calloutQueue
, &entries
[i
], PMSettingCallEntry
*, link
);
4761 if (pmso
->waitThread
) {
4762 PMSETTING_WAKEUP(pmso
);
4767 recordRTCAlarm(type
, object
);
4773 IODelete(entries
, PMSettingCallEntry
, capacity
);
4776 return kIOReturnSuccess
;
4779 //******************************************************************************
4780 // copyPMSetting (public)
4782 // Allows kexts to safely read setting values, without being subscribed to
4784 //******************************************************************************
4786 OSSharedPtr
<OSObject
>
4787 IOPMrootDomain::copyPMSetting(
4788 OSSymbol
*whichSetting
)
4790 OSSharedPtr
<OSObject
> obj
;
4792 if (!whichSetting
) {
4797 obj
.reset(fPMSettingsDict
->getObject(whichSetting
), OSRetain
);
4803 //******************************************************************************
4804 // registerPMSettingController (public)
4806 // direct wrapper to registerPMSettingController with uint32_t power source arg
4807 //******************************************************************************
4810 IOPMrootDomain::registerPMSettingController(
4811 const OSSymbol
* settings
[],
4812 IOPMSettingControllerCallback func
,
4817 return registerPMSettingController(
4819 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
4820 func
, target
, refcon
, handle
);
4823 //******************************************************************************
4824 // registerPMSettingController (public)
4826 // Kexts may register for notifications when a particular setting is changed.
4827 // A list of settings is available in IOPM.h.
4829 // * settings - An OSArray containing OSSymbols. Caller should populate this
4830 // array with a list of settings caller wants notifications from.
4831 // * func - A C function callback of the type IOPMSettingControllerCallback
4832 // * target - caller may provide an OSObject *, which PM will pass as an
4833 // target to calls to "func"
4834 // * refcon - caller may provide an void *, which PM will pass as an
4835 // argument to calls to "func"
4836 // * handle - This is a return argument. We will populate this pointer upon
4837 // call success. Hold onto this and pass this argument to
4838 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4840 // kIOReturnSuccess on success
4841 //******************************************************************************
4844 IOPMrootDomain::registerPMSettingController(
4845 const OSSymbol
* settings
[],
4846 uint32_t supportedPowerSources
,
4847 IOPMSettingControllerCallback func
,
4852 PMSettingObject
*pmso
= NULL
;
4853 OSObject
*pmsh
= NULL
;
4856 if (NULL
== settings
||
4859 return kIOReturnBadArgument
;
4862 pmso
= PMSettingObject::pmSettingObject(
4863 (IOPMrootDomain
*) this, func
, target
,
4864 refcon
, supportedPowerSources
, settings
, &pmsh
);
4868 return kIOReturnInternalError
;
4872 for (i
= 0; settings
[i
]; i
++) {
4873 OSSharedPtr
<OSArray
> newList
;
4874 OSArray
*list
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(settings
[i
]));
4876 // New array of callbacks for this setting
4877 newList
= OSArray::withCapacity(1);
4878 settingsCallbacks
->setObject(settings
[i
], newList
.get());
4879 list
= newList
.get();
4882 // Add caller to the callback list
4883 list
->setObject(pmso
);
4887 // Return handle to the caller, the setting object is private.
4890 return kIOReturnSuccess
;
4893 //******************************************************************************
4894 // deregisterPMSettingObject (private)
4896 // Only called from PMSettingObject.
4897 //******************************************************************************
4900 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject
* pmso
)
4902 thread_t thisThread
= current_thread();
4903 PMSettingCallEntry
*callEntry
;
4904 OSSharedPtr
<OSCollectionIterator
> iter
;
4912 pmso
->disabled
= true;
4914 // Wait for all callout threads to finish.
4917 queue_iterate(&pmso
->calloutQueue
, callEntry
, PMSettingCallEntry
*, link
)
4919 if (callEntry
->thread
!= thisThread
) {
4925 assert(NULL
== pmso
->waitThread
);
4926 pmso
->waitThread
= thisThread
;
4927 PMSETTING_WAIT(pmso
);
4928 pmso
->waitThread
= NULL
;
4932 // Search each PM settings array in the kernel.
4933 iter
= OSCollectionIterator::withCollection(settingsCallbacks
.get());
4935 while ((sym
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) {
4936 array
= OSDynamicCast(OSArray
, settingsCallbacks
->getObject(sym
));
4937 index
= array
->getNextIndexOfObject(pmso
, 0);
4939 array
->removeObject(index
);
4949 //******************************************************************************
4950 // informCPUStateChange
4952 // Call into PM CPU code so that CPU power savings may dynamically adjust for
4953 // running on battery, with the lid closed, etc.
4955 // informCPUStateChange is a no-op on non x86 systems
4956 // only x86 has explicit support in the IntelCPUPowerManagement kext
4957 //******************************************************************************
4960 IOPMrootDomain::informCPUStateChange(
4964 #if defined(__i386__) || defined(__x86_64__)
4966 pmioctlVariableInfo_t varInfoStruct
;
4968 const char *varNameStr
= NULL
;
4969 int32_t *varIndex
= NULL
;
4971 if (kInformAC
== type
) {
4972 varNameStr
= kIOPMRootDomainBatPowerCString
;
4973 varIndex
= &idxPMCPULimitedPower
;
4974 } else if (kInformLid
== type
) {
4975 varNameStr
= kIOPMRootDomainLidCloseCString
;
4976 varIndex
= &idxPMCPUClamshell
;
4981 // Set the new value!
4982 // pmCPUControl will assign us a new ID if one doesn't exist yet
4983 bzero(&varInfoStruct
, sizeof(pmioctlVariableInfo_t
));
4984 varInfoStruct
.varID
= *varIndex
;
4985 varInfoStruct
.varType
= vBool
;
4986 varInfoStruct
.varInitValue
= value
;
4987 varInfoStruct
.varCurValue
= value
;
4988 strlcpy((char *)varInfoStruct
.varName
,
4989 (const char *)varNameStr
,
4990 sizeof(varInfoStruct
.varName
));
4993 pmCPUret
= pmCPUControl( PMIOCSETVARINFO
, (void *)&varInfoStruct
);
4995 // pmCPU only assigns numerical id's when a new varName is specified
4997 && (*varIndex
== kCPUUnknownIndex
)) {
4998 // pmCPUControl has assigned us a new variable ID.
4999 // Let's re-read the structure we just SET to learn that ID.
5000 pmCPUret
= pmCPUControl( PMIOCGETVARNAMEINFO
, (void *)&varInfoStruct
);
5002 if (0 == pmCPUret
) {
5003 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5004 *varIndex
= varInfoStruct
.varID
;
5010 #endif /* __i386__ || __x86_64__ */
5014 // MARK: Deep Sleep Policy
5018 //******************************************************************************
5019 // evaluateSystemSleepPolicy
5020 //******************************************************************************
5022 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5026 kIOPMSleepFlagHibernate
= 0x00000001,
5027 kIOPMSleepFlagSleepTimerEnable
= 0x00000002
5030 struct IOPMSystemSleepPolicyEntry
{
5031 uint32_t factorMask
;
5032 uint32_t factorBits
;
5033 uint32_t sleepFlags
;
5034 uint32_t wakeEvents
;
5035 } __attribute__((packed
));
5037 struct IOPMSystemSleepPolicyTable
{
5040 uint16_t entryCount
;
5041 IOPMSystemSleepPolicyEntry entries
[];
5042 } __attribute__((packed
));
5045 kIOPMSleepAttributeHibernateSetup
= 0x00000001,
5046 kIOPMSleepAttributeHibernateSleep
= 0x00000002
5050 getSleepTypeAttributes( uint32_t sleepType
)
5052 static const uint32_t sleepTypeAttributes
[kIOPMSleepTypeLast
] =
5057 /* safesleep */ kIOPMSleepAttributeHibernateSetup
,
5058 /* hibernate */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
5059 /* standby */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
5060 /* poweroff */ kIOPMSleepAttributeHibernateSetup
| kIOPMSleepAttributeHibernateSleep
,
5064 if (sleepType
>= kIOPMSleepTypeLast
) {
5068 return sleepTypeAttributes
[sleepType
];
5072 IOPMrootDomain::evaluateSystemSleepPolicy(
5073 IOPMSystemSleepParameters
* params
, int sleepPhase
, uint32_t * hibMode
)
5075 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5077 static const IONamedValue factorValues
[] = {
5078 SLEEP_FACTOR( SleepTimerWake
),
5079 SLEEP_FACTOR( LidOpen
),
5080 SLEEP_FACTOR( ACPower
),
5081 SLEEP_FACTOR( BatteryLow
),
5082 SLEEP_FACTOR( StandbyNoDelay
),
5083 SLEEP_FACTOR( StandbyForced
),
5084 SLEEP_FACTOR( StandbyDisabled
),
5085 SLEEP_FACTOR( USBExternalDevice
),
5086 SLEEP_FACTOR( BluetoothHIDDevice
),
5087 SLEEP_FACTOR( ExternalMediaMounted
),
5088 SLEEP_FACTOR( ThunderboltDevice
),
5089 SLEEP_FACTOR( RTCAlarmScheduled
),
5090 SLEEP_FACTOR( MagicPacketWakeEnabled
),
5091 SLEEP_FACTOR( HibernateForced
),
5092 SLEEP_FACTOR( AutoPowerOffDisabled
),
5093 SLEEP_FACTOR( AutoPowerOffForced
),
5094 SLEEP_FACTOR( ExternalDisplay
),
5095 SLEEP_FACTOR( NetworkKeepAliveActive
),
5096 SLEEP_FACTOR( LocalUserActivity
),
5097 SLEEP_FACTOR( HibernateFailed
),
5098 SLEEP_FACTOR( ThermalWarning
),
5099 SLEEP_FACTOR( DisplayCaptured
),
5103 const IOPMSystemSleepPolicyTable
* pt
;
5104 OSSharedPtr
<OSObject
> prop
;
5105 OSData
* policyData
;
5106 uint64_t currentFactors
= 0;
5107 char currentFactorsBuf
[512];
5108 uint32_t standbyDelay
= 0;
5109 uint32_t powerOffDelay
= 0;
5110 uint32_t powerOffTimer
= 0;
5111 uint32_t standbyTimer
= 0;
5113 bool standbyEnabled
;
5114 bool powerOffEnabled
;
5117 // Get platform's sleep policy table
5118 if (!gSleepPolicyHandler
) {
5119 prop
= getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey
);
5125 // Fetch additional settings
5126 standbyEnabled
= (getSleepOption(kIOPMDeepSleepDelayKey
, &standbyDelay
)
5127 && propertyHasValue(kIOPMDeepSleepEnabledKey
, kOSBooleanTrue
));
5128 powerOffEnabled
= (getSleepOption(kIOPMAutoPowerOffDelayKey
, &powerOffDelay
)
5129 && propertyHasValue(kIOPMAutoPowerOffEnabledKey
, kOSBooleanTrue
));
5130 if (!getSleepOption(kIOPMAutoPowerOffTimerKey
, &powerOffTimer
)) {
5131 powerOffTimer
= powerOffDelay
;
5133 if (!getSleepOption(kIOPMDeepSleepTimerKey
, &standbyTimer
)) {
5134 standbyTimer
= standbyDelay
;
5137 DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5138 sleepPhase
, standbyEnabled
, standbyDelay
, standbyTimer
,
5139 powerOffEnabled
, powerOffDelay
, powerOffTimer
, *hibMode
);
5141 currentFactorsBuf
[0] = 0;
5142 // pmset level overrides
5143 if ((*hibMode
& kIOHibernateModeOn
) == 0) {
5144 if (!gSleepPolicyHandler
) {
5145 standbyEnabled
= false;
5146 powerOffEnabled
= false;
5148 } else if (!(*hibMode
& kIOHibernateModeSleep
)) {
5149 // Force hibernate (i.e. mode 25)
5150 // If standby is enabled, force standy.
5151 // If poweroff is enabled, force poweroff.
5152 if (standbyEnabled
) {
5153 currentFactors
|= kIOPMSleepFactorStandbyForced
;
5154 } else if (powerOffEnabled
) {
5155 currentFactors
|= kIOPMSleepFactorAutoPowerOffForced
;
5157 currentFactors
|= kIOPMSleepFactorHibernateForced
;
5161 // Current factors based on environment and assertions
5162 if (sleepTimerMaintenance
) {
5163 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
5165 if (standbyEnabled
&& sleepToStandby
&& !gSleepPolicyHandler
) {
5166 currentFactors
|= kIOPMSleepFactorSleepTimerWake
;
5168 if (!clamshellClosed
) {
5169 currentFactors
|= kIOPMSleepFactorLidOpen
;
5171 if (acAdaptorConnected
) {
5172 currentFactors
|= kIOPMSleepFactorACPower
;
5174 if (lowBatteryCondition
) {
5176 getSleepOption(kIOHibernateModeKey
, &hibernateMode
);
5177 if ((hibernateMode
& kIOHibernateModeOn
) == 0) {
5178 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5180 currentFactors
|= kIOPMSleepFactorBatteryLow
;
5183 if (!standbyDelay
|| !standbyTimer
) {
5184 currentFactors
|= kIOPMSleepFactorStandbyNoDelay
;
5186 if (standbyNixed
|| !standbyEnabled
) {
5187 currentFactors
|= kIOPMSleepFactorStandbyDisabled
;
5190 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
5191 currentFactors
&= ~kIOPMSleepFactorSleepTimerWake
;
5193 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit
) !=
5194 kIOPMDriverAssertionLevelOff
) {
5195 currentFactors
|= kIOPMSleepFactorUSBExternalDevice
;
5197 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit
) !=
5198 kIOPMDriverAssertionLevelOff
) {
5199 currentFactors
|= kIOPMSleepFactorBluetoothHIDDevice
;
5201 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit
) !=
5202 kIOPMDriverAssertionLevelOff
) {
5203 currentFactors
|= kIOPMSleepFactorExternalMediaMounted
;
5205 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5
) !=
5206 kIOPMDriverAssertionLevelOff
) {
5207 currentFactors
|= kIOPMSleepFactorThunderboltDevice
;
5209 if (_scheduledAlarmMask
!= 0) {
5210 currentFactors
|= kIOPMSleepFactorRTCAlarmScheduled
;
5212 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit
) !=
5213 kIOPMDriverAssertionLevelOff
) {
5214 currentFactors
|= kIOPMSleepFactorMagicPacketWakeEnabled
;
5216 #define TCPKEEPALIVE 1
5218 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit
) !=
5219 kIOPMDriverAssertionLevelOff
) {
5220 currentFactors
|= kIOPMSleepFactorNetworkKeepAliveActive
;
5223 if (!powerOffEnabled
) {
5224 currentFactors
|= kIOPMSleepFactorAutoPowerOffDisabled
;
5227 currentFactors
|= kIOPMSleepFactorExternalDisplay
;
5229 if (userWasActive
) {
5230 currentFactors
|= kIOPMSleepFactorLocalUserActivity
;
5232 if (darkWakeHibernateError
&& !CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
5233 currentFactors
|= kIOPMSleepFactorHibernateFailed
;
5235 if (thermalWarningState
) {
5236 currentFactors
|= kIOPMSleepFactorThermalWarning
;
5239 for (int factorBit
= 0; factorBit
< (8 * sizeof(uint32_t)); factorBit
++) {
5240 uint32_t factor
= 1 << factorBit
;
5241 if (factor
& currentFactors
) {
5242 strlcat(currentFactorsBuf
, ", ", sizeof(currentFactorsBuf
));
5243 strlcat(currentFactorsBuf
, IOFindNameForValue(factor
, factorValues
), sizeof(currentFactorsBuf
));
5246 DLOG("sleep factors 0x%llx%s\n", currentFactors
, currentFactorsBuf
);
5248 if (gSleepPolicyHandler
) {
5249 uint32_t savedHibernateMode
;
5252 if (!gSleepPolicyVars
) {
5253 gSleepPolicyVars
= IONew(IOPMSystemSleepPolicyVariables
, 1);
5254 if (!gSleepPolicyVars
) {
5257 bzero(gSleepPolicyVars
, sizeof(*gSleepPolicyVars
));
5259 gSleepPolicyVars
->signature
= kIOPMSystemSleepPolicySignature
;
5260 gSleepPolicyVars
->version
= kIOPMSystemSleepPolicyVersion
;
5261 gSleepPolicyVars
->currentCapability
= _currentCapability
;
5262 gSleepPolicyVars
->highestCapability
= _highestCapability
;
5263 gSleepPolicyVars
->sleepFactors
= currentFactors
;
5264 gSleepPolicyVars
->sleepReason
= lastSleepReason
;
5265 gSleepPolicyVars
->sleepPhase
= sleepPhase
;
5266 gSleepPolicyVars
->standbyDelay
= standbyDelay
;
5267 gSleepPolicyVars
->standbyTimer
= standbyTimer
;
5268 gSleepPolicyVars
->poweroffDelay
= powerOffDelay
;
5269 gSleepPolicyVars
->scheduledAlarms
= _scheduledAlarmMask
| _userScheduledAlarmMask
;
5270 gSleepPolicyVars
->poweroffTimer
= powerOffTimer
;
5272 if (kIOPMSleepPhase0
== sleepPhase
) {
5273 // preserve hibernateMode
5274 savedHibernateMode
= gSleepPolicyVars
->hibernateMode
;
5275 gSleepPolicyVars
->hibernateMode
= *hibMode
;
5276 } else if (kIOPMSleepPhase1
== sleepPhase
) {
5277 // use original hibernateMode for phase2
5278 gSleepPolicyVars
->hibernateMode
= *hibMode
;
5281 result
= gSleepPolicyHandler(gSleepPolicyTarget
, gSleepPolicyVars
, params
);
5283 if (kIOPMSleepPhase0
== sleepPhase
) {
5284 // restore hibernateMode
5285 gSleepPolicyVars
->hibernateMode
= savedHibernateMode
;
5288 if ((result
!= kIOReturnSuccess
) ||
5289 (kIOPMSleepTypeInvalid
== params
->sleepType
) ||
5290 (params
->sleepType
>= kIOPMSleepTypeLast
) ||
5291 (kIOPMSystemSleepParametersVersion
!= params
->version
)) {
5292 MSG("sleep policy handler error\n");
5296 if ((getSleepTypeAttributes(params
->sleepType
) &
5297 kIOPMSleepAttributeHibernateSetup
) &&
5298 ((*hibMode
& kIOHibernateModeOn
) == 0)) {
5299 *hibMode
|= (kIOHibernateModeOn
| kIOHibernateModeSleep
);
5302 DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5303 params
->version
, params
->sleepType
, params
->sleepFlags
,
5304 params
->ecWakeEvents
, params
->ecWakeTimer
, params
->ecPoweroffTimer
);
5309 // Policy table is meaningless without standby enabled
5310 if (!standbyEnabled
) {
5314 // Validate the sleep policy table
5315 policyData
= OSDynamicCast(OSData
, prop
.get());
5316 if (!policyData
|| (policyData
->getLength() <= sizeof(IOPMSystemSleepPolicyTable
))) {
5320 pt
= (const IOPMSystemSleepPolicyTable
*) policyData
->getBytesNoCopy();
5321 if ((pt
->signature
!= kIOPMSystemSleepPolicySignature
) ||
5322 (pt
->version
!= 1) || (0 == pt
->entryCount
)) {
5326 if (((policyData
->getLength() - sizeof(IOPMSystemSleepPolicyTable
)) !=
5327 (sizeof(IOPMSystemSleepPolicyEntry
) * pt
->entryCount
))) {
5331 for (uint32_t i
= 0; i
< pt
->entryCount
; i
++) {
5332 const IOPMSystemSleepPolicyEntry
* entry
= &pt
->entries
[i
];
5333 mismatch
= (((uint32_t)currentFactors
^ entry
->factorBits
) & entry
->factorMask
);
5335 DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5336 entry
->factorMask
, entry
->factorBits
,
5337 entry
->sleepFlags
, entry
->wakeEvents
, mismatch
);
5342 DLOG("^ found match\n");
5345 params
->version
= kIOPMSystemSleepParametersVersion
;
5346 params
->reserved1
= 1;
5347 if (entry
->sleepFlags
& kIOPMSleepFlagHibernate
) {
5348 params
->sleepType
= kIOPMSleepTypeStandby
;
5350 params
->sleepType
= kIOPMSleepTypeNormalSleep
;
5353 params
->ecWakeEvents
= entry
->wakeEvents
;
5354 if (entry
->sleepFlags
& kIOPMSleepFlagSleepTimerEnable
) {
5355 if (kIOPMSleepPhase2
== sleepPhase
) {
5356 clock_sec_t now_secs
= gIOLastSleepTime
.tv_sec
;
5358 if (!_standbyTimerResetSeconds
||
5359 (now_secs
<= _standbyTimerResetSeconds
)) {
5360 // Reset standby timer adjustment
5361 _standbyTimerResetSeconds
= now_secs
;
5362 DLOG("standby delay %u, reset %u\n",
5363 standbyDelay
, (uint32_t) _standbyTimerResetSeconds
);
5364 } else if (standbyDelay
) {
5365 // Shorten the standby delay timer
5366 clock_sec_t elapsed
= now_secs
- _standbyTimerResetSeconds
;
5367 if (standbyDelay
> elapsed
) {
5368 standbyDelay
-= elapsed
;
5370 standbyDelay
= 1; // must be > 0
5372 DLOG("standby delay %u, elapsed %u\n",
5373 standbyDelay
, (uint32_t) elapsed
);
5376 params
->ecWakeTimer
= standbyDelay
;
5377 } else if (kIOPMSleepPhase2
== sleepPhase
) {
5378 // A sleep that does not enable the sleep timer will reset
5379 // the standby delay adjustment.
5380 _standbyTimerResetSeconds
= 0;
5389 static IOPMSystemSleepParameters gEarlySystemSleepParams
;
5392 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5394 // Evaluate early (priority interest phase), before drivers sleep.
5396 DLOG("%s\n", __FUNCTION__
);
5397 removeProperty(kIOPMSystemSleepParametersKey
);
5399 // Full wake resets the standby timer delay adjustment
5400 if (_highestCapability
& kIOPMSystemCapabilityGraphics
) {
5401 _standbyTimerResetSeconds
= 0;
5404 hibernateDisabled
= false;
5406 getSleepOption(kIOHibernateModeKey
, &hibernateMode
);
5408 // Save for late evaluation if sleep is aborted
5409 bzero(&gEarlySystemSleepParams
, sizeof(gEarlySystemSleepParams
));
5411 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams
, kIOPMSleepPhase1
,
5413 if (!hibernateRetry
&&
5414 ((getSleepTypeAttributes(gEarlySystemSleepParams
.sleepType
) &
5415 kIOPMSleepAttributeHibernateSetup
) == 0)) {
5416 // skip hibernate setup
5417 hibernateDisabled
= true;
5421 // Publish IOPMSystemSleepType
5422 uint32_t sleepType
= gEarlySystemSleepParams
.sleepType
;
5423 if (sleepType
== kIOPMSleepTypeInvalid
) {
5425 sleepType
= kIOPMSleepTypeNormalSleep
;
5426 if (hibernateMode
& kIOHibernateModeOn
) {
5427 sleepType
= (hibernateMode
& kIOHibernateModeSleep
) ?
5428 kIOPMSleepTypeSafeSleep
: kIOPMSleepTypeHibernate
;
5430 } else if ((sleepType
== kIOPMSleepTypeStandby
) &&
5431 (gEarlySystemSleepParams
.ecPoweroffTimer
)) {
5432 // report the lowest possible sleep state
5433 sleepType
= kIOPMSleepTypePowerOff
;
5436 setProperty(kIOPMSystemSleepTypeKey
, sleepType
, 32);
5440 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5442 IOPMSystemSleepParameters params
;
5443 OSSharedPtr
<OSData
> paramsData
;
5445 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5447 DLOG("%s\n", __FUNCTION__
);
5449 bzero(¶ms
, sizeof(params
));
5451 if (evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase2
, &hibernateMode
)) {
5452 if ((kIOPMSleepTypeStandby
== params
.sleepType
)
5453 && gIOHibernateStandbyDisabled
&& gSleepPolicyVars
5454 && (!((kIOPMSleepFactorStandbyForced
| kIOPMSleepFactorAutoPowerOffForced
| kIOPMSleepFactorHibernateForced
)
5455 & gSleepPolicyVars
->sleepFactors
))) {
5456 standbyNixed
= true;
5460 || ((hibernateDisabled
|| hibernateAborted
) &&
5461 (getSleepTypeAttributes(params
.sleepType
) &
5462 kIOPMSleepAttributeHibernateSetup
))) {
5463 // Final evaluation picked a state requiring hibernation,
5464 // but hibernate isn't going to proceed. Arm a short sleep using
5465 // the early non-hibernate sleep parameters.
5466 bcopy(&gEarlySystemSleepParams
, ¶ms
, sizeof(params
));
5467 params
.sleepType
= kIOPMSleepTypeAbortedSleep
;
5468 params
.ecWakeTimer
= 1;
5472 // Set hibernateRetry flag to force hibernate setup on the
5474 hibernateRetry
= true;
5476 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5477 params
.ecWakeTimer
, hibernateDisabled
, hibernateAborted
, standbyNixed
);
5479 hibernateRetry
= false;
5482 if (kIOPMSleepTypeAbortedSleep
!= params
.sleepType
) {
5483 resetTimers
= false;
5486 paramsData
= OSData::withBytes(¶ms
, sizeof(params
));
5488 setProperty(kIOPMSystemSleepParametersKey
, paramsData
.get());
5491 if (getSleepTypeAttributes(params
.sleepType
) &
5492 kIOPMSleepAttributeHibernateSleep
) {
5493 // Disable sleep to force hibernation
5494 gIOHibernateMode
&= ~kIOHibernateModeSleep
;
5500 IOPMrootDomain::getHibernateSettings(
5501 uint32_t * hibernateModePtr
,
5502 uint32_t * hibernateFreeRatio
,
5503 uint32_t * hibernateFreeTime
)
5505 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5506 // has updated the hibernateDisabled flag.
5508 bool ok
= getSleepOption(kIOHibernateModeKey
, hibernateModePtr
);
5509 getSleepOption(kIOHibernateFreeRatioKey
, hibernateFreeRatio
);
5510 getSleepOption(kIOHibernateFreeTimeKey
, hibernateFreeTime
);
5511 if (hibernateDisabled
) {
5512 *hibernateModePtr
= 0;
5513 } else if (gSleepPolicyHandler
) {
5514 *hibernateModePtr
= hibernateMode
;
5516 DLOG("hibernateMode 0x%x\n", *hibernateModePtr
);
5521 IOPMrootDomain::getSleepOption( const char * key
, uint32_t * option
)
5523 OSSharedPtr
<OSObject
> optionsProp
;
5524 OSDictionary
* optionsDict
;
5525 OSSharedPtr
<OSObject
> obj
;
5529 optionsProp
= copyProperty(kRootDomainSleepOptionsKey
);
5530 optionsDict
= OSDynamicCast(OSDictionary
, optionsProp
.get());
5533 obj
.reset(optionsDict
->getObject(key
), OSRetain
);
5536 obj
= copyProperty(key
);
5539 if ((num
= OSDynamicCast(OSNumber
, obj
.get()))) {
5540 *option
= num
->unsigned32BitValue();
5542 } else if (OSDynamicCast(OSBoolean
, obj
.get())) {
5543 *option
= (obj
== kOSBooleanTrue
) ? 1 : 0;
5550 #endif /* HIBERNATION */
5553 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType
, uint32_t * standbyTimer
)
5556 IOPMSystemSleepParameters params
;
5557 uint32_t hibMode
= 0;
5560 if (gIOPMWorkLoop
->inGate() == false) {
5561 IOReturn ret
= gIOPMWorkLoop
->runAction(
5562 OSMemberFunctionCast(IOWorkLoop::Action
, this,
5563 &IOPMrootDomain::getSystemSleepType
),
5565 (void *) sleepType
, (void *) standbyTimer
);
5569 getSleepOption(kIOHibernateModeKey
, &hibMode
);
5570 bzero(¶ms
, sizeof(params
));
5572 ok
= evaluateSystemSleepPolicy(¶ms
, kIOPMSleepPhase0
, &hibMode
);
5574 *sleepType
= params
.sleepType
;
5575 if (!getSleepOption(kIOPMDeepSleepTimerKey
, standbyTimer
) &&
5576 !getSleepOption(kIOPMDeepSleepDelayKey
, standbyTimer
)) {
5577 DLOG("Standby delay is not set\n");
5580 return kIOReturnSuccess
;
5584 return kIOReturnUnsupported
;
5588 // MARK: Shutdown and Restart
5590 //******************************************************************************
5591 // handlePlatformHaltRestart
5593 //******************************************************************************
5595 // Phases while performing shutdown/restart
5598 kNotifyPriorityClients
= 0x10,
5599 kNotifyPowerPlaneDrivers
= 0x20,
5600 kNotifyHaltRestartAction
= 0x30,
5605 struct HaltRestartApplierContext
{
5606 IOPMrootDomain
* RootDomain
;
5607 unsigned long PowerState
;
5608 IOPMPowerFlags PowerFlags
;
5611 const char * LogString
;
5612 shutdownPhase_t phase
;
5614 IOServiceInterestHandler handler
;
5618 shutdownPhase2String(shutdownPhase_t phase
)
5622 return "Notifications completed";
5623 case kNotifyPriorityClients
:
5624 return "Notifying priority clients";
5625 case kNotifyPowerPlaneDrivers
:
5626 return "Notifying power plane drivers";
5627 case kNotifyHaltRestartAction
:
5628 return "Notifying HaltRestart action handlers";
5630 return "Quiescing PM";
5637 platformHaltRestartApplier( OSObject
* object
, void * context
)
5639 IOPowerStateChangeNotification notify
;
5640 HaltRestartApplierContext
* ctx
;
5641 AbsoluteTime startTime
, elapsedTime
;
5644 ctx
= (HaltRestartApplierContext
*) context
;
5646 _IOServiceInterestNotifier
* notifier
;
5647 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5648 memset(¬ify
, 0, sizeof(notify
));
5649 notify
.powerRef
= (void *)(uintptr_t)ctx
->Counter
;
5650 notify
.returnValue
= 0;
5651 notify
.stateNumber
= ctx
->PowerState
;
5652 notify
.stateFlags
= ctx
->PowerFlags
;
5655 ctx
->handler
= notifier
->handler
;
5658 clock_get_uptime(&startTime
);
5659 ctx
->RootDomain
->messageClient( ctx
->MessageType
, object
, (void *)¬ify
);
5660 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5662 if ((deltaTime
> kPMHaltTimeoutMS
) && notifier
) {
5663 LOG("%s handler %p took %u ms\n",
5664 ctx
->LogString
, OBFUSCATE(notifier
->handler
), deltaTime
);
5665 halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier
->handler
, elapsedTime
);
5668 ctx
->handler
= NULL
;
5673 quiescePowerTreeCallback( void * target
, void * param
)
5675 IOLockLock(gPMHaltLock
);
5677 thread_wakeup(param
);
5678 IOLockUnlock(gPMHaltLock
);
5682 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type
)
5684 AbsoluteTime startTime
, elapsedTime
;
5687 memset(&gHaltRestartCtx
, 0, sizeof(gHaltRestartCtx
));
5688 gHaltRestartCtx
.RootDomain
= this;
5690 clock_get_uptime(&startTime
);
5693 case kPEUPSDelayHaltCPU
:
5694 gHaltRestartCtx
.PowerState
= OFF_STATE
;
5695 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillPowerOff
;
5696 gHaltRestartCtx
.LogString
= "PowerOff";
5700 gHaltRestartCtx
.PowerState
= RESTART_STATE
;
5701 gHaltRestartCtx
.MessageType
= kIOMessageSystemWillRestart
;
5702 gHaltRestartCtx
.LogString
= "Restart";
5706 gHaltRestartCtx
.PowerState
= ON_STATE
;
5707 gHaltRestartCtx
.MessageType
= kIOMessageSystemPagingOff
;
5708 gHaltRestartCtx
.LogString
= "PagingOff";
5709 IOService::updateConsoleUsers(NULL
, kIOMessageSystemPagingOff
);
5711 IOHibernateSystemRestart();
5719 gHaltRestartCtx
.phase
= kNotifyPriorityClients
;
5720 // Notify legacy clients
5721 applyToInterested(gIOPriorityPowerStateInterest
, platformHaltRestartApplier
, &gHaltRestartCtx
);
5723 // For normal shutdown, turn off File Server Mode.
5724 if (kPEHaltCPU
== pe_type
) {
5725 OSSharedPtr
<const OSSymbol
> setting
= OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
);
5726 OSSharedPtr
<OSNumber
> num
= OSNumber::withNumber((unsigned long long) 0, 32);
5727 if (setting
&& num
) {
5728 setPMSetting(setting
.get(), num
.get());
5732 if (kPEPagingOff
!= pe_type
) {
5733 gHaltRestartCtx
.phase
= kNotifyPowerPlaneDrivers
;
5734 // Notify in power tree order
5735 notifySystemShutdown(this, gHaltRestartCtx
.MessageType
);
5738 gHaltRestartCtx
.phase
= kNotifyHaltRestartAction
;
5739 #if defined(XNU_TARGET_OS_OSX)
5740 IOCPURunPlatformHaltRestartActions(pe_type
);
5741 #else /* !defined(XNU_TARGET_OS_OSX) */
5742 if (kPEPagingOff
!= pe_type
) {
5743 IOCPURunPlatformHaltRestartActions(pe_type
);
5745 #endif /* !defined(XNU_TARGET_OS_OSX) */
5747 // Wait for PM to quiesce
5748 if ((kPEPagingOff
!= pe_type
) && gPMHaltLock
) {
5749 gHaltRestartCtx
.phase
= kQuiescePM
;
5750 AbsoluteTime quiesceTime
= mach_absolute_time();
5752 IOLockLock(gPMHaltLock
);
5753 gPMQuiesced
= false;
5754 if (quiescePowerTree(this, &quiescePowerTreeCallback
, &gPMQuiesced
) ==
5756 while (!gPMQuiesced
) {
5757 IOLockSleep(gPMHaltLock
, &gPMQuiesced
, THREAD_UNINT
);
5760 IOLockUnlock(gPMHaltLock
);
5761 deltaTime
= computeDeltaTimeMS(&quiesceTime
, &elapsedTime
);
5762 DLOG("PM quiesce took %u ms\n", deltaTime
);
5763 halt_log_enter("Quiesce", NULL
, elapsedTime
);
5765 gHaltRestartCtx
.phase
= kNotifyDone
;
5767 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
5768 LOG("%s all drivers took %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5770 halt_log_enter(gHaltRestartCtx
.LogString
, NULL
, elapsedTime
);
5772 deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5773 LOG("%s total %u ms\n", gHaltRestartCtx
.LogString
, deltaTime
);
5775 if (gHaltLog
&& gHaltTimeMaxLog
&& (deltaTime
>= gHaltTimeMaxLog
)) {
5776 printf("%s total %d ms:%s\n", gHaltRestartCtx
.LogString
, deltaTime
, gHaltLog
);
5779 checkShutdownTimeout();
5783 IOPMrootDomain::checkShutdownTimeout()
5785 AbsoluteTime elapsedTime
;
5786 uint32_t deltaTime
= computeDeltaTimeMS(&gHaltStartTime
, &elapsedTime
);
5788 if (gHaltTimeMaxPanic
&& (deltaTime
>= gHaltTimeMaxPanic
)) {
5795 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs
)
5798 if ((gHaltRestartCtx
.phase
== kNotifyPriorityClients
) && gHaltRestartCtx
.handler
) {
5799 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx
.handler
, mach_absolute_time() - gHaltStartTime
);
5801 panic("%s timed out in phase '%s'. Total %d ms:%s",
5802 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
, gHaltLog
);
5804 panic("%s timed out in phase \'%s\'. Total %d ms",
5805 gHaltRestartCtx
.LogString
, shutdownPhase2String(gHaltRestartCtx
.phase
), timeoutInMs
);
5809 //******************************************************************************
5812 //******************************************************************************
5815 IOPMrootDomain::shutdownSystem( void )
5817 return kIOReturnUnsupported
;
5820 //******************************************************************************
5823 //******************************************************************************
5826 IOPMrootDomain::restartSystem( void )
5828 return kIOReturnUnsupported
;
5832 // MARK: System Capability
5834 //******************************************************************************
5835 // tagPowerPlaneService
5837 // Running on PM work loop thread.
5838 //******************************************************************************
5841 IOPMrootDomain::tagPowerPlaneService(
5842 IOService
* service
,
5843 IOPMActions
* actions
,
5844 IOPMPowerStateIndex maxPowerState
)
5848 memset(actions
, 0, sizeof(*actions
));
5849 actions
->target
= this;
5851 if (service
== this) {
5852 actions
->actionPowerChangeStart
=
5853 OSMemberFunctionCast(
5854 IOPMActionPowerChangeStart
, this,
5855 &IOPMrootDomain::handleOurPowerChangeStart
);
5857 actions
->actionPowerChangeDone
=
5858 OSMemberFunctionCast(
5859 IOPMActionPowerChangeDone
, this,
5860 &IOPMrootDomain::handleOurPowerChangeDone
);
5862 actions
->actionPowerChangeOverride
=
5863 OSMemberFunctionCast(
5864 IOPMActionPowerChangeOverride
, this,
5865 &IOPMrootDomain::overrideOurPowerChange
);
5869 #if DISPLAY_WRANGLER_PRESENT
5870 if (NULL
!= service
->metaCast("IODisplayWrangler")) {
5871 // XXX should this really retain?
5872 wrangler
.reset(service
, OSRetain
);
5873 wrangler
->registerInterest(gIOGeneralInterest
,
5874 &displayWranglerNotification
, this, NULL
);
5876 // found the display wrangler, check for any display assertions already created
5877 if (pmAssertions
->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit
) {
5878 DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5879 wrangler
->setIgnoreIdleTimer( true );
5881 flags
|= kPMActionsFlagIsDisplayWrangler
;
5883 #endif /* DISPLAY_WRANGLER_PRESENT */
5885 if (service
->propertyExists("IOPMStrictTreeOrder")) {
5886 flags
|= kPMActionsFlagIsGraphicsDriver
;
5888 if (service
->propertyExists("IOPMUnattendedWakePowerState")) {
5889 flags
|= kPMActionsFlagIsAudioDriver
;
5892 OSSharedPtr
<OSObject
> prop
= service
->copyProperty(kIOPMDarkWakeMaxPowerStateKey
);
5894 OSNumber
* num
= OSDynamicCast(OSNumber
, prop
.get());
5896 actions
->darkWakePowerState
= num
->unsigned32BitValue();
5897 if (actions
->darkWakePowerState
< maxPowerState
) {
5898 flags
|= kPMActionsFlagHasDarkWakePowerState
;
5903 // Find the power connection object that is a child of the PCI host
5904 // bridge, and has a graphics/audio device attached below. Mark the
5905 // power branch for delayed child notifications.
5908 IORegistryEntry
* child
= service
;
5909 IORegistryEntry
* parent
= child
->getParentEntry(gIOPowerPlane
);
5911 while (child
!= this) {
5912 if (child
->propertyHasValue("IOPCITunnelled", kOSBooleanTrue
)) {
5913 // Skip delaying notifications and clamping power on external graphics and audio devices.
5914 DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service
->getRegistryEntryID(), flags
);
5918 if ((parent
== pciHostBridgeDriver
) ||
5920 if (OSDynamicCast(IOPowerConnection
, child
)) {
5921 IOPowerConnection
* conn
= (IOPowerConnection
*) child
;
5922 conn
->delayChildNotification
= true;
5923 DLOG("delayChildNotification for 0x%llx\n", conn
->getRegistryEntryID());
5928 parent
= child
->getParentEntry(gIOPowerPlane
);
5933 DLOG("%s tag flags %x\n", service
->getName(), flags
);
5934 actions
->flags
|= flags
;
5935 actions
->actionPowerChangeOverride
=
5936 OSMemberFunctionCast(
5937 IOPMActionPowerChangeOverride
, this,
5938 &IOPMrootDomain::overridePowerChangeForService
);
5940 if (flags
& kPMActionsFlagIsDisplayWrangler
) {
5941 actions
->actionActivityTickle
=
5942 OSMemberFunctionCast(
5943 IOPMActionActivityTickle
, this,
5944 &IOPMrootDomain::handleActivityTickleForDisplayWrangler
);
5946 actions
->actionUpdatePowerClient
=
5947 OSMemberFunctionCast(
5948 IOPMActionUpdatePowerClient
, this,
5949 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler
);
5954 // Locate the first PCI host bridge for PMTrace.
5955 if (!pciHostBridgeDevice
&& service
->metaCast("IOPCIBridge")) {
5956 IOService
* provider
= service
->getProvider();
5957 if (OSDynamicCast(IOPlatformDevice
, provider
) &&
5958 provider
->inPlane(gIODTPlane
)) {
5959 pciHostBridgeDevice
.reset(provider
, OSNoRetain
);
5960 pciHostBridgeDriver
.reset(service
, OSNoRetain
);
5961 DLOG("PMTrace found PCI host bridge %s->%s\n",
5962 provider
->getName(), service
->getName());
5966 // Tag top-level PCI devices. The order of PMinit() call does not
5967 // change across boots and is used as the PCI bit number.
5968 if (pciHostBridgeDevice
&& service
->metaCast("IOPCIDevice")) {
5969 // Would prefer to check built-in property, but tagPowerPlaneService()
5970 // is called before pciDevice->registerService().
5971 IORegistryEntry
* parent
= service
->getParentEntry(gIODTPlane
);
5972 if ((parent
== pciHostBridgeDevice
) && service
->propertyExists("acpi-device")) {
5973 int bit
= pmTracer
->recordTopLevelPCIDevice( service
);
5975 // Save the assigned bit for fast lookup.
5976 actions
->flags
|= (bit
& kPMActionsPCIBitNumberMask
);
5978 actions
->actionPowerChangeStart
=
5979 OSMemberFunctionCast(
5980 IOPMActionPowerChangeStart
, this,
5981 &IOPMrootDomain::handlePowerChangeStartForPCIDevice
);
5983 actions
->actionPowerChangeDone
=
5984 OSMemberFunctionCast(
5985 IOPMActionPowerChangeDone
, this,
5986 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice
);
5992 //******************************************************************************
5993 // PM actions for root domain
5994 //******************************************************************************
5997 IOPMrootDomain::overrideOurPowerChange(
5998 IOService
* service
,
5999 IOPMActions
* actions
,
6000 const IOPMRequest
* request
,
6001 IOPMPowerStateIndex
* inOutPowerState
,
6002 IOPMPowerChangeFlags
* inOutChangeFlags
)
6004 uint32_t changeFlags
= *inOutChangeFlags
;
6005 uint32_t desiredPowerState
= (uint32_t) *inOutPowerState
;
6006 uint32_t currentPowerState
= (uint32_t) getPowerState();
6008 if (request
->getTag() == 0) {
6009 // Set a tag for any request that originates from IOServicePM
6010 (const_cast<IOPMRequest
*>(request
))->fTag
= nextRequestTag(kCPSReasonPMInternals
);
6013 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6014 getPowerStateString(currentPowerState
),
6015 getPowerStateString(desiredPowerState
),
6016 _currentCapability
, changeFlags
,
6020 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6022 * ASBM send lowBattery notifications every 1 second until the device
6023 * enters hibernation. This queues up multiple sleep requests.
6024 * After the device wakes from hibernation, none of these previously
6025 * queued sleep requests are valid.
6026 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6027 * and is cleared at the very last point in sleep.
6028 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6029 * lowBatteryCondition is invalid
6031 if (REQUEST_TAG_TO_REASON(request
->getTag()) == kIOPMSleepReasonLowPower
) {
6032 if (!lowBatteryCondition
) {
6033 DLOG("Duplicate lowBattery sleep");
6034 *inOutChangeFlags
|= kIOPMNotDone
;
6040 if ((AOT_STATE
== desiredPowerState
) && (ON_STATE
== currentPowerState
)) {
6041 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6042 *inOutChangeFlags
|= kIOPMNotDone
;
6046 if (changeFlags
& kIOPMParentInitiated
) {
6047 // Root parent is permanently pegged at max power,
6048 // a parent initiated power change is unexpected.
6049 *inOutChangeFlags
|= kIOPMNotDone
;
6053 if (desiredPowerState
< currentPowerState
) {
6054 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
6055 // Root domain is dropping power state from ON->SLEEP.
6056 // If system is in full wake, first enter dark wake by
6057 // converting the power drop to a capability change.
6058 // Once in dark wake, transition to sleep state ASAP.
6060 darkWakeToSleepASAP
= true;
6062 // Drop graphics and audio capability
6063 _desiredCapability
&= ~(
6064 kIOPMSystemCapabilityGraphics
|
6065 kIOPMSystemCapabilityAudio
);
6067 // Convert to capability change (ON->ON)
6068 *inOutPowerState
= getRUN_STATE();
6069 *inOutChangeFlags
|= kIOPMSynchronize
;
6071 // Revert device desire from SLEEP to ON
6072 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride
);
6074 // System is already in dark wake, ok to drop power state.
6075 // Broadcast root power down to entire tree.
6076 *inOutChangeFlags
|= kIOPMRootChangeDown
;
6078 } else if (desiredPowerState
> currentPowerState
) {
6079 if ((_currentCapability
& kIOPMSystemCapabilityCPU
) == 0) {
6080 // Broadcast power up when waking from sleep, but not for the
6081 // initial power change at boot by checking for cpu capability.
6082 *inOutChangeFlags
|= kIOPMRootChangeUp
;
6088 IOPMrootDomain::handleOurPowerChangeStart(
6089 IOService
* service
,
6090 IOPMActions
* actions
,
6091 const IOPMRequest
* request
,
6092 IOPMPowerStateIndex newPowerState
,
6093 IOPMPowerChangeFlags
* inOutChangeFlags
)
6095 IOPMRequestTag requestTag
= request
->getTag();
6096 IOPMRequestTag sleepReason
;
6098 uint32_t changeFlags
= *inOutChangeFlags
;
6099 uint32_t currentPowerState
= (uint32_t) getPowerState();
6100 bool publishSleepReason
= false;
6102 // Check if request has a valid sleep reason
6103 sleepReason
= REQUEST_TAG_TO_REASON(requestTag
);
6104 if (sleepReason
< kIOPMSleepReasonClamshell
) {
6105 sleepReason
= kIOPMSleepReasonIdle
;
6108 _systemTransitionType
= kSystemTransitionNone
;
6109 _systemMessageClientMask
= 0;
6110 capabilityLoss
= false;
6111 toldPowerdCapWillChange
= false;
6113 // Emergency notifications may arrive after the initial sleep request
6114 // has been queued. Override the sleep reason so powerd and others can
6115 // treat this as an emergency sleep.
6116 if (lowBatteryCondition
) {
6117 sleepReason
= kIOPMSleepReasonLowPower
;
6118 } else if (thermalEmergencyState
) {
6119 sleepReason
= kIOPMSleepReasonThermalEmergency
;
6122 // 1. Explicit capability change.
6123 if (changeFlags
& kIOPMSynchronize
) {
6124 if (newPowerState
== ON_STATE
) {
6125 if (changeFlags
& kIOPMSyncNoChildNotify
) {
6126 _systemTransitionType
= kSystemTransitionNewCapClient
;
6128 _systemTransitionType
= kSystemTransitionCapability
;
6132 // 2. Going to sleep (cancellation still possible).
6133 else if (newPowerState
< currentPowerState
) {
6134 _systemTransitionType
= kSystemTransitionSleep
;
6136 // 3. Woke from (idle or demand) sleep.
6137 else if (!systemBooting
&&
6138 (changeFlags
& kIOPMSelfInitiated
) &&
6139 (newPowerState
> currentPowerState
)) {
6140 _systemTransitionType
= kSystemTransitionWake
;
6141 _desiredCapability
= kIOPMSystemCapabilityCPU
| kIOPMSystemCapabilityNetwork
;
6143 // Early exit from dark wake to full (e.g. LID open)
6144 if (kFullWakeReasonNone
!= fullWakeReason
) {
6145 _desiredCapability
|= (
6146 kIOPMSystemCapabilityGraphics
|
6147 kIOPMSystemCapabilityAudio
);
6149 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6150 if (fullWakeReason
== kFullWakeReasonLocalUser
) {
6151 darkWakeExit
= true;
6152 darkWakeToSleepASAP
= false;
6153 setProperty(kIOPMRootDomainWakeTypeKey
, isRTCAlarmWake
?
6154 kIOPMRootDomainWakeTypeAlarm
: kIOPMRootDomainWakeTypeUser
);
6159 IOHibernateSetWakeCapabilities(_desiredCapability
);
6163 // Update pending wake capability at the beginning of every
6164 // state transition (including synchronize). This will become
6165 // the current capability at the end of the transition.
6167 if (kSystemTransitionSleep
== _systemTransitionType
) {
6168 _pendingCapability
= 0;
6169 capabilityLoss
= true;
6170 } else if (kSystemTransitionNewCapClient
!= _systemTransitionType
) {
6171 _pendingCapability
= _desiredCapability
|
6172 kIOPMSystemCapabilityCPU
|
6173 kIOPMSystemCapabilityNetwork
;
6175 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
6176 _pendingCapability
|= kIOPMSystemCapabilityAudio
;
6179 if ((kSystemTransitionCapability
== _systemTransitionType
) &&
6180 (_pendingCapability
== _currentCapability
)) {
6181 // Cancel the PM state change.
6182 _systemTransitionType
= kSystemTransitionNone
;
6183 *inOutChangeFlags
|= kIOPMNotDone
;
6185 if (__builtin_popcount(_pendingCapability
) <
6186 __builtin_popcount(_currentCapability
)) {
6187 capabilityLoss
= true;
6191 // 1. Capability change.
6192 if (kSystemTransitionCapability
== _systemTransitionType
) {
6193 // Dark to Full transition.
6194 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
6195 tracePoint( kIOPMTracePointDarkWakeExit
);
6197 #if defined(XNU_TARGET_OS_OSX)
6198 // rdar://problem/65627936
6199 // When a dark->full wake promotion is scheduled before an ON->SLEEP
6200 // power state drop, invalidate any request to drop power state already
6201 // in the queue, including the override variant, unless full wake cannot
6202 // be sustained. Any power state drop queued after this SustainFullWake
6203 // request will not be affected.
6204 if (checkSystemCanSustainFullWake()) {
6205 changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake
);
6209 willEnterFullWake();
6212 // Full to Dark transition.
6213 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
6214 // Clear previous stats
6215 IOLockLock(pmStatsLock
);
6216 if (pmStatsAppResponses
) {
6217 pmStatsAppResponses
= OSArray::withCapacity(5);
6219 IOLockUnlock(pmStatsLock
);
6221 tracePoint( kIOPMTracePointDarkWakeEntry
);
6222 *inOutChangeFlags
|= kIOPMSyncTellPowerDown
;
6223 _systemMessageClientMask
= kSystemMessageClientPowerd
|
6224 kSystemMessageClientLegacyApp
;
6227 // Prevent user active transitions before notifying clients
6228 // that system will sleep.
6229 preventTransitionToUserActive(true);
6231 IOService::setAdvisoryTickleEnable( false );
6233 // Publish the sleep reason for full to dark wake
6234 publishSleepReason
= true;
6235 lastSleepReason
= fullToDarkReason
= sleepReason
;
6237 // Publish a UUID for the Sleep --> Wake cycle
6238 handlePublishSleepWakeUUID(true);
6239 if (sleepDelaysReport
) {
6240 clock_get_uptime(&ts_sleepStart
);
6241 DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart
);
6244 darkWakeExit
= false;
6248 else if (kSystemTransitionSleep
== _systemTransitionType
) {
6249 // Beginning of a system sleep transition.
6250 // Cancellation is still possible.
6251 tracePoint( kIOPMTracePointSleepStarted
);
6253 _systemMessageClientMask
= kSystemMessageClientAll
;
6254 if ((_currentCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
6255 _systemMessageClientMask
&= ~kSystemMessageClientLegacyApp
;
6257 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
6258 // Kernel priority clients are only notified on the initial
6259 // transition to full wake, so don't notify them unless system
6260 // has gained graphics capability since the last system wake.
6261 _systemMessageClientMask
&= ~kSystemMessageClientKernel
;
6263 // System was in full wake, but the downwards power transition is driven
6264 // by a request that originates from IOServicePM, so it isn't tagged with
6265 // a valid system sleep reason.
6266 if (REQUEST_TAG_TO_REASON(requestTag
) == kCPSReasonPMInternals
) {
6267 // Publish the same reason for full to dark
6268 sleepReason
= fullToDarkReason
;
6272 gIOHibernateState
= 0;
6275 // Record the reason for dark wake back to sleep
6276 // System may not have ever achieved full wake
6278 publishSleepReason
= true;
6279 lastSleepReason
= sleepReason
;
6280 if (sleepDelaysReport
) {
6281 clock_get_uptime(&ts_sleepStart
);
6282 DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart
);
6286 else if (kSystemTransitionWake
== _systemTransitionType
) {
6287 tracePoint( kIOPMTracePointWakeWillPowerOnClients
);
6288 // Clear stats about sleep
6290 if (AOT_STATE
== newPowerState
) {
6291 _pendingCapability
= 0;
6294 if (AOT_STATE
== currentPowerState
) {
6295 // Wake events are no longer accepted after waking to AOT_STATE.
6296 // Re-enable wake event acceptance to append wake events claimed
6297 // during the AOT to ON_STATE transition.
6298 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable
);
6301 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
6302 willEnterFullWake();
6306 // The only location where the sleep reason is published. At this point
6307 // sleep can still be cancelled, but sleep reason should be published
6308 // early for logging purposes.
6310 if (publishSleepReason
) {
6311 static const char * IOPMSleepReasons
[] =
6313 kIOPMClamshellSleepKey
,
6314 kIOPMPowerButtonSleepKey
,
6315 kIOPMSoftwareSleepKey
,
6316 kIOPMOSSwitchHibernationKey
,
6318 kIOPMLowPowerSleepKey
,
6319 kIOPMThermalEmergencySleepKey
,
6320 kIOPMMaintenanceSleepKey
,
6321 kIOPMSleepServiceExitKey
,
6322 kIOPMDarkWakeThermalEmergencyKey
,
6323 kIOPMNotificationWakeExitKey
6326 // Record sleep cause in IORegistry
6327 uint32_t reasonIndex
= sleepReason
- kIOPMSleepReasonClamshell
;
6328 if (reasonIndex
< sizeof(IOPMSleepReasons
) / sizeof(IOPMSleepReasons
[0])) {
6329 DLOG("sleep reason %s\n", IOPMSleepReasons
[reasonIndex
]);
6330 setProperty(kRootDomainSleepReasonKey
, IOPMSleepReasons
[reasonIndex
]);
6334 if ((kSystemTransitionNone
!= _systemTransitionType
) &&
6335 (kSystemTransitionNewCapClient
!= _systemTransitionType
)) {
6336 _systemStateGeneration
++;
6337 systemDarkWake
= false;
6339 DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6340 getPowerStateString(currentPowerState
),
6341 getPowerStateString((uint32_t) newPowerState
),
6342 _currentCapability
, _pendingCapability
,
6343 *inOutChangeFlags
, _systemStateGeneration
, _systemMessageClientMask
,
6347 if ((AOT_STATE
== newPowerState
) && (SLEEP_STATE
!= currentPowerState
)) {
6348 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState
));
6350 if (_aotNow
&& (ON_STATE
== newPowerState
)) {
6352 aotShouldExit(false, true);
6359 IOPMrootDomain::handleOurPowerChangeDone(
6360 IOService
* service
,
6361 IOPMActions
* actions
,
6362 const IOPMRequest
* request
,
6363 IOPMPowerStateIndex oldPowerState
,
6364 IOPMPowerChangeFlags changeFlags
)
6366 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
6367 _systemTransitionType
= kSystemTransitionNone
;
6371 if (_systemTransitionType
!= kSystemTransitionNone
) {
6372 uint32_t currentPowerState
= (uint32_t) getPowerState();
6374 if (changeFlags
& kIOPMNotDone
) {
6375 // Power down was cancelled or vetoed.
6376 _pendingCapability
= _currentCapability
;
6377 lastSleepReason
= 0;
6379 // When sleep is cancelled or reverted, don't report
6380 // the target (lower) power state as the previous state.
6381 oldPowerState
= currentPowerState
;
6383 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
) &&
6384 CAP_CURRENT(kIOPMSystemCapabilityCPU
)) {
6385 #if defined(XNU_TARGET_OS_OSX)
6386 pmPowerStateQueue
->submitPowerEvent(
6387 kPowerEventPolicyStimulus
,
6388 (void *) kStimulusDarkWakeReentry
,
6389 _systemStateGeneration
);
6390 #else /* !defined(XNU_TARGET_OS_OSX) */
6391 // On embedded, there are no factors that can prolong a
6392 // "darkWake" when a power down is vetoed. We need to
6393 // promote to "fullWake" at least once so that factors
6394 // that prevent idle sleep can assert themselves if required
6395 pmPowerStateQueue
->submitPowerEvent(
6396 kPowerEventPolicyStimulus
,
6397 (void *) kStimulusDarkWakeActivityTickle
);
6398 #endif /* !defined(XNU_TARGET_OS_OSX) */
6401 // Revert device desire to max.
6402 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel
);
6404 // Send message on dark wake to full wake promotion.
6405 // tellChangeUp() handles the normal SLEEP->ON case.
6407 if (kSystemTransitionCapability
== _systemTransitionType
) {
6408 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
6409 lastSleepReason
= 0; // stop logging wrangler tickles
6410 tellClients(kIOMessageSystemHasPoweredOn
);
6412 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
6413 // Going dark, reset full wake state
6414 // userIsActive will be cleared by wrangler powering down
6415 fullWakeReason
= kFullWakeReasonNone
;
6417 if (ts_sleepStart
) {
6418 clock_get_uptime(&wake2DarkwakeDelay
);
6419 SUB_ABSOLUTETIME(&wake2DarkwakeDelay
, &ts_sleepStart
);
6420 DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay
);
6426 // Reset state after exiting from dark wake.
6428 if (CAP_GAIN(kIOPMSystemCapabilityGraphics
) ||
6429 CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
6430 darkWakeMaintenance
= false;
6431 darkWakeToSleepASAP
= false;
6432 pciCantSleepValid
= false;
6433 darkWakeSleepService
= false;
6435 if (CAP_LOSS(kIOPMSystemCapabilityCPU
)) {
6436 // Remove the influence of display power assertion
6437 // before next system wake.
6439 wrangler
->changePowerStateForRootDomain(
6440 kWranglerPowerStateMin
);
6442 removeProperty(gIOPMUserTriggeredFullWakeKey
.get());
6446 // Entered dark mode.
6448 if (((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6449 (_pendingCapability
& kIOPMSystemCapabilityCPU
)) {
6450 // Queue an evaluation of whether to remain in dark wake,
6451 // and for how long. This serves the purpose of draining
6452 // any assertions from the queue.
6454 pmPowerStateQueue
->submitPowerEvent(
6455 kPowerEventPolicyStimulus
,
6456 (void *) kStimulusDarkWakeEntry
,
6457 _systemStateGeneration
);
6461 DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6462 getPowerStateString((uint32_t) oldPowerState
), getPowerStateString(currentPowerState
),
6463 _currentCapability
, _pendingCapability
,
6464 changeFlags
, _systemStateGeneration
, _systemMessageClientMask
,
6467 if ((currentPowerState
== ON_STATE
) && pmAssertions
) {
6468 pmAssertions
->reportCPUBitAccounting();
6471 if (_pendingCapability
& kIOPMSystemCapabilityGraphics
) {
6473 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6474 if (clamshellExists
&& fullWakeThreadCall
) {
6475 AbsoluteTime deadline
;
6476 clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
, kSecondScale
, &deadline
);
6477 thread_call_enter_delayed(fullWakeThreadCall
, deadline
);
6480 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU
)) {
6484 // Update current system capability.
6485 if (_currentCapability
!= _pendingCapability
) {
6486 _currentCapability
= _pendingCapability
;
6489 // Update highest system capability.
6491 _highestCapability
|= _currentCapability
;
6493 if (darkWakePostTickle
&&
6494 (kSystemTransitionWake
== _systemTransitionType
) &&
6495 (gDarkWakeFlags
& kDarkWakeFlagPromotionMask
) ==
6496 kDarkWakeFlagPromotionLate
) {
6497 darkWakePostTickle
= false;
6499 } else if (darkWakeExit
) {
6500 requestFullWake( kFullWakeReasonLocalUser
);
6503 // Reset tracepoint at completion of capability change,
6504 // completion of wake transition, and aborted sleep transition.
6506 if ((_systemTransitionType
== kSystemTransitionCapability
) ||
6507 (_systemTransitionType
== kSystemTransitionWake
) ||
6508 ((_systemTransitionType
== kSystemTransitionSleep
) &&
6509 (changeFlags
& kIOPMNotDone
))) {
6510 setProperty(kIOPMSystemCapabilitiesKey
, _currentCapability
, 64);
6511 tracePoint( kIOPMTracePointSystemUp
);
6514 _systemTransitionType
= kSystemTransitionNone
;
6515 _systemMessageClientMask
= 0;
6516 toldPowerdCapWillChange
= false;
6518 darkWakeLogClamp
= false;
6520 if (lowBatteryCondition
) {
6521 privateSleepSystem(kIOPMSleepReasonLowPower
);
6522 } else if (thermalEmergencyState
) {
6523 privateSleepSystem(kIOPMSleepReasonThermalEmergency
);
6524 } else if ((fullWakeReason
== kFullWakeReasonDisplayOn
) && !displayPowerOnRequested
) {
6525 // Request for full wake is removed while system is waking up to full wake
6526 DLOG("DisplayOn fullwake request is removed\n");
6527 handleSetDisplayPowerOn(false);
6530 if ((gClamshellFlags
& kClamshell_WAR_47715679
) && isRTCAlarmWake
) {
6531 pmPowerStateQueue
->submitPowerEvent(
6532 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) kLocalEvalClamshellCommand
);
6537 //******************************************************************************
6538 // PM actions for graphics and audio.
6539 //******************************************************************************
6542 IOPMrootDomain::overridePowerChangeForService(
6543 IOService
* service
,
6544 IOPMActions
* actions
,
6545 const IOPMRequest
* request
,
6546 IOPMPowerStateIndex
* inOutPowerState
,
6547 IOPMPowerChangeFlags
* inOutChangeFlags
)
6549 uint32_t powerState
= (uint32_t) *inOutPowerState
;
6550 uint32_t changeFlags
= (uint32_t) *inOutChangeFlags
;
6551 const uint32_t actionFlags
= actions
->flags
;
6553 if (kSystemTransitionNone
== _systemTransitionType
) {
6554 // Not in midst of a system transition.
6555 // Do not set kPMActionsStatePowerClamped.
6556 } else if ((actions
->state
& kPMActionsStatePowerClamped
) == 0) {
6557 bool enableClamp
= false;
6559 // For most drivers, enable the clamp during ON->Dark transition
6560 // which has the kIOPMSynchronize flag set in changeFlags.
6561 if ((actionFlags
& kPMActionsFlagIsDisplayWrangler
) &&
6562 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6563 (changeFlags
& kIOPMSynchronize
)) {
6565 } else if ((actionFlags
& kPMActionsFlagIsAudioDriver
) &&
6566 ((gDarkWakeFlags
& kDarkWakeFlagAudioNotSuppressed
) == 0) &&
6567 ((_pendingCapability
& kIOPMSystemCapabilityAudio
) == 0) &&
6568 (changeFlags
& kIOPMSynchronize
)) {
6570 } else if ((actionFlags
& kPMActionsFlagHasDarkWakePowerState
) &&
6571 ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0) &&
6572 (changeFlags
& kIOPMSynchronize
)) {
6574 } else if ((actionFlags
& kPMActionsFlagIsGraphicsDriver
) &&
6575 (_systemTransitionType
== kSystemTransitionSleep
)) {
6576 // For graphics drivers, clamp power when entering
6577 // system sleep. Not when dropping to dark wake.
6582 actions
->state
|= kPMActionsStatePowerClamped
;
6583 DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6584 service
->getName(), service
->getRegistryEntryID(),
6585 _pendingCapability
, powerState
, changeFlags
);
6587 } else if ((actions
->state
& kPMActionsStatePowerClamped
) != 0) {
6588 bool disableClamp
= false;
6590 if ((actionFlags
& (
6591 kPMActionsFlagIsDisplayWrangler
|
6592 kPMActionsFlagIsGraphicsDriver
)) &&
6593 (_pendingCapability
& kIOPMSystemCapabilityGraphics
)) {
6594 disableClamp
= true;
6595 } else if ((actionFlags
& kPMActionsFlagIsAudioDriver
) &&
6596 (_pendingCapability
& kIOPMSystemCapabilityAudio
)) {
6597 disableClamp
= true;
6598 } else if ((actionFlags
& kPMActionsFlagHasDarkWakePowerState
) &&
6599 (_pendingCapability
& kIOPMSystemCapabilityGraphics
)) {
6600 disableClamp
= true;
6604 actions
->state
&= ~kPMActionsStatePowerClamped
;
6605 DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6606 service
->getName(), service
->getRegistryEntryID(),
6607 _pendingCapability
, powerState
, changeFlags
);
6611 if (actions
->state
& kPMActionsStatePowerClamped
) {
6612 uint32_t maxPowerState
= 0;
6614 // Determine the max power state allowed when clamp is enabled
6615 if (changeFlags
& (kIOPMDomainDidChange
| kIOPMDomainWillChange
)) {
6616 // Parent intiated power state changes
6617 if ((service
->getPowerState() > maxPowerState
) &&
6618 (actionFlags
& kPMActionsFlagIsDisplayWrangler
)) {
6621 // Remove lingering effects of any tickle before entering
6622 // dark wake. It will take a new tickle to return to full
6623 // wake, so the existing tickle state is useless.
6625 if (changeFlags
& kIOPMDomainDidChange
) {
6626 *inOutChangeFlags
|= kIOPMExpireIdleTimer
;
6628 } else if (actionFlags
& kPMActionsFlagIsGraphicsDriver
) {
6630 } else if (actionFlags
& kPMActionsFlagHasDarkWakePowerState
) {
6631 maxPowerState
= actions
->darkWakePowerState
;
6634 // Deny all self-initiated changes when power is limited.
6635 // Wrangler tickle should never defeat the limiter.
6636 maxPowerState
= service
->getPowerState();
6639 if (powerState
> maxPowerState
) {
6640 DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6641 service
->getName(), service
->getRegistryEntryID(),
6642 powerState
, maxPowerState
, changeFlags
);
6643 *inOutPowerState
= maxPowerState
;
6645 if (darkWakePostTickle
&&
6646 (actionFlags
& kPMActionsFlagIsDisplayWrangler
) &&
6647 (changeFlags
& kIOPMDomainWillChange
) &&
6648 ((gDarkWakeFlags
& kDarkWakeFlagPromotionMask
) ==
6649 kDarkWakeFlagPromotionEarly
)) {
6650 darkWakePostTickle
= false;
6655 if (!darkWakePowerClamped
&& (changeFlags
& kIOPMDomainDidChange
)) {
6656 if (darkWakeLogClamp
) {
6660 clock_get_uptime(&now
);
6661 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
6662 absolutetime_to_nanoseconds(now
, &nsec
);
6663 DLOG("dark wake power clamped after %u ms\n",
6664 ((int)((nsec
) / NSEC_PER_MSEC
)));
6666 darkWakePowerClamped
= true;
6672 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6673 IOService
* service
,
6674 IOPMActions
* actions
)
6676 #if DISPLAY_WRANGLER_PRESENT
6677 // Warning: Not running in PM work loop context - don't modify state !!!
6678 // Trap tickle directed to IODisplayWrangler while running with graphics
6679 // capability suppressed.
6681 assert(service
== wrangler
);
6683 clock_get_uptime(&userActivityTime
);
6684 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonIdle
)
6685 || (lastSleepReason
== kIOPMSleepReasonMaintenance
)
6686 || (lastSleepReason
== kIOPMSleepReasonSoftware
));
6688 userActivityCount
++;
6689 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6690 userActivityCount
, lastSleepReason
);
6693 if (!darkWakeExit
&& ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0)) {
6694 DLOG("display wrangler tickled\n");
6695 if (kIOLogPMRootDomain
& gIOKitDebug
) {
6696 OSReportWithBacktrace("Dark wake display tickle");
6698 if (pmPowerStateQueue
) {
6699 pmPowerStateQueue
->submitPowerEvent(
6700 kPowerEventPolicyStimulus
,
6701 (void *) kStimulusDarkWakeActivityTickle
,
6702 true /* set wake type */ );
6705 #endif /* DISPLAY_WRANGLER_PRESENT */
6709 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6710 IOService
* service
,
6711 IOPMActions
* actions
,
6712 const OSSymbol
* powerClient
,
6713 IOPMPowerStateIndex oldPowerState
,
6714 IOPMPowerStateIndex newPowerState
)
6716 #if DISPLAY_WRANGLER_PRESENT
6717 assert(service
== wrangler
);
6719 // This function implements half of the user active detection
6720 // by monitoring changes to the display wrangler's device desire.
6722 // User becomes active when either:
6723 // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6724 // in max power state. This desire change in absence of a power state
6725 // change is detected within. This handles the case when user becomes
6726 // active while the display is already lit by setDisplayPowerOn().
6728 // 2. Power state change to max, and DeviceDesire is also at max.
6729 // Handled by displayWranglerNotification().
6731 // User becomes inactive when DeviceDesire drops to sleep state or below.
6733 DLOG("wrangler %s (ps %u, %u->%u)\n",
6734 powerClient
->getCStringNoCopy(),
6735 (uint32_t) service
->getPowerState(),
6736 (uint32_t) oldPowerState
, (uint32_t) newPowerState
);
6738 if (powerClient
== gIOPMPowerClientDevice
) {
6739 if ((newPowerState
> oldPowerState
) &&
6740 (newPowerState
== kWranglerPowerStateMax
) &&
6741 (service
->getPowerState() == kWranglerPowerStateMax
)) {
6742 evaluatePolicy( kStimulusEnterUserActiveState
);
6743 } else if ((newPowerState
< oldPowerState
) &&
6744 (newPowerState
<= kWranglerPowerStateSleep
)) {
6745 evaluatePolicy( kStimulusLeaveUserActiveState
);
6749 if (newPowerState
<= kWranglerPowerStateSleep
) {
6750 evaluatePolicy( kStimulusDisplayWranglerSleep
);
6751 } else if (newPowerState
== kWranglerPowerStateMax
) {
6752 evaluatePolicy( kStimulusDisplayWranglerWake
);
6754 #endif /* DISPLAY_WRANGLER_PRESENT */
6757 //******************************************************************************
6758 // User active state management
6759 //******************************************************************************
6762 IOPMrootDomain::preventTransitionToUserActive( bool prevent
)
6764 #if DISPLAY_WRANGLER_PRESENT
6765 _preventUserActive
= prevent
;
6766 if (wrangler
&& !_preventUserActive
) {
6767 // Allowing transition to user active, but the wrangler may have
6768 // already powered ON in case of sleep cancel/revert. Poll the
6769 // same conditions checked for in displayWranglerNotification()
6770 // to bring the user active state up to date.
6772 if ((wrangler
->getPowerState() == kWranglerPowerStateMax
) &&
6773 (wrangler
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
6774 kWranglerPowerStateMax
)) {
6775 evaluatePolicy( kStimulusEnterUserActiveState
);
6778 #endif /* DISPLAY_WRANGLER_PRESENT */
6781 //******************************************************************************
6782 // Approve usage of delayed child notification by PM.
6783 //******************************************************************************
6786 IOPMrootDomain::shouldDelayChildNotification(
6787 IOService
* service
)
6789 if ((kFullWakeReasonNone
== fullWakeReason
) &&
6790 (kSystemTransitionWake
== _systemTransitionType
)) {
6791 DLOG("%s: delay child notify\n", service
->getName());
6797 //******************************************************************************
6798 // PM actions for PCI device.
6799 //******************************************************************************
6802 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6803 IOService
* service
,
6804 IOPMActions
* actions
,
6805 const IOPMRequest
* request
,
6806 IOPMPowerStateIndex powerState
,
6807 IOPMPowerChangeFlags
* inOutChangeFlags
)
6809 pmTracer
->tracePCIPowerChange(
6810 PMTraceWorker::kPowerChangeStart
,
6811 service
, *inOutChangeFlags
,
6812 (actions
->flags
& kPMActionsPCIBitNumberMask
));
6816 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6817 IOService
* service
,
6818 IOPMActions
* actions
,
6819 const IOPMRequest
* request
,
6820 IOPMPowerStateIndex powerState
,
6821 IOPMPowerChangeFlags changeFlags
)
6823 pmTracer
->tracePCIPowerChange(
6824 PMTraceWorker::kPowerChangeCompleted
,
6825 service
, changeFlags
,
6826 (actions
->flags
& kPMActionsPCIBitNumberMask
));
6829 //******************************************************************************
6832 // Override IOService::registerInterest() for root domain clients.
6833 //******************************************************************************
6835 class IOPMServiceInterestNotifier
: public _IOServiceInterestNotifier
6837 friend class IOPMrootDomain
;
6838 OSDeclareDefaultStructors(IOPMServiceInterestNotifier
);
6841 uint32_t ackTimeoutCnt
;
6842 uint32_t msgType
; // Message pending ack
6844 uint32_t maxMsgDelayMS
;
6845 uint32_t maxAckDelayMS
;
6846 uint64_t msgAbsTime
;
6849 OSSharedPtr
<const OSSymbol
> identifier
;
6850 OSSharedPtr
<const OSSymbol
> clientName
;
6853 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier
, _IOServiceInterestNotifier
)
6855 OSSharedPtr
<IONotifier
>
6856 IOPMrootDomain::registerInterest(
6857 const OSSymbol
* typeOfInterest
,
6858 IOServiceInterestHandler handler
,
6859 void * target
, void * ref
)
6861 IOPMServiceInterestNotifier
* notifier
;
6862 bool isSystemCapabilityClient
;
6863 bool isKernelCapabilityClient
;
6864 IOReturn rc
= kIOReturnError
;
6866 isSystemCapabilityClient
= typeOfInterest
&&
6867 typeOfInterest
->isEqualTo(kIOPMSystemCapabilityInterest
);
6869 isKernelCapabilityClient
= typeOfInterest
&&
6870 typeOfInterest
->isEqualTo(gIOPriorityPowerStateInterest
);
6872 if (isSystemCapabilityClient
) {
6873 typeOfInterest
= gIOAppPowerStateInterest
;
6876 notifier
= new IOPMServiceInterestNotifier
;
6881 if (notifier
->init()) {
6882 rc
= super::registerInterestForNotifier(notifier
, typeOfInterest
, handler
, target
, ref
);
6884 if (rc
!= kIOReturnSuccess
) {
6888 notifier
->ackTimeoutCnt
= 0;
6890 if (pmPowerStateQueue
) {
6891 if (isSystemCapabilityClient
) {
6893 if (pmPowerStateQueue
->submitPowerEvent(
6894 kPowerEventRegisterSystemCapabilityClient
, notifier
) == false) {
6895 notifier
->release();
6899 if (isKernelCapabilityClient
) {
6901 if (pmPowerStateQueue
->submitPowerEvent(
6902 kPowerEventRegisterKernelCapabilityClient
, notifier
) == false) {
6903 notifier
->release();
6908 OSSharedPtr
<OSData
> data
;
6909 uint8_t *uuid
= NULL
;
6910 OSSharedPtr
<OSKext
> kext
= OSKext::lookupKextWithAddress((vm_address_t
)handler
);
6912 data
= kext
->copyUUID();
6914 if (data
&& (data
->getLength() == sizeof(uuid_t
))) {
6915 uuid
= (uint8_t *)(data
->getBytesNoCopy());
6917 notifier
->uuid0
= ((uint64_t)(uuid
[0]) << 56) | ((uint64_t)(uuid
[1]) << 48) | ((uint64_t)(uuid
[2]) << 40) |
6918 ((uint64_t)(uuid
[3]) << 32) | ((uint64_t)(uuid
[4]) << 24) | ((uint64_t)(uuid
[5]) << 16) |
6919 ((uint64_t)(uuid
[6]) << 8) | (uuid
[7]);
6920 notifier
->uuid1
= ((uint64_t)(uuid
[8]) << 56) | ((uint64_t)(uuid
[9]) << 48) | ((uint64_t)(uuid
[10]) << 40) |
6921 ((uint64_t)(uuid
[11]) << 32) | ((uint64_t)(uuid
[12]) << 24) | ((uint64_t)(uuid
[13]) << 16) |
6922 ((uint64_t)(uuid
[14]) << 8) | (uuid
[15]);
6924 notifier
->identifier
= copyKextIdentifierWithAddress((vm_address_t
) handler
);
6926 return OSSharedPtr
<IOPMServiceInterestNotifier
>(notifier
, OSNoRetain
);
6929 //******************************************************************************
6930 // systemMessageFilter
6932 //******************************************************************************
6935 IOPMrootDomain::systemMessageFilter(
6936 void * object
, void * arg1
, void * arg2
, void * arg3
)
6938 const IOPMInterestContext
* context
= (const IOPMInterestContext
*) arg1
;
6939 bool isCapMsg
= (context
->messageType
== kIOMessageSystemCapabilityChange
);
6940 bool isCapClient
= false;
6942 IOPMServiceInterestNotifier
*notifier
;
6944 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, (OSObject
*)object
);
6947 if ((kSystemTransitionNewCapClient
== _systemTransitionType
) &&
6948 (!isCapMsg
|| !_joinedCapabilityClients
||
6949 !_joinedCapabilityClients
->containsObject((OSObject
*) object
))) {
6953 // Capability change message for app and kernel clients.
6957 if ((context
->notifyType
== kNotifyPriority
) ||
6958 (context
->notifyType
== kNotifyCapabilityChangePriority
)) {
6962 // powerd's systemCapabilityNotifier
6963 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) &&
6964 (object
== (void *) systemCapabilityNotifier
.get())) {
6970 IOPMSystemCapabilityChangeParameters
* capArgs
=
6971 (IOPMSystemCapabilityChangeParameters
*) arg2
;
6973 if (kSystemTransitionNewCapClient
== _systemTransitionType
) {
6974 capArgs
->fromCapabilities
= 0;
6975 capArgs
->toCapabilities
= _currentCapability
;
6976 capArgs
->changeFlags
= 0;
6978 capArgs
->fromCapabilities
= _currentCapability
;
6979 capArgs
->toCapabilities
= _pendingCapability
;
6981 if (context
->isPreChange
) {
6982 capArgs
->changeFlags
= kIOPMSystemCapabilityWillChange
;
6984 capArgs
->changeFlags
= kIOPMSystemCapabilityDidChange
;
6987 if ((object
== (void *) systemCapabilityNotifier
.get()) &&
6988 context
->isPreChange
) {
6989 toldPowerdCapWillChange
= true;
6993 // Capability change messages only go to the PM configd plugin.
6994 // Wait for response post-change if capabilitiy is increasing.
6995 // Wait for response pre-change if capability is decreasing.
6997 if ((context
->notifyType
== kNotifyCapabilityChangeApps
) && arg3
&&
6998 ((capabilityLoss
&& context
->isPreChange
) ||
6999 (!capabilityLoss
&& !context
->isPreChange
))) {
7000 // app has not replied yet, wait for it
7001 *((OSObject
**) arg3
) = kOSBooleanFalse
;
7008 // Capability client will always see kIOMessageCanSystemSleep,
7009 // even for demand sleep. It will also have a chance to veto
7010 // sleep one last time after all clients have responded to
7011 // kIOMessageSystemWillSleep
7013 if ((kIOMessageCanSystemSleep
== context
->messageType
) ||
7014 (kIOMessageSystemWillNotSleep
== context
->messageType
)) {
7015 if (object
== (OSObject
*) systemCapabilityNotifier
.get()) {
7020 // Not idle sleep, don't ask apps.
7021 if (context
->changeFlags
& kIOPMSkipAskPowerDown
) {
7026 if (kIOPMMessageLastCallBeforeSleep
== context
->messageType
) {
7027 if ((object
== (OSObject
*) systemCapabilityNotifier
.get()) &&
7028 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) &&
7029 (fullToDarkReason
== kIOPMSleepReasonIdle
)) {
7035 // Reject capability change messages for legacy clients.
7036 // Reject legacy system sleep messages for capability client.
7038 if (isCapMsg
|| (object
== (OSObject
*) systemCapabilityNotifier
.get())) {
7042 // Filter system sleep messages.
7044 if ((context
->notifyType
== kNotifyApps
) &&
7045 (_systemMessageClientMask
& kSystemMessageClientLegacyApp
)) {
7050 if (notifier
->ackTimeoutCnt
>= 3) {
7051 *((OSObject
**) arg3
) = kOSBooleanFalse
;
7053 *((OSObject
**) arg3
) = kOSBooleanTrue
;
7057 } else if ((context
->notifyType
== kNotifyPriority
) &&
7058 (_systemMessageClientMask
& kSystemMessageClientKernel
)) {
7063 if (allow
&& isCapMsg
&& _joinedCapabilityClients
) {
7064 _joinedCapabilityClients
->removeObject((OSObject
*) object
);
7065 if (_joinedCapabilityClients
->getCount() == 0) {
7066 DLOG("destroyed capability client set %p\n",
7067 OBFUSCATE(_joinedCapabilityClients
.get()));
7068 _joinedCapabilityClients
.reset();
7072 notifier
->msgType
= context
->messageType
;
7078 //******************************************************************************
7079 // setMaintenanceWakeCalendar
7081 //******************************************************************************
7084 IOPMrootDomain::setMaintenanceWakeCalendar(
7085 const IOPMCalendarStruct
* calendar
)
7087 OSSharedPtr
<OSData
> data
;
7091 return kIOReturnBadArgument
;
7094 data
= OSData::withBytes((void *) calendar
, sizeof(*calendar
));
7096 return kIOReturnNoMemory
;
7099 if (kPMCalendarTypeMaintenance
== calendar
->selector
) {
7100 ret
= setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey
.get(), data
.get());
7101 } else if (kPMCalendarTypeSleepService
== calendar
->selector
) {
7102 ret
= setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey
.get(), data
.get());
7109 // MARK: Display Wrangler
7111 //******************************************************************************
7112 // displayWranglerNotification
7114 // Handle the notification when the IODisplayWrangler changes power state.
7115 //******************************************************************************
7118 IOPMrootDomain::displayWranglerNotification(
7119 void * target
, void * refCon
,
7120 UInt32 messageType
, IOService
* service
,
7121 void * messageArgument
, vm_size_t argSize
)
7123 #if DISPLAY_WRANGLER_PRESENT
7124 IOPMPowerStateIndex displayPowerState
;
7125 IOPowerStateChangeNotification
* params
=
7126 (IOPowerStateChangeNotification
*) messageArgument
;
7128 if ((messageType
!= kIOMessageDeviceWillPowerOff
) &&
7129 (messageType
!= kIOMessageDeviceHasPoweredOn
)) {
7130 return kIOReturnUnsupported
;
7135 return kIOReturnUnsupported
;
7138 displayPowerState
= params
->stateNumber
;
7139 DLOG("wrangler %s ps %d\n",
7140 getIOMessageString(messageType
), (uint32_t) displayPowerState
);
7142 switch (messageType
) {
7143 case kIOMessageDeviceWillPowerOff
:
7144 // Display wrangler has dropped power due to display idle
7145 // or force system sleep.
7147 // 4 Display ON kWranglerPowerStateMax
7148 // 3 Display Dim kWranglerPowerStateDim
7149 // 2 Display Sleep kWranglerPowerStateSleep
7150 // 1 Not visible to user
7151 // 0 Not visible to user kWranglerPowerStateMin
7153 if (displayPowerState
<= kWranglerPowerStateSleep
) {
7154 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerSleep
);
7158 case kIOMessageDeviceHasPoweredOn
:
7159 // Display wrangler has powered on due to user activity
7160 // or wake from sleep.
7162 if (kWranglerPowerStateMax
== displayPowerState
) {
7163 gRootDomain
->evaluatePolicy( kStimulusDisplayWranglerWake
);
7165 // See comment in handleUpdatePowerClientForDisplayWrangler
7166 if (service
->getPowerStateForClient(gIOPMPowerClientDevice
) ==
7167 kWranglerPowerStateMax
) {
7168 gRootDomain
->evaluatePolicy( kStimulusEnterUserActiveState
);
7173 #endif /* DISPLAY_WRANGLER_PRESENT */
7174 return kIOReturnUnsupported
;
7177 //******************************************************************************
7180 //******************************************************************************
7183 IOPMrootDomain::updateUserActivity( void )
7185 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7186 clock_get_uptime(&userActivityTime
);
7187 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonSoftware
)
7188 || (lastSleepReason
== kIOPMSleepReasonIdle
)
7189 || (lastSleepReason
== kIOPMSleepReasonMaintenance
));
7191 userActivityCount
++;
7192 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
);
7197 IOPMrootDomain::reportUserInput( void )
7200 wrangler
->activityTickle(0, 0);
7202 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7203 // Update user activity
7204 updateUserActivity();
7206 if (!darkWakeExit
&& ((_pendingCapability
& kIOPMSystemCapabilityGraphics
) == 0)) {
7207 // update user active abs time
7208 clock_get_uptime(&gUserActiveAbsTime
);
7209 pmPowerStateQueue
->submitPowerEvent(
7210 kPowerEventPolicyStimulus
,
7211 (void *) kStimulusDarkWakeActivityTickle
,
7212 true /* set wake type */ );
7218 IOPMrootDomain::requestUserActive(IOService
*device
, const char *reason
)
7220 #if DISPLAY_WRANGLER_PRESENT
7222 wrangler
->activityTickle(0, 0);
7226 DLOG("requestUserActive: device is null\n");
7229 OSSharedPtr
<const OSSymbol
> deviceName
= device
->copyName();
7230 uint64_t registryID
= device
->getRegistryEntryID();
7232 if (!deviceName
|| !registryID
) {
7233 DLOG("requestUserActive: no device name or registry entry\n");
7236 const char *name
= deviceName
->getCStringNoCopy();
7238 snprintf(payload
, sizeof(payload
), "%s:%s", name
, reason
);
7239 DLOG("requestUserActive from %s (0x%llx) for %s\n", name
, registryID
, reason
);
7240 messageClient(kIOPMMessageRequestUserActive
, systemCapabilityNotifier
.get(), (void *)payload
, sizeof(payload
));
7244 //******************************************************************************
7245 // latchDisplayWranglerTickle
7246 //******************************************************************************
7249 IOPMrootDomain::latchDisplayWranglerTickle( bool latch
)
7251 #if DISPLAY_WRANGLER_PRESENT
7253 if (!(_currentCapability
& kIOPMSystemCapabilityGraphics
) &&
7254 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
7255 !checkSystemCanSustainFullWake()) {
7256 // Currently in dark wake, and not transitioning to full wake.
7257 // Full wake is unsustainable, so latch the tickle to prevent
7258 // the display from lighting up momentarily.
7259 wranglerTickled
= true;
7261 wranglerTickled
= false;
7263 } else if (wranglerTickled
&& checkSystemCanSustainFullWake()) {
7264 wranglerTickled
= false;
7266 pmPowerStateQueue
->submitPowerEvent(
7267 kPowerEventPolicyStimulus
,
7268 (void *) kStimulusDarkWakeActivityTickle
);
7271 return wranglerTickled
;
7272 #else /* ! DISPLAY_WRANGLER_PRESENT */
7274 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7277 //******************************************************************************
7278 // setDisplayPowerOn
7280 // For root domain user client
7281 //******************************************************************************
7284 IOPMrootDomain::setDisplayPowerOn( uint32_t options
)
7286 pmPowerStateQueue
->submitPowerEvent( kPowerEventSetDisplayPowerOn
,
7287 (void *) NULL
, options
);
7291 // MARK: System PM Policy
7293 //******************************************************************************
7294 // checkSystemSleepAllowed
7296 //******************************************************************************
7299 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options
,
7300 uint32_t sleepReason
)
7304 // Conditions that prevent idle and demand system sleep.
7307 if (userDisabledAllSleep
) {
7308 err
= kPMUserDisabledAllSleep
; // 1. user-space sleep kill switch
7312 if (systemBooting
|| systemShutdown
|| gWillShutdown
) {
7313 err
= kPMSystemRestartBootingInProgress
; // 2. restart or shutdown in progress
7321 // Conditions above pegs the system at full wake.
7322 // Conditions below prevent system sleep but does not prevent
7323 // dark wake, and must be called from gated context.
7326 err
= kPMConfigPreventSystemSleep
; // 3. config does not support sleep
7330 if (lowBatteryCondition
|| thermalWarningState
|| thermalEmergencyState
) {
7331 break; // always sleep on low battery or when in thermal warning/emergency state
7334 if (sleepReason
== kIOPMSleepReasonDarkWakeThermalEmergency
) {
7335 break; // always sleep on dark wake thermal emergencies
7338 if (preventSystemSleepList
->getCount() != 0) {
7339 err
= kPMChildPreventSystemSleep
; // 4. child prevent system sleep clamp
7343 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit
) ==
7344 kIOPMDriverAssertionLevelOn
) {
7345 err
= kPMCPUAssertion
; // 5. CPU assertion
7349 if (pciCantSleepValid
) {
7350 if (pciCantSleepFlag
) {
7351 err
= kPMPCIUnsupported
; // 6. PCI card does not support PM (cached)
7354 } else if (sleepSupportedPEFunction
&&
7355 CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
7357 OSBitAndAtomic(~kPCICantSleep
, &platformSleepSupport
);
7358 ret
= getPlatform()->callPlatformFunction(
7359 sleepSupportedPEFunction
.get(), false,
7360 NULL
, NULL
, NULL
, NULL
);
7361 pciCantSleepValid
= true;
7362 pciCantSleepFlag
= false;
7363 if ((platformSleepSupport
& kPCICantSleep
) ||
7364 ((ret
!= kIOReturnSuccess
) && (ret
!= kIOReturnUnsupported
))) {
7365 err
= 6; // 6. PCI card does not support PM
7366 pciCantSleepFlag
= true;
7373 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err
));
7380 IOPMrootDomain::checkSystemSleepEnabled( void )
7382 return checkSystemSleepAllowed(0, 0);
7386 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason
)
7389 return checkSystemSleepAllowed(1, sleepReason
);
7392 //******************************************************************************
7393 // checkSystemCanSustainFullWake
7394 //******************************************************************************
7397 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7399 if (lowBatteryCondition
|| thermalWarningState
|| thermalEmergencyState
) {
7400 // Low battery wake, or received a low battery notification
7401 // while system is awake. This condition will persist until
7402 // the following wake.
7406 if (clamshellExists
&& clamshellClosed
&& !clamshellSleepDisableMask
) {
7407 // Graphics state is unknown and external display might not be probed.
7408 // Do not incorporate state that requires graphics to be in max power
7409 // such as desktopMode or clamshellDisabled.
7411 if (!acAdaptorConnected
) {
7412 DLOG("full wake check: no AC\n");
7419 //******************************************************************************
7421 //******************************************************************************
7426 IOPMrootDomain::mustHibernate( void )
7428 return lowBatteryCondition
|| thermalWarningState
;
7431 #endif /* HIBERNATION */
7433 //******************************************************************************
7435 //******************************************************************************
7437 // Tables for accumulated days in year by month, latter used for leap years
7439 static const unsigned int daysbymonth
[] =
7440 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7442 static const unsigned int lydaysbymonth
[] =
7443 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7446 IOPMConvertSecondsToCalendar(clock_sec_t secs
, IOPMCalendarStruct
* dt
)
7448 const unsigned int * dbm
= daysbymonth
;
7449 clock_sec_t n
, x
, y
, z
;
7451 // Calculate seconds, minutes and hours
7453 n
= secs
% (24 * 3600);
7454 dt
->second
= n
% 60;
7456 dt
->minute
= n
% 60;
7457 dt
->hour
= (typeof(dt
->hour
))(n
/ 60);
7459 // Calculate day of week
7461 n
= secs
/ (24 * 3600);
7462 // dt->dayWeek = (n + 4) % 7;
7465 // Rebase from days since Unix epoch (1/1/1970) store in 'n',
7466 // to days since 1/1/1968 to start on 4 year cycle, beginning
7471 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7472 // Valid before 2100, since 2100 is not a leap year.
7474 x
= n
/ 1461; // number of 4 year cycles
7475 y
= n
% 1461; // days into current 4 year cycle
7478 // Add in years in the current 4 year cycle
7481 y
-= 366; // days after the leap year
7482 n
= y
% 365; // days into the current year
7483 z
+= (1 + y
/ 365); // years after the past 4-yr cycle
7486 dbm
= lydaysbymonth
;
7492 dt
->year
= (typeof(dt
->year
))z
;
7494 // Adjust remaining days value to start at 1
7500 for (x
= 1; (n
> dbm
[x
]) && (x
< 12); x
++) {
7503 dt
->month
= (typeof(dt
->month
))x
;
7505 // Calculate day of month
7507 dt
->day
= (typeof(dt
->day
))(n
- dbm
[x
- 1]);
7513 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct
* dt
)
7515 const unsigned int * dbm
= daysbymonth
;
7518 if (dt
->year
< 1970 || dt
->month
> 12) {
7522 // Seconds elapsed in the current day
7524 secs
= dt
->second
+ 60 * dt
->minute
+ 3600 * dt
->hour
;
7526 // Number of days from 1/1/70 to beginning of current year
7527 // Account for extra day every 4 years starting at 1973
7529 y
= dt
->year
- 1970;
7530 days
= (y
* 365) + ((y
+ 1) / 4);
7532 // Change table if current year is a leap year
7534 if ((dt
->year
% 4) == 0) {
7535 dbm
= lydaysbymonth
;
7538 // Add in days elapsed in the current year
7540 days
+= (dt
->day
- 1) + dbm
[dt
->month
- 1];
7542 // Add accumulated days to accumulated seconds
7544 secs
+= 24 * 3600 * days
;
7550 IOPMrootDomain::getRUN_STATE(void)
7552 return _aotNow
? AOT_STATE
: ON_STATE
;
7556 IOPMrootDomain::isAOTMode()
7562 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime
)
7564 clock_sec_t nowsecs
, wakesecs
;
7565 clock_usec_t nowmicrosecs
, wakemicrosecs
;
7566 uint64_t nowAbs
, wakeAbs
;
7568 clock_gettimeofday_and_absolute_time(&nowsecs
, &nowmicrosecs
, &nowAbs
);
7569 wakeAbs
= continuoustime_to_absolutetime(wakeContinuousTime
);
7570 if (wakeAbs
< nowAbs
) {
7571 printf(LOG_PREFIX
"wakeAbs %qd < nowAbs %qd\n", wakeAbs
, nowAbs
);
7575 absolutetime_to_microtime(wakeAbs
, &wakesecs
, &wakemicrosecs
);
7577 wakesecs
+= nowsecs
;
7578 wakemicrosecs
+= nowmicrosecs
;
7579 if (wakemicrosecs
>= USEC_PER_SEC
) {
7581 wakemicrosecs
-= USEC_PER_SEC
;
7583 if (wakemicrosecs
>= (USEC_PER_SEC
/ 10)) {
7587 IOPMConvertSecondsToCalendar(wakesecs
, &_aotWakeTimeCalendar
);
7589 if (_aotWakeTimeContinuous
!= wakeContinuousTime
) {
7590 _aotWakeTimeContinuous
= wakeContinuousTime
;
7591 IOLog(LOG_PREFIX
"setWakeTime: " YMDTF
"\n", YMDT(&_aotWakeTimeCalendar
));
7593 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeMaintenance
;
7594 _aotWakeTimeUTC
= wakesecs
;
7596 return kIOReturnSuccess
;
7599 // assumes WAKEEVENT_LOCK
7601 IOPMrootDomain::aotShouldExit(bool checkTimeSet
, bool software
)
7604 const char * reason
= "";
7608 _aotMetrics
->softwareRequestCount
++;
7609 reason
= "software request";
7610 } else if (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
) {
7612 reason
= gWakeReasonString
;
7613 } else if (checkTimeSet
&& (kPMCalendarTypeInvalid
== _aotWakeTimeCalendar
.selector
)) {
7615 _aotMetrics
->noTimeSetCount
++;
7616 reason
= "flipbook expired";
7617 } else if ((kIOPMAOTModeRespectTimers
& _aotMode
) && _calendarWakeAlarmUTC
) {
7620 clock_get_calendar_microtime(&sec
, &usec
);
7621 if (_calendarWakeAlarmUTC
<= sec
) {
7623 _aotMetrics
->rtcAlarmsCount
++;
7624 reason
= "user alarm";
7627 exitNow
= (_aotNow
&& _aotExit
);
7630 IOLog(LOG_PREFIX
"AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7632 _aotMetrics
->sleepCount
,
7633 _aotMetrics
->possibleCount
,
7634 _aotMetrics
->confirmedPossibleCount
,
7635 _aotMetrics
->rejectedPossibleCount
,
7636 _aotMetrics
->expiredPossibleCount
,
7637 _aotMetrics
->noTimeSetCount
,
7638 _aotMetrics
->rtcAlarmsCount
);
7644 IOPMrootDomain::aotExit(bool cps
)
7646 uint32_t savedMessageMask
;
7649 _aotTasksSuspended
= false;
7650 _aotReadyToFullWake
= false;
7651 if (_aotTimerScheduled
) {
7652 _aotTimerES
->cancelTimeout();
7653 _aotTimerScheduled
= false;
7655 updateTasksSuspend();
7657 _aotMetrics
->totalTime
+= mach_absolute_time() - _aotLastWakeTime
;
7658 _aotLastWakeTime
= 0;
7659 if (_aotMetrics
->sleepCount
&& (_aotMetrics
->sleepCount
<= kIOPMAOTMetricsKernelWakeCountMax
)) {
7661 strlcpy(&_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
- 1][0],
7663 sizeof(_aotMetrics
->kernelWakeReason
[_aotMetrics
->sleepCount
]));
7667 _aotWakeTimeCalendar
.selector
= kPMCalendarTypeInvalid
;
7669 // Preserve the message mask since a system wake transition
7670 // may have already started and initialized the mask.
7671 savedMessageMask
= _systemMessageClientMask
;
7672 _systemMessageClientMask
= kSystemMessageClientLegacyApp
;
7673 tellClients(kIOMessageSystemWillPowerOn
);
7674 _systemMessageClientMask
= savedMessageMask
| kSystemMessageClientLegacyApp
;
7677 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit
);
7682 IOPMrootDomain::aotEvaluate(IOTimerEventSource
* timer
)
7686 IOLog("aotEvaluate(%d) 0x%x\n", (timer
!= NULL
), _aotPendingFlags
);
7689 exitNow
= aotShouldExit(false, false);
7690 if (timer
!= NULL
) {
7691 _aotTimerScheduled
= false;
7698 if (_aotLingerTime
) {
7700 IOLog("aot linger before sleep\n");
7701 clock_absolutetime_interval_to_deadline(_aotLingerTime
, &deadline
);
7702 clock_delay_until(deadline
);
7705 privateSleepSystem(kIOPMSleepReasonSoftware
);
7709 //******************************************************************************
7712 // Conditions that affect our wake/sleep decision has changed.
7713 // If conditions dictate that the system must remain awake, clamp power
7714 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7715 // is TRUE, then remove the power clamp and allow the power state to drop
7717 //******************************************************************************
7720 IOPMrootDomain::adjustPowerState( bool sleepASAP
)
7722 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7723 getPowerStateString((uint32_t) getPowerState()), sleepASAP
, idleSleepEnabled
);
7730 if (AOT_STATE
!= getPowerState()) {
7734 exitNow
= aotShouldExit(true, false);
7736 && !_aotTimerScheduled
7737 && (kIOPMWakeEventAOTPossibleExit
== (kIOPMWakeEventAOTPossibleFlags
& _aotPendingFlags
))) {
7738 _aotTimerScheduled
= true;
7739 if (_aotLingerTime
) {
7740 _aotTimerES
->setTimeout(_aotLingerTime
);
7742 _aotTimerES
->setTimeout(800, kMillisecondScale
);
7749 _aotReadyToFullWake
= true;
7750 if (!_aotTimerScheduled
) {
7751 privateSleepSystem(kIOPMSleepReasonSoftware
);
7757 if ((!idleSleepEnabled
) || !checkSystemSleepEnabled()) {
7758 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState
);
7759 } else if (sleepASAP
) {
7760 changePowerStateWithTagToPriv(SLEEP_STATE
, kCPSReasonAdjustPowerState
);
7765 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn
)
7768 if (!checkSystemCanSustainFullWake()) {
7769 DLOG("System cannot sustain full wake\n");
7773 // Force wrangler to max power state. If system is in dark wake
7774 // this alone won't raise the wrangler's power state.
7776 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMax
);
7779 // System in dark wake, always requesting full wake should
7780 // not have any bad side-effects, even if the request fails.
7782 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
7783 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeNotification
);
7784 requestFullWake( kFullWakeReasonDisplayOn
);
7787 // Relenquish desire to power up display.
7788 // Must first transition to state 1 since wrangler doesn't
7789 // power off the displays at state 0. At state 0 the root
7790 // domain is removed from the wrangler's power client list.
7792 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
+ 1);
7793 wrangler
->changePowerStateForRootDomain(kWranglerPowerStateMin
);
7798 //******************************************************************************
7799 // dispatchPowerEvent
7801 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7802 //******************************************************************************
7805 IOPMrootDomain::dispatchPowerEvent(
7806 uint32_t event
, void * arg0
, uint64_t arg1
)
7811 case kPowerEventFeatureChanged
:
7812 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7813 messageClients(kIOPMMessageFeatureChange
, this);
7816 case kPowerEventReceivedPowerNotification
:
7817 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7818 handlePowerNotification((UInt32
)(uintptr_t) arg0
);
7821 case kPowerEventSystemBootCompleted
:
7822 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7823 if (systemBooting
) {
7824 systemBooting
= false;
7826 // read noidle setting from Device Tree
7827 OSSharedPtr
<IORegistryEntry
> defaults
= IORegistryEntry::fromPath("IODeviceTree:/defaults");
7828 if (defaults
!= NULL
) {
7829 OSSharedPtr
<OSObject
> noIdleProp
= defaults
->copyProperty("no-idle");
7830 OSData
*data
= OSDynamicCast(OSData
, noIdleProp
.get());
7831 if ((data
!= NULL
) && (data
->getLength() == 4)) {
7832 gNoIdleFlag
= *(uint32_t*)data
->getBytesNoCopy();
7833 DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag
);
7836 if (lowBatteryCondition
|| thermalEmergencyState
) {
7837 if (lowBatteryCondition
) {
7838 privateSleepSystem(kIOPMSleepReasonLowPower
);
7840 privateSleepSystem(kIOPMSleepReasonThermalEmergency
);
7842 // The rest is unnecessary since the system is expected
7843 // to sleep immediately. The following wake will update
7848 sleepWakeDebugMemAlloc();
7849 saveFailureData2File();
7851 // If lid is closed, re-send lid closed notification
7852 // now that booting is complete.
7853 if (clamshellClosed
) {
7854 handlePowerNotification(kLocalEvalClamshellCommand
);
7856 evaluatePolicy( kStimulusAllowSystemSleepChanged
);
7860 case kPowerEventSystemShutdown
:
7861 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7862 if (kOSBooleanTrue
== (OSBoolean
*) arg0
) {
7863 /* We set systemShutdown = true during shutdown
7864 * to prevent sleep at unexpected times while loginwindow is trying
7865 * to shutdown apps and while the OS is trying to transition to
7866 * complete power of.
7868 * Set to true during shutdown, as soon as loginwindow shows
7869 * the "shutdown countdown dialog", through individual app
7870 * termination, and through black screen kernel shutdown.
7872 systemShutdown
= true;
7875 * A shutdown was initiated, but then the shutdown
7876 * was cancelled, clearing systemShutdown to false here.
7878 systemShutdown
= false;
7882 case kPowerEventUserDisabledSleep
:
7883 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7884 userDisabledAllSleep
= (kOSBooleanTrue
== (OSBoolean
*) arg0
);
7887 case kPowerEventRegisterSystemCapabilityClient
:
7888 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7890 // reset() handles the arg0 == nullptr case for us
7891 systemCapabilityNotifier
.reset((IONotifier
*) arg0
, OSRetain
);
7892 /* intentional fall-through */
7893 [[clang::fallthrough]];
7895 case kPowerEventRegisterKernelCapabilityClient
:
7896 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7897 if (!_joinedCapabilityClients
) {
7898 _joinedCapabilityClients
= OSSet::withCapacity(8);
7901 OSSharedPtr
<IONotifier
> notify((IONotifier
*) arg0
, OSNoRetain
);
7902 if (_joinedCapabilityClients
) {
7903 _joinedCapabilityClients
->setObject(notify
.get());
7904 synchronizePowerTree( kIOPMSyncNoChildNotify
);
7909 case kPowerEventPolicyStimulus
:
7910 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7912 int stimulus
= (int)(uintptr_t) arg0
;
7913 evaluatePolicy(stimulus
, (uint32_t) arg1
);
7917 case kPowerEventAssertionCreate
:
7918 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7920 pmAssertions
->handleCreateAssertion((OSData
*)arg0
);
7925 case kPowerEventAssertionRelease
:
7926 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7928 pmAssertions
->handleReleaseAssertion(arg1
);
7932 case kPowerEventAssertionSetLevel
:
7933 DMSG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7935 pmAssertions
->handleSetAssertionLevel(arg1
, (IOPMDriverAssertionLevel
)(uintptr_t)arg0
);
7939 case kPowerEventQueueSleepWakeUUID
:
7940 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7941 handleQueueSleepWakeUUID((OSObject
*)arg0
);
7943 case kPowerEventPublishSleepWakeUUID
:
7944 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7945 handlePublishSleepWakeUUID((bool)arg0
);
7948 case kPowerEventSetDisplayPowerOn
:
7949 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7951 displayPowerOnRequested
= true;
7953 displayPowerOnRequested
= false;
7955 handleSetDisplayPowerOn(displayPowerOnRequested
);
7958 case kPowerEventPublishWakeType
:
7959 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7961 // Don't replace wake type property if already set
7962 if ((arg0
== gIOPMWakeTypeUserKey
) ||
7963 !propertyExists(kIOPMRootDomainWakeTypeKey
)) {
7964 const char * wakeType
= NULL
;
7966 if (arg0
== gIOPMWakeTypeUserKey
) {
7967 requestUserActive(this, "WakeTypeUser");
7968 wakeType
= kIOPMRootDomainWakeTypeUser
;
7969 } else if (arg0
== gIOPMSettingDebugWakeRelativeKey
) {
7970 requestUserActive(this, "WakeTypeAlarm");
7971 wakeType
= kIOPMRootDomainWakeTypeAlarm
;
7972 } else if (arg0
== gIOPMSettingSleepServiceWakeCalendarKey
) {
7973 darkWakeSleepService
= true;
7974 wakeType
= kIOPMRootDomainWakeTypeSleepService
;
7975 } else if (arg0
== gIOPMSettingMaintenanceWakeCalendarKey
) {
7976 wakeType
= kIOPMRootDomainWakeTypeMaintenance
;
7980 setProperty(kIOPMRootDomainWakeTypeKey
, wakeType
);
7985 case kPowerEventAOTEvaluate
:
7986 DLOG("power event %u args %p 0x%llx\n", event
, OBFUSCATE(arg0
), arg1
);
7987 if (_aotReadyToFullWake
) {
7994 //******************************************************************************
7995 // systemPowerEventOccurred
7997 // The power controller is notifying us of a hardware-related power management
7998 // event that we must handle.
8000 // systemPowerEventOccurred covers the same functionality that
8001 // receivePowerNotification does; it simply provides a richer API for conveying
8002 // more information.
8003 //******************************************************************************
8006 IOPMrootDomain::systemPowerEventOccurred(
8007 const OSSymbol
*event
,
8010 IOReturn attempt
= kIOReturnSuccess
;
8011 OSSharedPtr
<OSNumber
> newNumber
;
8014 return kIOReturnBadArgument
;
8017 newNumber
= OSNumber::withNumber(intValue
, 8 * sizeof(intValue
));
8019 return kIOReturnInternalError
;
8022 attempt
= systemPowerEventOccurred(event
, static_cast<OSObject
*>(newNumber
.get()));
8028 IOPMrootDomain::setThermalState(OSObject
*value
)
8032 if (gIOPMWorkLoop
->inGate() == false) {
8033 gIOPMWorkLoop
->runAction(
8034 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::setThermalState
),
8040 if (value
&& (num
= OSDynamicCast(OSNumber
, value
))) {
8041 thermalWarningState
= ((num
->unsigned32BitValue() == kIOPMThermalLevelWarning
) ||
8042 (num
->unsigned32BitValue() == kIOPMThermalLevelTrap
)) ? 1 : 0;
8047 IOPMrootDomain::systemPowerEventOccurred(
8048 const OSSymbol
*event
,
8051 OSSharedPtr
<OSDictionary
> thermalsDict
;
8052 bool shouldUpdate
= true;
8054 if (!event
|| !value
) {
8055 return kIOReturnBadArgument
;
8059 // We reuse featuresDict Lock because it already exists and guards
8060 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
8061 // of stepping on that lock.
8062 if (featuresDictLock
) {
8063 IOLockLock(featuresDictLock
);
8066 OSSharedPtr
<OSObject
> origThermalsProp
= copyProperty(kIOPMRootDomainPowerStatusKey
);
8067 OSDictionary
* origThermalsDict
= OSDynamicCast(OSDictionary
, origThermalsProp
.get());
8069 if (origThermalsDict
) {
8070 thermalsDict
= OSDictionary::withDictionary(origThermalsDict
);
8072 thermalsDict
= OSDictionary::withCapacity(1);
8075 if (!thermalsDict
) {
8076 shouldUpdate
= false;
8080 thermalsDict
->setObject(event
, value
);
8082 setProperty(kIOPMRootDomainPowerStatusKey
, thermalsDict
.get());
8086 if (featuresDictLock
) {
8087 IOLockUnlock(featuresDictLock
);
8092 event
->isEqualTo(kIOPMThermalLevelWarningKey
)) {
8093 setThermalState(value
);
8095 messageClients(kIOPMMessageSystemPowerEventOccurred
, (void *)NULL
);
8098 return kIOReturnSuccess
;
8101 //******************************************************************************
8102 // receivePowerNotification
8104 // The power controller is notifying us of a hardware-related power management
8105 // event that we must handle. This may be a result of an 'environment' interrupt
8106 // from the power mgt micro.
8107 //******************************************************************************
8110 IOPMrootDomain::receivePowerNotification( UInt32 msg
)
8112 if (msg
& kIOPMPowerButton
) {
8113 uint32_t currentPhase
= pmTracer
->getTracePhase();
8114 if (currentPhase
!= kIOPMTracePointSystemUp
&& currentPhase
> kIOPMTracePointSystemSleep
) {
8115 DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase
);
8116 swd_flags
|= SWD_PWR_BTN_STACKSHOT
;
8117 thread_call_enter(powerButtonDown
);
8119 DEBUG_LOG("power button pressed when system is up\n");
8121 } else if (msg
& kIOPMPowerButtonUp
) {
8122 if (swd_flags
& SWD_PWR_BTN_STACKSHOT
) {
8123 swd_flags
&= ~SWD_PWR_BTN_STACKSHOT
;
8124 thread_call_enter(powerButtonUp
);
8127 pmPowerStateQueue
->submitPowerEvent(
8128 kPowerEventReceivedPowerNotification
, (void *)(uintptr_t) msg
);
8130 return kIOReturnSuccess
;
8134 IOPMrootDomain::handlePowerNotification( UInt32 msg
)
8136 bool eval_clamshell
= false;
8137 bool eval_clamshell_alarm
= false;
8142 * Local (IOPMrootDomain only) eval clamshell command
8144 if (msg
& kLocalEvalClamshellCommand
) {
8145 if ((gClamshellFlags
& kClamshell_WAR_47715679
) && isRTCAlarmWake
) {
8146 eval_clamshell_alarm
= true;
8148 // reset isRTCAlarmWake. This evaluation should happen only once
8149 // on RTC/Alarm wake. Any clamshell events after wake should follow
8150 // the regular evaluation
8151 isRTCAlarmWake
= false;
8153 eval_clamshell
= true;
8160 if (msg
& kIOPMOverTemp
) {
8161 DLOG("Thermal overtemp message received!\n");
8162 thermalEmergencyState
= true;
8163 privateSleepSystem(kIOPMSleepReasonThermalEmergency
);
8167 * Forward DW thermal notification to client, if system is not going to sleep
8169 if ((msg
& kIOPMDWOverTemp
) && (_systemTransitionType
!= kSystemTransitionSleep
)) {
8170 DLOG("DarkWake thermal limits message received!\n");
8171 messageClients(kIOPMMessageDarkWakeThermalEmergency
);
8177 if (msg
& kIOPMSleepNow
) {
8178 privateSleepSystem(kIOPMSleepReasonSoftware
);
8184 if (msg
& kIOPMPowerEmergency
) {
8185 DLOG("Received kIOPMPowerEmergency");
8186 lowBatteryCondition
= true;
8187 privateSleepSystem(kIOPMSleepReasonLowPower
);
8193 if (msg
& kIOPMClamshellOpened
) {
8194 DLOG("Clamshell opened\n");
8195 // Received clamshel open message from clamshell controlling driver
8196 // Update our internal state and tell general interest clients
8197 clamshellClosed
= false;
8198 clamshellExists
= true;
8200 // Don't issue a hid tickle when lid is open and polled on wake
8201 if (msg
& kIOPMSetValue
) {
8202 setProperty(kIOPMRootDomainWakeTypeKey
, "Lid Open");
8207 informCPUStateChange(kInformLid
, 0);
8209 // Tell general interest clients
8210 sendClientClamshellNotification();
8212 bool aborting
= ((lastSleepReason
== kIOPMSleepReasonClamshell
)
8213 || (lastSleepReason
== kIOPMSleepReasonIdle
)
8214 || (lastSleepReason
== kIOPMSleepReasonMaintenance
));
8216 userActivityCount
++;
8218 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount
, lastSleepReason
);
8223 * Send the clamshell interest notification since the lid is closing.
8225 if (msg
& kIOPMClamshellClosed
) {
8226 if ((clamshellIgnoreClose
|| (gClamshellFlags
& kClamshell_WAR_38378787
)) &&
8227 clamshellClosed
&& clamshellExists
) {
8228 DLOG("Ignoring redundant Clamshell close event\n");
8230 DLOG("Clamshell closed\n");
8231 // Received clamshel open message from clamshell controlling driver
8232 // Update our internal state and tell general interest clients
8233 clamshellClosed
= true;
8234 clamshellExists
= true;
8236 // Ignore all following clamshell close events until the clamshell
8237 // is opened or the system sleeps. When a clamshell close triggers
8238 // a system wake, the lid driver may send us two clamshell close
8239 // events, one for the clamshell close event itself, and a second
8240 // close event when the driver polls the lid state on wake.
8241 clamshellIgnoreClose
= true;
8244 informCPUStateChange(kInformLid
, 1);
8246 // Tell general interest clients
8247 sendClientClamshellNotification();
8249 // And set eval_clamshell = so we can attempt
8250 eval_clamshell
= true;
8255 * Set Desktop mode (sent from graphics)
8257 * -> reevaluate lid state
8259 if (msg
& kIOPMSetDesktopMode
) {
8260 desktopMode
= (0 != (msg
& kIOPMSetValue
));
8261 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
8262 DLOG("Desktop mode %d\n", desktopMode
);
8264 sendClientClamshellNotification();
8266 // Re-evaluate the lid state
8267 eval_clamshell
= true;
8271 * AC Adaptor connected
8273 * -> reevaluate lid state
8275 if (msg
& kIOPMSetACAdaptorConnected
) {
8276 acAdaptorConnected
= (0 != (msg
& kIOPMSetValue
));
8277 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
8280 informCPUStateChange(kInformAC
, !acAdaptorConnected
);
8282 // Tell BSD if AC is connected
8283 // 0 == external power source; 1 == on battery
8284 post_sys_powersource(acAdaptorConnected
? 0:1);
8286 sendClientClamshellNotification();
8288 // Re-evaluate the lid state
8289 eval_clamshell
= true;
8291 // Lack of AC may have latched a display wrangler tickle.
8292 // This mirrors the hardware's USB wake event latch, where a latched
8293 // USB wake event followed by an AC attach will trigger a full wake.
8294 latchDisplayWranglerTickle( false );
8297 // AC presence will reset the standy timer delay adjustment.
8298 _standbyTimerResetSeconds
= 0;
8300 if (!userIsActive
) {
8301 // Reset userActivityTime when power supply is changed(rdr 13789330)
8302 clock_get_uptime(&userActivityTime
);
8307 * Enable Clamshell (external display disappear)
8309 * -> reevaluate lid state
8311 if (msg
& kIOPMEnableClamshell
) {
8312 DLOG("Clamshell enabled\n");
8314 // Re-evaluate the lid state
8315 // System should sleep on external display disappearance
8316 // in lid closed operation.
8317 if (true == clamshellDisabled
) {
8318 eval_clamshell
= true;
8320 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8321 // Also clear kClamshellSleepDisableInternal when graphics enables
8322 // the clamshell during a full wake. When graphics is behaving as
8323 // expected, this will allow clamshell close to be honored earlier
8324 // rather than waiting for the delayed evaluation.
8325 if ((clamshellSleepDisableMask
& kClamshellSleepDisableInternal
) &&
8326 (CAP_PENDING(kIOPMSystemCapabilityGraphics
) ||
8327 CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) {
8328 setClamShellSleepDisable(false, kClamshellSleepDisableInternal
);
8330 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8331 // when timer expires which is harmless but useless.
8332 thread_call_cancel(fullWakeThreadCall
);
8337 clamshellDisabled
= false;
8338 sendClientClamshellNotification();
8342 * Disable Clamshell (external display appeared)
8343 * We don't bother re-evaluating clamshell state. If the system is awake,
8344 * the lid is probably open.
8346 if (msg
& kIOPMDisableClamshell
) {
8347 DLOG("Clamshell disabled\n");
8348 clamshellDisabled
= true;
8349 sendClientClamshellNotification();
8353 * Evaluate clamshell and SLEEP if appropriate
8355 if (eval_clamshell_alarm
&& clamshellClosed
) {
8356 if (shouldSleepOnRTCAlarmWake()) {
8357 privateSleepSystem(kIOPMSleepReasonClamshell
);
8359 } else if (eval_clamshell
&& clamshellClosed
) {
8360 if (shouldSleepOnClamshellClosed()) {
8361 privateSleepSystem(kIOPMSleepReasonClamshell
);
8363 evaluatePolicy( kStimulusDarkWakeEvaluate
);
8367 if (msg
& kIOPMProModeEngaged
) {
8369 DLOG("ProModeEngaged\n");
8370 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
.get(), &newState
, sizeof(newState
));
8373 if (msg
& kIOPMProModeDisengaged
) {
8375 DLOG("ProModeDisengaged\n");
8376 messageClient(kIOPMMessageProModeStateChange
, systemCapabilityNotifier
.get(), &newState
, sizeof(newState
));
8380 //******************************************************************************
8383 // Evaluate root-domain policy in response to external changes.
8384 //******************************************************************************
8387 IOPMrootDomain::evaluatePolicy( int stimulus
, uint32_t arg
)
8391 int idleSleepEnabled
: 1;
8392 int idleSleepDisabled
: 1;
8393 int displaySleep
: 1;
8394 int sleepDelayChanged
: 1;
8395 int evaluateDarkWake
: 1;
8396 int adjustPowerState
: 1;
8397 int userBecameInactive
: 1;
8398 int displaySleepEntry
: 1;
8408 case kStimulusDisplayWranglerSleep
:
8409 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8410 if (!wranglerPowerOff
) {
8411 // wrangler is in sleep state or lower
8412 flags
.bit
.displaySleep
= true;
8414 if (!wranglerAsleep
) {
8415 // transition from wrangler wake to wrangler sleep
8416 flags
.bit
.displaySleepEntry
= true;
8417 wranglerAsleep
= true;
8421 case kStimulusDisplayWranglerWake
:
8422 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8423 displayIdleForDemandSleep
= false;
8424 wranglerPowerOff
= false;
8425 wranglerAsleep
= false;
8428 case kStimulusEnterUserActiveState
:
8429 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8430 if (_preventUserActive
) {
8431 DLOG("user active dropped\n");
8434 if (!userIsActive
) {
8435 userIsActive
= true;
8436 userWasActive
= true;
8437 clock_get_uptime(&gUserActiveAbsTime
);
8439 // Stay awake after dropping demand for display power on
8440 if (kFullWakeReasonDisplayOn
== fullWakeReason
) {
8441 fullWakeReason
= fFullWakeReasonDisplayOnAndLocalUser
;
8442 DLOG("User activity while in notification wake\n");
8443 changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8446 kdebugTrace(kPMLogUserActiveState
, 0, 1, 0);
8447 setProperty(gIOPMUserIsActiveKey
.get(), kOSBooleanTrue
);
8448 messageClients(kIOPMMessageUserIsActiveChanged
);
8450 flags
.bit
.idleSleepDisabled
= true;
8453 case kStimulusLeaveUserActiveState
:
8454 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8456 clock_get_uptime(&gUserInactiveAbsTime
);
8457 userIsActive
= false;
8458 clock_get_uptime(&userBecameInactiveTime
);
8459 flags
.bit
.userBecameInactive
= true;
8461 kdebugTrace(kPMLogUserActiveState
, 0, 0, 0);
8462 setProperty(gIOPMUserIsActiveKey
.get(), kOSBooleanFalse
);
8463 messageClients(kIOPMMessageUserIsActiveChanged
);
8467 case kStimulusAggressivenessChanged
:
8469 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8470 unsigned long aggressiveValue
;
8471 uint32_t minutesToIdleSleep
= 0;
8472 uint32_t minutesToDisplayDim
= 0;
8473 uint32_t minutesDelta
= 0;
8475 // Fetch latest display and system sleep slider values.
8476 aggressiveValue
= 0;
8477 getAggressiveness(kPMMinutesToSleep
, &aggressiveValue
);
8478 minutesToIdleSleep
= (uint32_t) aggressiveValue
;
8480 aggressiveValue
= 0;
8481 getAggressiveness(kPMMinutesToDim
, &aggressiveValue
);
8482 minutesToDisplayDim
= (uint32_t) aggressiveValue
;
8483 DLOG("aggressiveness changed: system %u->%u, display %u\n",
8484 sleepSlider
, minutesToIdleSleep
, minutesToDisplayDim
);
8486 DLOG("idle time -> %d secs (ena %d)\n",
8487 idleSeconds
, (minutesToIdleSleep
!= 0));
8489 // How long to wait before sleeping the system once
8490 // the displays turns off is indicated by 'extraSleepDelay'.
8492 if (minutesToIdleSleep
> minutesToDisplayDim
) {
8493 minutesDelta
= minutesToIdleSleep
- minutesToDisplayDim
;
8494 } else if (minutesToIdleSleep
== minutesToDisplayDim
) {
8498 if ((!idleSleepEnabled
) && (minutesToIdleSleep
!= 0)) {
8499 idleSleepEnabled
= flags
.bit
.idleSleepEnabled
= true;
8502 if ((idleSleepEnabled
) && (minutesToIdleSleep
== 0)) {
8503 flags
.bit
.idleSleepDisabled
= true;
8504 idleSleepEnabled
= false;
8506 #if !defined(XNU_TARGET_OS_OSX)
8507 if (0x7fffffff == minutesToIdleSleep
) {
8508 minutesToIdleSleep
= idleSeconds
;
8510 #endif /* !defined(XNU_TARGET_OS_OSX) */
8512 if (((minutesDelta
!= extraSleepDelay
) ||
8513 (userActivityTime
!= userActivityTime_prev
)) &&
8514 !flags
.bit
.idleSleepEnabled
&& !flags
.bit
.idleSleepDisabled
) {
8515 flags
.bit
.sleepDelayChanged
= true;
8518 if (systemDarkWake
&& !darkWakeToSleepASAP
&&
8519 (flags
.bit
.idleSleepEnabled
|| flags
.bit
.idleSleepDisabled
)) {
8520 // Reconsider decision to remain in dark wake
8521 flags
.bit
.evaluateDarkWake
= true;
8524 sleepSlider
= minutesToIdleSleep
;
8525 extraSleepDelay
= minutesDelta
;
8526 userActivityTime_prev
= userActivityTime
;
8529 case kStimulusDemandSystemSleep
:
8530 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8531 displayIdleForDemandSleep
= true;
8532 if (wrangler
&& wranglerIdleSettings
) {
8533 // Request wrangler idle only when demand sleep is triggered
8535 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics
)) {
8536 wrangler
->setProperties(wranglerIdleSettings
.get());
8537 DLOG("Requested wrangler idle\n");
8540 // arg = sleepReason
8541 changePowerStateWithOverrideTo( SLEEP_STATE
, arg
);
8544 case kStimulusAllowSystemSleepChanged
:
8545 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8546 flags
.bit
.adjustPowerState
= true;
8549 case kStimulusDarkWakeActivityTickle
:
8550 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8551 // arg == true implies real and not self generated wrangler tickle.
8552 // Update wake type on PM work loop instead of the tickle thread to
8553 // eliminate the possibility of an early tickle clobbering the wake
8554 // type set by the platform driver.
8556 setProperty(kIOPMRootDomainWakeTypeKey
, kIOPMRootDomainWakeTypeHIDActivity
);
8559 if (!darkWakeExit
) {
8560 if (latchDisplayWranglerTickle(true)) {
8561 DLOG("latched tickle\n");
8565 darkWakeExit
= true;
8566 DLOG("Requesting full wake due to dark wake activity tickle\n");
8567 requestFullWake( kFullWakeReasonLocalUser
);
8571 case kStimulusDarkWakeEntry
:
8572 case kStimulusDarkWakeReentry
:
8573 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8574 // Any system transitions since the last dark wake transition
8575 // will invalid the stimulus.
8577 if (arg
== _systemStateGeneration
) {
8578 DLOG("dark wake entry\n");
8579 systemDarkWake
= true;
8581 // Keep wranglerPowerOff an invariant when wrangler is absent
8583 wranglerPowerOff
= true;
8586 if (kStimulusDarkWakeEntry
== stimulus
) {
8587 clock_get_uptime(&userBecameInactiveTime
);
8588 flags
.bit
.evaluateDarkWake
= true;
8589 if (activitySinceSleep()) {
8590 DLOG("User activity recorded while going to darkwake\n");
8595 // Always accelerate disk spindown while in dark wake,
8596 // even if system does not support/allow sleep.
8598 cancelIdleSleepTimer();
8599 setQuickSpinDownTimeout();
8603 case kStimulusDarkWakeEvaluate
:
8604 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8605 if (systemDarkWake
) {
8606 flags
.bit
.evaluateDarkWake
= true;
8610 case kStimulusNoIdleSleepPreventers
:
8611 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus
, arg
);
8612 flags
.bit
.adjustPowerState
= true;
8614 } /* switch(stimulus) */
8616 if (flags
.bit
.evaluateDarkWake
&& (kFullWakeReasonNone
== fullWakeReason
)) {
8617 DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8618 darkWakeToSleepASAP
, clamshellClosed
, clamshellDisabled
, clamshellSleepDisableMask
, desktopMode
, acAdaptorConnected
);
8619 if (darkWakeToSleepASAP
||
8620 (clamshellClosed
&& !(desktopMode
&& acAdaptorConnected
))) {
8621 uint32_t newSleepReason
;
8623 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8624 // System was previously in full wake. Sleep reason from
8625 // full to dark already recorded in fullToDarkReason.
8627 if (lowBatteryCondition
) {
8628 newSleepReason
= kIOPMSleepReasonLowPower
;
8629 } else if (thermalEmergencyState
) {
8630 newSleepReason
= kIOPMSleepReasonThermalEmergency
;
8632 newSleepReason
= fullToDarkReason
;
8635 // In dark wake from system sleep.
8637 if (darkWakeSleepService
) {
8638 newSleepReason
= kIOPMSleepReasonSleepServiceExit
;
8640 newSleepReason
= kIOPMSleepReasonMaintenance
;
8644 if (checkSystemCanSleep(newSleepReason
)) {
8645 privateSleepSystem(newSleepReason
);
8647 } else { // non-maintenance (network) dark wake
8648 if (checkSystemCanSleep(kIOPMSleepReasonIdle
)) {
8649 // Release power clamp, and wait for children idle.
8650 adjustPowerState(true);
8652 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep
);
8657 if (systemDarkWake
) {
8658 // The rest are irrelevant while system is in dark wake.
8662 if ((flags
.bit
.displaySleepEntry
) &&
8663 (kFullWakeReasonDisplayOn
== fullWakeReason
)) {
8664 // kIOPMSleepReasonNotificationWakeExit
8665 DLOG("Display sleep while in notification wake\n");
8666 changePowerStateWithOverrideTo(SLEEP_STATE
, kIOPMSleepReasonNotificationWakeExit
);
8669 if (flags
.bit
.userBecameInactive
|| flags
.bit
.sleepDelayChanged
) {
8670 bool cancelQuickSpindown
= false;
8672 if (flags
.bit
.sleepDelayChanged
) {
8673 // Cancel existing idle sleep timer and quick disk spindown.
8674 // New settings will be applied by the idleSleepEnabled flag
8675 // handler below if idle sleep is enabled.
8677 DLOG("extra sleep timer changed\n");
8678 cancelIdleSleepTimer();
8679 cancelQuickSpindown
= true;
8681 DLOG("user inactive\n");
8684 if (!userIsActive
&& idleSleepEnabled
) {
8685 startIdleSleepTimer(getTimeToIdleSleep());
8688 if (cancelQuickSpindown
) {
8689 restoreUserSpinDownTimeout();
8693 if (flags
.bit
.idleSleepEnabled
) {
8694 DLOG("idle sleep timer enabled\n");
8696 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8697 startIdleSleepTimer(getTimeToIdleSleep());
8699 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled
);
8700 startIdleSleepTimer( idleSeconds
);
8703 // Start idle timer if prefs now allow system sleep
8704 // and user is already inactive. Disk spindown is
8705 // accelerated upon timer expiration.
8707 if (!userIsActive
) {
8708 startIdleSleepTimer(getTimeToIdleSleep());
8713 if (flags
.bit
.idleSleepDisabled
) {
8714 DLOG("idle sleep timer disabled\n");
8715 cancelIdleSleepTimer();
8716 restoreUserSpinDownTimeout();
8720 if (flags
.bit
.adjustPowerState
) {
8721 bool sleepASAP
= false;
8723 if (!systemBooting
&& (0 == idleSleepPreventersCount())) {
8725 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy
);
8726 if (idleSleepEnabled
) {
8727 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8728 if (!extraSleepDelay
&& !idleSleepTimerPending
) {
8732 // stay awake for at least idleSeconds
8733 startIdleSleepTimer(idleSeconds
);
8736 } else if (!extraSleepDelay
&& !idleSleepTimerPending
&& !systemDarkWake
) {
8741 adjustPowerState(sleepASAP
);
8745 //******************************************************************************
8748 IOPMrootDomain::idleSleepPreventersCount()
8751 unsigned int count __block
;
8753 preventIdleSleepList
->iterateObjects(^bool (OSObject
* obj
)
8755 count
+= (NULL
== obj
->metaCast("AppleARMBacklight"));
8761 return preventIdleSleepList
->getCount();
8765 //******************************************************************************
8768 // Request transition from dark wake to full wake
8769 //******************************************************************************
8772 IOPMrootDomain::requestFullWake( FullWakeReason reason
)
8774 uint32_t options
= 0;
8775 IOService
* pciRoot
= NULL
;
8776 bool promotion
= false;
8778 // System must be in dark wake and a valid reason for entering full wake
8779 if ((kFullWakeReasonNone
== reason
) ||
8780 (kFullWakeReasonNone
!= fullWakeReason
) ||
8781 (CAP_CURRENT(kIOPMSystemCapabilityGraphics
))) {
8785 // Will clear reason upon exit from full wake
8786 fullWakeReason
= reason
;
8788 _desiredCapability
|= (kIOPMSystemCapabilityGraphics
|
8789 kIOPMSystemCapabilityAudio
);
8791 if ((kSystemTransitionWake
== _systemTransitionType
) &&
8792 !(_pendingCapability
& kIOPMSystemCapabilityGraphics
) &&
8793 !darkWakePowerClamped
) {
8794 // Promote to full wake while waking up to dark wake due to tickle.
8795 // PM will hold off notifying the graphics subsystem about system wake
8796 // as late as possible, so if a HID tickle does arrive, graphics can
8797 // power up from this same wake transition. Otherwise, the latency to
8798 // power up graphics on the following transition can be huge on certain
8799 // systems. However, once any power clamping has taken effect, it is
8800 // too late to promote the current dark wake transition to a full wake.
8801 _pendingCapability
|= (kIOPMSystemCapabilityGraphics
|
8802 kIOPMSystemCapabilityAudio
);
8804 // Tell the PCI parent of audio and graphics drivers to stop
8805 // delaying the child notifications. Same for root domain.
8806 pciRoot
= pciHostBridgeDriver
.get();
8807 willEnterFullWake();
8811 // Unsafe to cancel once graphics was powered.
8812 // If system woke from dark wake, the return to sleep can
8813 // be cancelled. "awake -> dark -> sleep" transition
8814 // can be cancelled also, during the "dark -> sleep" phase
8815 // *prior* to driver power down.
8816 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
) ||
8817 _pendingCapability
== 0) {
8818 options
|= kIOPMSyncCancelPowerDown
;
8821 synchronizePowerTree(options
, pciRoot
);
8823 if (kFullWakeReasonLocalUser
== fullWakeReason
) {
8824 // IOGraphics doesn't light the display even though graphics is
8825 // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
8826 // So, do an explicit activity tickle
8828 wrangler
->activityTickle(0, 0);
8832 // Log a timestamp for the initial full wake request.
8833 // System may not always honor this full wake request.
8834 if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics
)) {
8838 clock_get_uptime(&now
);
8839 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8840 absolutetime_to_nanoseconds(now
, &nsec
);
8841 MSG("full wake %s (reason %u) %u ms\n",
8842 promotion
? "promotion" : "request",
8843 fullWakeReason
, ((int)((nsec
) / NSEC_PER_MSEC
)));
8847 //******************************************************************************
8848 // willEnterFullWake
8850 // System will enter full wake from sleep, from dark wake, or from dark
8851 // wake promotion. This function aggregate things that are in common to
8852 // all three full wake transitions.
8854 // Assumptions: fullWakeReason was updated
8855 //******************************************************************************
8858 IOPMrootDomain::willEnterFullWake( void )
8860 hibernateRetry
= false;
8861 sleepToStandby
= false;
8862 standbyNixed
= false;
8863 resetTimers
= false;
8864 sleepTimerMaintenance
= false;
8866 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics
));
8868 _systemMessageClientMask
= kSystemMessageClientPowerd
|
8869 kSystemMessageClientLegacyApp
;
8871 if ((_highestCapability
& kIOPMSystemCapabilityGraphics
) == 0) {
8872 // First time to attain full wake capability since the last wake
8873 _systemMessageClientMask
|= kSystemMessageClientKernel
;
8875 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
8876 setProperty(gIOPMUserTriggeredFullWakeKey
.get(),
8877 (kFullWakeReasonLocalUser
== fullWakeReason
) ?
8878 kOSBooleanTrue
: kOSBooleanFalse
);
8881 IOHibernateSetWakeCapabilities(_pendingCapability
);
8884 IOService::setAdvisoryTickleEnable( true );
8885 tellClients(kIOMessageSystemWillPowerOn
);
8886 preventTransitionToUserActive(false);
8889 //******************************************************************************
8890 // fullWakeDelayedWork
8892 // System has already entered full wake. Invoked by a delayed thread call.
8893 //******************************************************************************
8896 IOPMrootDomain::fullWakeDelayedWork( void )
8898 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8899 if (!gIOPMWorkLoop
->inGate()) {
8900 gIOPMWorkLoop
->runAction(
8901 OSMemberFunctionCast(IOWorkLoop::Action
, this,
8902 &IOPMrootDomain::fullWakeDelayedWork
), this);
8906 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
8907 _currentCapability
, _pendingCapability
, _highestCapability
,
8908 clamshellDisabled
, clamshellSleepDisableMask
);
8910 if (clamshellExists
&&
8911 CAP_CURRENT(kIOPMSystemCapabilityGraphics
) &&
8912 !CAP_CHANGE(kIOPMSystemCapabilityGraphics
)) {
8913 if (clamshellSleepDisableMask
& kClamshellSleepDisableInternal
) {
8914 setClamShellSleepDisable(false, kClamshellSleepDisableInternal
);
8916 // Not the initial full wake after waking from sleep.
8917 // Evaluate the clamshell for rdar://problem/9157444.
8918 receivePowerNotification(kLocalEvalClamshellCommand
);
8924 //******************************************************************************
8925 // evaluateAssertions
8927 //******************************************************************************
8929 // Bitmask of all kernel assertions that prevent system idle sleep.
8930 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
8931 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
8932 (kIOPMDriverAssertionReservedBit7 | \
8933 kIOPMDriverAssertionPreventSystemIdleSleepBit)
8936 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions
, IOPMDriverAssertionType oldAssertions
)
8938 IOPMDriverAssertionType changedBits
= newAssertions
^ oldAssertions
;
8940 messageClients(kIOPMMessageDriverAssertionsChanged
);
8942 if (changedBits
& kIOPMDriverAssertionPreventDisplaySleepBit
) {
8944 bool value
= (newAssertions
& kIOPMDriverAssertionPreventDisplaySleepBit
) ? true : false;
8946 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value
);
8947 wrangler
->setIgnoreIdleTimer( value
);
8951 if (changedBits
& kIOPMDriverAssertionCPUBit
) {
8953 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit
& newAssertions
)));
8955 evaluatePolicy(_aotNow
? kStimulusNoIdleSleepPreventers
: kStimulusDarkWakeEvaluate
);
8956 if (!assertOnWakeSecs
&& gIOLastWakeAbsTime
) {
8958 clock_usec_t microsecs
;
8959 clock_get_uptime(&now
);
8960 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
8961 absolutetime_to_microtime(now
, &assertOnWakeSecs
, µsecs
);
8962 if (assertOnWakeReport
) {
8963 HISTREPORT_TALLYVALUE(assertOnWakeReport
, (int64_t)assertOnWakeSecs
);
8964 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs
);
8969 if (changedBits
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) {
8970 if ((newAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) != 0) {
8971 if ((oldAssertions
& NO_IDLE_SLEEP_ASSERTIONS_MASK
) == 0) {
8972 DLOG("PreventIdleSleep driver assertion raised\n");
8973 bool ok
= updatePreventIdleSleepList(this, true);
8974 if (ok
&& (changedBits
& kIOPMDriverAssertionPreventSystemIdleSleepBit
)) {
8975 // Cancel idle sleep if there is one in progress
8976 cancelIdlePowerDown(this);
8980 DLOG("PreventIdleSleep driver assertion dropped\n");
8981 updatePreventIdleSleepList(this, false);
8989 //******************************************************************************
8992 //******************************************************************************
8995 IOPMrootDomain::pmStatsRecordEvent(
8997 AbsoluteTime timestamp
)
8999 bool starting
= eventIndex
& kIOPMStatsEventStartFlag
? true:false;
9000 bool stopping
= eventIndex
& kIOPMStatsEventStopFlag
? true:false;
9003 OSSharedPtr
<OSData
> publishPMStats
;
9005 eventIndex
&= ~(kIOPMStatsEventStartFlag
| kIOPMStatsEventStopFlag
);
9007 absolutetime_to_nanoseconds(timestamp
, &nsec
);
9009 switch (eventIndex
) {
9010 case kIOPMStatsHibernateImageWrite
:
9012 gPMStats
.hibWrite
.start
= nsec
;
9013 } else if (stopping
) {
9014 gPMStats
.hibWrite
.stop
= nsec
;
9018 delta
= gPMStats
.hibWrite
.stop
- gPMStats
.hibWrite
.start
;
9019 IOLog("PMStats: Hibernate write took %qd ms\n", delta
/ NSEC_PER_MSEC
);
9022 case kIOPMStatsHibernateImageRead
:
9024 gPMStats
.hibRead
.start
= nsec
;
9025 } else if (stopping
) {
9026 gPMStats
.hibRead
.stop
= nsec
;
9030 delta
= gPMStats
.hibRead
.stop
- gPMStats
.hibRead
.start
;
9031 IOLog("PMStats: Hibernate read took %qd ms\n", delta
/ NSEC_PER_MSEC
);
9033 publishPMStats
= OSData::withBytes(&gPMStats
, sizeof(gPMStats
));
9034 setProperty(kIOPMSleepStatisticsKey
, publishPMStats
.get());
9035 bzero(&gPMStats
, sizeof(gPMStats
));
9042 * Appends a record of the application response to
9043 * IOPMrootDomain::pmStatsAppResponses
9046 IOPMrootDomain::pmStatsRecordApplicationResponse(
9047 const OSSymbol
*response
,
9053 IOPMPowerStateIndex powerState
,
9056 OSSharedPtr
<OSDictionary
> responseDescription
;
9057 OSSharedPtr
<OSNumber
> delayNum
;
9058 OSSharedPtr
<OSNumber
> powerCaps
;
9059 OSSharedPtr
<OSNumber
> pidNum
;
9060 OSSharedPtr
<OSNumber
> msgNum
;
9061 OSSharedPtr
<const OSSymbol
> appname
;
9062 OSSharedPtr
<const OSSymbol
> sleep
;
9063 OSSharedPtr
<const OSSymbol
> wake
;
9064 IOPMServiceInterestNotifier
*notify
= NULL
;
9066 if (object
&& (notify
= OSDynamicCast(IOPMServiceInterestNotifier
, object
))) {
9067 if (response
->isEqualTo(gIOPMStatsResponseTimedOut
.get())) {
9068 notify
->ackTimeoutCnt
++;
9070 notify
->ackTimeoutCnt
= 0;
9074 if (response
->isEqualTo(gIOPMStatsResponsePrompt
.get()) ||
9075 (_systemTransitionType
== kSystemTransitionNone
) || (_systemTransitionType
== kSystemTransitionNewCapClient
)) {
9080 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
.get())) {
9081 kdebugTrace(kPMLogDrvPSChangeDelay
, id
, messageType
, delay_ms
);
9082 } else if (notify
) {
9083 // User space app or kernel capability client
9085 kdebugTrace(kPMLogAppResponseDelay
, id
, notify
->msgType
, delay_ms
);
9087 kdebugTrace(kPMLogDrvResponseDelay
, notify
->uuid0
, messageType
, delay_ms
);
9089 notify
->msgType
= 0;
9092 responseDescription
= OSDictionary::withCapacity(5);
9093 if (responseDescription
) {
9095 responseDescription
->setObject(_statsResponseTypeKey
.get(), response
);
9098 msgNum
= OSNumber::withNumber(messageType
, 32);
9100 responseDescription
->setObject(_statsMessageTypeKey
.get(), msgNum
.get());
9103 if (!name
&& notify
&& notify
->identifier
) {
9104 name
= notify
->identifier
->getCStringNoCopy();
9107 if (name
&& (strlen(name
) > 0)) {
9108 appname
= OSSymbol::withCString(name
);
9110 responseDescription
->setObject(_statsNameKey
.get(), appname
.get());
9114 if (!id
&& notify
) {
9118 pidNum
= OSNumber::withNumber(id
, 64);
9120 responseDescription
->setObject(_statsPIDKey
.get(), pidNum
.get());
9124 delayNum
= OSNumber::withNumber(delay_ms
, 32);
9126 responseDescription
->setObject(_statsTimeMSKey
.get(), delayNum
.get());
9129 if (response
->isEqualTo(gIOPMStatsDriverPSChangeSlow
.get())) {
9130 powerCaps
= OSNumber::withNumber(powerState
, 32);
9132 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9133 static const char * driverCallTypes
[] = {
9134 [kDriverCallInformPreChange
] = "powerStateWillChangeTo",
9135 [kDriverCallInformPostChange
] = "powerStateDidChangeTo",
9136 [kDriverCallSetPowerState
] = "setPowerState"
9139 if (messageType
< (sizeof(driverCallTypes
) / sizeof(driverCallTypes
[0]))) {
9140 DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9141 name
, id
, driverCallTypes
[messageType
], (uint32_t) powerState
,
9142 async
? "async " : "", delay_ms
);
9146 powerCaps
= OSNumber::withNumber(_pendingCapability
, 32);
9149 responseDescription
->setObject(_statsPowerCapsKey
.get(), powerCaps
.get());
9152 sleep
= OSSymbol::withCString("Sleep");
9153 wake
= OSSymbol::withCString("Wake");
9154 if (_systemTransitionType
== kSystemTransitionSleep
) {
9155 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
.get());
9156 } else if (_systemTransitionType
== kSystemTransitionWake
) {
9157 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
.get());
9158 } else if (_systemTransitionType
== kSystemTransitionCapability
) {
9159 if (CAP_LOSS(kIOPMSystemCapabilityGraphics
)) {
9160 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, sleep
.get());
9161 } else if (CAP_GAIN(kIOPMSystemCapabilityGraphics
)) {
9162 responseDescription
->setObject(kIOPMStatsSystemTransitionKey
, wake
.get());
9166 IOLockLock(pmStatsLock
);
9167 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount() < 50) {
9168 pmStatsAppResponses
->setObject(responseDescription
.get());
9170 IOLockUnlock(pmStatsLock
);
9177 // MARK: PMTraceWorker
9179 //******************************************************************************
9180 // TracePoint support
9182 //******************************************************************************
9184 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9185 "IOPMRegisterNVRAMTracePointHandler"
9188 IOPMrootDomain::callPlatformFunction(
9189 const OSSymbol
* functionName
,
9190 bool waitForFunction
,
9191 void * param1
, void * param2
,
9192 void * param3
, void * param4
)
9194 if (pmTracer
&& functionName
&&
9195 functionName
->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey
) &&
9196 !pmTracer
->tracePointHandler
&& !pmTracer
->tracePointTarget
) {
9197 uint32_t tracePointPhases
, tracePointPCI
;
9198 uint64_t statusCode
;
9200 pmTracer
->tracePointHandler
= (IOPMTracePointHandler
) param1
;
9201 pmTracer
->tracePointTarget
= (void *) param2
;
9202 tracePointPCI
= (uint32_t)(uintptr_t) param3
;
9203 tracePointPhases
= (uint32_t)(uintptr_t) param4
;
9204 if ((tracePointPhases
& 0xff) == kIOPMTracePointSystemSleep
) {
9205 OSSharedPtr
<IORegistryEntry
> node
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
9207 OSSharedPtr
<OSObject
> bootRomFailureProp
;
9208 bootRomFailureProp
= node
->copyProperty(kIOEFIBootRomFailureKey
);
9209 OSData
*data
= OSDynamicCast(OSData
, bootRomFailureProp
.get());
9210 uint32_t bootFailureCode
;
9211 if (data
&& data
->getLength() == sizeof(bootFailureCode
)) {
9212 // Failure code from EFI/BootRom is a four byte structure
9213 memcpy(&bootFailureCode
, data
->getBytesNoCopy(), sizeof(bootFailureCode
));
9214 tracePointPCI
= OSSwapBigToHostInt32(bootFailureCode
);
9218 statusCode
= (((uint64_t)tracePointPCI
) << 32) | tracePointPhases
;
9219 if ((tracePointPhases
& 0xff) != kIOPMTracePointSystemUp
) {
9220 MSG("Sleep failure code 0x%08x 0x%08x\n",
9221 tracePointPCI
, tracePointPhases
);
9223 setProperty(kIOPMSleepWakeFailureCodeKey
, statusCode
, 64);
9224 pmTracer
->tracePointHandler( pmTracer
->tracePointTarget
, 0, 0 );
9226 return kIOReturnSuccess
;
9229 else if (functionName
&&
9230 functionName
->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey
)) {
9231 if (gSleepPolicyHandler
) {
9232 return kIOReturnExclusiveAccess
;
9235 return kIOReturnBadArgument
;
9237 gSleepPolicyHandler
= (IOPMSystemSleepPolicyHandler
) param1
;
9238 gSleepPolicyTarget
= (void *) param2
;
9239 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue
);
9240 return kIOReturnSuccess
;
9244 return super::callPlatformFunction(
9245 functionName
, waitForFunction
, param1
, param2
, param3
, param4
);
9249 IOPMrootDomain::kdebugTrace(uint32_t event
, uint64_t id
,
9250 uintptr_t param1
, uintptr_t param2
, uintptr_t param3
)
9252 uint32_t code
= IODBG_POWER(event
);
9253 uint64_t regId
= id
;
9255 regId
= getRegistryEntryID();
9257 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
, code
, (uintptr_t) regId
, param1
, param2
, param3
, 0);
9261 IOPMrootDomain::tracePoint( uint8_t point
)
9263 if (systemBooting
) {
9267 if (kIOPMTracePointWakeCapabilityClients
== point
) {
9268 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable
);
9271 kdebugTrace(kPMLogSleepWakeTracePoint
, 0, point
, 0);
9272 pmTracer
->tracePoint(point
);
9276 kext_log_putc(char c
)
9278 if (gKextNameEnd
|| gKextNamePos
>= (sizeof(gKextNameBuf
) - 1)) {
9281 if (c
== '(' || c
== '[' || c
== ' ') {
9283 gKextNameEnd
= true;
9286 gKextNameBuf
[gKextNamePos
++] = c
;
9290 kext_log(const char *fmt
, ...)
9294 va_start(listp
, fmt
);
9295 _doprnt(fmt
, &listp
, &kext_log_putc
, 16);
9301 static OSPtr
<const OSSymbol
>
9302 copyKextIdentifierWithAddress(vm_address_t address
)
9304 OSSharedPtr
<const OSSymbol
> identifer
;
9306 IOLockLock(gHaltLogLock
);
9308 gKextNameEnd
= false;
9310 gKextNameBuf
[0] = 0;
9312 OSKext::printKextsInBacktrace(&address
, 1, kext_log
, OSKext::kPrintKextsLock
| OSKext::kPrintKextsTerse
);
9313 gKextNameBuf
[sizeof(gKextNameBuf
) - 1] = 0;
9314 identifer
= OSSymbol::withCString((gKextNameBuf
[0] != 0) ? gKextNameBuf
: kOSKextKernelIdentifier
);
9316 IOLockUnlock(gHaltLogLock
);
9321 // Caller serialized using PM workloop
9323 IOPMrootDomain::getNotificationClientName(OSObject
*object
)
9325 IOPMServiceInterestNotifier
*notifier
= (typeof(notifier
))object
;
9326 const char *clientName
= "UNKNOWN";
9328 if (!notifier
->clientName
) {
9329 // Check for user client
9330 if (systemCapabilityNotifier
&& (((IOPMServiceInterestNotifier
*) systemCapabilityNotifier
.get())->handler
== notifier
->handler
)) {
9331 OSNumber
*clientID
= NULL
;
9332 messageClient(kIOMessageCopyClientID
, object
, &clientID
);
9334 OSSharedPtr
<OSString
> string(IOCopyLogNameForPID(clientID
->unsigned32BitValue()), OSNoRetain
);
9336 notifier
->clientName
= OSSymbol::withString(string
.get());
9338 clientID
->release();
9340 } else if (notifier
->identifier
) {
9341 notifier
->clientName
.reset(notifier
->identifier
.get(), OSRetain
);
9345 if (notifier
->clientName
) {
9346 clientName
= notifier
->clientName
->getCStringNoCopy();
9353 IOPMrootDomain::traceNotification(OSObject
*object
, bool start
, uint64_t timestamp
, uint32_t msgIndex
)
9355 IOPMServiceInterestNotifier
*notifier
;
9357 if (systemBooting
) {
9360 notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
9366 pmTracer
->traceDetail(notifier
->uuid0
>> 32);
9367 kdebugTrace(kPMLogSleepWakeMessage
, pmTracer
->getTracePhase(),
9368 (uintptr_t) notifier
->msgType
, (uintptr_t) notifier
->uuid0
, (uintptr_t) notifier
->uuid1
);
9370 // Update notifier state used for response/ack logging
9371 notifier
->msgIndex
= msgIndex
;
9372 notifier
->msgAbsTime
= timestamp
;
9374 if (msgIndex
!= UINT_MAX
) {
9375 DLOG("%s[%u] to %s\n", getIOMessageString(notifier
->msgType
), msgIndex
, getNotificationClientName(notifier
));
9377 DLOG("%s to %s\n", getIOMessageString(notifier
->msgType
), getNotificationClientName(notifier
));
9380 assert(notifierObject
== NULL
);
9381 notifierThread
= current_thread();
9382 notifierObject
.reset(notifier
, OSRetain
);
9387 SUB_ABSOLUTETIME(×tamp
, ¬ifier
->msgAbsTime
);
9388 absolutetime_to_nanoseconds(timestamp
, &nsec
);
9389 delayMS
= (uint32_t)(nsec
/ 1000000ULL);
9390 if (delayMS
> notifier
->maxMsgDelayMS
) {
9391 notifier
->maxMsgDelayMS
= delayMS
;
9394 assert(notifierObject
== notifier
);
9395 notifierObject
.reset();
9396 notifierThread
= NULL
;
9401 IOPMrootDomain::traceNotificationAck(OSObject
*object
, uint32_t delay_ms
)
9403 if (systemBooting
) {
9406 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
9411 kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
,
9412 (uintptr_t) notifier
->uuid1
, (uintptr_t) 0, (uintptr_t) delay_ms
);
9414 DLOG("%s[%u] ack from %s took %d ms\n",
9415 getIOMessageString(notifier
->msgType
), notifier
->msgIndex
, getNotificationClientName(notifier
), delay_ms
);
9416 if (delay_ms
> notifier
->maxAckDelayMS
) {
9417 notifier
->maxAckDelayMS
= delay_ms
;
9422 IOPMrootDomain::traceNotificationResponse(OSObject
*object
, uint32_t delay_ms
, uint32_t ack_time_us
)
9424 if (systemBooting
) {
9427 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
9432 kdebugTrace(kPMLogDrvResponseDelay
, notifier
->uuid0
,
9433 (uintptr_t) notifier
->uuid1
, (uintptr_t)(ack_time_us
/ 1000), (uintptr_t) delay_ms
);
9435 if (ack_time_us
== 0) {
9436 // Client work is done and ack will not be forthcoming
9437 DLOG("%s[%u] response from %s took %d ms\n",
9438 getIOMessageString(notifier
->msgType
), notifier
->msgIndex
, getNotificationClientName(notifier
), delay_ms
);
9440 // Client needs more time and it must ack within ack_time_us
9441 DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9442 getIOMessageString(notifier
->msgType
), notifier
->msgIndex
, getNotificationClientName(notifier
), delay_ms
, ack_time_us
);
9447 IOPMrootDomain::traceFilteredNotification(OSObject
*object
)
9449 if ((kIOLogDebugPower
& gIOKitDebug
) == 0) {
9452 if (systemBooting
) {
9455 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, object
);
9460 DLOG("%s to %s dropped\n", getIOMessageString(notifier
->msgType
), getNotificationClientName(notifier
));
9464 IOPMrootDomain::traceDetail(uint32_t msgType
, uint32_t msgIndex
, uint32_t delay
)
9466 if (!systemBooting
) {
9467 uint32_t detail
= ((msgType
& 0xffff) << 16) | (delay
& 0xffff);
9468 pmTracer
->traceDetail( detail
);
9469 kdebugTrace(kPMLogSleepWakeTracePoint
, pmTracer
->getTracePhase(), msgType
, delay
);
9470 DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer
->getTracePhase(), msgType
, delay
);
9475 IOPMrootDomain::configureReportGated(uint64_t channel_id
, uint64_t action
, void *result
)
9478 void **report
= NULL
;
9481 uint32_t *clientCnt
;
9486 if (channel_id
== kAssertDelayChID
) {
9487 report
= &assertOnWakeReport
;
9488 bktCnt
= kAssertDelayBcktCnt
;
9489 bktSize
= kAssertDelayBcktSize
;
9490 clientCnt
= &assertOnWakeClientCnt
;
9491 } else if (channel_id
== kSleepDelaysChID
) {
9492 report
= &sleepDelaysReport
;
9493 bktCnt
= kSleepDelaysBcktCnt
;
9494 bktSize
= kSleepDelaysBcktSize
;
9495 clientCnt
= &sleepDelaysClientCnt
;
9502 case kIOReportEnable
:
9509 reportSize
= HISTREPORT_BUFSIZE(bktCnt
);
9510 *report
= IOMalloc(reportSize
);
9511 if (*report
== NULL
) {
9514 bzero(*report
, reportSize
);
9515 HISTREPORT_INIT((uint16_t)bktCnt
, bktSize
, *report
, reportSize
,
9516 getRegistryEntryID(), channel_id
, kIOReportCategoryPower
);
9518 if (channel_id
== kAssertDelayChID
) {
9519 assertOnWakeSecs
= 0;
9524 case kIOReportDisable
:
9525 if (*clientCnt
== 0) {
9528 if (*clientCnt
== 1) {
9529 IOFree(*report
, HISTREPORT_BUFSIZE(bktCnt
));
9534 if (channel_id
== kAssertDelayChID
) {
9535 assertOnWakeSecs
= -1; // Invalid value to prevent updates
9539 case kIOReportGetDimensions
:
9541 HISTREPORT_UPDATERES(*report
, kIOReportGetDimensions
, result
);
9550 IOPMrootDomain::configureReport(IOReportChannelList
*channelList
,
9551 IOReportConfigureAction action
,
9556 uint64_t configAction
= (uint64_t)action
;
9558 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
9559 if ((channelList
->channels
[cnt
].channel_id
== kSleepCntChID
) ||
9560 (channelList
->channels
[cnt
].channel_id
== kDarkWkCntChID
) ||
9561 (channelList
->channels
[cnt
].channel_id
== kUserWkCntChID
)) {
9562 if (action
!= kIOReportGetDimensions
) {
9565 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
9566 } else if ((channelList
->channels
[cnt
].channel_id
== kAssertDelayChID
) ||
9567 (channelList
->channels
[cnt
].channel_id
== kSleepDelaysChID
)) {
9568 gIOPMWorkLoop
->runAction(
9569 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::configureReportGated
),
9570 (OSObject
*)this, (void *)channelList
->channels
[cnt
].channel_id
,
9571 (void *)configAction
, (void *)result
);
9575 return super::configureReport(channelList
, action
, result
, destination
);
9579 IOPMrootDomain::updateReportGated(uint64_t ch_id
, void *result
, IOBufferMemoryDescriptor
*dest
)
9588 if (ch_id
== kAssertDelayChID
) {
9589 report
= &assertOnWakeReport
;
9590 } else if (ch_id
== kSleepDelaysChID
) {
9591 report
= &sleepDelaysReport
;
9594 return kIOReturnBadArgument
;
9597 if (*report
== NULL
) {
9598 return kIOReturnNotOpen
;
9601 HISTREPORT_UPDATEPREP(*report
, data2cpy
, size2cpy
);
9602 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
9603 return kIOReturnOverrun
;
9606 HISTREPORT_UPDATERES(*report
, kIOReportCopyChannelData
, result
);
9607 dest
->appendBytes(data2cpy
, size2cpy
);
9609 return kIOReturnSuccess
;
9613 IOPMrootDomain::updateReport(IOReportChannelList
*channelList
,
9614 IOReportUpdateAction action
,
9620 uint8_t buf
[SIMPLEREPORT_BUFSIZE
];
9621 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
9625 if (action
!= kIOReportCopyChannelData
) {
9629 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
9630 ch_id
= channelList
->channels
[cnt
].channel_id
;
9632 if ((ch_id
== kAssertDelayChID
) || (ch_id
== kSleepDelaysChID
)) {
9633 gIOPMWorkLoop
->runAction(
9634 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOPMrootDomain::updateReportGated
),
9635 (OSObject
*)this, (void *)ch_id
,
9636 (void *)result
, (void *)dest
);
9638 } else if ((ch_id
== kSleepCntChID
) ||
9639 (ch_id
== kDarkWkCntChID
) || (ch_id
== kUserWkCntChID
)) {
9640 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), ch_id
, kIOReportCategoryPower
);
9645 if (ch_id
== kSleepCntChID
) {
9646 SIMPLEREPORT_SETVALUE(buf
, sleepCnt
);
9647 } else if (ch_id
== kDarkWkCntChID
) {
9648 SIMPLEREPORT_SETVALUE(buf
, darkWakeCnt
);
9649 } else if (ch_id
== kUserWkCntChID
) {
9650 SIMPLEREPORT_SETVALUE(buf
, displayWakeCnt
);
9653 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
9654 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
9655 dest
->appendBytes(data2cpy
, size2cpy
);
9659 return super::updateReport(channelList
, action
, result
, destination
);
9663 //******************************************************************************
9664 // PMTraceWorker Class
9666 //******************************************************************************
9669 #define super OSObject
9670 OSDefineMetaClassAndStructors(PMTraceWorker
, OSObject
)
9672 #define kPMBestGuessPCIDevicesCount 25
9673 #define kPMMaxRTCBitfieldSize 32
9675 OSPtr
<PMTraceWorker
>
9676 PMTraceWorker::tracer(IOPMrootDomain
* owner
)
9678 OSSharedPtr
<PMTraceWorker
> me
= OSMakeShared
<PMTraceWorker
>();
9679 if (!me
|| !me
->init()) {
9683 DLOG("PMTraceWorker %p\n", OBFUSCATE(me
.get()));
9685 // Note that we cannot instantiate the PCI device -> bit mappings here, since
9686 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
9687 // this dictionary lazily.
9689 me
->pciDeviceBitMappings
= NULL
;
9690 me
->pmTraceWorkerLock
= IOLockAlloc();
9691 me
->tracePhase
= kIOPMTracePointSystemUp
;
9692 me
->traceData32
= 0;
9693 me
->loginWindowData
= 0;
9694 me
->coreDisplayData
= 0;
9695 me
->coreGraphicsData
= 0;
9700 PMTraceWorker::RTC_TRACE(void)
9702 if (tracePointHandler
&& tracePointTarget
) {
9705 IOLockLock(pmTraceWorkerLock
);
9706 wordA
= (loginWindowData
<< 24) | (coreDisplayData
<< 16) |
9707 (coreGraphicsData
<< 8) | tracePhase
;
9708 IOLockUnlock(pmTraceWorkerLock
);
9710 tracePointHandler( tracePointTarget
, traceData32
, wordA
);
9711 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32
, wordA
);
9713 #if DEVELOPMENT || DEBUG
9714 if ((swd_panic_phase
!= 0) && (swd_panic_phase
== tracePhase
)) {
9715 DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase
);
9716 IOLock
*l
= IOLockAlloc();
9724 PMTraceWorker::recordTopLevelPCIDevice(IOService
* pciDevice
)
9726 OSSharedPtr
<const OSSymbol
> deviceName
;
9729 IOLockLock(pmTraceWorkerLock
);
9731 if (!pciDeviceBitMappings
) {
9732 pciDeviceBitMappings
= OSArray::withCapacity(kPMBestGuessPCIDevicesCount
);
9733 if (!pciDeviceBitMappings
) {
9738 // Check for bitmask overflow.
9739 if (pciDeviceBitMappings
->getCount() >= kPMMaxRTCBitfieldSize
) {
9743 if ((deviceName
= pciDevice
->copyName()) &&
9744 (pciDeviceBitMappings
->getNextIndexOfObject(deviceName
.get(), 0) == (unsigned int)-1) &&
9745 pciDeviceBitMappings
->setObject(deviceName
.get())) {
9746 index
= pciDeviceBitMappings
->getCount() - 1;
9747 _LOG("PMTrace PCI array: set object %s => %d\n",
9748 deviceName
->getCStringNoCopy(), index
);
9751 if (!addedToRegistry
&& (index
>= 0)) {
9752 addedToRegistry
= owner
->setProperty("PCITopLevel", this);
9756 IOLockUnlock(pmTraceWorkerLock
);
9761 PMTraceWorker::serialize(OSSerialize
*s
) const
9764 if (pciDeviceBitMappings
) {
9765 IOLockLock(pmTraceWorkerLock
);
9766 ok
= pciDeviceBitMappings
->serialize(s
);
9767 IOLockUnlock(pmTraceWorkerLock
);
9773 PMTraceWorker::tracePoint(uint8_t phase
)
9775 // clear trace detail when phase begins
9776 if (tracePhase
!= phase
) {
9782 DLOG("trace point 0x%02x\n", tracePhase
);
9787 PMTraceWorker::traceDetail(uint32_t detail
)
9789 if (detail
== traceData32
) {
9792 traceData32
= detail
;
9797 PMTraceWorker::traceComponentWakeProgress(uint32_t component
, uint32_t data
)
9799 switch (component
) {
9800 case kIOPMLoginWindowProgress
:
9801 loginWindowData
= data
& kIOPMLoginWindowProgressMask
;
9803 case kIOPMCoreDisplayProgress
:
9804 coreDisplayData
= data
& kIOPMCoreDisplayProgressMask
;
9806 case kIOPMCoreGraphicsProgress
:
9807 coreGraphicsData
= data
& kIOPMCoreGraphicsProgressMask
;
9813 DLOG("component trace point 0x%02x data 0x%08x\n", component
, data
);
9818 PMTraceWorker::tracePCIPowerChange(
9819 change_t type
, IOService
*service
, uint32_t changeFlags
, uint32_t bitNum
)
9822 uint32_t expectedFlag
;
9824 // Ignore PCI changes outside of system sleep/wake.
9825 if ((kIOPMTracePointSleepPowerPlaneDrivers
!= tracePhase
) &&
9826 (kIOPMTracePointWakePowerPlaneDrivers
!= tracePhase
)) {
9830 // Only record the WillChange transition when going to sleep,
9831 // and the DidChange on the way up.
9832 changeFlags
&= (kIOPMDomainWillChange
| kIOPMDomainDidChange
);
9833 expectedFlag
= (kIOPMTracePointSleepPowerPlaneDrivers
== tracePhase
) ?
9834 kIOPMDomainWillChange
: kIOPMDomainDidChange
;
9835 if (changeFlags
!= expectedFlag
) {
9839 // Mark this device off in our bitfield
9840 if (bitNum
< kPMMaxRTCBitfieldSize
) {
9841 bitMask
= (1 << bitNum
);
9843 if (kPowerChangeStart
== type
) {
9844 traceData32
|= bitMask
;
9845 _LOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
9846 service
->getName(), bitNum
, bitMask
, traceData32
);
9847 owner
->kdebugTrace(kPMLogPCIDevChangeStart
, service
->getRegistryEntryID(), traceData32
, 0);
9849 traceData32
&= ~bitMask
;
9850 _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
9851 service
->getName(), bitNum
, bitMask
, traceData32
);
9852 owner
->kdebugTrace(kPMLogPCIDevChangeDone
, service
->getRegistryEntryID(), traceData32
, 0);
9855 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase
, traceData32
);
9861 PMTraceWorker::getPMStatusCode()
9863 return ((uint64_t)traceData32
<< 32) | ((uint64_t)tracePhase
);
9867 PMTraceWorker::getTracePhase()
9873 PMTraceWorker::getTraceData()
9879 // MARK: PMHaltWorker
9881 //******************************************************************************
9882 // PMHaltWorker Class
9884 //******************************************************************************
9887 PMHaltWorker::worker( void )
9893 me
= OSTypeAlloc( PMHaltWorker
);
9894 if (!me
|| !me
->init()) {
9898 me
->lock
= IOLockAlloc();
9903 DLOG("PMHaltWorker %p\n", OBFUSCATE(me
));
9904 me
->retain(); // thread holds extra retain
9905 if (KERN_SUCCESS
!= kernel_thread_start(&PMHaltWorker::main
, (void *) me
, &thread
)) {
9909 thread_deallocate(thread
);
9920 PMHaltWorker::free( void )
9922 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
9927 return OSObject::free();
9931 PMHaltWorker::main( void * arg
, wait_result_t waitResult
)
9933 PMHaltWorker
* me
= (PMHaltWorker
*) arg
;
9935 IOLockLock( gPMHaltLock
);
9937 me
->depth
= gPMHaltDepth
;
9938 IOLockUnlock( gPMHaltLock
);
9940 while (me
->depth
>= 0) {
9941 PMHaltWorker::work( me
);
9943 IOLockLock( gPMHaltLock
);
9944 if (++gPMHaltIdleCount
>= gPMHaltBusyCount
) {
9945 // This is the last thread to finish work on this level,
9946 // inform everyone to start working on next lower level.
9948 me
->depth
= gPMHaltDepth
;
9949 gPMHaltIdleCount
= 0;
9950 thread_wakeup((event_t
) &gPMHaltIdleCount
);
9952 // One or more threads are still working on this level,
9953 // this thread must wait.
9954 me
->depth
= gPMHaltDepth
- 1;
9956 IOLockSleep(gPMHaltLock
, &gPMHaltIdleCount
, THREAD_UNINT
);
9957 } while (me
->depth
!= gPMHaltDepth
);
9959 IOLockUnlock( gPMHaltLock
);
9962 // No more work to do, terminate thread
9963 DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me
), me
->visits
);
9964 thread_wakeup( &gPMHaltDepth
);
9969 PMHaltWorker::work( PMHaltWorker
* me
)
9971 OSSharedPtr
<IOService
> service
;
9973 AbsoluteTime startTime
, elapsedTime
;
9980 // Claim an unit of work from the shared pool
9981 IOLockLock( gPMHaltLock
);
9982 inner
= (OSSet
*)gPMHaltArray
->getObject(me
->depth
);
9984 service
.reset(OSDynamicCast(IOService
, inner
->getAnyObject()), OSRetain
);
9986 inner
->removeObject(service
.get());
9989 IOLockUnlock( gPMHaltLock
);
9991 break; // no more work at this depth
9993 clock_get_uptime(&startTime
);
9995 if (!service
->isInactive() &&
9996 service
->setProperty(gPMHaltClientAcknowledgeKey
.get(), me
)) {
9997 IOLockLock(me
->lock
);
9998 me
->startTime
= startTime
;
9999 me
->service
= service
.get();
10000 me
->timeout
= false;
10001 IOLockUnlock(me
->lock
);
10003 service
->systemWillShutdown( gPMHaltMessageType
);
10005 // Wait for driver acknowledgement
10006 IOLockLock(me
->lock
);
10007 while (service
->propertyExists(gPMHaltClientAcknowledgeKey
.get())) {
10008 IOLockSleep(me
->lock
, me
, THREAD_UNINT
);
10010 me
->service
= NULL
;
10011 timeout
= me
->timeout
;
10012 IOLockUnlock(me
->lock
);
10015 deltaTime
= computeDeltaTimeMS(&startTime
, &elapsedTime
);
10016 if ((deltaTime
> kPMHaltTimeoutMS
) || timeout
) {
10017 LOG("%s driver %s (0x%llx) took %u ms\n",
10018 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ?
10019 "PowerOff" : "Restart",
10020 service
->getName(), service
->getRegistryEntryID(),
10021 (uint32_t) deltaTime
);
10022 halt_log_enter("PowerOff/Restart handler completed",
10023 OSMemberFunctionCast(const void *, service
.get(), &IOService::systemWillShutdown
),
10032 PMHaltWorker::checkTimeout( PMHaltWorker
* me
, AbsoluteTime
* now
)
10035 AbsoluteTime startTime
;
10036 AbsoluteTime endTime
;
10040 IOLockLock(me
->lock
);
10041 if (me
->service
&& !me
->timeout
) {
10042 startTime
= me
->startTime
;
10044 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0) {
10045 SUB_ABSOLUTETIME(&endTime
, &startTime
);
10046 absolutetime_to_nanoseconds(endTime
, &nano
);
10048 if (nano
> 3000000000ULL) {
10049 me
->timeout
= true;
10051 halt_log_enter("PowerOff/Restart still waiting on handler",
10052 OSMemberFunctionCast(const void *, me
->service
, &IOService::systemWillShutdown
),
10054 MSG("%s still waiting on %s\n",
10055 (gPMHaltMessageType
== kIOMessageSystemWillPowerOff
) ? "PowerOff" : "Restart",
10056 me
->service
->getName());
10059 IOLockUnlock(me
->lock
);
10062 //******************************************************************************
10063 // acknowledgeSystemWillShutdown
10065 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10066 //******************************************************************************
10069 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService
* from
)
10071 PMHaltWorker
* worker
;
10072 OSSharedPtr
<OSObject
> prop
;
10078 //DLOG("%s acknowledged\n", from->getName());
10079 prop
= from
->copyProperty( gPMHaltClientAcknowledgeKey
.get());
10081 worker
= (PMHaltWorker
*) prop
.get();
10082 IOLockLock(worker
->lock
);
10083 from
->removeProperty( gPMHaltClientAcknowledgeKey
.get());
10084 thread_wakeup((event_t
) worker
);
10085 IOLockUnlock(worker
->lock
);
10087 DLOG("%s acknowledged without worker property\n",
10093 //******************************************************************************
10094 // notifySystemShutdown
10096 // Notify all objects in PM tree that system will shutdown or restart
10097 //******************************************************************************
10100 notifySystemShutdown( IOService
* root
, uint32_t messageType
)
10102 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10103 OSSharedPtr
<IORegistryIterator
> iter
;
10104 IORegistryEntry
* entry
;
10107 OSSharedPtr
<OSSet
> newInner
;
10108 PMHaltWorker
* workers
[kPMHaltMaxWorkers
];
10109 AbsoluteTime deadline
;
10110 unsigned int totalNodes
= 0;
10111 unsigned int depth
;
10112 unsigned int rootDepth
;
10113 unsigned int numWorkers
;
10114 unsigned int count
;
10119 DLOG("%s msgType = 0x%x\n", __FUNCTION__
, messageType
);
10121 baseFunc
= OSMemberFunctionCast(void *, root
, &IOService::systemWillShutdown
);
10123 // Iterate the entire PM tree starting from root
10125 rootDepth
= root
->getDepth( gIOPowerPlane
);
10130 // debug - for repeated test runs
10131 while (PMHaltWorker::metaClass
->getInstanceCount()) {
10135 if (!gPMHaltArray
) {
10136 gPMHaltArray
= OSArray::withCapacity(40);
10137 if (!gPMHaltArray
) {
10141 gPMHaltArray
->flushCollection();
10144 if (!gPMHaltLock
) {
10145 gPMHaltLock
= IOLockAlloc();
10146 if (!gPMHaltLock
) {
10151 if (!gPMHaltClientAcknowledgeKey
) {
10152 gPMHaltClientAcknowledgeKey
=
10153 OSSymbol::withCStringNoCopy("PMShutdown");
10154 if (!gPMHaltClientAcknowledgeKey
) {
10159 gPMHaltMessageType
= messageType
;
10161 // Depth-first walk of PM plane
10163 iter
= IORegistryIterator::iterateOver(
10164 root
, gIOPowerPlane
, kIORegistryIterateRecursively
);
10167 while ((entry
= iter
->getNextObject())) {
10168 node
= OSDynamicCast(IOService
, entry
);
10174 OSMemberFunctionCast(void *, node
, &IOService::systemWillShutdown
)) {
10178 depth
= node
->getDepth( gIOPowerPlane
);
10179 if (depth
<= rootDepth
) {
10185 // adjust to zero based depth
10186 depth
-= (rootDepth
+ 1);
10188 // gPMHaltArray is an array of containers, each container
10189 // refers to nodes with the same depth.
10191 count
= gPMHaltArray
->getCount();
10192 while (depth
>= count
) {
10193 // expand array and insert placeholders
10194 gPMHaltArray
->setObject(PLACEHOLDER
);
10197 count
= gPMHaltArray
->getCount();
10198 if (depth
< count
) {
10199 inner
= (OSSet
*)gPMHaltArray
->getObject(depth
);
10200 if (inner
== PLACEHOLDER
) {
10201 newInner
= OSSet::withCapacity(40);
10203 gPMHaltArray
->replaceObject(depth
, newInner
.get());
10204 inner
= newInner
.get();
10208 // PM nodes that appear more than once in the tree will have
10209 // the same depth, OSSet will refuse to add the node twice.
10211 ok
= inner
->setObject(node
);
10215 DLOG("Skipped PM node %s\n", node
->getName());
10221 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
)); i
++) {
10223 if (inner
!= PLACEHOLDER
) {
10224 count
= inner
->getCount();
10226 DLOG("Nodes at depth %u = %u\n", i
, count
);
10229 // strip placeholders (not all depths are populated)
10231 for (int i
= 0; (inner
= (OSSet
*)gPMHaltArray
->getObject(i
));) {
10232 if (inner
== PLACEHOLDER
) {
10233 gPMHaltArray
->removeObject(i
);
10236 count
= inner
->getCount();
10237 if (count
> numWorkers
) {
10238 numWorkers
= count
;
10240 totalNodes
+= count
;
10244 if (gPMHaltArray
->getCount() == 0 || !numWorkers
) {
10248 gPMHaltBusyCount
= 0;
10249 gPMHaltIdleCount
= 0;
10250 gPMHaltDepth
= gPMHaltArray
->getCount() - 1;
10252 // Create multiple workers (and threads)
10254 if (numWorkers
> kPMHaltMaxWorkers
) {
10255 numWorkers
= kPMHaltMaxWorkers
;
10258 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10259 totalNodes
, gPMHaltArray
->getCount(), numWorkers
);
10261 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
10262 workers
[i
] = PMHaltWorker::worker();
10265 // Wait for workers to exhaust all available work
10267 IOLockLock(gPMHaltLock
);
10268 while (gPMHaltDepth
>= 0) {
10269 clock_interval_to_deadline(1000, kMillisecondScale
, &deadline
);
10271 waitResult
= IOLockSleepDeadline(
10272 gPMHaltLock
, &gPMHaltDepth
, deadline
, THREAD_UNINT
);
10273 if (THREAD_TIMED_OUT
== waitResult
) {
10275 clock_get_uptime(&now
);
10277 IOLockUnlock(gPMHaltLock
);
10278 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
10280 PMHaltWorker::checkTimeout(workers
[i
], &now
);
10283 IOLockLock(gPMHaltLock
);
10286 IOLockUnlock(gPMHaltLock
);
10288 // Release all workers
10290 for (unsigned int i
= 0; i
< numWorkers
; i
++) {
10292 workers
[i
]->release();
10294 // worker also retained by it's own thread
10298 DLOG("%s done\n", __FUNCTION__
);
10303 // MARK: Kernel Assertion
10305 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10307 IOPMDriverAssertionID
10308 IOPMrootDomain::createPMAssertion(
10309 IOPMDriverAssertionType whichAssertionBits
,
10310 IOPMDriverAssertionLevel assertionLevel
,
10311 IOService
*ownerService
,
10312 const char *ownerDescription
)
10315 IOPMDriverAssertionID newAssertion
;
10317 if (!pmAssertions
) {
10321 ret
= pmAssertions
->createAssertion(whichAssertionBits
, assertionLevel
, ownerService
, ownerDescription
, &newAssertion
);
10323 if (kIOReturnSuccess
== ret
) {
10324 return newAssertion
;
10331 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion
)
10333 if (!pmAssertions
) {
10334 return kIOReturnInternalError
;
10337 return pmAssertions
->releaseAssertion(releaseAssertion
);
10342 IOPMrootDomain::setPMAssertionLevel(
10343 IOPMDriverAssertionID assertionID
,
10344 IOPMDriverAssertionLevel assertionLevel
)
10346 return pmAssertions
->setAssertionLevel(assertionID
, assertionLevel
);
10349 IOPMDriverAssertionLevel
10350 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion
)
10352 IOPMDriverAssertionType sysLevels
;
10354 if (!pmAssertions
|| whichAssertion
== 0) {
10355 return kIOPMDriverAssertionLevelOff
;
10358 sysLevels
= pmAssertions
->getActivatedAssertions();
10360 // Check that every bit set in argument 'whichAssertion' is asserted
10361 // in the aggregate bits.
10362 if ((sysLevels
& whichAssertion
) == whichAssertion
) {
10363 return kIOPMDriverAssertionLevelOn
;
10365 return kIOPMDriverAssertionLevelOff
;
10370 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels
)
10372 if (!pmAssertions
) {
10373 return kIOReturnNotFound
;
10376 return pmAssertions
->setUserAssertionLevels(inLevels
);
10380 IOPMrootDomain::serializeProperties( OSSerialize
* s
) const
10382 if (pmAssertions
) {
10383 pmAssertions
->publishProperties();
10385 return IOService::serializeProperties(s
);
10388 OSSharedPtr
<OSObject
>
10389 IOPMrootDomain::copyProperty( const char * aKey
) const
10391 OSSharedPtr
<OSObject
> obj
;
10392 obj
= IOService::copyProperty(aKey
);
10398 if (!strncmp(aKey
, kIOPMSleepWakeWdogRebootKey
,
10399 sizeof(kIOPMSleepWakeWdogRebootKey
))) {
10400 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
10401 return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
);
10403 return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
);
10407 if (!strncmp(aKey
, kIOPMSleepWakeWdogLogsValidKey
,
10408 sizeof(kIOPMSleepWakeWdogLogsValidKey
))) {
10409 if (swd_flags
& SWD_VALID_LOGS
) {
10410 return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
);
10412 return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
);
10417 * XXX: We should get rid of "DesktopMode" property when 'kAppleClamshellCausesSleepKey'
10418 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10419 * issued by DisplayWrangler on darkwake.
10421 if (!strcmp(aKey
, "DesktopMode")) {
10423 return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
);
10425 return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
);
10428 if (!strcmp(aKey
, "DisplayIdleForDemandSleep")) {
10429 if (displayIdleForDemandSleep
) {
10430 return OSSharedPtr
<OSBoolean
>(kOSBooleanTrue
, OSNoRetain
);
10432 return OSSharedPtr
<OSBoolean
>(kOSBooleanFalse
, OSNoRetain
);
10436 if (!strcmp(aKey
, kIOPMDriverWakeEventsKey
)) {
10437 OSSharedPtr
<OSArray
> array
;
10439 if (_systemWakeEventsArray
&& _systemWakeEventsArray
->getCount()) {
10440 OSSharedPtr
<OSCollection
> collection
= _systemWakeEventsArray
->copyCollection();
10442 array
= OSDynamicPtrCast
<OSArray
>(collection
);
10445 WAKEEVENT_UNLOCK();
10446 return os::move(array
);
10449 if (!strcmp(aKey
, kIOPMSleepStatisticsAppsKey
)) {
10450 OSSharedPtr
<OSArray
> array
;
10451 IOLockLock(pmStatsLock
);
10452 if (pmStatsAppResponses
&& pmStatsAppResponses
->getCount()) {
10453 OSSharedPtr
<OSCollection
> collection
= pmStatsAppResponses
->copyCollection();
10455 array
= OSDynamicPtrCast
<OSArray
>(collection
);
10458 IOLockUnlock(pmStatsLock
);
10459 return os::move(array
);
10462 if (!strcmp(aKey
, kIOPMIdleSleepPreventersKey
)) {
10463 OSArray
*idleSleepList
= NULL
;
10464 gRootDomain
->copySleepPreventersList(&idleSleepList
, NULL
);
10465 return OSSharedPtr
<OSArray
>(idleSleepList
, OSNoRetain
);
10468 if (!strcmp(aKey
, kIOPMSystemSleepPreventersKey
)) {
10469 OSArray
*systemSleepList
= NULL
;
10470 gRootDomain
->copySleepPreventersList(NULL
, &systemSleepList
);
10471 return OSSharedPtr
<OSArray
>(systemSleepList
, OSNoRetain
);
10474 if (!strcmp(aKey
, kIOPMIdleSleepPreventersWithIDKey
)) {
10475 OSArray
*idleSleepList
= NULL
;
10476 gRootDomain
->copySleepPreventersListWithID(&idleSleepList
, NULL
);
10477 return OSSharedPtr
<OSArray
>(idleSleepList
, OSNoRetain
);
10480 if (!strcmp(aKey
, kIOPMSystemSleepPreventersWithIDKey
)) {
10481 OSArray
*systemSleepList
= NULL
;
10482 gRootDomain
->copySleepPreventersListWithID(NULL
, &systemSleepList
);
10483 return OSSharedPtr
<OSArray
>(systemSleepList
, OSNoRetain
);
10489 // MARK: Wake Event Reporting
10492 IOPMrootDomain::copyWakeReasonString( char * outBuf
, size_t bufSize
)
10495 strlcpy(outBuf
, gWakeReasonString
, bufSize
);
10496 WAKEEVENT_UNLOCK();
10500 IOPMrootDomain::copyShutdownReasonString( char * outBuf
, size_t bufSize
)
10503 strlcpy(outBuf
, gShutdownReasonString
, bufSize
);
10504 WAKEEVENT_UNLOCK();
10507 //******************************************************************************
10508 // acceptSystemWakeEvents
10510 // Private control for the acceptance of driver wake event claims.
10511 //******************************************************************************
10514 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control
)
10516 bool logWakeReason
= false;
10520 case kAcceptSystemWakeEvents_Enable
:
10521 assert(_acceptSystemWakeEvents
== false);
10522 if (!_systemWakeEventsArray
) {
10523 _systemWakeEventsArray
= OSArray::withCapacity(4);
10525 _acceptSystemWakeEvents
= (_systemWakeEventsArray
!= NULL
);
10526 if (!(_aotNow
&& (kIOPMWakeEventAOTExitFlags
& _aotPendingFlags
))) {
10527 gWakeReasonString
[0] = '\0';
10528 if (_systemWakeEventsArray
) {
10529 _systemWakeEventsArray
->flushCollection();
10533 // Remove stale WakeType property before system sleep
10534 removeProperty(kIOPMRootDomainWakeTypeKey
);
10535 removeProperty(kIOPMRootDomainWakeReasonKey
);
10538 case kAcceptSystemWakeEvents_Disable
:
10539 _acceptSystemWakeEvents
= false;
10540 #if defined(XNU_TARGET_OS_OSX)
10541 logWakeReason
= (gWakeReasonString
[0] != '\0');
10542 #else /* !defined(XNU_TARGET_OS_OSX) */
10543 logWakeReason
= gWakeReasonSysctlRegistered
;
10545 static int panic_allowed
= -1;
10547 if ((panic_allowed
== -1) &&
10548 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed
, sizeof(panic_allowed
)) == false)) {
10552 if (panic_allowed
) {
10554 // Panic if wake reason is null or empty
10555 for (i
= 0; (i
< strlen(gWakeReasonString
)); i
++) {
10556 if ((gWakeReasonString
[i
] != ' ') && (gWakeReasonString
[i
] != '\t')) {
10560 if (i
>= strlen(gWakeReasonString
)) {
10561 panic("Wake reason is empty\n");
10564 #endif /* DEVELOPMENT */
10565 #endif /* !defined(XNU_TARGET_OS_OSX) */
10567 // publish kIOPMRootDomainWakeReasonKey if not already set
10568 if (!propertyExists(kIOPMRootDomainWakeReasonKey
)) {
10569 setProperty(kIOPMRootDomainWakeReasonKey
, gWakeReasonString
);
10573 case kAcceptSystemWakeEvents_Reenable
:
10574 assert(_acceptSystemWakeEvents
== false);
10575 _acceptSystemWakeEvents
= (_systemWakeEventsArray
!= NULL
);
10576 removeProperty(kIOPMRootDomainWakeReasonKey
);
10579 WAKEEVENT_UNLOCK();
10581 if (logWakeReason
) {
10582 MSG("system wake events: %s\n", gWakeReasonString
);
10586 //******************************************************************************
10587 // claimSystemWakeEvent
10589 // For a driver to claim a device is the source/conduit of a system wake event.
10590 //******************************************************************************
10593 IOPMrootDomain::claimSystemWakeEvent(
10594 IOService
* device
,
10595 IOOptionBits flags
,
10596 const char * reason
,
10597 OSObject
* details
)
10599 OSSharedPtr
<const OSSymbol
> deviceName
;
10600 OSSharedPtr
<OSNumber
> deviceRegId
;
10601 OSSharedPtr
<OSNumber
> claimTime
;
10602 OSSharedPtr
<OSData
> flagsData
;
10603 OSSharedPtr
<OSString
> reasonString
;
10604 OSSharedPtr
<OSDictionary
> dict
;
10605 uint64_t timestamp
;
10606 bool addWakeReason
;
10608 if (!device
|| !reason
) {
10612 pmEventTimeStamp(×tamp
);
10614 IOOptionBits aotFlags
= 0;
10615 bool needAOTEvaluate
= FALSE
;
10617 if (kIOPMAOTModeAddEventFlags
& _aotMode
) {
10618 if (!strcmp("hold", reason
)
10619 || !strcmp("help", reason
)
10620 || !strcmp("menu", reason
)
10621 || !strcmp("stockholm", reason
)
10622 || !strcmp("ringer", reason
)
10623 || !strcmp("ringerab", reason
)
10624 || !strcmp("smc0", reason
)
10625 || !strcmp("AOP.RTPWakeupAP", reason
)
10626 || !strcmp("BT.OutboxNotEmpty", reason
)
10627 || !strcmp("WL.OutboxNotEmpty", reason
)) {
10628 flags
|= kIOPMWakeEventAOTExit
;
10632 #if DEVELOPMENT || DEBUG
10633 if (_aotLingerTime
&& !strcmp("rtc", reason
)) {
10634 flags
|= kIOPMWakeEventAOTPossibleExit
;
10636 #endif /* DEVELOPMENT || DEBUG */
10638 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10639 // Publishing the WakeType is serialized by the PM work loop
10640 if (!strcmp("rtc", reason
) && (_nextScheduledAlarmType
!= NULL
)) {
10641 pmPowerStateQueue
->submitPowerEvent(kPowerEventPublishWakeType
,
10642 (void *) _nextScheduledAlarmType
.get());
10645 // Workaround for the missing wake HID event
10646 if (gDarkWakeFlags
& kDarkWakeFlagUserWakeWorkaround
) {
10647 if (!strcmp("trackpadkeyboard", reason
)) {
10648 pmPowerStateQueue
->submitPowerEvent(kPowerEventPublishWakeType
,
10649 (void *) gIOPMWakeTypeUserKey
.get());
10654 deviceName
= device
->copyName(gIOServicePlane
);
10655 deviceRegId
= OSNumber::withNumber(device
->getRegistryEntryID(), 64);
10656 claimTime
= OSNumber::withNumber(timestamp
, 64);
10657 flagsData
= OSData::withBytes(&flags
, sizeof(flags
));
10658 reasonString
= OSString::withCString(reason
);
10659 dict
= OSDictionary::withCapacity(5 + (details
? 1 : 0));
10660 if (!dict
|| !deviceName
|| !deviceRegId
|| !claimTime
|| !flagsData
|| !reasonString
) {
10664 dict
->setObject(gIONameKey
, deviceName
.get());
10665 dict
->setObject(gIORegistryEntryIDKey
, deviceRegId
.get());
10666 dict
->setObject(kIOPMWakeEventTimeKey
, claimTime
.get());
10667 dict
->setObject(kIOPMWakeEventFlagsKey
, flagsData
.get());
10668 dict
->setObject(kIOPMWakeEventReasonKey
, reasonString
.get());
10670 dict
->setObject(kIOPMWakeEventDetailsKey
, details
);
10674 addWakeReason
= _acceptSystemWakeEvents
;
10676 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason
, deviceName
->getCStringNoCopy(), (int)flags
, _aotPendingFlags
, _aotReadyToFullWake
);
10678 aotFlags
= (kIOPMWakeEventAOTFlags
& flags
);
10679 aotFlags
= (aotFlags
& ~_aotPendingFlags
);
10680 needAOTEvaluate
= false;
10681 if (_aotNow
&& aotFlags
) {
10682 if (kIOPMWakeEventAOTPossibleExit
& flags
) {
10683 _aotMetrics
->possibleCount
++;
10685 if (kIOPMWakeEventAOTConfirmedPossibleExit
& flags
) {
10686 _aotMetrics
->confirmedPossibleCount
++;
10688 if (kIOPMWakeEventAOTRejectedPossibleExit
& flags
) {
10689 _aotMetrics
->rejectedPossibleCount
++;
10691 if (kIOPMWakeEventAOTExpiredPossibleExit
& flags
) {
10692 _aotMetrics
->expiredPossibleCount
++;
10695 _aotPendingFlags
|= aotFlags
;
10696 addWakeReason
= _aotNow
&& _systemWakeEventsArray
&& ((kIOPMWakeEventAOTExitFlags
& aotFlags
));
10697 needAOTEvaluate
= _aotReadyToFullWake
;
10699 DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
10700 reason
, (int)flags
, deviceName
->getCStringNoCopy(), device
->getRegistryEntryID(),
10701 _aotNow
, pmTracer
->getTracePhase(), addWakeReason
);
10703 if (!gWakeReasonSysctlRegistered
) {
10704 // Lazy registration until the platform driver stops registering
10706 gWakeReasonSysctlRegistered
= true;
10708 if (addWakeReason
) {
10709 _systemWakeEventsArray
->setObject(dict
.get());
10710 if (gWakeReasonString
[0] != '\0') {
10711 strlcat(gWakeReasonString
, " ", sizeof(gWakeReasonString
));
10713 strlcat(gWakeReasonString
, reason
, sizeof(gWakeReasonString
));
10716 WAKEEVENT_UNLOCK();
10717 if (needAOTEvaluate
) {
10718 // Call aotEvaluate() on PM work loop since it may call
10719 // aotExit() which accesses PM state.
10720 pmPowerStateQueue
->submitPowerEvent(kPowerEventAOTEvaluate
);
10727 //******************************************************************************
10728 // claimSystemBootEvent
10730 // For a driver to claim a device is the source/conduit of a system boot event.
10731 //******************************************************************************
10734 IOPMrootDomain::claimSystemBootEvent(
10735 IOService
* device
,
10736 IOOptionBits flags
,
10737 const char * reason
,
10738 __unused OSObject
* details
)
10740 if (!device
|| !reason
) {
10744 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason
, device
->getName(), (uint32_t) flags
);
10746 if (!gBootReasonSysctlRegistered
) {
10747 // Lazy sysctl registration after setting gBootReasonString
10748 strlcat(gBootReasonString
, reason
, sizeof(gBootReasonString
));
10749 os_atomic_store(&gBootReasonSysctlRegistered
, true, release
);
10751 WAKEEVENT_UNLOCK();
10754 //******************************************************************************
10755 // claimSystemShutdownEvent
10757 // For drivers to claim a system shutdown event on the ensuing boot.
10758 //******************************************************************************
10761 IOPMrootDomain::claimSystemShutdownEvent(
10762 IOService
* device
,
10763 IOOptionBits flags
,
10764 const char * reason
,
10765 __unused OSObject
* details
)
10767 if (!device
|| !reason
) {
10771 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason
, device
->getName(), (uint32_t) flags
);
10773 if (gShutdownReasonString
[0] != '\0') {
10774 strlcat(gShutdownReasonString
, " ", sizeof(gShutdownReasonString
));
10776 strlcat(gShutdownReasonString
, reason
, sizeof(gShutdownReasonString
));
10778 gShutdownReasonSysctlRegistered
= true;
10779 WAKEEVENT_UNLOCK();
10782 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10785 // MARK: PMSettingHandle
10787 OSDefineMetaClassAndStructors( PMSettingHandle
, OSObject
)
10790 PMSettingHandle::free( void )
10793 pmso
->clientHandleFreed();
10802 // MARK: PMSettingObject
10805 #define super OSObject
10806 OSDefineMetaClassAndFinalStructors( PMSettingObject
, OSObject
)
10809 * Static constructor/initializer for PMSettingObject
10811 PMSettingObject
*PMSettingObject::pmSettingObject(
10812 IOPMrootDomain
* parent_arg
,
10813 IOPMSettingControllerCallback handler_arg
,
10814 OSObject
* target_arg
,
10815 uintptr_t refcon_arg
,
10816 uint32_t supportedPowerSources
,
10817 const OSSymbol
* settings
[],
10818 OSObject
* *handle_obj
)
10820 uint32_t settingCount
= 0;
10821 PMSettingObject
*pmso
= NULL
;
10822 PMSettingHandle
*pmsh
= NULL
;
10824 if (!parent_arg
|| !handler_arg
|| !settings
|| !handle_obj
) {
10828 // count OSSymbol entries in NULL terminated settings array
10829 while (settings
[settingCount
]) {
10832 if (0 == settingCount
) {
10836 pmso
= new PMSettingObject
;
10837 if (!pmso
|| !pmso
->init()) {
10841 pmsh
= new PMSettingHandle
;
10842 if (!pmsh
|| !pmsh
->init()) {
10846 queue_init(&pmso
->calloutQueue
);
10847 pmso
->parent
= parent_arg
;
10848 pmso
->func
= handler_arg
;
10849 pmso
->target
= target_arg
;
10850 pmso
->refcon
= refcon_arg
;
10851 pmso
->settingCount
= settingCount
;
10853 pmso
->retain(); // handle holds a retain on pmso
10857 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t) * settingCount
);
10858 if (pmso
->publishedFeatureID
) {
10859 for (unsigned int i
= 0; i
< settingCount
; i
++) {
10860 // Since there is now at least one listener to this setting, publish
10861 // PM root domain support for it.
10862 parent_arg
->publishPMSetting( settings
[i
],
10863 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
10867 *handle_obj
= pmsh
;
10881 PMSettingObject::free( void )
10883 if (publishedFeatureID
) {
10884 for (uint32_t i
= 0; i
< settingCount
; i
++) {
10885 if (publishedFeatureID
[i
]) {
10886 parent
->removePublishedFeature( publishedFeatureID
[i
] );
10890 IOFree(publishedFeatureID
, sizeof(uint32_t) * settingCount
);
10897 PMSettingObject::dispatchPMSetting( const OSSymbol
* type
, OSObject
* object
)
10899 return (*func
)(target
, type
, object
, refcon
);
10903 PMSettingObject::clientHandleFreed( void )
10905 parent
->deregisterPMSettingObject(this);
10909 // MARK: PMAssertionsTracker
10911 //*********************************************************************************
10912 //*********************************************************************************
10913 //*********************************************************************************
10914 // class PMAssertionsTracker Implementation
10916 #define kAssertUniqueIDStart 500
10918 PMAssertionsTracker
*
10919 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain
*rootDomain
)
10921 PMAssertionsTracker
*me
;
10923 me
= new PMAssertionsTracker
;
10924 if (!me
|| !me
->init()) {
10931 me
->owner
= rootDomain
;
10932 me
->issuingUniqueID
= kAssertUniqueIDStart
;
10933 me
->assertionsArray
= OSArray::withCapacity(5);
10934 me
->assertionsKernel
= 0;
10935 me
->assertionsUser
= 0;
10936 me
->assertionsCombined
= 0;
10937 me
->assertionsArrayLock
= IOLockAlloc();
10938 me
->tabulateProducerCount
= me
->tabulateConsumerCount
= 0;
10940 assert(me
->assertionsArray
);
10941 assert(me
->assertionsArrayLock
);
10947 * - Update assertionsKernel to reflect the state of all
10948 * assertions in the kernel.
10949 * - Update assertionsCombined to reflect both kernel & user space.
10952 PMAssertionsTracker::tabulate(void)
10956 PMAssertStruct
*_a
= NULL
;
10959 IOPMDriverAssertionType oldKernel
= assertionsKernel
;
10960 IOPMDriverAssertionType oldCombined
= assertionsCombined
;
10964 assertionsKernel
= 0;
10965 assertionsCombined
= 0;
10967 if (!assertionsArray
) {
10971 if ((count
= assertionsArray
->getCount())) {
10972 for (i
= 0; i
< count
; i
++) {
10973 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
10975 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
10976 if (_a
&& (kIOPMDriverAssertionLevelOn
== _a
->level
)) {
10977 assertionsKernel
|= _a
->assertionBits
;
10983 tabulateProducerCount
++;
10984 assertionsCombined
= assertionsKernel
| assertionsUser
;
10986 if ((assertionsKernel
!= oldKernel
) ||
10987 (assertionsCombined
!= oldCombined
)) {
10988 owner
->evaluateAssertions(assertionsCombined
, oldCombined
);
10993 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct
*assertStruct
)
10998 if (((assertStruct
->assertionBits
& kIOPMDriverAssertionCPUBit
) == 0) ||
10999 (assertStruct
->assertCPUStartTime
== 0)) {
11003 now
= mach_absolute_time();
11004 SUB_ABSOLUTETIME(&now
, &assertStruct
->assertCPUStartTime
);
11005 absolutetime_to_nanoseconds(now
, &nsec
);
11006 assertStruct
->assertCPUDuration
+= nsec
;
11007 assertStruct
->assertCPUStartTime
= 0;
11009 if (assertStruct
->assertCPUDuration
> maxAssertCPUDuration
) {
11010 maxAssertCPUDuration
= assertStruct
->assertCPUDuration
;
11011 maxAssertCPUEntryId
= assertStruct
->registryEntryID
;
11016 PMAssertionsTracker::reportCPUBitAccounting( void )
11018 PMAssertStruct
*_a
;
11026 // Account for drivers that are still holding the CPU assertion
11027 if (assertionsKernel
& kIOPMDriverAssertionCPUBit
) {
11028 now
= mach_absolute_time();
11029 if ((count
= assertionsArray
->getCount())) {
11030 for (i
= 0; i
< count
; i
++) {
11031 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
11033 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
11034 if ((_a
->assertionBits
& kIOPMDriverAssertionCPUBit
) &&
11035 (_a
->level
== kIOPMDriverAssertionLevelOn
) &&
11036 (_a
->assertCPUStartTime
!= 0)) {
11037 // Don't modify PMAssertStruct, leave that
11038 // for updateCPUBitAccounting()
11039 SUB_ABSOLUTETIME(&now
, &_a
->assertCPUStartTime
);
11040 absolutetime_to_nanoseconds(now
, &nsec
);
11041 nsec
+= _a
->assertCPUDuration
;
11042 if (nsec
> maxAssertCPUDuration
) {
11043 maxAssertCPUDuration
= nsec
;
11044 maxAssertCPUEntryId
= _a
->registryEntryID
;
11052 if (maxAssertCPUDuration
) {
11053 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11054 (maxAssertCPUDuration
/ NSEC_PER_MSEC
), maxAssertCPUEntryId
);
11057 maxAssertCPUDuration
= 0;
11058 maxAssertCPUEntryId
= 0;
11062 PMAssertionsTracker::publishProperties( void )
11064 OSSharedPtr
<OSArray
> assertionsSummary
;
11066 if (tabulateConsumerCount
!= tabulateProducerCount
) {
11067 IOLockLock(assertionsArrayLock
);
11069 tabulateConsumerCount
= tabulateProducerCount
;
11071 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11073 assertionsSummary
= copyAssertionsArray();
11074 if (assertionsSummary
) {
11075 owner
->setProperty(kIOPMAssertionsDriverDetailedKey
, assertionsSummary
.get());
11077 owner
->removeProperty(kIOPMAssertionsDriverDetailedKey
);
11080 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11082 owner
->setProperty(kIOPMAssertionsDriverKey
, assertionsKernel
, 64);
11084 IOLockUnlock(assertionsArrayLock
);
11088 PMAssertionsTracker::PMAssertStruct
*
11089 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id
, int *index
)
11091 PMAssertStruct
*_a
= NULL
;
11097 if (assertionsArray
11098 && (count
= assertionsArray
->getCount())) {
11099 for (i
= 0; i
< count
; i
++) {
11100 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
11102 _a
= (PMAssertStruct
*)_d
->getBytesNoCopy();
11103 if (_a
&& (_id
== _a
->id
)) {
11121 /* PMAssertionsTracker::handleCreateAssertion
11122 * Perform assertion work on the PM workloop. Do not call directly.
11125 PMAssertionsTracker::handleCreateAssertion(OSData
*newAssertion
)
11127 PMAssertStruct
*assertStruct
;
11131 if (newAssertion
) {
11132 IOLockLock(assertionsArrayLock
);
11133 assertStruct
= (PMAssertStruct
*) newAssertion
->getBytesNoCopy();
11134 if ((assertStruct
->assertionBits
& kIOPMDriverAssertionCPUBit
) &&
11135 (assertStruct
->level
== kIOPMDriverAssertionLevelOn
)) {
11136 assertStruct
->assertCPUStartTime
= mach_absolute_time();
11138 assertionsArray
->setObject(newAssertion
);
11139 IOLockUnlock(assertionsArrayLock
);
11140 newAssertion
->release();
11144 return kIOReturnSuccess
;
11147 /* PMAssertionsTracker::createAssertion
11148 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11152 PMAssertionsTracker::createAssertion(
11153 IOPMDriverAssertionType which
,
11154 IOPMDriverAssertionLevel level
,
11155 IOService
*serviceID
,
11156 const char *whoItIs
,
11157 IOPMDriverAssertionID
*outID
)
11159 OSSharedPtr
<OSData
> dataStore
;
11160 PMAssertStruct track
;
11162 // Warning: trillions and trillions of created assertions may overflow the unique ID.
11163 track
.id
= OSIncrementAtomic64((SInt64
*) &issuingUniqueID
);
11164 track
.level
= level
;
11165 track
.assertionBits
= which
;
11167 // NB: ownerString is explicitly managed by PMAssertStruct
11168 // it will be released in `handleReleaseAssertion' below
11169 track
.ownerString
= whoItIs
? OSSymbol::withCString(whoItIs
).detach():nullptr;
11170 track
.ownerService
= serviceID
;
11171 track
.registryEntryID
= serviceID
? serviceID
->getRegistryEntryID():0;
11172 track
.modifiedTime
= 0;
11173 pmEventTimeStamp(&track
.createdTime
);
11174 track
.assertCPUStartTime
= 0;
11175 track
.assertCPUDuration
= 0;
11177 dataStore
= OSData::withBytes(&track
, sizeof(PMAssertStruct
));
11179 if (track
.ownerString
) {
11180 track
.ownerString
->release();
11181 track
.ownerString
= NULL
;
11183 return kIOReturnNoMemory
;
11188 if (owner
&& owner
->pmPowerStateQueue
) {
11189 // queue action is responsible for releasing dataStore
11190 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionCreate
, (void *)dataStore
.detach());
11193 return kIOReturnSuccess
;
11196 /* PMAssertionsTracker::handleReleaseAssertion
11197 * Runs in PM workloop. Do not call directly.
11200 PMAssertionsTracker::handleReleaseAssertion(
11201 IOPMDriverAssertionID _id
)
11206 PMAssertStruct
*assertStruct
= detailsForID(_id
, &index
);
11208 if (!assertStruct
) {
11209 return kIOReturnNotFound
;
11212 IOLockLock(assertionsArrayLock
);
11214 if ((assertStruct
->assertionBits
& kIOPMDriverAssertionCPUBit
) &&
11215 (assertStruct
->level
== kIOPMDriverAssertionLevelOn
)) {
11216 updateCPUBitAccounting(assertStruct
);
11219 if (assertStruct
->ownerString
) {
11220 assertStruct
->ownerString
->release();
11221 assertStruct
->ownerString
= NULL
;
11224 assertionsArray
->removeObject(index
);
11225 IOLockUnlock(assertionsArrayLock
);
11228 return kIOReturnSuccess
;
11231 /* PMAssertionsTracker::releaseAssertion
11232 * Releases an assertion and affects system behavior if appropiate.
11233 * Actual work happens on PM workloop.
11236 PMAssertionsTracker::releaseAssertion(
11237 IOPMDriverAssertionID _id
)
11239 if (owner
&& owner
->pmPowerStateQueue
) {
11240 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionRelease
, NULL
, _id
);
11242 return kIOReturnSuccess
;
11245 /* PMAssertionsTracker::handleSetAssertionLevel
11246 * Runs in PM workloop. Do not call directly.
11249 PMAssertionsTracker::handleSetAssertionLevel(
11250 IOPMDriverAssertionID _id
,
11251 IOPMDriverAssertionLevel _level
)
11253 PMAssertStruct
*assertStruct
= detailsForID(_id
, NULL
);
11257 if (!assertStruct
) {
11258 return kIOReturnNotFound
;
11261 IOLockLock(assertionsArrayLock
);
11262 pmEventTimeStamp(&assertStruct
->modifiedTime
);
11263 if ((assertStruct
->assertionBits
& kIOPMDriverAssertionCPUBit
) &&
11264 (assertStruct
->level
!= _level
)) {
11265 if (_level
== kIOPMDriverAssertionLevelOn
) {
11266 assertStruct
->assertCPUStartTime
= mach_absolute_time();
11268 updateCPUBitAccounting(assertStruct
);
11271 assertStruct
->level
= _level
;
11272 IOLockUnlock(assertionsArrayLock
);
11275 return kIOReturnSuccess
;
11278 /* PMAssertionsTracker::setAssertionLevel
11281 PMAssertionsTracker::setAssertionLevel(
11282 IOPMDriverAssertionID _id
,
11283 IOPMDriverAssertionLevel _level
)
11285 if (owner
&& owner
->pmPowerStateQueue
) {
11286 owner
->pmPowerStateQueue
->submitPowerEvent(kPowerEventAssertionSetLevel
,
11287 (void *)(uintptr_t)_level
, _id
);
11290 return kIOReturnSuccess
;
11294 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0
)
11296 IOPMDriverAssertionType new_user_levels
= *(IOPMDriverAssertionType
*) arg0
;
11300 if (new_user_levels
!= assertionsUser
) {
11301 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser
, new_user_levels
);
11302 assertionsUser
= new_user_levels
;
11306 return kIOReturnSuccess
;
11310 PMAssertionsTracker::setUserAssertionLevels(
11311 IOPMDriverAssertionType new_user_levels
)
11313 if (gIOPMWorkLoop
) {
11314 gIOPMWorkLoop
->runAction(
11315 OSMemberFunctionCast(
11316 IOWorkLoop::Action
,
11318 &PMAssertionsTracker::handleSetUserAssertionLevels
),
11320 (void *) &new_user_levels
, NULL
, NULL
, NULL
);
11323 return kIOReturnSuccess
;
11327 OSSharedPtr
<OSArray
>
11328 PMAssertionsTracker::copyAssertionsArray(void)
11332 OSSharedPtr
<OSArray
> outArray
= NULL
;
11334 if (!assertionsArray
|| (0 == (count
= assertionsArray
->getCount()))) {
11337 outArray
= OSArray::withCapacity(count
);
11342 for (i
= 0; i
< count
; i
++) {
11343 PMAssertStruct
*_a
= NULL
;
11345 OSSharedPtr
<OSDictionary
> details
;
11347 _d
= OSDynamicCast(OSData
, assertionsArray
->getObject(i
));
11348 if (_d
&& (_a
= (PMAssertStruct
*)_d
->getBytesNoCopy())) {
11349 OSSharedPtr
<OSNumber
> _n
;
11351 details
= OSDictionary::withCapacity(7);
11356 outArray
->setObject(details
.get());
11358 _n
= OSNumber::withNumber(_a
->id
, 64);
11360 details
->setObject(kIOPMDriverAssertionIDKey
, _n
.get());
11362 _n
= OSNumber::withNumber(_a
->createdTime
, 64);
11364 details
->setObject(kIOPMDriverAssertionCreatedTimeKey
, _n
.get());
11366 _n
= OSNumber::withNumber(_a
->modifiedTime
, 64);
11368 details
->setObject(kIOPMDriverAssertionModifiedTimeKey
, _n
.get());
11370 _n
= OSNumber::withNumber((uintptr_t)_a
->registryEntryID
, 64);
11372 details
->setObject(kIOPMDriverAssertionRegistryEntryIDKey
, _n
.get());
11374 _n
= OSNumber::withNumber(_a
->level
, 64);
11376 details
->setObject(kIOPMDriverAssertionLevelKey
, _n
.get());
11378 _n
= OSNumber::withNumber(_a
->assertionBits
, 64);
11380 details
->setObject(kIOPMDriverAssertionAssertedKey
, _n
.get());
11383 if (_a
->ownerString
) {
11384 details
->setObject(kIOPMDriverAssertionOwnerStringKey
, _a
->ownerString
);
11390 return os::move(outArray
);
11393 IOPMDriverAssertionType
11394 PMAssertionsTracker::getActivatedAssertions(void)
11396 return assertionsCombined
;
11399 IOPMDriverAssertionLevel
11400 PMAssertionsTracker::getAssertionLevel(
11401 IOPMDriverAssertionType type
)
11403 // FIXME: unused and also wrong
11404 if (type
&& ((type
& assertionsKernel
) == assertionsKernel
)) {
11405 return kIOPMDriverAssertionLevelOn
;
11407 return kIOPMDriverAssertionLevelOff
;
11411 //*********************************************************************************
11412 //*********************************************************************************
11413 //*********************************************************************************
11417 pmEventTimeStamp(uint64_t *recordTS
)
11420 clock_usec_t tusec
;
11426 // We assume tsec fits into 32 bits; 32 bits holds enough
11427 // seconds for 136 years since the epoch in 1970.
11428 clock_get_calendar_microtime(&tsec
, &tusec
);
11431 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11433 *recordTS
|= (uint32_t)tusec
;
11434 *recordTS
|= ((uint64_t)tsec
<< 32);
11440 // MARK: IORootParent
11442 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11444 OSDefineMetaClassAndFinalStructors(IORootParent
, IOService
)
11446 // The reason that root domain needs a root parent is to facilitate demand
11447 // sleep, since a power change from the root parent cannot be vetoed.
11449 // The above statement is no longer true since root domain now performs
11450 // demand sleep using overrides. But root parent remains to avoid changing
11451 // the power tree stacking. Root parent is parked at the max power state.
11454 static IOPMPowerState patriarchPowerStates
[2] =
11456 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11457 {1, 0, ON_POWER
, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11461 IORootParent::initialize( void )
11464 gIOPMPSExternalConnectedKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey
);
11465 gIOPMPSExternalChargeCapableKey
= OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey
);
11466 gIOPMPSBatteryInstalledKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey
);
11467 gIOPMPSIsChargingKey
= OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey
);
11468 gIOPMPSAtWarnLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey
);
11469 gIOPMPSAtCriticalLevelKey
= OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey
);
11470 gIOPMPSCurrentCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey
);
11471 gIOPMPSMaxCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey
);
11472 gIOPMPSDesignCapacityKey
= OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey
);
11473 gIOPMPSTimeRemainingKey
= OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey
);
11474 gIOPMPSAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey
);
11475 gIOPMPSVoltageKey
= OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey
);
11476 gIOPMPSCycleCountKey
= OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey
);
11477 gIOPMPSMaxErrKey
= OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey
);
11478 gIOPMPSAdapterInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey
);
11479 gIOPMPSLocationKey
= OSSymbol::withCStringNoCopy(kIOPMPSLocationKey
);
11480 gIOPMPSErrorConditionKey
= OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey
);
11481 gIOPMPSManufacturerKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey
);
11482 gIOPMPSManufactureDateKey
= OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey
);
11483 gIOPMPSModelKey
= OSSymbol::withCStringNoCopy(kIOPMPSModelKey
);
11484 gIOPMPSSerialKey
= OSSymbol::withCStringNoCopy(kIOPMPSSerialKey
);
11485 gIOPMPSLegacyBatteryInfoKey
= OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey
);
11486 gIOPMPSBatteryHealthKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey
);
11487 gIOPMPSHealthConfidenceKey
= OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey
);
11488 gIOPMPSCapacityEstimatedKey
= OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey
);
11489 gIOPMPSBatteryChargeStatusKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey
);
11490 gIOPMPSBatteryTemperatureKey
= OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey
);
11491 gIOPMPSAdapterDetailsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey
);
11492 gIOPMPSChargerConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey
);
11493 gIOPMPSAdapterDetailsIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey
);
11494 gIOPMPSAdapterDetailsWattsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey
);
11495 gIOPMPSAdapterDetailsRevisionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey
);
11496 gIOPMPSAdapterDetailsSerialNumberKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey
);
11497 gIOPMPSAdapterDetailsFamilyKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey
);
11498 gIOPMPSAdapterDetailsAmperageKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey
);
11499 gIOPMPSAdapterDetailsDescriptionKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey
);
11500 gIOPMPSAdapterDetailsPMUConfigurationKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey
);
11501 gIOPMPSAdapterDetailsSourceIDKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey
);
11502 gIOPMPSAdapterDetailsErrorFlagsKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey
);
11503 gIOPMPSAdapterDetailsSharedSourceKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey
);
11504 gIOPMPSAdapterDetailsCloakedKey
= OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey
);
11505 gIOPMPSInvalidWakeSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey
);
11506 gIOPMPSPostChargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey
);
11507 gIOPMPSPostDishargeWaitSecondsKey
= OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey
);
11511 IORootParent::start( IOService
* nub
)
11513 IOService::start(nub
);
11514 attachToParent( getRegistryRoot(), gIOPowerPlane
);
11516 registerPowerDriver(this, patriarchPowerStates
, 2);
11522 IORootParent::shutDownSystem( void )
11527 IORootParent::restartSystem( void )
11532 IORootParent::sleepSystem( void )
11537 IORootParent::dozeSystem( void )
11542 IORootParent::sleepToDoze( void )
11547 IORootParent::wakeSystem( void )
11551 OSSharedPtr
<OSObject
>
11552 IORootParent::copyProperty( const char * aKey
) const
11554 return IOService::copyProperty(aKey
);
11558 IOPMrootDomain::getWatchdogTimeout()
11560 if (gSwdSleepWakeTimeout
) {
11561 gSwdSleepTimeout
= gSwdWakeTimeout
= gSwdSleepWakeTimeout
;
11563 if ((pmTracer
->getTracePhase() < kIOPMTracePointSystemSleep
) ||
11564 (pmTracer
->getTracePhase() == kIOPMTracePointDarkWakeEntry
)) {
11565 return gSwdSleepTimeout
? gSwdSleepTimeout
: WATCHDOG_SLEEP_TIMEOUT
;
11567 return gSwdWakeTimeout
? gSwdWakeTimeout
: WATCHDOG_WAKE_TIMEOUT
;
11572 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11574 IOPMrootDomain::restartWithStackshot()
11576 takeStackshot(true);
11578 return kIOReturnSuccess
;
11582 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger
)
11584 takeStackshot(wdogTrigger
);
11588 IOPMrootDomain::tracePhase2String(uint32_t tracePhase
, const char **phaseString
, const char **description
)
11590 switch (tracePhase
) {
11591 case kIOPMTracePointSleepStarted
:
11592 *phaseString
= "kIOPMTracePointSleepStarted";
11593 *description
= "starting sleep";
11596 case kIOPMTracePointSleepApplications
:
11597 *phaseString
= "kIOPMTracePointSleepApplications";
11598 *description
= "notifying applications";
11601 case kIOPMTracePointSleepPriorityClients
:
11602 *phaseString
= "kIOPMTracePointSleepPriorityClients";
11603 *description
= "notifying clients about upcoming system capability changes";
11606 case kIOPMTracePointSleepWillChangeInterests
:
11607 *phaseString
= "kIOPMTracePointSleepWillChangeInterests";
11608 *description
= "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11611 case kIOPMTracePointSleepPowerPlaneDrivers
:
11612 *phaseString
= "kIOPMTracePointSleepPowerPlaneDrivers";
11613 *description
= "calling power state change callbacks";
11616 case kIOPMTracePointSleepDidChangeInterests
:
11617 *phaseString
= "kIOPMTracePointSleepDidChangeInterests";
11618 *description
= "calling rootDomain's clients about rootDomain's state changes";
11621 case kIOPMTracePointSleepCapabilityClients
:
11622 *phaseString
= "kIOPMTracePointSleepCapabilityClients";
11623 *description
= "notifying clients about current system capabilities";
11626 case kIOPMTracePointSleepPlatformActions
:
11627 *phaseString
= "kIOPMTracePointSleepPlatformActions";
11628 *description
= "calling Quiesce/Sleep action callbacks";
11631 case kIOPMTracePointSleepCPUs
:
11633 *phaseString
= "kIOPMTracePointSleepCPUs";
11634 #if defined(__i386__) || defined(__x86_64__)
11636 * We cannot use the getCPUNumber() method to get the cpu number, since
11637 * that cpu number is unrelated to the cpu number we need (we need the cpu
11638 * number as enumerated by the scheduler, NOT the CPU number enumerated
11639 * by ACPIPlatform as the CPUs are enumerated in MADT order).
11640 * Instead, pass the Mach processor pointer associated with the current
11641 * shutdown target so its associated cpu_id can be used in
11642 * processor_to_datastring.
11644 if (currentShutdownTarget
!= NULL
&&
11645 currentShutdownTarget
->getMachProcessor() != NULL
) {
11646 const char *sbuf
= processor_to_datastring("halting all non-boot CPUs",
11647 currentShutdownTarget
->getMachProcessor());
11648 *description
= sbuf
;
11650 *description
= "halting all non-boot CPUs";
11653 *description
= "halting all non-boot CPUs";
11657 case kIOPMTracePointSleepPlatformDriver
:
11658 *phaseString
= "kIOPMTracePointSleepPlatformDriver";
11659 *description
= "executing platform specific code";
11662 case kIOPMTracePointHibernate
:
11663 *phaseString
= "kIOPMTracePointHibernate";
11664 *description
= "writing the hibernation image";
11667 case kIOPMTracePointSystemSleep
:
11668 *phaseString
= "kIOPMTracePointSystemSleep";
11669 *description
= "in EFI/Bootrom after last point of entry to sleep";
11672 case kIOPMTracePointWakePlatformDriver
:
11673 *phaseString
= "kIOPMTracePointWakePlatformDriver";
11674 *description
= "executing platform specific code";
11678 case kIOPMTracePointWakePlatformActions
:
11679 *phaseString
= "kIOPMTracePointWakePlatformActions";
11680 *description
= "calling Wake action callbacks";
11683 case kIOPMTracePointWakeCPUs
:
11684 *phaseString
= "kIOPMTracePointWakeCPUs";
11685 *description
= "starting non-boot CPUs";
11688 case kIOPMTracePointWakeWillPowerOnClients
:
11689 *phaseString
= "kIOPMTracePointWakeWillPowerOnClients";
11690 *description
= "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
11693 case kIOPMTracePointWakeWillChangeInterests
:
11694 *phaseString
= "kIOPMTracePointWakeWillChangeInterests";
11695 *description
= "calling rootDomain's clients about upcoming rootDomain's state changes";
11698 case kIOPMTracePointWakeDidChangeInterests
:
11699 *phaseString
= "kIOPMTracePointWakeDidChangeInterests";
11700 *description
= "calling rootDomain's clients about completed rootDomain's state changes";
11703 case kIOPMTracePointWakePowerPlaneDrivers
:
11704 *phaseString
= "kIOPMTracePointWakePowerPlaneDrivers";
11705 *description
= "calling power state change callbacks";
11708 case kIOPMTracePointWakeCapabilityClients
:
11709 *phaseString
= "kIOPMTracePointWakeCapabilityClients";
11710 *description
= "informing clients about current system capabilities";
11713 case kIOPMTracePointWakeApplications
:
11714 *phaseString
= "kIOPMTracePointWakeApplications";
11715 *description
= "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
11718 case kIOPMTracePointDarkWakeEntry
:
11719 *phaseString
= "kIOPMTracePointDarkWakeEntry";
11720 *description
= "entering darkwake on way to sleep";
11723 case kIOPMTracePointDarkWakeExit
:
11724 *phaseString
= "kIOPMTracePointDarkWakeExit";
11725 *description
= "entering fullwake from darkwake";
11729 *phaseString
= NULL
;
11730 *description
= NULL
;
11735 IOPMrootDomain::saveFailureData2File()
11737 unsigned int len
= 0;
11738 char failureStr
[512];
11741 OSNumber
*statusCode
;
11742 uint64_t pmStatusCode
= 0;
11743 uint32_t phaseData
= 0;
11744 uint32_t phaseDetail
= 0;
11745 bool efiFailure
= false;
11747 OSSharedPtr
<OSObject
> statusCodeProp
= copyProperty(kIOPMSleepWakeFailureCodeKey
);
11748 statusCode
= OSDynamicCast(OSNumber
, statusCodeProp
.get());
11750 pmStatusCode
= statusCode
->unsigned64BitValue();
11751 phaseData
= pmStatusCode
& 0xFFFFFFFF;
11752 phaseDetail
= (pmStatusCode
>> 32) & 0xFFFFFFFF;
11753 if ((phaseData
& 0xFF) == kIOPMTracePointSystemSleep
) {
11754 LOG("Sleep Wake failure in EFI\n");
11757 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
);
11758 len
= (typeof(len
))strnlen(failureStr
, sizeof(failureStr
));
11763 if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic
, NULL
, &len
)) {
11764 swd_flags
|= SWD_BOOT_BY_SW_WDOG
;
11765 PERemoveNVRAMProperty(kIOSleepWakeFailurePanic
);
11766 // dump panic will handle saving nvram data
11770 /* Keeping this around for capturing data during power
11773 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString
, NULL
, &len
)) {
11774 DLOG("No sleep wake failure string\n");
11778 DLOG("Ignoring zero byte SleepWake failure string\n");
11782 // if PMStatus code is zero, delete stackshot and return
11784 if (((pmStatusCode
& 0xFFFFFFFF) & 0xFF) == 0) {
11785 // there was no sleep wake failure
11786 // this can happen if delete stackshot was called
11787 // before take stackshot completed. Let us delete any
11788 // sleep wake failure data in nvram
11789 DLOG("Deleting stackshot on successful wake\n");
11795 if (len
> sizeof(failureStr
)) {
11796 len
= sizeof(failureStr
);
11799 PEReadNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, &len
);
11801 if (failureStr
[0] != 0) {
11802 error
= sleepWakeDebugSaveFile(kSleepWakeFailureStringFile
, failureStr
, len
);
11804 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error
);
11806 DLOG("Saved SleepWake failure string to file.\n");
11810 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
11815 unsigned int len
= 0;
11817 char nvram_var_name_buffer
[20];
11818 unsigned int concat_len
= 0;
11819 swd_hdr
*hdr
= NULL
;
11822 hdr
= (swd_hdr
*)swd_buffer
;
11823 outbuf
= (char *)hdr
+ hdr
->spindump_offset
;
11824 OSBoundedArrayRef
<char> boundedOutBuf(outbuf
, hdr
->alloc_size
- hdr
->spindump_offset
);
11826 for (int i
= 0; i
< 8; i
++) {
11827 snprintf(nvram_var_name_buffer
, sizeof(nvram_var_name_buffer
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
11828 if (!PEReadNVRAMProperty(nvram_var_name_buffer
, NULL
, &len
)) {
11829 LOG("No SleepWake blob to read beyond chunk %d\n", i
);
11832 if (PEReadNVRAMProperty(nvram_var_name_buffer
, boundedOutBuf
.slice(concat_len
, len
).data(), &len
) == FALSE
) {
11833 PERemoveNVRAMProperty(nvram_var_name_buffer
);
11834 LOG("Could not read the property :-(\n");
11837 PERemoveNVRAMProperty(nvram_var_name_buffer
);
11840 LOG("Concatenated length for the SWD blob %d\n", concat_len
);
11843 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, concat_len
);
11845 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
11847 LOG("Saved SleepWake zipped data to file.\n");
11850 // There is a sleep wake failure string but no stackshot
11851 // Write a placeholder stacks file so that swd runs
11852 snprintf(outbuf
, 20, "%s", "No stackshot data\n");
11853 error
= sleepWakeDebugSaveFile(kSleepWakeStacksFilename
, outbuf
, 20);
11855 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error
);
11857 LOG("Saved SleepWake zipped data to file.\n");
11861 LOG("No buffer allocated to save failure stackshot\n");
11865 gRootDomain
->swd_lock
= 0;
11867 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
11873 IOPMrootDomain::getFailureData(thread_t
*thread
, char *failureStr
, size_t strLen
)
11875 OSSharedPtr
<IORegistryIterator
> iter
;
11876 OSSharedPtr
<const OSSymbol
> kextName
= NULL
;
11877 IORegistryEntry
* entry
;
11879 bool nodeFound
= false;
11881 const void * callMethod
= NULL
;
11882 const char * objectName
= NULL
;
11883 uint32_t timeout
= getWatchdogTimeout();
11884 const char * phaseString
= NULL
;
11885 const char * phaseDescription
= NULL
;
11887 IOPMServiceInterestNotifier
*notifier
= OSDynamicCast(IOPMServiceInterestNotifier
, notifierObject
.get());
11888 uint32_t tracePhase
= pmTracer
->getTracePhase();
11891 if ((tracePhase
< kIOPMTracePointSystemSleep
) || (tracePhase
== kIOPMTracePointDarkWakeEntry
)) {
11892 snprintf(failureStr
, strLen
, "Sleep transition timed out after %d seconds", timeout
);
11894 snprintf(failureStr
, strLen
, "Wake transition timed out after %d seconds", timeout
);
11896 tracePhase2String(tracePhase
, &phaseString
, &phaseDescription
);
11898 if (notifierThread
) {
11899 if (notifier
&& (notifier
->identifier
)) {
11900 objectName
= notifier
->identifier
->getCStringNoCopy();
11902 *thread
= notifierThread
;
11904 iter
= IORegistryIterator::iterateOver(
11905 getPMRootDomain(), gIOPowerPlane
, kIORegistryIterateRecursively
);
11908 while ((entry
= iter
->getNextObject())) {
11909 node
= OSDynamicCast(IOService
, entry
);
11913 if (OSDynamicCast(IOPowerConnection
, node
)) {
11917 if (node
->getBlockingDriverCall(thread
, &callMethod
)) {
11924 kextName
= copyKextIdentifierWithAddress((vm_address_t
) callMethod
);
11926 objectName
= kextName
->getCStringNoCopy();
11930 if (phaseDescription
) {
11931 strlcat(failureStr
, " while ", strLen
);
11932 strlcat(failureStr
, phaseDescription
, strLen
);
11933 strlcat(failureStr
, ".", strLen
);
11936 strlcat(failureStr
, " Suspected bundle: ", strLen
);
11937 strlcat(failureStr
, objectName
, strLen
);
11938 strlcat(failureStr
, ".", strLen
);
11941 char threadName
[40];
11942 snprintf(threadName
, sizeof(threadName
), " Thread 0x%llx.", thread_tid(*thread
));
11943 strlcat(failureStr
, threadName
, strLen
);
11946 DLOG("%s\n", failureStr
);
11949 struct swd_stackshot_compressed_data
{
11950 z_output_func zoutput
;
11952 uint64_t totalbytes
;
11953 uint64_t lastpercent
;
11955 unsigned outremain
;
11960 struct swd_stackshot_compressed_data swd_zip_var
= { };
11963 swd_zs_alloc(void *__unused ref
, u_int items
, u_int size
)
11966 LOG("Alloc in zipping %d items of size %d\n", items
, size
);
11968 result
= (void *)(swd_zs_zmem
+ swd_zs_zoffset
);
11969 swd_zs_zoffset
+= ~31L & (31 + (items
* size
)); // 32b align for vector crc
11970 LOG("Offset %zu\n", swd_zs_zoffset
);
11975 swd_zinput(z_streamp strm
, Bytef
*buf
, unsigned size
)
11979 len
= strm
->avail_in
;
11988 if (strm
->next_in
!= (Bytef
*) strm
) {
11989 memcpy(buf
, strm
->next_in
, len
);
11994 strm
->adler
= z_crc32(strm
->adler
, buf
, len
);
11996 strm
->avail_in
-= len
;
11997 strm
->next_in
+= len
;
11998 strm
->total_in
+= len
;
12004 swd_zoutput(z_streamp strm
, Bytef
*buf
, unsigned len
)
12006 unsigned int i
= 0;
12007 // if outlen > max size don't add to the buffer
12008 assert(buf
!= NULL
);
12010 if (swd_zip_var
.outlen
+ len
> SWD_COMPRESSED_BUFSIZE
) {
12011 LOG("No space to GZIP... not writing to NVRAM\n");
12015 for (i
= 0; i
< len
; i
++) {
12016 *(swd_zip_var
.outbuf
+ swd_zip_var
.outlen
+ i
) = *(buf
+ i
);
12018 swd_zip_var
.outlen
+= len
;
12023 swd_zs_free(void * __unused ref
, void * __unused ptr
)
12028 swd_compress(char *inPtr
, char *outPtr
, size_t numBytes
)
12033 if (((unsigned int) numBytes
) != numBytes
) {
12037 if (!swd_zs
.zalloc
) {
12038 swd_zs
.zalloc
= swd_zs_alloc
;
12039 swd_zs
.zfree
= swd_zs_free
;
12040 if (deflateInit2(&swd_zs
, Z_BEST_SPEED
, Z_DEFLATED
, wbits
+ 16, memlevel
, Z_DEFAULT_STRATEGY
)) {
12041 // allocation failed
12042 bzero(&swd_zs
, sizeof(swd_zs
));
12043 // swd_zs_zoffset = 0;
12045 LOG("PMRD inited the zlib allocation routines\n");
12049 swd_zip_var
.zipped
= 0;
12050 swd_zip_var
.totalbytes
= 0; // should this be the max that we have?
12051 swd_zip_var
.lastpercent
= 0;
12052 swd_zip_var
.error
= kIOReturnSuccess
;
12053 swd_zip_var
.outremain
= 0;
12054 swd_zip_var
.outlen
= 0;
12055 swd_zip_var
.writes
= 0;
12056 swd_zip_var
.outbuf
= (Bytef
*)outPtr
;
12058 swd_zip_var
.totalbytes
= numBytes
;
12060 swd_zs
.avail_in
= 0;
12061 swd_zs
.next_in
= NULL
;
12062 swd_zs
.avail_out
= 0;
12063 swd_zs
.next_out
= NULL
;
12065 deflateResetWithIO(&swd_zs
, swd_zinput
, swd_zoutput
);
12071 while (swd_zip_var
.error
>= 0) {
12072 if (!zs
->avail_in
) {
12073 zs
->next_in
= (unsigned char *)inPtr
? (Bytef
*)inPtr
: (Bytef
*)zs
; /* zero marker? */
12074 zs
->avail_in
= (unsigned int) numBytes
;
12076 if (!zs
->avail_out
) {
12077 zs
->next_out
= (Bytef
*)zs
;
12078 zs
->avail_out
= UINT32_MAX
;
12080 zr
= deflate(zs
, Z_NO_FLUSH
);
12081 if (Z_STREAM_END
== zr
) {
12085 LOG("ZERR %d\n", zr
);
12086 swd_zip_var
.error
= zr
;
12088 if (zs
->total_in
== numBytes
) {
12094 //now flush the stream
12095 while (swd_zip_var
.error
>= 0) {
12096 if (!zs
->avail_out
) {
12097 zs
->next_out
= (Bytef
*)zs
;
12098 zs
->avail_out
= UINT32_MAX
;
12100 zr
= deflate(zs
, Z_FINISH
);
12101 if (Z_STREAM_END
== zr
) {
12105 LOG("ZERR %d\n", zr
);
12106 swd_zip_var
.error
= zr
;
12108 if (zs
->total_in
== numBytes
) {
12109 LOG("Total output size %d\n", swd_zip_var
.outlen
);
12115 return swd_zip_var
.outlen
;
12119 IOPMrootDomain::deleteStackshot()
12121 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
12122 // takeStackshot hasn't completed
12125 LOG("Deleting any sleepwake failure data in nvram\n");
12127 PERemoveNVRAMProperty(kIOSleepWakeFailureString
);
12128 char nvram_var_name_buf
[20];
12129 for (int i
= 0; i
< 8; i
++) {
12130 snprintf(nvram_var_name_buf
, sizeof(nvram_var_name_buf
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, i
+ 1);
12131 if (PERemoveNVRAMProperty(nvram_var_name_buf
) == false) {
12132 LOG("Removing %s returned false\n", nvram_var_name_buf
);
12135 // force NVRAM sync
12136 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
12137 DLOG("Failed to force nvram sync\n");
12139 gRootDomain
->swd_lock
= 0;
12143 IOPMrootDomain::takeStackshot(bool wdogTrigger
)
12145 swd_hdr
* hdr
= NULL
;
12149 kern_return_t kr
= KERN_SUCCESS
;
12154 uint32_t bytesRemaining
;
12155 unsigned bytesWritten
= 0;
12157 char failureStr
[512];
12158 thread_t thread
= NULL
;
12159 const char * swfPanic
= "swfPanic";
12164 #if defined(__i386__) || defined(__x86_64__)
12165 const bool concise
= false;
12167 const bool concise
= true;
12170 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
12175 if ((kIOSleepWakeWdogOff
& gIOKitDebug
) || systemBooting
|| systemShutdown
|| gWillShutdown
) {
12180 getFailureData(&thread
, failureStr
, sizeof(failureStr
));
12182 if (concise
|| (PEGetCoprocessorVersion() >= kCoprocessorVersion2
)) {
12183 goto skip_stackshot
;
12188 clock_get_uptime(&now
);
12189 SUB_ABSOLUTETIME(&now
, &gIOLastWakeAbsTime
);
12190 absolutetime_to_nanoseconds(now
, &nsec
);
12191 snprintf(failureStr
, sizeof(failureStr
), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec
) / NSEC_PER_MSEC
)));
12194 if (swd_buffer
== NULL
) {
12195 sleepWakeDebugMemAlloc();
12196 if (swd_buffer
== NULL
) {
12200 hdr
= (swd_hdr
*)swd_buffer
;
12201 bufSize
= hdr
->alloc_size
;
12203 dstAddr
= (char*)hdr
+ hdr
->spindump_offset
;
12204 flags
= STACKSHOT_KCDATA_FORMAT
| STACKSHOT_NO_IO_STATS
| STACKSHOT_SAVE_KEXT_LOADINFO
| STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY
| STACKSHOT_THREAD_WAITINFO
;
12205 /* If not wdogTrigger only take kernel tasks stackshot
12213 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12214 * If we run out of space, take stackshot with only kernel task
12216 while (success
== 0 && cnt
< max_cnt
) {
12217 bytesRemaining
= bufSize
- hdr
->spindump_offset
;
12219 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining
);
12221 size
= bytesRemaining
;
12222 kr
= stack_snapshot_from_kernel(pid
, dstAddr
, size
, flags
, 0, 0, &bytesWritten
);
12223 DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12224 kr
, pid
, size
, flags
, bytesWritten
);
12225 if (kr
== KERN_INSUFFICIENT_BUFFER_SIZE
) {
12229 LOG("Insufficient buffer size for only kernel task\n");
12233 if (kr
== KERN_SUCCESS
) {
12234 if (bytesWritten
== 0) {
12235 MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr
, size
, flags
);
12238 bytesRemaining
-= bytesWritten
;
12239 hdr
->spindump_size
= (bufSize
- bytesRemaining
- hdr
->spindump_offset
);
12241 memset(hdr
->reason
, 0x20, sizeof(hdr
->reason
));
12243 // Compress stackshot and save to NVRAM
12245 char *outbuf
= (char *)swd_compressed_buffer
;
12247 int num_chunks
= 0;
12248 int max_chunks
= 0;
12250 char nvram_var_name_buffer
[20];
12252 outlen
= swd_compress((char*)hdr
+ hdr
->spindump_offset
, outbuf
, bytesWritten
);
12255 max_chunks
= outlen
/ (2096 - 200);
12256 leftover
= outlen
% (2096 - 200);
12258 if (max_chunks
< 8) {
12259 for (num_chunks
= 0; num_chunks
< max_chunks
; num_chunks
++) {
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))), (2096 - 200)) == FALSE
) {
12262 LOG("Failed to update NVRAM %d\n", num_chunks
);
12267 snprintf(nvram_var_name_buffer
, sizeof(nvram_var_name_buffer
), "%s%02d", SWD_STACKSHOT_VAR_PREFIX
, num_chunks
+ 1);
12268 if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer
, (outbuf
+ (num_chunks
* (2096 - 200))), leftover
) == FALSE
) {
12269 LOG("Failed to update NVRAM with leftovers\n");
12273 LOG("Successfully saved stackshot to NVRAM\n");
12275 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen
);
12279 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen
);
12288 if (failureStr
[0]) {
12289 // append sleep-wake failure code
12290 char traceCode
[80];
12291 snprintf(traceCode
, sizeof(traceCode
), "\nFailure code:: 0x%08x %08x\n",
12292 pmTracer
->getTraceData(), pmTracer
->getTracePhase());
12293 strlcat(failureStr
, traceCode
, sizeof(failureStr
));
12294 if (PEWriteNVRAMProperty(kIOSleepWakeFailureString
, failureStr
, (unsigned int) strnlen(failureStr
, sizeof(failureStr
))) == false) {
12295 DLOG("Failed to write SleepWake failure string\n");
12299 // force NVRAM sync
12300 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey
)) == false) {
12301 DLOG("Failed to force nvram sync\n");
12306 if (PEGetCoprocessorVersion() < kCoprocessorVersion2
) {
12307 if (swd_flags
& SWD_BOOT_BY_SW_WDOG
) {
12308 // If current boot is due to this watch dog trigger restart in previous boot,
12309 // then don't trigger again until at least 1 successful sleep & wake.
12310 if (!(sleepCnt
&& (displayWakeCnt
|| darkWakeCnt
))) {
12311 LOG("Shutting down due to repeated Sleep/Wake failures\n");
12312 if (!tasksSuspended
) {
12313 tasksSuspended
= TRUE
;
12314 updateTasksSuspend();
12316 PEHaltRestart(kPEHaltCPU
);
12320 if (gSwdPanic
== 0) {
12321 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12322 if (!tasksSuspended
) {
12323 tasksSuspended
= TRUE
;
12324 updateTasksSuspend();
12326 PEHaltRestart(kPERestartCPU
);
12329 if (!concise
&& (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic
, swfPanic
, (unsigned int) strlen(swfPanic
)) == false)) {
12330 DLOG("Failed to write SleepWake failure panic key\n");
12332 #if defined(__x86_64__)
12334 panic_with_thread_context(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, thread
, "%s", failureStr
);
12336 #endif /* defined(__x86_64__) */
12338 panic_with_options(0, NULL
, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT
, "%s", failureStr
);
12341 gRootDomain
->swd_lock
= 0;
12347 IOPMrootDomain::sleepWakeDebugMemAlloc()
12349 vm_size_t size
= SWD_STACKSHOT_SIZE
+ SWD_COMPRESSED_BUFSIZE
+ SWD_ZLIB_BUFSIZE
;
12351 swd_hdr
*hdr
= NULL
;
12352 void *bufPtr
= NULL
;
12354 OSSharedPtr
<IOBufferMemoryDescriptor
> memDesc
;
12357 if (kIOSleepWakeWdogOff
& gIOKitDebug
) {
12361 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
12365 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
12366 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
12368 if (memDesc
== NULL
) {
12369 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12373 bufPtr
= memDesc
->getBytesNoCopy();
12375 // Carve out memory for zlib routines
12376 swd_zs_zmem
= (vm_offset_t
)bufPtr
;
12377 bufPtr
= (char *)bufPtr
+ SWD_ZLIB_BUFSIZE
;
12379 // Carve out memory for compressed stackshots
12380 swd_compressed_buffer
= bufPtr
;
12381 bufPtr
= (char *)bufPtr
+ SWD_COMPRESSED_BUFSIZE
;
12383 // Remaining is used for holding stackshot
12384 hdr
= (swd_hdr
*)bufPtr
;
12385 memset(hdr
, 0, sizeof(swd_hdr
));
12387 hdr
->signature
= SWD_HDR_SIGNATURE
;
12388 hdr
->alloc_size
= SWD_STACKSHOT_SIZE
;
12390 hdr
->spindump_offset
= sizeof(swd_hdr
);
12391 swd_buffer
= (void *)hdr
;
12392 swd_memDesc
= os::move(memDesc
);
12393 DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr
->alloc_size
, hdr
->spindump_offset
);
12396 gRootDomain
->swd_lock
= 0;
12400 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12403 vm_size_t size
= SWD_SPINDUMP_SIZE
;
12405 swd_hdr
*hdr
= NULL
;
12407 OSSharedPtr
<IOBufferMemoryDescriptor
> memDesc
;
12409 if (!OSCompareAndSwap(0, 1, &gRootDomain
->swd_lock
)) {
12413 memDesc
= IOBufferMemoryDescriptor::inTaskWithOptions(
12414 kernel_task
, kIODirectionIn
| kIOMemoryMapperNone
,
12415 SWD_SPINDUMP_SIZE
);
12417 if (memDesc
== NULL
) {
12418 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12423 hdr
= (swd_hdr
*)memDesc
->getBytesNoCopy();
12424 memset(hdr
, 0, sizeof(swd_hdr
));
12426 hdr
->signature
= SWD_HDR_SIGNATURE
;
12427 hdr
->alloc_size
= size
;
12429 hdr
->spindump_offset
= sizeof(swd_hdr
);
12430 swd_spindump_buffer
= (void *)hdr
;
12431 swd_spindump_memDesc
= os::move(memDesc
);
12434 gRootDomain
->swd_lock
= 0;
12435 #endif /* UNUSED */
12439 IOPMrootDomain::sleepWakeDebugEnableWdog()
12444 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12446 return !systemBooting
&& !systemShutdown
&& !gWillShutdown
;
12450 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12452 swd_hdr
*hdr
= NULL
;
12453 errno_t error
= EIO
;
12455 if (swd_spindump_buffer
&& gSpinDumpBufferFull
) {
12456 hdr
= (swd_hdr
*)swd_spindump_buffer
;
12458 error
= sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12459 (char*)hdr
+ hdr
->spindump_offset
, hdr
->spindump_size
);
12465 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12466 (char*)hdr
+ offsetof(swd_hdr
, UUID
),
12467 sizeof(swd_hdr
) - offsetof(swd_hdr
, UUID
));
12469 gSpinDumpBufferFull
= false;
12474 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)
12476 struct vnode
*vp
= NULL
;
12477 vfs_context_t ctx
= vfs_context_create(vfs_context_current());
12478 kauth_cred_t cred
= vfs_context_ucred(ctx
);
12479 struct vnode_attr va
;
12480 errno_t error
= EIO
;
12482 if (vnode_open(name
, (O_CREAT
| FWRITE
| O_NOFOLLOW
),
12483 S_IRUSR
| S_IRGRP
| S_IROTH
, VNODE_LOOKUP_NOFOLLOW
, &vp
, ctx
) != 0) {
12484 LOG("Failed to open the file %s\n", name
);
12485 swd_flags
|= SWD_FILEOP_ERROR
;
12489 VATTR_WANTED(&va
, va_nlink
);
12490 /* Don't dump to non-regular files or files with links. */
12491 if (vp
->v_type
!= VREG
||
12492 vnode_getattr(vp
, &va
, ctx
) || va
.va_nlink
!= 1) {
12493 LOG("Bailing as this is not a regular file\n");
12494 swd_flags
|= SWD_FILEOP_ERROR
;
12498 VATTR_SET(&va
, va_data_size
, 0);
12499 vnode_setattr(vp
, &va
, ctx
);
12503 error
= vn_rdwr(UIO_WRITE
, vp
, buf
, len
, 0,
12504 UIO_SYSSPACE
, IO_NODELOCKED
| IO_UNIT
, cred
, (int *) NULL
, vfs_context_proc(ctx
));
12506 LOG("Failed to save sleep wake log. err 0x%x\n", error
);
12507 swd_flags
|= SWD_FILEOP_ERROR
;
12509 DLOG("Saved %d bytes to file %s\n", len
, name
);
12515 vnode_close(vp
, FWRITE
, ctx
);
12518 vfs_context_rele(ctx
);
12524 #else /* defined(__i386__) || defined(__x86_64__) */
12527 IOPMrootDomain::sleepWakeDebugTrig(bool restart
)
12530 if (gSwdPanic
== 0) {
12533 panic("Sleep/Wake hang detected");
12539 IOPMrootDomain::takeStackshot(bool restart
)
12541 #pragma unused(restart)
12545 IOPMrootDomain::deleteStackshot()
12550 IOPMrootDomain::sleepWakeDebugMemAlloc()
12555 IOPMrootDomain::saveFailureData2File()
12560 IOPMrootDomain::sleepWakeDebugEnableWdog()
12565 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12571 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12576 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name
, char *buf
, int len
)
12581 #endif /* defined(__i386__) || defined(__x86_64__) */