]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMrootDomain.cpp
xnu-7195.101.1.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMrootDomain.cpp
1 /*
2 * Copyright (c) 1998-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #define IOKIT_ENABLE_SHARED_PTR
30
31 #include <libkern/c++/OSKext.h>
32 #include <libkern/c++/OSMetaClass.h>
33 #include <libkern/OSAtomic.h>
34 #include <libkern/OSDebug.h>
35 #include <IOKit/IOWorkLoop.h>
36 #include <IOKit/IOCommandGate.h>
37 #include <IOKit/IOTimerEventSource.h>
38 #include <IOKit/IOPlatformExpert.h>
39 #include <IOKit/IOCPU.h>
40 #include <IOKit/IOPlatformActions.h>
41 #include <IOKit/IOKitDebug.h>
42 #include <IOKit/IOTimeStamp.h>
43 #include <IOKit/pwr_mgt/IOPMlog.h>
44 #include <IOKit/pwr_mgt/RootDomain.h>
45 #include <IOKit/pwr_mgt/IOPMPrivate.h>
46 #include <IOKit/IODeviceTreeSupport.h>
47 #include <IOKit/IOMessage.h>
48 #include <IOKit/IOReturn.h>
49 #include <IOKit/IONVRAM.h>
50 #include "RootDomainUserClient.h"
51 #include "IOKit/pwr_mgt/IOPowerConnection.h"
52 #include "IOPMPowerStateQueue.h"
53 #include <IOKit/IOCatalogue.h>
54 #include <IOKit/IOReportMacros.h>
55 #include <IOKit/IOLib.h>
56 #include <IOKit/IOKitKeys.h>
57 #include <IOKit/IOUserServer.h>
58 #include "IOKitKernelInternal.h"
59 #if HIBERNATION
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>
68 #include <os/log.h>
69 #include <pexpert/protos.h>
70 #include <AssertMacros.h>
71
72 #include <sys/time.h>
73 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
74 #include "IOServicePMPrivate.h"
75
76 #include <libkern/zlib.h>
77 #include <os/cpp_util.h>
78 #include <libkern/c++/OSBoundedArrayRef.h>
79
80 __BEGIN_DECLS
81 #include <mach/shared_region.h>
82 #include <kern/clock.h>
83 __END_DECLS
84
85 #if defined(__i386__) || defined(__x86_64__)
86 __BEGIN_DECLS
87 #include "IOPMrootDomainInternal.h"
88 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
89 __END_DECLS
90 #endif
91
92 #define kIOPMrootDomainClass "IOPMrootDomain"
93 #define LOG_PREFIX "PMRD: "
94
95
96 #define MSG(x...) \
97 do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
98
99 #define LOG(x...) \
100 do { kprintf(LOG_PREFIX x); } while (false)
101
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); \
107 } while (false)
108 #else
109 #define DEBUG_LOG(x...)
110 #endif
111
112 #define DLOG(x...) do { \
113 if (kIOLogPMRootDomain & gIOKitDebug) \
114 kprintf(LOG_PREFIX x); \
115 else \
116 os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
117 } while (false)
118
119 #define DMSG(x...) do { \
120 if (kIOLogPMRootDomain & gIOKitDebug) { \
121 kprintf(LOG_PREFIX x); \
122 } \
123 } while (false)
124
125
126 #define _LOG(x...)
127
128 #define CHECK_THREAD_CONTEXT
129 #ifdef CHECK_THREAD_CONTEXT
130 static IOWorkLoop * gIOPMWorkLoop = NULL;
131 #define ASSERT_GATED() \
132 do { \
133 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
134 panic("RootDomain: not inside PM gate"); \
135 } \
136 } while(false)
137 #else
138 #define ASSERT_GATED()
139 #endif /* CHECK_THREAD_CONTEXT */
140
141 #define CAP_LOSS(c) \
142 (((_pendingCapability & (c)) == 0) && \
143 ((_currentCapability & (c)) != 0))
144
145 #define CAP_GAIN(c) \
146 (((_currentCapability & (c)) == 0) && \
147 ((_pendingCapability & (c)) != 0))
148
149 #define CAP_CHANGE(c) \
150 (((_currentCapability ^ _pendingCapability) & (c)) != 0)
151
152 #define CAP_CURRENT(c) \
153 ((_currentCapability & (c)) != 0)
154
155 #define CAP_HIGHEST(c) \
156 ((_highestCapability & (c)) != 0)
157
158 #define CAP_PENDING(c) \
159 ((_pendingCapability & (c)) != 0)
160
161 // rdar://problem/9157444
162 #if defined(__i386__) || defined(__x86_64__)
163 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY 20
164 #endif
165
166 // Event types for IOPMPowerStateQueue::submitPowerEvent()
167 enum {
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
184 };
185
186 // For evaluatePolicy()
187 // List of stimuli that affects the root domain policy.
188 enum {
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
201 };
202
203 // Internal power state change reasons
204 // Must be less than kIOPMSleepReasonClamshell=101
205 enum {
206 kCPSReasonNone = 0, // 0
207 kCPSReasonInit, // 1
208 kCPSReasonWake, // 2
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)
220 };
221
222 extern "C" {
223 IOReturn OSKextSystemSleepOrWake( UInt32 );
224 }
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();
228
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);
236
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
241
242 // "IOPMSetSleepSupported" callPlatformFunction name
243 static OSSharedPtr<const OSSymbol> sleepSupportedPEFunction;
244 static OSSharedPtr<const OSSymbol> sleepMessagePEFunction;
245 static OSSharedPtr<const OSSymbol> gIOPMWakeTypeUserKey;
246
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;
291
292 #define kIOSleepSupportedKey "IOSleepSupported"
293 #define kIOPMSystemCapabilitiesKey "System Capabilities"
294 #define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
295
296 #define kIORequestWranglerIdleKey "IORequestIdle"
297 #define kDefaultWranglerIdlePeriod 1000 // in milliseconds
298
299 #define kIOSleepWakeFailureString "SleepWakeFailureString"
300 #define kIOEFIBootRomFailureKey "wake-failure"
301 #define kIOSleepWakeFailurePanic "SleepWakeFailurePanic"
302
303 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
304 | kIOPMSupportedOnBatt \
305 | kIOPMSupportedOnUPS)
306
307 #define kLocalEvalClamshellCommand (1 << 15)
308 #define kIdleSleepRetryInterval (3 * 60)
309
310 #define DISPLAY_WRANGLER_PRESENT (!NO_KERNEL_HID)
311
312 enum {
313 kWranglerPowerStateMin = 0,
314 kWranglerPowerStateSleep = 2,
315 kWranglerPowerStateDim = 3,
316 kWranglerPowerStateMax = 4
317 };
318
319 enum {
320 OFF_STATE = 0,
321 RESTART_STATE = 1,
322 SLEEP_STATE = 2,
323 AOT_STATE = 3,
324 ON_STATE = 4,
325 NUM_POWER_STATES
326 };
327
328 const char *
329 getPowerStateString( uint32_t state )
330 {
331 #define POWER_STATE(x) {(uint32_t) x, #x}
332
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 ),
339 { 0, NULL }
340 };
341 return IOFindNameForValue(state, powerStates);
342 }
343
344 #define ON_POWER kIOPMPowerOn
345 #define RESTART_POWER kIOPMRestart
346 #define SLEEP_POWER kIOPMAuxPowerOn
347
348 static IOPMPowerState
349 ourPowerStates[NUM_POWER_STATES] =
350 {
351 { .version = 1,
352 .capabilityFlags = 0,
353 .outputPowerCharacter = 0,
354 .inputPowerRequirement = 0 },
355 { .version = 1,
356 .capabilityFlags = kIOPMRestartCapability,
357 .outputPowerCharacter = kIOPMRestart,
358 .inputPowerRequirement = RESTART_POWER },
359 { .version = 1,
360 .capabilityFlags = kIOPMSleepCapability,
361 .outputPowerCharacter = kIOPMSleep,
362 .inputPowerRequirement = SLEEP_POWER },
363 { .version = 1,
364 .capabilityFlags = kIOPMAOTCapability,
365 .outputPowerCharacter = kIOPMAOTPower,
366 .inputPowerRequirement = ON_POWER },
367 { .version = 1,
368 .capabilityFlags = kIOPMPowerOn,
369 .outputPowerCharacter = kIOPMPowerOn,
370 .inputPowerRequirement = ON_POWER },
371 };
372
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"
383
384 // Special interest that entitles the interested client from receiving
385 // all system messages. Only used by powerd.
386 //
387 #define kIOPMSystemCapabilityInterest "IOPMSystemCapabilityInterest"
388
389 // Entitlement required for root domain clients
390 #define kRootDomainEntitlementSetProperty "com.apple.private.iokit.rootdomain-set-property"
391
392 #define WAKEEVENT_LOCK() IOLockLock(wakeEventLock)
393 #define WAKEEVENT_UNLOCK() IOLockUnlock(wakeEventLock)
394
395 /*
396 * Aggressiveness
397 */
398 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
399 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
400
401 #define kAggressivesMinValue 1
402
403 const char *
404 getAggressivenessTypeString( uint32_t type )
405 {
406 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
407
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 ),
418 { 0, NULL }
419 };
420 return IOFindNameForValue(type, aggressivenessTypes);
421 }
422
423 enum {
424 kAggressivesStateBusy = 0x01,
425 kAggressivesStateQuickSpindown = 0x02
426 };
427
428 struct AggressivesRecord {
429 uint32_t flags;
430 uint32_t type;
431 uint32_t value;
432 };
433
434 struct AggressivesRequest {
435 queue_chain_t chain;
436 uint32_t options;
437 uint32_t dataType;
438 union {
439 OSSharedPtr<IOService> service;
440 AggressivesRecord record;
441 } data;
442 };
443
444 enum {
445 kAggressivesRequestTypeService = 1,
446 kAggressivesRequestTypeRecord
447 };
448
449 enum {
450 kAggressivesOptionSynchronous = 0x00000001,
451 kAggressivesOptionQuickSpindownEnable = 0x00000100,
452 kAggressivesOptionQuickSpindownDisable = 0x00000200,
453 kAggressivesOptionQuickSpindownMask = 0x00000300
454 };
455
456 enum {
457 kAggressivesRecordFlagModified = 0x00000001,
458 kAggressivesRecordFlagMinValue = 0x00000002
459 };
460
461 // System Sleep Preventers
462
463 enum {
464 kPMUserDisabledAllSleep = 1,
465 kPMSystemRestartBootingInProgress,
466 kPMConfigPreventSystemSleep,
467 kPMChildPreventSystemSleep,
468 kPMCPUAssertion,
469 kPMPCIUnsupported,
470 };
471
472 const char *
473 getSystemSleepPreventerString( uint32_t preventer )
474 {
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 ),
483 { 0, NULL }
484 };
485 return IOFindNameForValue(preventer, systemSleepPreventers);
486 }
487
488 // gDarkWakeFlags
489 enum {
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
497 };
498
499 // gClamshellFlags
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.
502 enum {
503 kClamshell_WAR_38378787 = 0x00000001,
504 kClamshell_WAR_47715679 = 0x00000002,
505 kClamshell_WAR_58009435 = 0x00000004
506 };
507
508 // acceptSystemWakeEvents()
509 enum {
510 kAcceptSystemWakeEvents_Disable = 0,
511 kAcceptSystemWakeEvents_Enable,
512 kAcceptSystemWakeEvents_Reenable
513 };
514
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;
533
534 uuid_string_t bootsessionuuid_string;
535
536 #if defined(XNU_TARGET_OS_OSX)
537 #if DISPLAY_WRANGLER_PRESENT
538 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionNone;
539 #elif CONFIG_ARROW
540 // Enable temporary full wake promotion workarounds
541 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
542 #else
543 // Enable full wake promotion workarounds
544 static uint32_t gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
545 #endif
546 #else /* !defined(XNU_TARGET_OS_OSX) */
547 static uint32_t gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
548 #endif /* !defined(XNU_TARGET_OS_OSX) */
549
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;
558 #endif
559
560 static uint32_t gClamshellFlags = 0
561 #if defined(__i386__) || defined(__x86_64__)
562 | kClamshell_WAR_58009435
563 #endif
564 ;
565
566 #if HIBERNATION
567
568 #if defined(__arm64__)
569 static IOReturn
570 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
571 {
572 uint32_t sleepType = kIOPMSleepTypeDeepIdle;
573
574 assert(vars->signature == kIOPMSystemSleepPolicySignature);
575 assert(vars->version == kIOPMSystemSleepPolicyVersion);
576
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;
582 }
583 params->version = kIOPMSystemSleepParametersVersion;
584 params->sleepType = sleepType;
585 return kIOReturnSuccess;
586 }
587 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = &defaultSleepPolicyHandler;
588 #else /* defined(__arm64__) */
589 static IOPMSystemSleepPolicyHandler gSleepPolicyHandler = NULL;
590 #endif /* defined(__arm64__) */
591
592 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
593 static void * gSleepPolicyTarget;
594 #endif
595
596 struct timeval gIOLastSleepTime;
597 struct timeval gIOLastWakeTime;
598 AbsoluteTime gIOLastWakeAbsTime;
599 AbsoluteTime gIOLastSleepAbsTime;
600
601 struct timeval gIOLastUserSleepTime;
602
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;
612
613 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
614 static bool gSpinDumpBufferFull = false;
615 #endif
616
617 z_stream swd_zs;
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;
623 #endif
624
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;
633
634 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
635 #define kCPUUnknownIndex 9999999
636 enum {
637 kInformAC = 0,
638 kInformLid = 1,
639 kInformableCount = 2
640 };
641
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;
647
648 #define kBadPMFeatureID 0
649
650 /*
651 * PMSettingHandle
652 * Opaque handle passed to clients of registerPMSettingController()
653 */
654 class PMSettingHandle : public OSObject
655 {
656 OSDeclareFinalStructors( PMSettingHandle );
657 friend class PMSettingObject;
658
659 private:
660 PMSettingObject *pmso;
661 void free(void) APPLE_KEXT_OVERRIDE;
662 };
663
664 /*
665 * PMSettingObject
666 * Internal object to track each PM setting controller
667 */
668 class PMSettingObject : public OSObject
669 {
670 OSDeclareFinalStructors( PMSettingObject );
671 friend class IOPMrootDomain;
672
673 private:
674 queue_head_t calloutQueue;
675 thread_t waitThread;
676 IOPMrootDomain *parent;
677 PMSettingHandle *pmsh;
678 IOPMSettingControllerCallback func;
679 OSObject *target;
680 uintptr_t refcon;
681 uint32_t *publishedFeatureID;
682 uint32_t settingCount;
683 bool disabled;
684
685 void free(void) APPLE_KEXT_OVERRIDE;
686
687 public:
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);
696
697 IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
698 void clientHandleFreed(void);
699 };
700
701 struct PMSettingCallEntry {
702 queue_chain_t link;
703 thread_t thread;
704 };
705
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)
710
711 /*
712 * PMTraceWorker
713 * Internal helper object for logging trace points to RTC
714 * IOPMrootDomain and only IOPMrootDomain should instantiate
715 * exactly one of these.
716 */
717
718 typedef void (*IOPMTracePointHandler)(
719 void * target, uint32_t code, uint32_t data );
720
721 class PMTraceWorker : public OSObject
722 {
723 OSDeclareDefaultStructors(PMTraceWorker);
724 public:
725 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
726
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;
735
736 IOPMTracePointHandler tracePointHandler;
737 void * tracePointTarget;
738 uint64_t getPMStatusCode();
739 uint8_t getTracePhase();
740 uint32_t getTraceData();
741 private:
742 IOPMrootDomain *owner;
743 IOLock *pmTraceWorkerLock;
744 OSSharedPtr<OSArray> pciDeviceBitMappings;
745
746 uint8_t addedToRegistry;
747 uint8_t tracePhase;
748 uint32_t traceData32;
749 uint8_t loginWindowData;
750 uint8_t coreDisplayData;
751 uint8_t coreGraphicsData;
752 };
753
754 /*
755 * PMAssertionsTracker
756 * Tracks kernel and user space PM assertions
757 */
758 class PMAssertionsTracker : public OSObject
759 {
760 OSDeclareFinalStructors(PMAssertionsTracker);
761 public:
762 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
763
764 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
765 IOReturn releaseAssertion(IOPMDriverAssertionID);
766 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
767 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
768
769 OSSharedPtr<OSArray> copyAssertionsArray(void);
770 IOPMDriverAssertionType getActivatedAssertions(void);
771 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
772
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);
779
780 private:
781 /*
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
784 */
785 typedef struct {
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;
796 } PMAssertStruct;
797
798 uint32_t tabulateProducerCount;
799 uint32_t tabulateConsumerCount;
800
801 uint64_t maxAssertCPUDuration;
802 uint64_t maxAssertCPUEntryId;
803
804 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
805 void tabulate(void);
806 void updateCPUBitAccounting(PMAssertStruct * assertStruct);
807
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;
815 };
816
817 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
818
819 /*
820 * PMHaltWorker
821 * Internal helper object for Shutdown/Restart notifications.
822 */
823 #define kPMHaltMaxWorkers 8
824 #define kPMHaltTimeoutMS 100
825
826 class PMHaltWorker : public OSObject
827 {
828 OSDeclareFinalStructors( PMHaltWorker );
829
830 public:
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)
835 IOLock * lock;
836 bool timeout;// service took too long
837
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;
843 };
844
845 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
846
847
848 #define super IOService
849 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
850
851 boolean_t
852 IOPMRootDomainGetWillShutdown(void)
853 {
854 return gWillShutdown != 0;
855 }
856
857 static void
858 IOPMRootDomainWillShutdown(void)
859 {
860 if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
861 IOService::willShutdown();
862 for (int i = 0; i < 100; i++) {
863 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
864 break;
865 }
866 IOSleep( 100 );
867 }
868 }
869 }
870
871 extern "C" IONotifier *
872 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
873 {
874 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
875 }
876
877 extern "C" IONotifier *
878 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
879 {
880 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
881 }
882
883 extern "C" IOReturn
884 acknowledgeSleepWakeNotification(void * PMrefcon)
885 {
886 return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
887 }
888
889 extern "C" IOReturn
890 vetoSleepWakeNotification(void * PMrefcon)
891 {
892 return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
893 }
894
895 extern "C" IOReturn
896 rootDomainRestart( void )
897 {
898 return gRootDomain->restartSystem();
899 }
900
901 extern "C" IOReturn
902 rootDomainShutdown( void )
903 {
904 return gRootDomain->shutdownSystem();
905 }
906
907 static void
908 halt_log_putc(char c)
909 {
910 if (gHaltLogPos >= (kHaltLogSize - 2)) {
911 return;
912 }
913 gHaltLog[gHaltLogPos++] = c;
914 }
915
916 extern "C" void
917 _doprnt_log(const char *fmt,
918 va_list *argp,
919 void (*putc)(char),
920 int radix);
921
922 static int
923 halt_log(const char *fmt, ...)
924 {
925 va_list listp;
926
927 va_start(listp, fmt);
928 _doprnt_log(fmt, &listp, &halt_log_putc, 16);
929 va_end(listp);
930
931 return 0;
932 }
933
934 extern "C" void
935 halt_log_enter(const char * what, const void * pc, uint64_t time)
936 {
937 uint64_t nano, millis;
938
939 if (!gHaltLog) {
940 return;
941 }
942 absolutetime_to_nanoseconds(time, &nano);
943 millis = nano / NSEC_PER_MSEC;
944 if (millis < 100) {
945 return;
946 }
947
948 IOLockLock(gHaltLogLock);
949 if (pc) {
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);
953 } else {
954 halt_log("%s: %qd ms\n", what, millis);
955 }
956
957 gHaltLog[gHaltLogPos] = 0;
958 IOLockUnlock(gHaltLogLock);
959 }
960
961 extern uint32_t gFSState;
962
963 extern "C" void
964 IOSystemShutdownNotification(int stage)
965 {
966 uint64_t startTime;
967
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);
977 }
978 #endif /* defined(XNU_TARGET_OS_OSX) */
979 return;
980 }
981
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);
990 }
991 return;
992 }
993
994 assert(kIOSystemShutdownNotificationStageProcessExit == stage);
995
996 IOLockLock(gHaltLogLock);
997 if (!gHaltLog) {
998 gHaltLog = IONew(char, kHaltLogSize);
999 gHaltStartTime = mach_absolute_time();
1000 if (gHaltLog) {
1001 halt_log_putc('\n');
1002 }
1003 }
1004 IOLockUnlock(gHaltLogLock);
1005
1006 startTime = mach_absolute_time();
1007 IOPMRootDomainWillShutdown();
1008 halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1009 #if HIBERNATION
1010 startTime = mach_absolute_time();
1011 IOHibernateSystemPostWake(true);
1012 halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1013 #endif
1014 if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1015 gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1016 }
1017 }
1018
1019 extern "C" int sync_internal(void);
1020
1021 /*
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().
1028 *
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.
1032 *
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.
1039 *
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.
1044 *
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.
1049 *
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.
1057 *
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.
1061 */
1062
1063 //******************************************************************************
1064
1065 IOPMrootDomain *
1066 IOPMrootDomain::construct( void )
1067 {
1068 IOPMrootDomain *root;
1069
1070 root = new IOPMrootDomain;
1071 if (root) {
1072 root->init();
1073 }
1074
1075 return root;
1076 }
1077
1078 //******************************************************************************
1079 // updateConsoleUsersCallout
1080 //
1081 //******************************************************************************
1082
1083 static void
1084 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1085 {
1086 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1087 rootDomain->updateConsoleUsers();
1088 }
1089
1090 void
1091 IOPMrootDomain::updateConsoleUsers(void)
1092 {
1093 IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1094 if (tasksSuspended) {
1095 tasksSuspended = FALSE;
1096 updateTasksSuspend();
1097 }
1098 }
1099
1100 void
1101 IOPMrootDomain::updateTasksSuspend(void)
1102 {
1103 bool newSuspend;
1104
1105 newSuspend = (tasksSuspended || _aotTasksSuspended);
1106 if (newSuspend == tasksSuspendState) {
1107 return;
1108 }
1109 tasksSuspendState = newSuspend;
1110 tasks_system_suspend(newSuspend);
1111 }
1112
1113 //******************************************************************************
1114
1115 static void
1116 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1117 {
1118 IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1119 uint32_t notifyRef = (uint32_t)(uintptr_t) p1;
1120 uint32_t powerState = rootDomain->getPowerState();
1121
1122 DLOG("disk_sync_callout ps=%u\n", powerState);
1123
1124 if (ON_STATE == powerState) {
1125 sync_internal();
1126
1127 #if HIBERNATION
1128 // Block sleep until trim issued on previous wake path is completed.
1129 IOHibernateSystemPostWake(true);
1130 #endif
1131 }
1132 #if HIBERNATION
1133 else {
1134 IOHibernateSystemPostWake(false);
1135
1136 rootDomain->sleepWakeDebugSaveSpinDumpFile();
1137 }
1138 #endif
1139
1140 rootDomain->allowPowerChange(notifyRef);
1141 DLOG("disk_sync_callout finish\n");
1142 }
1143
1144 //******************************************************************************
1145 static UInt32
1146 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1147 {
1148 AbsoluteTime endTime;
1149 UInt64 nano = 0;
1150
1151 clock_get_uptime(&endTime);
1152 if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1153 *elapsedTime = 0;
1154 } else {
1155 SUB_ABSOLUTETIME(&endTime, startTime);
1156 absolutetime_to_nanoseconds(endTime, &nano);
1157 *elapsedTime = endTime;
1158 }
1159
1160 return (UInt32)(nano / NSEC_PER_MSEC);
1161 }
1162
1163 //******************************************************************************
1164
1165 static int
1166 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1167 {
1168 struct timeval *swt = (struct timeval *)arg1;
1169 struct proc *p = req->p;
1170
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);
1178 } else {
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);
1183 }
1184 }
1185
1186 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1187 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1188 &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1189
1190 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1191 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1192 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1193
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, "");
1198
1199 static int
1200 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1201 {
1202 int new_value, changed, error;
1203
1204 if (!gWillShutdownSysctlRegistered) {
1205 return ENOENT;
1206 }
1207
1208 error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1209 if (changed) {
1210 if (!gWillShutdown && (new_value == 1)) {
1211 IOPMRootDomainWillShutdown();
1212 } else {
1213 error = EINVAL;
1214 }
1215 }
1216 return error;
1217 }
1218
1219 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1220 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1221 NULL, 0, sysctl_willshutdown, "I", "");
1222
1223 #if defined(XNU_TARGET_OS_OSX)
1224
1225 static int
1226 sysctl_progressmeterenable
1227 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1228 {
1229 int error;
1230 int new_value, changed;
1231
1232 error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1233
1234 if (changed) {
1235 vc_enable_progressmeter(new_value);
1236 }
1237
1238 return error;
1239 }
1240
1241 static int
1242 sysctl_progressmeter
1243 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1244 {
1245 int error;
1246 int new_value, changed;
1247
1248 error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1249
1250 if (changed) {
1251 vc_set_progressmeter(new_value);
1252 }
1253
1254 return error;
1255 }
1256
1257 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1258 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1259 NULL, 0, sysctl_progressmeterenable, "I", "");
1260
1261 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1262 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1263 NULL, 0, sysctl_progressmeter, "I", "");
1264
1265 #endif /* defined(XNU_TARGET_OS_OSX) */
1266
1267
1268
1269 static int
1270 sysctl_consoleoptions
1271 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1272 {
1273 int error, changed;
1274 uint32_t new_value;
1275
1276 error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1277
1278 if (changed) {
1279 vc_user_options.options = new_value;
1280 }
1281
1282 return error;
1283 }
1284
1285 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1286 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1287 NULL, 0, sysctl_consoleoptions, "I", "");
1288
1289
1290 static int
1291 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1292 {
1293 return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1294 }
1295
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", "");
1299
1300
1301 static int
1302 sysctl_wakereason SYSCTL_HANDLER_ARGS
1303 {
1304 char wr[sizeof(gWakeReasonString)];
1305
1306 wr[0] = '\0';
1307 if (gRootDomain && gWakeReasonSysctlRegistered) {
1308 gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1309 } else {
1310 return ENOENT;
1311 }
1312
1313 return sysctl_io_string(req, wr, 0, 0, NULL);
1314 }
1315
1316 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1317 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1318 NULL, 0, sysctl_wakereason, "A", "wakereason");
1319
1320 static int
1321 sysctl_bootreason SYSCTL_HANDLER_ARGS
1322 {
1323 if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1324 return ENOENT;
1325 }
1326
1327 return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1328 }
1329
1330 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1331 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1332 NULL, 0, sysctl_bootreason, "A", "");
1333
1334 static int
1335 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1336 {
1337 char sr[sizeof(gShutdownReasonString)];
1338
1339 sr[0] = '\0';
1340 if (gRootDomain && gShutdownReasonSysctlRegistered) {
1341 gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1342 } else {
1343 return ENOENT;
1344 }
1345
1346 return sysctl_io_string(req, sr, 0, 0, NULL);
1347 }
1348
1349 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1350 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1351 NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1352
1353 static int
1354 sysctl_targettype SYSCTL_HANDLER_ARGS
1355 {
1356 IOService * root;
1357 OSSharedPtr<OSObject> obj;
1358 OSData * data;
1359 char tt[32];
1360
1361 tt[0] = '\0';
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));
1366 }
1367 }
1368 return sysctl_io_string(req, tt, 0, 0, NULL);
1369 }
1370
1371 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1372 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1373 NULL, 0, sysctl_targettype, "A", "targettype");
1374
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 */
1387
1388 //******************************************************************************
1389 // AOT
1390
1391 static int
1392 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1393 {
1394 if (NULL == gRootDomain) {
1395 return ENOENT;
1396 }
1397 if (NULL == gRootDomain->_aotMetrics) {
1398 return ENOENT;
1399 }
1400 return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1401 }
1402
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", "");
1406
1407
1408 static int
1409 update_aotmode(uint32_t mode)
1410 {
1411 int result;
1412
1413 if (!gIOPMWorkLoop) {
1414 return ENOENT;
1415 }
1416 result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1417 unsigned int oldCount;
1418
1419 if (mode && !gRootDomain->_aotMetrics) {
1420 gRootDomain->_aotMetrics = IONewZero(IOPMAOTMetrics, 1);
1421 if (!gRootDomain->_aotMetrics) {
1422 return ENOMEM;
1423 }
1424 }
1425
1426 oldCount = gRootDomain->idleSleepPreventersCount();
1427 gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1428 gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1429 return 0;
1430 });
1431 return result;
1432 }
1433
1434 static int
1435 sysctl_aotmodebits
1436 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1437 {
1438 int error, changed;
1439 uint32_t new_value;
1440
1441 if (NULL == gRootDomain) {
1442 return ENOENT;
1443 }
1444 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1445 if (changed && gIOPMWorkLoop) {
1446 error = update_aotmode(new_value);
1447 }
1448
1449 return error;
1450 }
1451
1452 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1453 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1454 NULL, 0, sysctl_aotmodebits, "I", "");
1455
1456 static int
1457 sysctl_aotmode
1458 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1459 {
1460 int error, changed;
1461 uint32_t new_value;
1462
1463 if (NULL == gRootDomain) {
1464 return ENOENT;
1465 }
1466 error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1467 if (changed && gIOPMWorkLoop) {
1468 if (new_value) {
1469 new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1470 }
1471 error = update_aotmode(new_value);
1472 }
1473
1474 return error;
1475 }
1476
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", "");
1480
1481 //******************************************************************************
1482
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;
1495
1496 //******************************************************************************
1497 // start
1498 //
1499 //******************************************************************************
1500
1501 #define kRootDomainSettingsCount 20
1502 #define kRootDomainNoPublishSettingsCount 4
1503
1504 bool
1505 IOPMrootDomain::start( IOService * nub )
1506 {
1507 OSSharedPtr<OSIterator> psIterator;
1508 OSSharedPtr<OSDictionary> tmpDict;
1509
1510 super::start(nub);
1511
1512 gRootDomain = this;
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);
1525
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);
1531
1532 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1533 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1534 gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1535
1536 OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1537 {
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,
1558 };
1559
1560 OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1561 {
1562 OSSymbol::withCString(kIOPMSettingProModeControl),
1563 OSSymbol::withCString(kIOPMSettingProModeDefer),
1564 gIOPMSettingSilentRunningKey,
1565 gIOPMSettingLowLatencyAudioModeKey,
1566 };
1567
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 */
1574
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));
1581
1582 queue_init(&aggressivesQueue);
1583 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1584 aggressivesData = OSData::withCapacity(
1585 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1586
1587 featuresDictLock = IOLockAlloc();
1588 settingsCtrlLock = IOLockAlloc();
1589 wakeEventLock = IOLockAlloc();
1590 gHaltLogLock = IOLockAlloc();
1591 setPMRootDomain(this);
1592
1593 extraSleepTimer = thread_call_allocate(
1594 idleSleepTimerExpired,
1595 (thread_call_param_t) this);
1596
1597 powerButtonDown = thread_call_allocate(
1598 powerButtonDownCallout,
1599 (thread_call_param_t) this);
1600
1601 powerButtonUp = thread_call_allocate(
1602 powerButtonUpCallout,
1603 (thread_call_param_t) this);
1604
1605 diskSyncCalloutEntry = thread_call_allocate(
1606 &disk_sync_callout,
1607 (thread_call_param_t) this);
1608 updateConsoleUsersEntry = thread_call_allocate(
1609 &updateConsoleUsersCallout,
1610 (thread_call_param_t) this);
1611
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);
1618 #endif
1619
1620 setProperty(kIOSleepSupportedKey, true);
1621
1622 bzero(&gPMStats, sizeof(gPMStats));
1623
1624 pmTracer = PMTraceWorker::tracer(this);
1625
1626 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1627
1628 userDisabledAllSleep = false;
1629 systemBooting = true;
1630 idleSleepEnabled = false;
1631 sleepSlider = 0;
1632 idleSleepTimerPending = false;
1633 wrangler = NULL;
1634 clamshellClosed = false;
1635 clamshellExists = false;
1636 #if DISPLAY_WRANGLER_PRESENT
1637 clamshellDisabled = true;
1638 #else
1639 clamshellDisabled = false;
1640 #endif
1641 clamshellIgnoreClose = false;
1642 acAdaptorConnected = true;
1643 clamshellSleepDisableMask = 0;
1644 gWakeReasonString[0] = '\0';
1645
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);
1652
1653 // Set the default system capabilities at boot.
1654 _currentCapability = kIOPMSystemCapabilityCPU |
1655 kIOPMSystemCapabilityGraphics |
1656 kIOPMSystemCapabilityAudio |
1657 kIOPMSystemCapabilityNetwork;
1658
1659 _pendingCapability = _currentCapability;
1660 _desiredCapability = _currentCapability;
1661 _highestCapability = _currentCapability;
1662 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1663
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
1674
1675 pmStatsLock = IOLockAlloc();
1676 idxPMCPUClamshell = kCPUUnknownIndex;
1677 idxPMCPULimitedPower = kCPUUnknownIndex;
1678
1679 tmpDict = OSDictionary::withCapacity(1);
1680 setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1681
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());
1687 }
1688
1689 settingsCallbacks = OSDictionary::withCapacity(1);
1690
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,
1696 0);
1697
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,
1703 0);
1704
1705 fPMSettingsDict = OSDictionary::withCapacity(5);
1706 preventIdleSleepList = OSSet::withCapacity(8);
1707 preventSystemSleepList = OSSet::withCapacity(2);
1708
1709 PMinit(); // creates gIOPMWorkLoop
1710 gIOPMWorkLoop = getIOPMWorkloop();
1711
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);
1718
1719 _aotMode = 0;
1720 _aotTimerES = IOTimerEventSource::timerEventSource(this,
1721 OSMemberFunctionCast(IOTimerEventSource::Action,
1722 this, &IOPMrootDomain::aotEvaluate));
1723 gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1724
1725 // create our power parent
1726 gPatriarch = new IORootParent;
1727 gPatriarch->init();
1728 gPatriarch->attach(this);
1729 gPatriarch->start(this);
1730 gPatriarch->addPowerChild(this);
1731
1732 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1733 changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1734
1735 // install power change handler
1736 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1737
1738 #if DISPLAY_WRANGLER_PRESENT
1739 wranglerIdleSettings = OSDictionary::withCapacity(1);
1740 OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1741
1742 if (wranglerIdleSettings && wranglerIdlePeriod) {
1743 wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1744 wranglerIdlePeriod.get());
1745 }
1746
1747 #endif /* DISPLAY_WRANGLER_PRESENT */
1748
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);
1754
1755 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1756 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1757 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1758 lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1759 }
1760
1761 OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1762 setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1763
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());
1770
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");
1775 }
1776
1777 // read swd_panic boot-arg
1778 PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1779 gWillShutdownSysctlRegistered = true;
1780
1781 #if HIBERNATION
1782 #if defined(__arm64__)
1783 #endif /* defined(__arm64__) */
1784 IOHibernateSystemInit(this);
1785 #endif
1786
1787 registerService(); // let clients find us
1788
1789 return true;
1790 }
1791
1792 //******************************************************************************
1793 // setProperties
1794 //
1795 // Receive a setProperty call
1796 // The "System Boot" property means the system is completely booted.
1797 //******************************************************************************
1798
1799 IOReturn
1800 IOPMrootDomain::setProperties( OSObject * props_obj )
1801 {
1802 IOReturn return_value = kIOReturnSuccess;
1803 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
1804 OSBoolean *b = NULL;
1805 OSNumber *n = NULL;
1806 const OSSymbol *key = NULL;
1807 OSObject *obj = NULL;
1808 OSSharedPtr<OSCollectionIterator> iter;
1809
1810 if (!dict) {
1811 return kIOReturnBadArgument;
1812 }
1813
1814 bool clientEntitled = false;
1815 {
1816 OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1817 clientEntitled = (obj == kOSBooleanTrue);
1818 }
1819
1820 if (!clientEntitled) {
1821 const char * errorSuffix = NULL;
1822
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";
1835 }
1836 } else {
1837 return_value = kIOReturnNotPermitted;
1838 errorSuffix = "entitled";
1839 }
1840
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;
1846 }
1847 }
1848
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");
1867 #endif
1868
1869 #if HIBERNATION
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);
1876 #endif
1877
1878 iter = OSCollectionIterator::withCollection(dict);
1879 if (!iter) {
1880 return_value = kIOReturnNoMemory;
1881 goto exit;
1882 }
1883
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);
1889 }
1890 } else if (key->isEqualTo(idle_seconds_string.get())) {
1891 if ((n = OSDynamicCast(OSNumber, obj))) {
1892 setProperty(key, n);
1893 idleSeconds = n->unsigned32BitValue();
1894 }
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);
1900 }
1901 } else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1902 setProperty(key, obj);
1903 }
1904 #if HIBERNATION
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);
1912 }
1913 } else if (key->isEqualTo(hibernatefile_string.get())) {
1914 OSString * str = OSDynamicCast(OSString, obj);
1915 if (str) {
1916 setProperty(key, str);
1917 }
1918 }
1919 #endif
1920 else if (key->isEqualTo(sleepdisabled_string.get())) {
1921 if ((b = OSDynamicCast(OSBoolean, obj))) {
1922 setProperty(key, b);
1923 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1924 }
1925 } else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1926 obj->retain();
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);
1933 }
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);
1939 }
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);
1945 }
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);
1952 }
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);
1959 }
1960 } else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1961 if (kOSBooleanTrue == obj) {
1962 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1963 } else {
1964 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1965 }
1966 DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
1967 }
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);
1993 }
1994 #endif
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) {
1999 break;
2000 }
2001 } else {
2002 DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2003 }
2004 }
2005
2006 exit:
2007 return return_value;
2008 }
2009
2010 // MARK: -
2011 // MARK: Aggressiveness
2012
2013 //******************************************************************************
2014 // setAggressiveness
2015 //
2016 // Override IOService::setAggressiveness()
2017 //******************************************************************************
2018
2019 IOReturn
2020 IOPMrootDomain::setAggressiveness(
2021 unsigned long type,
2022 unsigned long value )
2023 {
2024 return setAggressiveness( type, value, 0 );
2025 }
2026
2027 /*
2028 * Private setAggressiveness() with an internal options argument.
2029 */
2030 IOReturn
2031 IOPMrootDomain::setAggressiveness(
2032 unsigned long type,
2033 unsigned long value,
2034 IOOptionBits options )
2035 {
2036 AggressivesRequest * entry;
2037 AggressivesRequest * request;
2038 bool found = false;
2039
2040 if ((type > UINT_MAX) || (value > UINT_MAX)) {
2041 return kIOReturnBadArgument;
2042 }
2043
2044 if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2045 DLOG("setAggressiveness(%x) %s = %u\n",
2046 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2047 } else {
2048 DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2049 (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2050 }
2051
2052 request = IONew(AggressivesRequest, 1);
2053 if (!request) {
2054 return kIOReturnNoMemory;
2055 }
2056
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;
2062
2063 AGGRESSIVES_LOCK();
2064
2065 // Update disk quick spindown flag used by getAggressiveness().
2066 // Never merge requests with quick spindown flags set.
2067
2068 if (options & kAggressivesOptionQuickSpindownEnable) {
2069 gAggressivesState |= kAggressivesStateQuickSpindown;
2070 } else if (options & kAggressivesOptionQuickSpindownDisable) {
2071 gAggressivesState &= ~kAggressivesStateQuickSpindown;
2072 } else {
2073 // Coalesce requests with identical aggressives types.
2074 // Deal with callers that calls us too "aggressively".
2075
2076 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2077 {
2078 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2079 (entry->data.record.type == type) &&
2080 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2081 entry->data.record.value = (uint32_t) value;
2082 found = true;
2083 break;
2084 }
2085 }
2086 }
2087
2088 if (!found) {
2089 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2090 }
2091
2092 AGGRESSIVES_UNLOCK();
2093
2094 if (found) {
2095 IODelete(request, AggressivesRequest, 1);
2096 }
2097
2098 if (options & kAggressivesOptionSynchronous) {
2099 handleAggressivesRequests(); // not truly synchronous
2100 } else {
2101 thread_call_enter(aggressivesThreadCall);
2102 }
2103
2104 return kIOReturnSuccess;
2105 }
2106
2107 //******************************************************************************
2108 // getAggressiveness
2109 //
2110 // Override IOService::setAggressiveness()
2111 // Fetch the aggressiveness factor with the given type.
2112 //******************************************************************************
2113
2114 IOReturn
2115 IOPMrootDomain::getAggressiveness(
2116 unsigned long type,
2117 unsigned long * outLevel )
2118 {
2119 uint32_t value = 0;
2120 int source = 0;
2121
2122 if (!outLevel || (type > UINT_MAX)) {
2123 return kIOReturnBadArgument;
2124 }
2125
2126 AGGRESSIVES_LOCK();
2127
2128 // Disk quick spindown in effect, report value = 1
2129
2130 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2131 (type == kPMMinutesToSpinDown)) {
2132 value = kAggressivesMinValue;
2133 source = 1;
2134 }
2135
2136 // Consult the pending request queue.
2137
2138 if (!source) {
2139 AggressivesRequest * entry;
2140
2141 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2142 {
2143 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2144 (entry->data.record.type == type) &&
2145 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2146 value = entry->data.record.value;
2147 source = 2;
2148 break;
2149 }
2150 }
2151 }
2152
2153 // Consult the backend records.
2154
2155 if (!source && aggressivesData) {
2156 AggressivesRecord * record;
2157 int i, count;
2158
2159 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2160 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2161
2162 for (i = 0; i < count; i++, record++) {
2163 if (record->type == type) {
2164 value = record->value;
2165 source = 3;
2166 break;
2167 }
2168 }
2169 }
2170
2171 AGGRESSIVES_UNLOCK();
2172
2173 if (source) {
2174 *outLevel = (unsigned long) value;
2175 return kIOReturnSuccess;
2176 } else {
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;
2180 }
2181 }
2182
2183 //******************************************************************************
2184 // joinAggressiveness
2185 //
2186 // Request from IOService to join future aggressiveness broadcasts.
2187 //******************************************************************************
2188
2189 IOReturn
2190 IOPMrootDomain::joinAggressiveness(
2191 IOService * service )
2192 {
2193 AggressivesRequest * request;
2194
2195 if (!service || (service == this)) {
2196 return kIOReturnBadArgument;
2197 }
2198
2199 DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2200
2201 request = IONew(AggressivesRequest, 1);
2202 if (!request) {
2203 return kIOReturnNoMemory;
2204 }
2205
2206 memset(request, 0, sizeof(*request));
2207 request->dataType = kAggressivesRequestTypeService;
2208 request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2209
2210 AGGRESSIVES_LOCK();
2211 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2212 AGGRESSIVES_UNLOCK();
2213
2214 thread_call_enter(aggressivesThreadCall);
2215
2216 return kIOReturnSuccess;
2217 }
2218
2219 //******************************************************************************
2220 // handleAggressivesRequests
2221 //
2222 // Backend thread processes all incoming aggressiveness requests in the queue.
2223 //******************************************************************************
2224
2225 static void
2226 handleAggressivesFunction(
2227 thread_call_param_t param1,
2228 thread_call_param_t param2 )
2229 {
2230 if (param1) {
2231 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
2232 }
2233 }
2234
2235 void
2236 IOPMrootDomain::handleAggressivesRequests( void )
2237 {
2238 AggressivesRecord * start;
2239 AggressivesRecord * record;
2240 AggressivesRequest * request;
2241 queue_head_t joinedQueue;
2242 int i, count;
2243 bool broadcast;
2244 bool found;
2245 bool pingSelf = false;
2246
2247 AGGRESSIVES_LOCK();
2248
2249 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2250 queue_empty(&aggressivesQueue)) {
2251 goto unlock_done;
2252 }
2253
2254 gAggressivesState |= kAggressivesStateBusy;
2255 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2256 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2257
2258 do{
2259 broadcast = false;
2260 queue_init(&joinedQueue);
2261
2262 do{
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.
2268 found = false;
2269 for (i = 0, record = start; i < count; i++, record++) {
2270 if (record->type == request->data.record.type) {
2271 found = true;
2272
2273 if (request->options & kAggressivesOptionQuickSpindownEnable) {
2274 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2275 broadcast = true;
2276 record->flags |= (kAggressivesRecordFlagMinValue |
2277 kAggressivesRecordFlagModified);
2278 DLOG("disk spindown accelerated, was %u min\n",
2279 record->value);
2280 }
2281 } else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2282 if (record->flags & kAggressivesRecordFlagMinValue) {
2283 broadcast = true;
2284 record->flags |= kAggressivesRecordFlagModified;
2285 record->flags &= ~kAggressivesRecordFlagMinValue;
2286 DLOG("disk spindown restored to %u min\n",
2287 record->value);
2288 }
2289 } else if (record->value != request->data.record.value) {
2290 record->value = request->data.record.value;
2291 if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2292 broadcast = true;
2293 record->flags |= kAggressivesRecordFlagModified;
2294 }
2295 }
2296 break;
2297 }
2298 }
2299
2300 // No matching record, append a new record.
2301 if (!found &&
2302 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2303 AggressivesRecord newRecord;
2304
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");
2311 }
2312
2313 aggressivesData->appendBytes(&newRecord, sizeof(newRecord));
2314
2315 // OSData may have switched to another (larger) buffer.
2316 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2317 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2318 broadcast = true;
2319 }
2320
2321 // Finished processing the request, release it.
2322 IODelete(request, AggressivesRequest, 1);
2323 break;
2324
2325 case kAggressivesRequestTypeService:
2326 // synchronizeAggressives() will free request.
2327 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2328 break;
2329
2330 default:
2331 panic("bad aggressives request type %x\n", request->dataType);
2332 break;
2333 }
2334 } while (!queue_empty(&aggressivesQueue));
2335
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);
2341 }
2342 if (broadcast) {
2343 broadcastAggressives(start, count);
2344 }
2345 AGGRESSIVES_LOCK();
2346 }
2347
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))) {
2353 pingSelf = true;
2354 }
2355
2356 record->flags &= ~kAggressivesRecordFlagModified;
2357 }
2358
2359 // Check the incoming queue again since new entries may have been
2360 // added while lock was released above.
2361 } while (!queue_empty(&aggressivesQueue));
2362
2363 gAggressivesState &= ~kAggressivesStateBusy;
2364
2365 unlock_done:
2366 AGGRESSIVES_UNLOCK();
2367
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.
2370
2371 if (pingSelf && pmPowerStateQueue) {
2372 pmPowerStateQueue->submitPowerEvent(
2373 kPowerEventPolicyStimulus,
2374 (void *) kStimulusAggressivenessChanged );
2375 }
2376 }
2377
2378 //******************************************************************************
2379 // synchronizeAggressives
2380 //
2381 // Push all known aggressiveness records to one or more IOService.
2382 //******************************************************************************
2383
2384 void
2385 IOPMrootDomain::synchronizeAggressives(
2386 queue_head_t * joinedQueue,
2387 const AggressivesRecord * array,
2388 int count )
2389 {
2390 OSSharedPtr<IOService> service;
2391 AggressivesRequest * request;
2392 const AggressivesRecord * record;
2393 IOPMDriverCallEntry callEntry;
2394 uint32_t value;
2395 int i;
2396
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);
2402 } else {
2403 service.reset();
2404 }
2405
2406 IODelete(request, AggressivesRequest, 1);
2407 request = NULL;
2408
2409 if (service) {
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;
2415 }
2416
2417 _LOG("synchronizeAggressives 0x%x = %u to %s\n",
2418 record->type, value, service->getName());
2419 service->setAggressiveness(record->type, value);
2420 }
2421 service->deassertPMDriverCall(&callEntry);
2422 }
2423 }
2424 }
2425 }
2426
2427 //******************************************************************************
2428 // broadcastAggressives
2429 //
2430 // Traverse PM tree and call setAggressiveness() for records that have changed.
2431 //******************************************************************************
2432
2433 void
2434 IOPMrootDomain::broadcastAggressives(
2435 const AggressivesRecord * array,
2436 int count )
2437 {
2438 OSSharedPtr<IORegistryIterator> iter;
2439 IORegistryEntry *entry;
2440 OSSharedPtr<IORegistryEntry> child;
2441 IOPowerConnection *connect;
2442 IOService *service;
2443 const AggressivesRecord *record;
2444 IOPMDriverCallEntry callEntry;
2445 uint32_t value;
2446 int i;
2447
2448 iter = IORegistryIterator::iterateOver(
2449 this, gIOPowerPlane, kIORegistryIterateRecursively);
2450 if (iter) {
2451 do{
2452 // !! reset the iterator
2453 iter->reset();
2454 while ((entry = iter->getNextObject())) {
2455 connect = OSDynamicCast(IOPowerConnection, entry);
2456 if (!connect || !connect->getReadyFlag()) {
2457 continue;
2458 }
2459
2460 child = connect->copyChildEntry(gIOPowerPlane);
2461 if (child) {
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;
2469 }
2470 _LOG("broadcastAggressives %x = %u to %s\n",
2471 record->type, value, service->getName());
2472 service->setAggressiveness(record->type, value);
2473 }
2474 }
2475 service->deassertPMDriverCall(&callEntry);
2476 }
2477 }
2478 }
2479 }
2480 }while (!entry && !iter->isValid());
2481 }
2482 }
2483
2484 //*****************************************
2485 // stackshot on power button press
2486 // ***************************************
2487 static void
2488 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2489 {
2490 /* Power button pressed during wake
2491 * Take a stackshot
2492 */
2493 DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2494 ((IOPMrootDomain *)us)->takeStackshot(false);
2495 }
2496
2497 static void
2498 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2499 {
2500 /* Power button released.
2501 * Delete any stackshot data
2502 */
2503 DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2504 ((IOPMrootDomain *)us)->deleteStackshot();
2505 }
2506 //*************************************************************************
2507 //
2508
2509 // MARK: -
2510 // MARK: System Sleep
2511
2512 //******************************************************************************
2513 // startIdleSleepTimer
2514 //
2515 //******************************************************************************
2516
2517 void
2518 IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds )
2519 {
2520 AbsoluteTime deadline;
2521
2522 ASSERT_GATED();
2523 if (gNoIdleFlag) {
2524 DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2525 return;
2526 }
2527 if (inSeconds) {
2528 clock_interval_to_deadline(inSeconds, kSecondScale, &deadline);
2529 thread_call_enter_delayed(extraSleepTimer, deadline);
2530 idleSleepTimerPending = true;
2531 } else {
2532 thread_call_enter(extraSleepTimer);
2533 }
2534 DLOG("idle timer set for %u seconds\n", inSeconds);
2535 }
2536
2537 //******************************************************************************
2538 // cancelIdleSleepTimer
2539 //
2540 //******************************************************************************
2541
2542 void
2543 IOPMrootDomain::cancelIdleSleepTimer( void )
2544 {
2545 ASSERT_GATED();
2546 if (idleSleepTimerPending) {
2547 DLOG("idle timer cancelled\n");
2548 thread_call_cancel(extraSleepTimer);
2549 idleSleepTimerPending = false;
2550
2551 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2552 AbsoluteTime now;
2553 clock_usec_t microsecs;
2554 clock_get_uptime(&now);
2555 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2556 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2557 if (assertOnWakeReport) {
2558 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2559 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2560 }
2561 }
2562 }
2563 }
2564
2565 //******************************************************************************
2566 // idleSleepTimerExpired
2567 //
2568 //******************************************************************************
2569
2570 static void
2571 idleSleepTimerExpired(
2572 thread_call_param_t us, thread_call_param_t )
2573 {
2574 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2575 }
2576
2577 //******************************************************************************
2578 // handleSleepTimerExpiration
2579 //
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 //******************************************************************************
2583
2584 void
2585 IOPMrootDomain::handleSleepTimerExpiration( void )
2586 {
2587 if (!gIOPMWorkLoop->inGate()) {
2588 gIOPMWorkLoop->runAction(
2589 OSMemberFunctionCast(IOWorkLoop::Action, this,
2590 &IOPMrootDomain::handleSleepTimerExpiration),
2591 this);
2592 return;
2593 }
2594
2595 DLOG("sleep timer expired\n");
2596 ASSERT_GATED();
2597
2598 idleSleepTimerPending = false;
2599 setQuickSpinDownTimeout();
2600 adjustPowerState(true);
2601 }
2602
2603 //******************************************************************************
2604 // getTimeToIdleSleep
2605 //
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
2608 // this function
2609 //******************************************************************************
2610
2611 uint32_t
2612 IOPMrootDomain::getTimeToIdleSleep( void )
2613 {
2614 AbsoluteTime now, lastActivityTime;
2615 uint64_t nanos;
2616 uint32_t minutesSinceUserInactive = 0;
2617 uint32_t sleepDelay = 0;
2618
2619 if (!idleSleepEnabled) {
2620 return 0xffffffff;
2621 }
2622
2623 if (userActivityTime) {
2624 lastActivityTime = userActivityTime;
2625 } else {
2626 lastActivityTime = userBecameInactiveTime;
2627 }
2628
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);
2640
2641 if (minutesSinceUserInactive >= sleepSlider) {
2642 sleepDelay = 0;
2643 } else {
2644 sleepDelay = sleepSlider - minutesSinceUserInactive;
2645 }
2646 } else {
2647 DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2648 lastActivityTime, now, gIOLastWakeAbsTime);
2649 sleepDelay = sleepSlider;
2650 }
2651
2652 DLOG("user inactive %u min, time to idle sleep %u min\n",
2653 minutesSinceUserInactive, sleepDelay);
2654
2655 return sleepDelay * 60;
2656 }
2657
2658 //******************************************************************************
2659 // setQuickSpinDownTimeout
2660 //
2661 //******************************************************************************
2662
2663 void
2664 IOPMrootDomain::setQuickSpinDownTimeout( void )
2665 {
2666 ASSERT_GATED();
2667 setAggressiveness(
2668 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2669 }
2670
2671 //******************************************************************************
2672 // restoreUserSpinDownTimeout
2673 //
2674 //******************************************************************************
2675
2676 void
2677 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2678 {
2679 ASSERT_GATED();
2680 setAggressiveness(
2681 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2682 }
2683
2684 //******************************************************************************
2685 // sleepSystem
2686 //
2687 //******************************************************************************
2688
2689 /* public */
2690 IOReturn
2691 IOPMrootDomain::sleepSystem( void )
2692 {
2693 return sleepSystemOptions(NULL);
2694 }
2695
2696 /* private */
2697 IOReturn
2698 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2699 {
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.
2705 *
2706 * Note that user space app calls to IOPMSleepSystem() will also travel
2707 * this code path and thus be correctly identified as software sleeps.
2708 */
2709
2710 if (options && options->getObject("OSSwitch")) {
2711 // Log specific sleep cause for OS Switch hibernation
2712 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2713 }
2714
2715 if (options && (obj = options->getObject("Sleep Reason"))) {
2716 reason = OSDynamicCast(OSString, obj);
2717 if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2718 return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2719 }
2720 if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2721 return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2722 }
2723 }
2724
2725 return privateSleepSystem( kIOPMSleepReasonSoftware);
2726 }
2727
2728 /* private */
2729 IOReturn
2730 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2731 {
2732 /* Called from both gated and non-gated context */
2733
2734 if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2735 return kIOReturnNotPermitted;
2736 }
2737
2738 pmPowerStateQueue->submitPowerEvent(
2739 kPowerEventPolicyStimulus,
2740 (void *) kStimulusDemandSystemSleep,
2741 sleepReason);
2742
2743 return kIOReturnSuccess;
2744 }
2745
2746 //******************************************************************************
2747 // powerChangeDone
2748 //
2749 // This overrides powerChangeDone in IOService.
2750 //******************************************************************************
2751 void
2752 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2753 {
2754 #if !__i386__ && !__x86_64__
2755 uint64_t timeSinceReset = 0;
2756 #endif
2757 uint64_t now;
2758 unsigned long newState;
2759 clock_sec_t secs;
2760 clock_usec_t microsecs;
2761 uint32_t lastDebugWakeSeconds;
2762 clock_sec_t adjWakeTime;
2763 IOPMCalendarStruct nowCalendar;
2764
2765 ASSERT_GATED();
2766 newState = getPowerState();
2767 DLOG("PowerChangeDone: %s->%s\n",
2768 getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2769
2770 if (previousPowerState == newState) {
2771 return;
2772 }
2773
2774 notifierThread = current_thread();
2775 switch (getPowerState()) {
2776 case SLEEP_STATE: {
2777 if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2778 secs = 0;
2779 microsecs = 0;
2780 PEGetUTCTimeOfDay(&secs, &microsecs);
2781
2782 adjWakeTime = 0;
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");
2788 adjWakeTime = secs;
2789 } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2790 IOLog("accelerate _aotWakeTime for assertion\n");
2791 adjWakeTime = secs;
2792 }
2793 if (adjWakeTime) {
2794 IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2795 }
2796
2797 IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2798 IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2799
2800 IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2801 assert(kIOReturnSuccess == ret);
2802 }
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],
2807 gWakeReasonString,
2808 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2809 }
2810 }
2811 _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2812 if (_aotTimerScheduled) {
2813 _aotTimerES->cancelTimeout();
2814 _aotTimerScheduled = false;
2815 }
2816 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2817
2818 // re-enable this timer for next sleep
2819 cancelIdleSleepTimer();
2820
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);
2829 }
2830 #endif
2831
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);
2836 }
2837
2838 clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
2839 logtime(secs);
2840 gIOLastSleepTime.tv_sec = secs;
2841 gIOLastSleepTime.tv_usec = microsecs;
2842 if (!_aotLastWakeTime) {
2843 gIOLastUserSleepTime = gIOLastSleepTime;
2844 }
2845
2846 gIOLastWakeTime.tv_sec = 0;
2847 gIOLastWakeTime.tv_usec = 0;
2848 gIOLastSleepAbsTime = now;
2849
2850 if (wake2DarkwakeDelay && sleepDelaysReport) {
2851 clock_sec_t wake2DarkwakeSecs, darkwake2SleepSecs;
2852 // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2853
2854 SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2855 absolutetime_to_microtime(now, &darkwake2SleepSecs, &microsecs);
2856 absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, &microsecs);
2857 HISTREPORT_TALLYVALUE(sleepDelaysReport,
2858 (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2859
2860 DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2861 wake2DarkwakeDelay = 0;
2862 }
2863 #if HIBERNATION
2864 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2865
2866 IOHibernateSystemHasSlept();
2867
2868 evaluateSystemSleepPolicyFinal();
2869 #else
2870 LOG("System Sleep\n");
2871 #endif
2872 if (thermalWarningState) {
2873 OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2874 if (event) {
2875 systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2876 }
2877 }
2878 assertOnWakeSecs = 0;
2879 lowBatteryCondition = false;
2880 thermalEmergencyState = false;
2881
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();
2888
2889 secs = 0;
2890 microsecs = 0;
2891 PEGetUTCTimeOfDay(&secs, &microsecs);
2892
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);
2896 }
2897 #endif
2898
2899 getPlatform()->sleepKernel();
2900
2901 // The CPU(s) are off at this point,
2902 // Code will resume execution here upon wake.
2903
2904 clock_get_uptime(&gIOLastWakeAbsTime);
2905 IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2906 _highestCapability = 0;
2907
2908 #if HIBERNATION
2909 IOHibernateSystemWake();
2910 #endif
2911
2912 // sleep transition complete
2913 gSleepOrShutdownPending = 0;
2914
2915 // trip the reset of the calendar clock
2916 clock_wakeup_calendar();
2917 clock_get_calendar_microtime(&secs, &microsecs);
2918 gIOLastWakeTime.tv_sec = secs;
2919 gIOLastWakeTime.tv_usec = microsecs;
2920
2921 // aot
2922 if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2923 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2924 secs = 0;
2925 microsecs = 0;
2926 PEGetUTCTimeOfDay(&secs, &microsecs);
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);
2936 }
2937
2938 if (_aotTestTime) {
2939 if (_aotWakeTimeUTC <= secs) {
2940 _aotTestTime = _aotTestTime + _aotTestInterval;
2941 }
2942 setWakeTime(_aotTestTime);
2943 }
2944 }
2945
2946 #if HIBERNATION
2947 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
2948 #endif
2949
2950 lastSleepReason = 0;
2951
2952 lastDebugWakeSeconds = _debugWakeSeconds;
2953 _debugWakeSeconds = 0;
2954 _scheduledAlarmMask = 0;
2955 _nextScheduledAlarmType = NULL;
2956
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;
2970
2971 #if defined(__i386__) || defined(__x86_64__)
2972 kdebugTrace(kPMLogSystemWake, 0, 0, 0);
2973
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());
2978
2979 if (wakeReason && (wakeReason->getLength() >= 2) &&
2980 gWakeReasonString[0] == '\0') {
2981 WAKEEVENT_LOCK();
2982 // Until the platform driver can claim its wake reasons
2983 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
2984 sizeof(gWakeReasonString));
2985 if (!gWakeReasonSysctlRegistered) {
2986 gWakeReasonSysctlRegistered = true;
2987 }
2988 WAKEEVENT_UNLOCK();
2989 }
2990
2991 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
2992 lowBatteryCondition = true;
2993 darkWakeMaintenance = true;
2994 } else {
2995 #if HIBERNATION
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");
3004 } else {
3005 DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3006 }
3007 } else
3008 #endif
3009 if (wakeType && (
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;
3016 }
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;
3033 #if HIBERNATION
3034 if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3035 sleepToStandby = true;
3036 }
3037 #endif
3038 } else if (wakeType &&
3039 wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3040 darkWakeMaintenance = true;
3041 darkWakeHibernateError = true;
3042 } else {
3043 // Unidentified wake source, resume to full wake if debug
3044 // alarm is pending.
3045
3046 if (lastDebugWakeSeconds &&
3047 (!wakeReason || wakeReason->isEqualTo(""))) {
3048 darkWakeExit = true;
3049 }
3050 }
3051 }
3052
3053 if (darkWakeExit) {
3054 darkWakeToSleepASAP = false;
3055 fullWakeReason = kFullWakeReasonLocalUser;
3056 reportUserInput();
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;
3063 }
3064 }
3065 #else /* !__i386__ && !__x86_64__ */
3066 timeSinceReset = ml_get_time_since_reset();
3067 kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3068
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");
3077 } else {
3078 #if HIBERNATION
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");
3084 }
3085 #endif
3086 }
3087
3088 // stay awake for at least 30 seconds
3089 startIdleSleepTimer(30);
3090 #endif
3091 sleepCnt++;
3092
3093 thread_call_enter(updateConsoleUsersEntry);
3094
3095 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3096 break;
3097 }
3098 #if !__i386__ && !__x86_64__
3099 case ON_STATE:
3100 case AOT_STATE:
3101 {
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 );
3107
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);
3115 }
3116 break;
3117 }
3118 #endif /* !__i386__ && !__x86_64__ */
3119 }
3120 notifierThread = NULL;
3121 }
3122
3123 //******************************************************************************
3124 // requestPowerDomainState
3125 //
3126 // Extend implementation in IOService. Running on PM work loop thread.
3127 //******************************************************************************
3128
3129 IOReturn
3130 IOPMrootDomain::requestPowerDomainState(
3131 IOPMPowerFlags childDesire,
3132 IOPowerConnection * childConnection,
3133 unsigned long specification )
3134 {
3135 // Idle and system sleep prevention flags affects driver desire.
3136 // Children desire are irrelevant so they are cleared.
3137
3138 return super::requestPowerDomainState(0, childConnection, specification);
3139 }
3140
3141
3142 static void
3143 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3144 {
3145 if (!preventers->getCount()) {
3146 return;
3147 }
3148
3149 char *buf_iter = buf + strlen(buf);
3150 char *buf_end = buf + buf_size;
3151
3152 OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3153 OSObject *obj = NULL;
3154
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());
3159 } else {
3160 DLOG("Print buffer exhausted for sleep preventers list\n");
3161 break;
3162 }
3163 }
3164 }
3165
3166 //******************************************************************************
3167 // updatePreventIdleSleepList
3168 //
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 //******************************************************************************
3173
3174 bool
3175 IOPMrootDomain::updatePreventIdleSleepList(
3176 IOService * service, bool addNotRemove)
3177 {
3178 unsigned int oldCount;
3179
3180 oldCount = idleSleepPreventersCount();
3181 return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3182 }
3183
3184 bool
3185 IOPMrootDomain::updatePreventIdleSleepListInternal(
3186 IOService * service, bool addNotRemove, unsigned int oldCount)
3187 {
3188 unsigned int newCount;
3189
3190 ASSERT_GATED();
3191
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)) {
3197 return false;
3198 }
3199 #endif
3200
3201 if (service) {
3202 if (addNotRemove) {
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());
3210 }
3211
3212 if (preventIdleSleepList->getCount()) {
3213 char buf[256] = "Idle Sleep Preventers:";
3214 makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3215 DLOG("%s\n", buf);
3216 }
3217 }
3218
3219 newCount = idleSleepPreventersCount();
3220
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.
3225
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.
3230
3231 changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3232 evaluatePolicy( kStimulusNoIdleSleepPreventers );
3233 }
3234 messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3235 &newCount, sizeof(newCount));
3236
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
3241 }
3242 #endif
3243
3244 return true;
3245 }
3246
3247 //******************************************************************************
3248 // startSpinDump
3249 //******************************************************************************
3250
3251 void
3252 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3253 {
3254 messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3255 }
3256
3257 //******************************************************************************
3258 // preventSystemSleepListUpdate
3259 //
3260 // Called by IOService on PM work loop.
3261 //******************************************************************************
3262
3263 void
3264 IOPMrootDomain::updatePreventSystemSleepList(
3265 IOService * service, bool addNotRemove )
3266 {
3267 unsigned int oldCount, newCount;
3268
3269 ASSERT_GATED();
3270 if (this == service) {
3271 return;
3272 }
3273
3274 oldCount = preventSystemSleepList->getCount();
3275 if (addNotRemove) {
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) {
3280 AbsoluteTime now;
3281 clock_usec_t microsecs;
3282 clock_get_uptime(&now);
3283 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3284 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
3285 if (assertOnWakeReport) {
3286 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3287 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3288 }
3289 }
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());
3294
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 );
3299 }
3300 }
3301
3302 newCount = preventSystemSleepList->getCount();
3303 if (newCount) {
3304 char buf[256] = "System Sleep Preventers:";
3305 makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3306 DLOG("%s\n", buf);
3307 }
3308
3309 messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3310 &newCount, sizeof(newCount));
3311 }
3312
3313 void
3314 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3315 {
3316 OSSharedPtr<OSCollectionIterator> iterator;
3317 OSObject *object = NULL;
3318 OSSharedPtr<OSArray> array;
3319
3320 if (!gIOPMWorkLoop->inGate()) {
3321 gIOPMWorkLoop->runAction(
3322 OSMemberFunctionCast(IOWorkLoop::Action, this,
3323 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3324 this, (void *)idleSleepList, (void *)systemSleepList);
3325 return;
3326 }
3327
3328 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3329 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3330 array = OSArray::withCapacity(5);
3331
3332 if (iterator && array) {
3333 while ((object = iterator->getNextObject())) {
3334 IOService *service = OSDynamicCast(IOService, object);
3335 if (service) {
3336 OSSharedPtr<const OSSymbol> name = service->copyName();
3337 if (name) {
3338 array->setObject(name.get());
3339 }
3340 }
3341 }
3342 }
3343 *idleSleepList = array.detach();
3344 }
3345
3346 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3347 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3348 array = OSArray::withCapacity(5);
3349
3350 if (iterator && array) {
3351 while ((object = iterator->getNextObject())) {
3352 IOService *service = OSDynamicCast(IOService, object);
3353 if (service) {
3354 OSSharedPtr<const OSSymbol> name = service->copyName();
3355 if (name) {
3356 array->setObject(name.get());
3357 }
3358 }
3359 }
3360 }
3361 *systemSleepList = array.detach();
3362 }
3363 }
3364
3365 void
3366 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3367 {
3368 OSSharedPtr<OSCollectionIterator> iterator;
3369 OSObject *object = NULL;
3370 OSSharedPtr<OSArray> array;
3371
3372 if (!gIOPMWorkLoop->inGate()) {
3373 gIOPMWorkLoop->runAction(
3374 OSMemberFunctionCast(IOWorkLoop::Action, this,
3375 &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3376 this, (void *)idleSleepList, (void *)systemSleepList);
3377 return;
3378 }
3379
3380 if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3381 iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3382 array = OSArray::withCapacity(5);
3383
3384 if (iterator && array) {
3385 while ((object = iterator->getNextObject())) {
3386 IOService *service = OSDynamicCast(IOService, object);
3387 if (service) {
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());
3395 }
3396 }
3397 }
3398 }
3399 *idleSleepList = array.detach();
3400 }
3401
3402 if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3403 iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3404 array = OSArray::withCapacity(5);
3405
3406 if (iterator && array) {
3407 while ((object = iterator->getNextObject())) {
3408 IOService *service = OSDynamicCast(IOService, object);
3409 if (service) {
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());
3417 }
3418 }
3419 }
3420 }
3421 *systemSleepList = array.detach();
3422 }
3423 }
3424
3425 //******************************************************************************
3426 // tellChangeDown
3427 //
3428 // Override the superclass implementation to send a different message type.
3429 //******************************************************************************
3430
3431 bool
3432 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3433 {
3434 DLOG("tellChangeDown %s->%s\n",
3435 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3436
3437 if (SLEEP_STATE == stateNum) {
3438 // Legacy apps were already told in the full->dark transition
3439 if (!ignoreTellChangeDown) {
3440 tracePoint( kIOPMTracePointSleepApplications );
3441 } else {
3442 tracePoint( kIOPMTracePointSleepPriorityClients );
3443 }
3444 }
3445
3446 if (!ignoreTellChangeDown) {
3447 userActivityAtSleep = userActivityCount;
3448 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3449
3450 if (SLEEP_STATE == stateNum) {
3451 hibernateAborted = false;
3452
3453 // Direct callout into OSKext so it can disable kext unloads
3454 // during sleep/wake to prevent deadlocks.
3455 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3456
3457 IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3458
3459 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3460 // But tellClientsWithResponse() must be called for both.
3461 ignoreTellChangeDown = true;
3462 }
3463 }
3464
3465 return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3466 }
3467
3468 //******************************************************************************
3469 // askChangeDown
3470 //
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 //******************************************************************************
3474
3475 bool
3476 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3477 {
3478 DLOG("askChangeDown %s->%s\n",
3479 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3480
3481 // Don't log for dark wake entry
3482 if (kSystemTransitionSleep == _systemTransitionType) {
3483 tracePoint( kIOPMTracePointSleepApplications );
3484 }
3485
3486 return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3487 }
3488
3489 //******************************************************************************
3490 // askChangeDownDone
3491 //
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.
3495 //
3496 // Idle sleep:
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()
3503 //
3504 // Demand sleep:
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 //******************************************************************************
3512
3513 void
3514 IOPMrootDomain::askChangeDownDone(
3515 IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3516 {
3517 DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3518 *inOutChangeFlags, *cancel,
3519 _systemTransitionType,
3520 _currentCapability, _pendingCapability);
3521
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()
3526
3527 if (!checkSystemCanSleep(lastSleepReason)) {
3528 // Cancel dark wake to sleep transition.
3529 // Must re-scan assertions upon entering dark wake.
3530
3531 *cancel = true;
3532 DLOG("cancel dark->sleep\n");
3533 }
3534 if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3535 uint64_t now = mach_continuous_time();
3536 if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3537 && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3538 *cancel = true;
3539 IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3540 }
3541 }
3542 }
3543 }
3544
3545 //******************************************************************************
3546 // systemDidNotSleep
3547 //
3548 // Work common to both canceled or aborted sleep.
3549 //******************************************************************************
3550
3551 void
3552 IOPMrootDomain::systemDidNotSleep( void )
3553 {
3554 // reset console lock state
3555 thread_call_enter(updateConsoleUsersEntry);
3556
3557 if (idleSleepEnabled) {
3558 if (!wrangler) {
3559 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3560 startIdleSleepTimer(kIdleSleepRetryInterval);
3561 #else
3562 startIdleSleepTimer(idleSeconds);
3563 #endif
3564 } else if (!userIsActive) {
3565 // Manually start the idle sleep timer besides waiting for
3566 // the user to become inactive.
3567 startIdleSleepTimer(kIdleSleepRetryInterval);
3568 }
3569 }
3570
3571 preventTransitionToUserActive(false);
3572 IOService::setAdvisoryTickleEnable( true );
3573
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.
3577
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.
3583
3584 IOPMSystemCapabilityChangeParameters params;
3585
3586 bzero(&params, sizeof(params));
3587 params.fromCapabilities = _pendingCapability;
3588 params.toCapabilities = _currentCapability;
3589 params.changeFlags = kIOPMSystemCapabilityDidChange;
3590
3591 DLOG("MESG cap %x->%x did change\n",
3592 params.fromCapabilities, params.toCapabilities);
3593 messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3594 &params, sizeof(params));
3595 }
3596 }
3597
3598 //******************************************************************************
3599 // tellNoChangeDown
3600 //
3601 // Notify registered applications and kernel clients that we are not dropping
3602 // power.
3603 //
3604 // We override the superclass implementation so we can send a different message
3605 // type to the client or application being notified.
3606 //
3607 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3608 //******************************************************************************
3609
3610 void
3611 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3612 {
3613 DLOG("tellNoChangeDown %s->%s\n",
3614 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3615
3616 // Sleep canceled, clear the sleep trace point.
3617 tracePoint(kIOPMTracePointSystemUp);
3618
3619 systemDidNotSleep();
3620 return tellClients( kIOMessageSystemWillNotSleep );
3621 }
3622
3623 //******************************************************************************
3624 // tellChangeUp
3625 //
3626 // Notify registered applications and kernel clients that we are raising power.
3627 //
3628 // We override the superclass implementation so we can send a different message
3629 // type to the client or application being notified.
3630 //******************************************************************************
3631
3632 void
3633 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3634 {
3635 DLOG("tellChangeUp %s->%s\n",
3636 getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3637
3638 ignoreTellChangeDown = false;
3639
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 );
3644
3645 // Notify platform that sleep was cancelled or resumed.
3646 getPlatform()->callPlatformFunction(
3647 sleepMessagePEFunction.get(), false,
3648 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3649 NULL, NULL, NULL);
3650
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;
3665 }
3666
3667 systemDidNotSleep();
3668 tellClients( kIOMessageSystemWillPowerOn );
3669 }
3670
3671 tracePoint( kIOPMTracePointWakeApplications );
3672 tellClients( kIOMessageSystemHasPoweredOn );
3673 }
3674 }
3675
3676 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3677 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3678 ((params)->fromCapabilities & (flag)) && \
3679 (((params)->toCapabilities & (flag)) == 0))
3680
3681 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3682 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3683 ((params)->toCapabilities & (flag)) && \
3684 (((params)->fromCapabilities & (flag)) == 0))
3685
3686 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3687 (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3688 ((params)->fromCapabilities & (flag)) && \
3689 (((params)->toCapabilities & (flag)) == 0))
3690
3691 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3692 (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3693 ((params)->toCapabilities & (flag)) && \
3694 (((params)->fromCapabilities & (flag)) == 0))
3695
3696 //******************************************************************************
3697 // sysPowerDownHandler
3698 //
3699 // Perform a vfs sync before system sleep.
3700 //******************************************************************************
3701
3702 IOReturn
3703 IOPMrootDomain::sysPowerDownHandler(
3704 void * target, void * refCon,
3705 UInt32 messageType, IOService * service,
3706 void * messageArgs, vm_size_t argSize )
3707 {
3708 static UInt32 lastSystemMessageType = 0;
3709 IOReturn ret = 0;
3710
3711 DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3712
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);
3722 break;
3723 case kIOMessageSystemHasPoweredOn:
3724 assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3725 break;
3726 }
3727
3728 lastSystemMessageType = messageType;
3729 }
3730
3731 if (!gRootDomain) {
3732 return kIOReturnUnsupported;
3733 }
3734
3735 if (messageType == kIOMessageSystemCapabilityChange) {
3736 IOPMSystemCapabilityChangeParameters * params =
3737 (IOPMSystemCapabilityChangeParameters *) messageArgs;
3738
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
3742 // down.
3743 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3744 // via callout
3745
3746 DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3747 params->fromCapabilities, params->toCapabilities,
3748 params->changeFlags);
3749
3750 if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3751 // We will ack within 20 seconds
3752 params->maxWaitForReply = 20 * 1000 * 1000;
3753
3754 #if HIBERNATION
3755 gRootDomain->evaluateSystemSleepPolicyEarly();
3756
3757 // add in time we could spend freeing pages
3758 if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3759 params->maxWaitForReply = kCapabilityClientMaxWait;
3760 }
3761 DLOG("sysPowerDownHandler max wait %d s\n",
3762 (int) (params->maxWaitForReply / 1000 / 1000));
3763 #endif
3764
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,
3770 NULL, NULL, NULL);
3771
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
3775 // ack timeout...
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,
3781 deadline );
3782 } else {
3783 thread_call_enter1(
3784 gRootDomain->diskSyncCalloutEntry,
3785 (thread_call_param_t)(uintptr_t) params->notifyRef);
3786 }
3787 }
3788 #if HIBERNATION
3789 else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3790 // We will ack within 110 seconds
3791 params->maxWaitForReply = 110 * 1000 * 1000;
3792
3793 thread_call_enter1(
3794 gRootDomain->diskSyncCalloutEntry,
3795 (thread_call_param_t)(uintptr_t) params->notifyRef);
3796 }
3797 #endif
3798 ret = kIOReturnSuccess;
3799 }
3800
3801 return ret;
3802 }
3803
3804 //******************************************************************************
3805 // handleQueueSleepWakeUUID
3806 //
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
3811 // sleep/wake.
3812 //
3813 // @param obj has a retain on it. We're responsible for releasing that retain.
3814 //******************************************************************************
3815
3816 void
3817 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3818 {
3819 OSSharedPtr<OSString> str;
3820
3821 if (kOSBooleanFalse == obj) {
3822 handlePublishSleepWakeUUID(false);
3823 } else {
3824 str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3825 if (str) {
3826 // This branch caches the UUID for an upcoming sleep/wake
3827 queuedSleepWakeUUIDString = str;
3828 DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3829 }
3830 }
3831 }
3832 //******************************************************************************
3833 // handlePublishSleepWakeUUID
3834 //
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
3839 // sleep/wake.
3840 //******************************************************************************
3841
3842 void
3843 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3844 {
3845 ASSERT_GATED();
3846
3847 /*
3848 * Clear the current UUID
3849 */
3850 if (gSleepWakeUUIDIsSet) {
3851 DLOG("SleepWake UUID cleared\n");
3852
3853 gSleepWakeUUIDIsSet = false;
3854
3855 removeProperty(kIOPMSleepWakeUUIDKey);
3856 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3857 }
3858
3859 /*
3860 * Optionally, publish a new UUID
3861 */
3862 if (queuedSleepWakeUUIDString && shouldPublish) {
3863 OSSharedPtr<OSString> publishThisUUID;
3864
3865 publishThisUUID = queuedSleepWakeUUIDString;
3866
3867 if (publishThisUUID) {
3868 setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3869 }
3870
3871 gSleepWakeUUIDIsSet = true;
3872 messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3873
3874 queuedSleepWakeUUIDString.reset();
3875 }
3876 }
3877
3878 //******************************************************************************
3879 // IOPMGetSleepWakeUUIDKey
3880 //
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 //******************************************************************************
3886
3887 extern "C" bool
3888 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3889 {
3890 if (!gSleepWakeUUIDIsSet) {
3891 return false;
3892 }
3893
3894 if (buffer != NULL) {
3895 OSSharedPtr<OSString> string =
3896 OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3897
3898 if (!string) {
3899 *buffer = '\0';
3900 } else {
3901 strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3902 }
3903 }
3904
3905 return true;
3906 }
3907
3908 //******************************************************************************
3909 // lowLatencyAudioNotify
3910 //
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 //******************************************************************************
3915
3916 void
3917 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
3918 {
3919 if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
3920 lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
3921 lowLatencyAudioNotifyTimestampVal->setValue(time);
3922 lowLatencyAudioNotifyStateVal->setValue(state);
3923 setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
3924 } else {
3925 DLOG("LowLatencyAudioNotify error\n");
3926 }
3927 return;
3928 }
3929
3930 //******************************************************************************
3931 // IOPMrootDomainRTNotifier
3932 //
3933 // Used by performance controller to update the timestamp and state associated
3934 // with low latency audio activity in the system.
3935 //******************************************************************************
3936
3937 extern "C" void
3938 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
3939 {
3940 gRootDomain->lowLatencyAudioNotify(time, state);
3941 return;
3942 }
3943
3944 //******************************************************************************
3945 // initializeBootSessionUUID
3946 //
3947 // Initialize the boot session uuid at boot up and sets it into registry.
3948 //******************************************************************************
3949
3950 void
3951 IOPMrootDomain::initializeBootSessionUUID(void)
3952 {
3953 uuid_t new_uuid;
3954 uuid_string_t new_uuid_string;
3955
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));
3959
3960 setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
3961 }
3962
3963 //******************************************************************************
3964 // Root domain uses the private and tagged changePowerState methods for
3965 // tracking and logging purposes.
3966 //******************************************************************************
3967
3968 #define REQUEST_TAG_TO_REASON(x) ((uint16_t)x)
3969
3970 static uint32_t
3971 nextRequestTag( IOPMRequestTag tag )
3972 {
3973 static SInt16 msb16 = 1;
3974 uint16_t id = OSAddAtomic16(1, &msb16);
3975 return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
3976 }
3977
3978 // TODO: remove this shim function and exported symbol
3979 IOReturn
3980 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
3981 {
3982 return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
3983 }
3984
3985 // TODO: remove this shim function and exported symbol
3986 IOReturn
3987 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
3988 {
3989 return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
3990 }
3991
3992 IOReturn
3993 IOPMrootDomain::changePowerStateWithOverrideTo(
3994 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
3995 {
3996 uint32_t tag = nextRequestTag(reason);
3997 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
3998
3999 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4000 return kIOReturnUnsupported;
4001 }
4002
4003 return super::changePowerStateWithOverrideTo(ordinal, tag);
4004 }
4005
4006 IOReturn
4007 IOPMrootDomain::changePowerStateWithTagTo(
4008 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4009 {
4010 uint32_t tag = nextRequestTag(reason);
4011 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4012
4013 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4014 return kIOReturnUnsupported;
4015 }
4016
4017 return super::changePowerStateWithTagTo(ordinal, tag);
4018 }
4019
4020 IOReturn
4021 IOPMrootDomain::changePowerStateWithTagToPriv(
4022 IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4023 {
4024 uint32_t tag = nextRequestTag(reason);
4025 DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4026
4027 if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4028 return kIOReturnUnsupported;
4029 }
4030
4031 return super::changePowerStateWithTagToPriv(ordinal, tag);
4032 }
4033
4034 //******************************************************************************
4035 // activity detect
4036 //
4037 //******************************************************************************
4038
4039 bool
4040 IOPMrootDomain::activitySinceSleep(void)
4041 {
4042 return userActivityCount != userActivityAtSleep;
4043 }
4044
4045 bool
4046 IOPMrootDomain::abortHibernation(void)
4047 {
4048 #if __arm64__
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
4052 return false;
4053 #else
4054 bool ret = activitySinceSleep();
4055
4056 if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4057 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4058 hibernateAborted = true;
4059 }
4060 return ret;
4061 #endif
4062 }
4063
4064 extern "C" int
4065 hibernate_should_abort(void)
4066 {
4067 if (gRootDomain) {
4068 return gRootDomain->abortHibernation();
4069 } else {
4070 return 0;
4071 }
4072 }
4073
4074 //******************************************************************************
4075 // willNotifyPowerChildren
4076 //
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 //******************************************************************************
4082
4083 void
4084 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4085 {
4086 OSSharedPtr<OSDictionary> dict;
4087 OSSharedPtr<OSNumber> secs;
4088
4089 if (SLEEP_STATE == newPowerState) {
4090 notifierThread = current_thread();
4091 if (!tasksSuspended) {
4092 AbsoluteTime deadline;
4093 tasksSuspended = TRUE;
4094 updateTasksSuspend();
4095
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) */
4100 }
4101
4102 _aotReadyToFullWake = false;
4103 #if 0
4104 if (_aotLingerTime) {
4105 uint64_t deadline;
4106 IOLog("aot linger no return\n");
4107 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4108 clock_delay_until(deadline);
4109 }
4110 #endif
4111 if (!_aotMode) {
4112 _aotTestTime = 0;
4113 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4114 if (_aotMetrics) {
4115 bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4116 }
4117 } else if (!_aotNow && !_debugWakeSeconds) {
4118 _aotNow = true;
4119 _aotExit = false;
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);
4128 }
4129 uint32_t lingerSecs;
4130 if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4131 lingerSecs = 0;
4132 }
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);
4136 }
4137
4138 #if HIBERNATION
4139 IOHibernateSystemSleep();
4140 IOHibernateIOKitSleep();
4141 #endif
4142 if (gRootDomain->activitySinceSleep()) {
4143 dict = OSDictionary::withCapacity(1);
4144 secs = OSNumber::withNumber(1, 32);
4145
4146 if (dict && secs) {
4147 dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4148 gRootDomain->setProperties(dict.get());
4149 MSG("Reverting sleep with relative wake\n");
4150 }
4151 }
4152
4153 notifierThread = NULL;
4154 }
4155 }
4156
4157 //******************************************************************************
4158 // willTellSystemCapabilityDidChange
4159 //
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 //******************************************************************************
4164
4165 void
4166 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4167 {
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.
4177 //
4178 // Last opportunity to exit dark wake using:
4179 // requestFullWake( kFullWakeReasonLocalUser );
4180
4181 if (!darkWakePowerClamped) {
4182 if (darkWakeLogClamp) {
4183 AbsoluteTime now;
4184 uint64_t nsec;
4185
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)));
4191 }
4192 darkWakePowerClamped = true;
4193 }
4194 }
4195 }
4196
4197 //******************************************************************************
4198 // sleepOnClamshellClosed
4199 //
4200 // contains the logic to determine if the system should sleep when the clamshell
4201 // is closed.
4202 //******************************************************************************
4203
4204 bool
4205 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4206 {
4207 if (!clamshellExists) {
4208 return false;
4209 }
4210
4211 DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4212 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4213
4214 return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4215 }
4216
4217 bool
4218 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4219 {
4220 // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4221 // closed && battery
4222 if (!clamshellExists) {
4223 return false;
4224 }
4225
4226 DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4227 clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4228
4229 return !acAdaptorConnected && !clamshellSleepDisableMask;
4230 }
4231
4232 void
4233 IOPMrootDomain::sendClientClamshellNotification( void )
4234 {
4235 /* Only broadcast clamshell alert if clamshell exists. */
4236 if (!clamshellExists) {
4237 return;
4238 }
4239
4240 setProperty(kAppleClamshellStateKey,
4241 clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4242
4243 setProperty(kAppleClamshellCausesSleepKey,
4244 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4245
4246 /* Argument to message is a bitfiel of
4247 * ( kClamshellStateBit | kClamshellSleepBit )
4248 */
4249 messageClients(kIOPMMessageClamshellStateChange,
4250 (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4251 | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4252 }
4253
4254 //******************************************************************************
4255 // getSleepSupported
4256 //
4257 // Deprecated
4258 //******************************************************************************
4259
4260 IOOptionBits
4261 IOPMrootDomain::getSleepSupported( void )
4262 {
4263 return platformSleepSupport;
4264 }
4265
4266 //******************************************************************************
4267 // setSleepSupported
4268 //
4269 // Deprecated
4270 //******************************************************************************
4271
4272 void
4273 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4274 {
4275 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4276 OSBitOrAtomic(flags, &platformSleepSupport);
4277 }
4278
4279 //******************************************************************************
4280 // setClamShellSleepDisable
4281 //
4282 //******************************************************************************
4283
4284 void
4285 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4286 {
4287 uint32_t oldMask;
4288
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),
4294 (OSObject *) this,
4295 (void *) disable, (void *)(uintptr_t) bitmask);
4296 return;
4297 }
4298
4299 oldMask = clamshellSleepDisableMask;
4300 if (disable) {
4301 clamshellSleepDisableMask |= bitmask;
4302 } else {
4303 clamshellSleepDisableMask &= ~bitmask;
4304 }
4305 DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4306
4307 if (clamshellExists && clamshellClosed &&
4308 (clamshellSleepDisableMask != oldMask) &&
4309 (clamshellSleepDisableMask == 0)) {
4310 handlePowerNotification(kLocalEvalClamshellCommand);
4311 }
4312 }
4313
4314 //******************************************************************************
4315 // wakeFromDoze
4316 //
4317 // Deprecated.
4318 //******************************************************************************
4319
4320 void
4321 IOPMrootDomain::wakeFromDoze( void )
4322 {
4323 // Preserve symbol for familes (IOUSBFamily and IOGraphics)
4324 }
4325
4326 //******************************************************************************
4327 // recordRTCAlarm
4328 //
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.
4334 //
4335 // Caller serialized using settingsCtrlLock.
4336 //******************************************************************************
4337
4338 void
4339 IOPMrootDomain::recordRTCAlarm(
4340 const OSSymbol *type,
4341 OSObject *object )
4342 {
4343 uint32_t previousAlarmMask = _scheduledAlarmMask;
4344
4345 if (type == gIOPMSettingDebugWakeRelativeKey) {
4346 OSNumber * n = OSDynamicCast(OSNumber, object);
4347 if (n) {
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;
4353
4354 _debugWakeSeconds = debugSecs;
4355 OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4356 DLOG("next alarm (%s) in %u secs\n",
4357 type->getCStringNoCopy(), debugSecs);
4358 }
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;
4366 clock_sec_t secs;
4367
4368 cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4369 secs = IOPMConvertCalendarToSeconds(cs);
4370 DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4371
4372 // Update the next scheduled alarm type
4373 if ((_nextScheduledAlarmType == NULL) ||
4374 ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4375 (secs < _nextScheduledAlarmUTC))) {
4376 replaceNextAlarm = true;
4377 }
4378
4379 if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4380 if (cs->year) {
4381 _calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4382 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4383 } else {
4384 // TODO: can this else-block be removed?
4385 _calendarWakeAlarmUTC = 0;
4386 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4387 }
4388 }
4389 if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4390 OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4391 }
4392 if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4393 OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4394 }
4395
4396 if (replaceNextAlarm) {
4397 _nextScheduledAlarmType.reset(type, OSRetain);
4398 _nextScheduledAlarmUTC = secs;
4399 DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4400 }
4401 }
4402 }
4403
4404 if (_scheduledAlarmMask != previousAlarmMask) {
4405 DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4406 }
4407 }
4408
4409 // MARK: -
4410 // MARK: Features
4411
4412 //******************************************************************************
4413 // publishFeature
4414 //
4415 // Adds a new feature to the supported features dictionary
4416 //******************************************************************************
4417
4418 void
4419 IOPMrootDomain::publishFeature( const char * feature )
4420 {
4421 publishFeature(feature, kRD_AllPowerSources, NULL);
4422 }
4423
4424 //******************************************************************************
4425 // publishFeature (with supported power source specified)
4426 //
4427 // Adds a new feature to the supported features dictionary
4428 //******************************************************************************
4429
4430 void
4431 IOPMrootDomain::publishFeature(
4432 const char *feature,
4433 uint32_t supportedWhere,
4434 uint32_t *uniqueFeatureID)
4435 {
4436 static uint16_t next_feature_id = 500;
4437
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;
4444
4445 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4446
4447 if (!supportedWhere) {
4448 // Feature isn't supported anywhere!
4449 return;
4450 }
4451
4452 if (next_feature_id > 5000) {
4453 // Far, far too many features!
4454 return;
4455 }
4456
4457 if (featuresDictLock) {
4458 IOLockLock(featuresDictLock);
4459 }
4460
4461 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4462 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4463 OSSharedPtr<OSDictionary> features;
4464
4465 // Create new features dict if necessary
4466 if (origFeatures) {
4467 features = OSDictionary::withDictionary(origFeatures);
4468 } else {
4469 features = OSDictionary::withCapacity(1);
4470 }
4471
4472 // Create OSNumber to track new feature
4473
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;
4480 }
4481
4482 feature_value = (uint32_t)next_feature_id;
4483 feature_value <<= 16;
4484 feature_value += supportedWhere;
4485
4486 new_feature_data = OSNumber::withNumber(
4487 (unsigned long long)feature_value, 32);
4488
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);
4500 }
4501
4502 if (existing_feature_arr) {
4503 existing_feature_arr->setObject(new_feature_data.get());
4504 features->setObject(feature, existing_feature_arr.get());
4505 }
4506 } else {
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());
4510 }
4511
4512 setProperty(kRootDomainSupportedFeatures, features.get());
4513
4514 if (featuresDictLock) {
4515 IOLockUnlock(featuresDictLock);
4516 }
4517
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 );
4522 }
4523 }
4524
4525 //******************************************************************************
4526 // removePublishedFeature
4527 //
4528 // Removes previously published feature
4529 //******************************************************************************
4530
4531 IOReturn
4532 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4533 {
4534 IOReturn ret = kIOReturnError;
4535 uint32_t feature_value = 0;
4536 uint16_t feature_id = 0;
4537 bool madeAChange = false;
4538
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;
4546
4547 if (kBadPMFeatureID == removeFeatureID) {
4548 return kIOReturnNotFound;
4549 }
4550
4551 if (featuresDictLock) {
4552 IOLockLock(featuresDictLock);
4553 }
4554
4555 OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4556 OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4557 OSSharedPtr<OSDictionary> features;
4558
4559 if (origFeatures) {
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);
4564 } else {
4565 features = NULL;
4566 ret = kIOReturnNotFound;
4567 goto exit;
4568 }
4569
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.
4573
4574 dictIterator = OSCollectionIterator::withCollection(features.get());
4575 if (!dictIterator) {
4576 goto exit;
4577 }
4578
4579 while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4580 osObj = features->getObject(dictKey);
4581
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);
4586
4587 if (feature_id == (uint16_t)removeFeatureID) {
4588 // Remove this node
4589 features->removeObject(dictKey);
4590 madeAChange = true;
4591 break;
4592 }
4593
4594 // Or tracked by an OSArray of OSNumbers
4595 } else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4596 unsigned int arrayCount = arrayMember->getCount();
4597
4598 for (unsigned int i = 0; i < arrayCount; i++) {
4599 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4600 if (!osNum) {
4601 continue;
4602 }
4603
4604 feature_value = osNum->unsigned32BitValue();
4605 feature_id = (uint16_t)(feature_value >> 16);
4606
4607 if (feature_id == (uint16_t)removeFeatureID) {
4608 // Remove this node
4609 if (1 == arrayCount) {
4610 // If the array only contains one element, remove
4611 // the whole thing.
4612 features->removeObject(dictKey);
4613 } else {
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());
4619 }
4620 }
4621
4622 madeAChange = true;
4623 break;
4624 }
4625 }
4626 }
4627 }
4628
4629 if (madeAChange) {
4630 ret = kIOReturnSuccess;
4631
4632 setProperty(kRootDomainSupportedFeatures, features.get());
4633
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 );
4638 }
4639 } else {
4640 ret = kIOReturnNotFound;
4641 }
4642
4643 exit:
4644 if (featuresDictLock) {
4645 IOLockUnlock(featuresDictLock);
4646 }
4647 return ret;
4648 }
4649
4650 //******************************************************************************
4651 // publishPMSetting (private)
4652 //
4653 // Should only be called by PMSettingObject to publish a PM Setting as a
4654 // supported feature.
4655 //******************************************************************************
4656
4657 void
4658 IOPMrootDomain::publishPMSetting(
4659 const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4660 {
4661 if (noPublishPMSettings &&
4662 (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4663 // Setting found in noPublishPMSettings array
4664 *featureID = kBadPMFeatureID;
4665 return;
4666 }
4667
4668 publishFeature(
4669 feature->getCStringNoCopy(), where, featureID);
4670 }
4671
4672 //******************************************************************************
4673 // setPMSetting (private)
4674 //
4675 // Internal helper to relay PM settings changes from user space to individual
4676 // drivers. Should be called only by IOPMrootDomain::setProperties.
4677 //******************************************************************************
4678
4679 IOReturn
4680 IOPMrootDomain::setPMSetting(
4681 const OSSymbol *type,
4682 OSObject *object )
4683 {
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;
4690 bool ok = false;
4691 IOReturn ret;
4692
4693 if (NULL == type) {
4694 return kIOReturnBadArgument;
4695 }
4696
4697 PMSETTING_LOCK();
4698
4699 // Update settings dict so changes are visible from copyPMSetting().
4700 fPMSettingsDict->setObject(type, object);
4701
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)) {
4705 goto unlock_exit;
4706 }
4707
4708 // Array to retain PMSetting objects targeted for callout.
4709 chosen = OSArray::withCapacity(capacity);
4710 if (!chosen) {
4711 goto unlock_exit; // error
4712 }
4713 entries = IONew(PMSettingCallEntry, capacity);
4714 if (!entries) {
4715 goto unlock_exit; // error
4716 }
4717 memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4718
4719 thisThread = current_thread();
4720
4721 for (i = 0, j = 0; i < capacity; i++) {
4722 pmso = (PMSettingObject *) array->getObject(i);
4723 if (pmso->disabled) {
4724 continue;
4725 }
4726 entries[j].thread = thisThread;
4727 queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4728 chosen->setObject(pmso);
4729 j++;
4730 }
4731 count = j;
4732 if (!count) {
4733 goto unlock_exit;
4734 }
4735
4736 PMSETTING_UNLOCK();
4737
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
4744 ok = true;
4745 #if DEVELOPMENT || DEBUG
4746 } else {
4747 // Log the handler and kext that failed
4748 OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4749 if (kextName) {
4750 DLOG("PMSetting(%s) error 0x%x from %s\n",
4751 type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4752 }
4753 #endif
4754 }
4755 }
4756
4757 PMSETTING_LOCK();
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);
4763 }
4764 }
4765
4766 if (ok) {
4767 recordRTCAlarm(type, object);
4768 }
4769 unlock_exit:
4770 PMSETTING_UNLOCK();
4771
4772 if (entries) {
4773 IODelete(entries, PMSettingCallEntry, capacity);
4774 }
4775
4776 return kIOReturnSuccess;
4777 }
4778
4779 //******************************************************************************
4780 // copyPMSetting (public)
4781 //
4782 // Allows kexts to safely read setting values, without being subscribed to
4783 // notifications.
4784 //******************************************************************************
4785
4786 OSSharedPtr<OSObject>
4787 IOPMrootDomain::copyPMSetting(
4788 OSSymbol *whichSetting)
4789 {
4790 OSSharedPtr<OSObject> obj;
4791
4792 if (!whichSetting) {
4793 return NULL;
4794 }
4795
4796 PMSETTING_LOCK();
4797 obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4798 PMSETTING_UNLOCK();
4799
4800 return obj;
4801 }
4802
4803 //******************************************************************************
4804 // registerPMSettingController (public)
4805 //
4806 // direct wrapper to registerPMSettingController with uint32_t power source arg
4807 //******************************************************************************
4808
4809 IOReturn
4810 IOPMrootDomain::registerPMSettingController(
4811 const OSSymbol * settings[],
4812 IOPMSettingControllerCallback func,
4813 OSObject *target,
4814 uintptr_t refcon,
4815 OSObject **handle)
4816 {
4817 return registerPMSettingController(
4818 settings,
4819 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4820 func, target, refcon, handle);
4821 }
4822
4823 //******************************************************************************
4824 // registerPMSettingController (public)
4825 //
4826 // Kexts may register for notifications when a particular setting is changed.
4827 // A list of settings is available in IOPM.h.
4828 // Arguments:
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
4839 // Returns:
4840 // kIOReturnSuccess on success
4841 //******************************************************************************
4842
4843 IOReturn
4844 IOPMrootDomain::registerPMSettingController(
4845 const OSSymbol * settings[],
4846 uint32_t supportedPowerSources,
4847 IOPMSettingControllerCallback func,
4848 OSObject *target,
4849 uintptr_t refcon,
4850 OSObject **handle)
4851 {
4852 PMSettingObject *pmso = NULL;
4853 OSObject *pmsh = NULL;
4854 int i;
4855
4856 if (NULL == settings ||
4857 NULL == func ||
4858 NULL == handle) {
4859 return kIOReturnBadArgument;
4860 }
4861
4862 pmso = PMSettingObject::pmSettingObject(
4863 (IOPMrootDomain *) this, func, target,
4864 refcon, supportedPowerSources, settings, &pmsh);
4865
4866 if (!pmso) {
4867 *handle = NULL;
4868 return kIOReturnInternalError;
4869 }
4870
4871 PMSETTING_LOCK();
4872 for (i = 0; settings[i]; i++) {
4873 OSSharedPtr<OSArray> newList;
4874 OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4875 if (!list) {
4876 // New array of callbacks for this setting
4877 newList = OSArray::withCapacity(1);
4878 settingsCallbacks->setObject(settings[i], newList.get());
4879 list = newList.get();
4880 }
4881
4882 // Add caller to the callback list
4883 list->setObject(pmso);
4884 }
4885 PMSETTING_UNLOCK();
4886
4887 // Return handle to the caller, the setting object is private.
4888 *handle = pmsh;
4889
4890 return kIOReturnSuccess;
4891 }
4892
4893 //******************************************************************************
4894 // deregisterPMSettingObject (private)
4895 //
4896 // Only called from PMSettingObject.
4897 //******************************************************************************
4898
4899 void
4900 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
4901 {
4902 thread_t thisThread = current_thread();
4903 PMSettingCallEntry *callEntry;
4904 OSSharedPtr<OSCollectionIterator> iter;
4905 OSSymbol *sym;
4906 OSArray *array;
4907 int index;
4908 bool wait;
4909
4910 PMSETTING_LOCK();
4911
4912 pmso->disabled = true;
4913
4914 // Wait for all callout threads to finish.
4915 do {
4916 wait = false;
4917 queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
4918 {
4919 if (callEntry->thread != thisThread) {
4920 wait = true;
4921 break;
4922 }
4923 }
4924 if (wait) {
4925 assert(NULL == pmso->waitThread);
4926 pmso->waitThread = thisThread;
4927 PMSETTING_WAIT(pmso);
4928 pmso->waitThread = NULL;
4929 }
4930 } while (wait);
4931
4932 // Search each PM settings array in the kernel.
4933 iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
4934 if (iter) {
4935 while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
4936 array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
4937 index = array->getNextIndexOfObject(pmso, 0);
4938 if (-1 != index) {
4939 array->removeObject(index);
4940 }
4941 }
4942 }
4943
4944 PMSETTING_UNLOCK();
4945
4946 pmso->release();
4947 }
4948
4949 //******************************************************************************
4950 // informCPUStateChange
4951 //
4952 // Call into PM CPU code so that CPU power savings may dynamically adjust for
4953 // running on battery, with the lid closed, etc.
4954 //
4955 // informCPUStateChange is a no-op on non x86 systems
4956 // only x86 has explicit support in the IntelCPUPowerManagement kext
4957 //******************************************************************************
4958
4959 void
4960 IOPMrootDomain::informCPUStateChange(
4961 uint32_t type,
4962 uint32_t value )
4963 {
4964 #if defined(__i386__) || defined(__x86_64__)
4965
4966 pmioctlVariableInfo_t varInfoStruct;
4967 int pmCPUret = 0;
4968 const char *varNameStr = NULL;
4969 int32_t *varIndex = NULL;
4970
4971 if (kInformAC == type) {
4972 varNameStr = kIOPMRootDomainBatPowerCString;
4973 varIndex = &idxPMCPULimitedPower;
4974 } else if (kInformLid == type) {
4975 varNameStr = kIOPMRootDomainLidCloseCString;
4976 varIndex = &idxPMCPUClamshell;
4977 } else {
4978 return;
4979 }
4980
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));
4991
4992 // Set!
4993 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
4994
4995 // pmCPU only assigns numerical id's when a new varName is specified
4996 if ((0 == pmCPUret)
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 );
5001
5002 if (0 == pmCPUret) {
5003 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5004 *varIndex = varInfoStruct.varID;
5005 }
5006 }
5007
5008 return;
5009
5010 #endif /* __i386__ || __x86_64__ */
5011 }
5012
5013 // MARK: -
5014 // MARK: Deep Sleep Policy
5015
5016 #if HIBERNATION
5017
5018 //******************************************************************************
5019 // evaluateSystemSleepPolicy
5020 //******************************************************************************
5021
5022 #define kIOPlatformSystemSleepPolicyKey "IOPlatformSystemSleepPolicy"
5023
5024 // Sleep flags
5025 enum {
5026 kIOPMSleepFlagHibernate = 0x00000001,
5027 kIOPMSleepFlagSleepTimerEnable = 0x00000002
5028 };
5029
5030 struct IOPMSystemSleepPolicyEntry {
5031 uint32_t factorMask;
5032 uint32_t factorBits;
5033 uint32_t sleepFlags;
5034 uint32_t wakeEvents;
5035 } __attribute__((packed));
5036
5037 struct IOPMSystemSleepPolicyTable {
5038 uint32_t signature;
5039 uint16_t version;
5040 uint16_t entryCount;
5041 IOPMSystemSleepPolicyEntry entries[];
5042 } __attribute__((packed));
5043
5044 enum {
5045 kIOPMSleepAttributeHibernateSetup = 0x00000001,
5046 kIOPMSleepAttributeHibernateSleep = 0x00000002
5047 };
5048
5049 static uint32_t
5050 getSleepTypeAttributes( uint32_t sleepType )
5051 {
5052 static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5053 {
5054 /* invalid */ 0,
5055 /* abort */ 0,
5056 /* normal */ 0,
5057 /* safesleep */ kIOPMSleepAttributeHibernateSetup,
5058 /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5059 /* standby */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5060 /* poweroff */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5061 /* deepidle */ 0
5062 };
5063
5064 if (sleepType >= kIOPMSleepTypeLast) {
5065 return 0;
5066 }
5067
5068 return sleepTypeAttributes[sleepType];
5069 }
5070
5071 bool
5072 IOPMrootDomain::evaluateSystemSleepPolicy(
5073 IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5074 {
5075 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5076
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 ),
5100 { 0, NULL }
5101 };
5102
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;
5112 uint32_t mismatch;
5113 bool standbyEnabled;
5114 bool powerOffEnabled;
5115 bool found = false;
5116
5117 // Get platform's sleep policy table
5118 if (!gSleepPolicyHandler) {
5119 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5120 if (!prop) {
5121 goto done;
5122 }
5123 }
5124
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;
5132 }
5133 if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5134 standbyTimer = standbyDelay;
5135 }
5136
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);
5140
5141 currentFactorsBuf[0] = 0;
5142 // pmset level overrides
5143 if ((*hibMode & kIOHibernateModeOn) == 0) {
5144 if (!gSleepPolicyHandler) {
5145 standbyEnabled = false;
5146 powerOffEnabled = false;
5147 }
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;
5156 } else {
5157 currentFactors |= kIOPMSleepFactorHibernateForced;
5158 }
5159 }
5160
5161 // Current factors based on environment and assertions
5162 if (sleepTimerMaintenance) {
5163 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5164 }
5165 if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5166 currentFactors |= kIOPMSleepFactorSleepTimerWake;
5167 }
5168 if (!clamshellClosed) {
5169 currentFactors |= kIOPMSleepFactorLidOpen;
5170 }
5171 if (acAdaptorConnected) {
5172 currentFactors |= kIOPMSleepFactorACPower;
5173 }
5174 if (lowBatteryCondition) {
5175 hibernateMode = 0;
5176 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5177 if ((hibernateMode & kIOHibernateModeOn) == 0) {
5178 DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5179 } else {
5180 currentFactors |= kIOPMSleepFactorBatteryLow;
5181 }
5182 }
5183 if (!standbyDelay || !standbyTimer) {
5184 currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5185 }
5186 if (standbyNixed || !standbyEnabled) {
5187 currentFactors |= kIOPMSleepFactorStandbyDisabled;
5188 }
5189 if (resetTimers) {
5190 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5191 currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5192 }
5193 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5194 kIOPMDriverAssertionLevelOff) {
5195 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5196 }
5197 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5198 kIOPMDriverAssertionLevelOff) {
5199 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5200 }
5201 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5202 kIOPMDriverAssertionLevelOff) {
5203 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5204 }
5205 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5206 kIOPMDriverAssertionLevelOff) {
5207 currentFactors |= kIOPMSleepFactorThunderboltDevice;
5208 }
5209 if (_scheduledAlarmMask != 0) {
5210 currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5211 }
5212 if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5213 kIOPMDriverAssertionLevelOff) {
5214 currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5215 }
5216 #define TCPKEEPALIVE 1
5217 #if TCPKEEPALIVE
5218 if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5219 kIOPMDriverAssertionLevelOff) {
5220 currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5221 }
5222 #endif
5223 if (!powerOffEnabled) {
5224 currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5225 }
5226 if (desktopMode) {
5227 currentFactors |= kIOPMSleepFactorExternalDisplay;
5228 }
5229 if (userWasActive) {
5230 currentFactors |= kIOPMSleepFactorLocalUserActivity;
5231 }
5232 if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5233 currentFactors |= kIOPMSleepFactorHibernateFailed;
5234 }
5235 if (thermalWarningState) {
5236 currentFactors |= kIOPMSleepFactorThermalWarning;
5237 }
5238
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));
5244 }
5245 }
5246 DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5247
5248 if (gSleepPolicyHandler) {
5249 uint32_t savedHibernateMode;
5250 IOReturn result;
5251
5252 if (!gSleepPolicyVars) {
5253 gSleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1);
5254 if (!gSleepPolicyVars) {
5255 goto done;
5256 }
5257 bzero(gSleepPolicyVars, sizeof(*gSleepPolicyVars));
5258 }
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;
5271
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;
5279 }
5280
5281 result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5282
5283 if (kIOPMSleepPhase0 == sleepPhase) {
5284 // restore hibernateMode
5285 gSleepPolicyVars->hibernateMode = savedHibernateMode;
5286 }
5287
5288 if ((result != kIOReturnSuccess) ||
5289 (kIOPMSleepTypeInvalid == params->sleepType) ||
5290 (params->sleepType >= kIOPMSleepTypeLast) ||
5291 (kIOPMSystemSleepParametersVersion != params->version)) {
5292 MSG("sleep policy handler error\n");
5293 goto done;
5294 }
5295
5296 if ((getSleepTypeAttributes(params->sleepType) &
5297 kIOPMSleepAttributeHibernateSetup) &&
5298 ((*hibMode & kIOHibernateModeOn) == 0)) {
5299 *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5300 }
5301
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);
5305 found = true;
5306 goto done;
5307 }
5308
5309 // Policy table is meaningless without standby enabled
5310 if (!standbyEnabled) {
5311 goto done;
5312 }
5313
5314 // Validate the sleep policy table
5315 policyData = OSDynamicCast(OSData, prop.get());
5316 if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5317 goto done;
5318 }
5319
5320 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5321 if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5322 (pt->version != 1) || (0 == pt->entryCount)) {
5323 goto done;
5324 }
5325
5326 if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5327 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5328 goto done;
5329 }
5330
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);
5334
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);
5338 if (mismatch) {
5339 continue;
5340 }
5341
5342 DLOG("^ found match\n");
5343 found = true;
5344
5345 params->version = kIOPMSystemSleepParametersVersion;
5346 params->reserved1 = 1;
5347 if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5348 params->sleepType = kIOPMSleepTypeStandby;
5349 } else {
5350 params->sleepType = kIOPMSleepTypeNormalSleep;
5351 }
5352
5353 params->ecWakeEvents = entry->wakeEvents;
5354 if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5355 if (kIOPMSleepPhase2 == sleepPhase) {
5356 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5357
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;
5369 } else {
5370 standbyDelay = 1; // must be > 0
5371 }
5372 DLOG("standby delay %u, elapsed %u\n",
5373 standbyDelay, (uint32_t) elapsed);
5374 }
5375 }
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;
5381 }
5382 break;
5383 }
5384
5385 done:
5386 return found;
5387 }
5388
5389 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5390
5391 void
5392 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5393 {
5394 // Evaluate early (priority interest phase), before drivers sleep.
5395
5396 DLOG("%s\n", __FUNCTION__);
5397 removeProperty(kIOPMSystemSleepParametersKey);
5398
5399 // Full wake resets the standby timer delay adjustment
5400 if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5401 _standbyTimerResetSeconds = 0;
5402 }
5403
5404 hibernateDisabled = false;
5405 hibernateMode = 0;
5406 getSleepOption(kIOHibernateModeKey, &hibernateMode);
5407
5408 // Save for late evaluation if sleep is aborted
5409 bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5410
5411 if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5412 &hibernateMode)) {
5413 if (!hibernateRetry &&
5414 ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5415 kIOPMSleepAttributeHibernateSetup) == 0)) {
5416 // skip hibernate setup
5417 hibernateDisabled = true;
5418 }
5419 }
5420
5421 // Publish IOPMSystemSleepType
5422 uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5423 if (sleepType == kIOPMSleepTypeInvalid) {
5424 // no sleep policy
5425 sleepType = kIOPMSleepTypeNormalSleep;
5426 if (hibernateMode & kIOHibernateModeOn) {
5427 sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5428 kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5429 }
5430 } else if ((sleepType == kIOPMSleepTypeStandby) &&
5431 (gEarlySystemSleepParams.ecPoweroffTimer)) {
5432 // report the lowest possible sleep state
5433 sleepType = kIOPMSleepTypePowerOff;
5434 }
5435
5436 setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5437 }
5438
5439 void
5440 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5441 {
5442 IOPMSystemSleepParameters params;
5443 OSSharedPtr<OSData> paramsData;
5444 bool wakeNow;
5445 // Evaluate sleep policy after sleeping drivers but before platform sleep.
5446
5447 DLOG("%s\n", __FUNCTION__);
5448
5449 bzero(&params, sizeof(params));
5450 wakeNow = false;
5451 if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode)) {
5452 if ((kIOPMSleepTypeStandby == params.sleepType)
5453 && gIOHibernateStandbyDisabled && gSleepPolicyVars
5454 && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5455 & gSleepPolicyVars->sleepFactors))) {
5456 standbyNixed = true;
5457 wakeNow = true;
5458 }
5459 if (wakeNow
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, &params, sizeof(params));
5467 params.sleepType = kIOPMSleepTypeAbortedSleep;
5468 params.ecWakeTimer = 1;
5469 if (standbyNixed) {
5470 resetTimers = true;
5471 } else {
5472 // Set hibernateRetry flag to force hibernate setup on the
5473 // next sleep.
5474 hibernateRetry = true;
5475 }
5476 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5477 params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5478 } else {
5479 hibernateRetry = false;
5480 }
5481
5482 if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5483 resetTimers = false;
5484 }
5485
5486 paramsData = OSData::withBytes(&params, sizeof(params));
5487 if (paramsData) {
5488 setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5489 }
5490
5491 if (getSleepTypeAttributes(params.sleepType) &
5492 kIOPMSleepAttributeHibernateSleep) {
5493 // Disable sleep to force hibernation
5494 gIOHibernateMode &= ~kIOHibernateModeSleep;
5495 }
5496 }
5497 }
5498
5499 bool
5500 IOPMrootDomain::getHibernateSettings(
5501 uint32_t * hibernateModePtr,
5502 uint32_t * hibernateFreeRatio,
5503 uint32_t * hibernateFreeTime )
5504 {
5505 // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5506 // has updated the hibernateDisabled flag.
5507
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;
5515 }
5516 DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5517 return ok;
5518 }
5519
5520 bool
5521 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5522 {
5523 OSSharedPtr<OSObject> optionsProp;
5524 OSDictionary * optionsDict;
5525 OSSharedPtr<OSObject> obj;
5526 OSNumber * num;
5527 bool ok = false;
5528
5529 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5530 optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5531
5532 if (optionsDict) {
5533 obj.reset(optionsDict->getObject(key), OSRetain);
5534 }
5535 if (!obj) {
5536 obj = copyProperty(key);
5537 }
5538 if (obj) {
5539 if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5540 *option = num->unsigned32BitValue();
5541 ok = true;
5542 } else if (OSDynamicCast(OSBoolean, obj.get())) {
5543 *option = (obj == kOSBooleanTrue) ? 1 : 0;
5544 ok = true;
5545 }
5546 }
5547
5548 return ok;
5549 }
5550 #endif /* HIBERNATION */
5551
5552 IOReturn
5553 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5554 {
5555 #if HIBERNATION
5556 IOPMSystemSleepParameters params;
5557 uint32_t hibMode = 0;
5558 bool ok;
5559
5560 if (gIOPMWorkLoop->inGate() == false) {
5561 IOReturn ret = gIOPMWorkLoop->runAction(
5562 OSMemberFunctionCast(IOWorkLoop::Action, this,
5563 &IOPMrootDomain::getSystemSleepType),
5564 (OSObject *) this,
5565 (void *) sleepType, (void *) standbyTimer);
5566 return ret;
5567 }
5568
5569 getSleepOption(kIOHibernateModeKey, &hibMode);
5570 bzero(&params, sizeof(params));
5571
5572 ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
5573 if (ok) {
5574 *sleepType = params.sleepType;
5575 if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5576 !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5577 DLOG("Standby delay is not set\n");
5578 *standbyTimer = 0;
5579 }
5580 return kIOReturnSuccess;
5581 }
5582 #endif
5583
5584 return kIOReturnUnsupported;
5585 }
5586
5587 // MARK: -
5588 // MARK: Shutdown and Restart
5589
5590 //******************************************************************************
5591 // handlePlatformHaltRestart
5592 //
5593 //******************************************************************************
5594
5595 // Phases while performing shutdown/restart
5596 typedef enum {
5597 kNotifyDone = 0x00,
5598 kNotifyPriorityClients = 0x10,
5599 kNotifyPowerPlaneDrivers = 0x20,
5600 kNotifyHaltRestartAction = 0x30,
5601 kQuiescePM = 0x40,
5602 } shutdownPhase_t;
5603
5604
5605 struct HaltRestartApplierContext {
5606 IOPMrootDomain * RootDomain;
5607 unsigned long PowerState;
5608 IOPMPowerFlags PowerFlags;
5609 UInt32 MessageType;
5610 UInt32 Counter;
5611 const char * LogString;
5612 shutdownPhase_t phase;
5613
5614 IOServiceInterestHandler handler;
5615 } gHaltRestartCtx;
5616
5617 const char *
5618 shutdownPhase2String(shutdownPhase_t phase)
5619 {
5620 switch (phase) {
5621 case kNotifyDone:
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";
5629 case kQuiescePM:
5630 return "Quiescing PM";
5631 default:
5632 return "Unknown";
5633 }
5634 }
5635
5636 static void
5637 platformHaltRestartApplier( OSObject * object, void * context )
5638 {
5639 IOPowerStateChangeNotification notify;
5640 HaltRestartApplierContext * ctx;
5641 AbsoluteTime startTime, elapsedTime;
5642 uint32_t deltaTime;
5643
5644 ctx = (HaltRestartApplierContext *) context;
5645
5646 _IOServiceInterestNotifier * notifier;
5647 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5648 memset(&notify, 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;
5653
5654 if (notifier) {
5655 ctx->handler = notifier->handler;
5656 }
5657
5658 clock_get_uptime(&startTime);
5659 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
5660 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5661
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);
5666 }
5667
5668 ctx->handler = NULL;
5669 ctx->Counter++;
5670 }
5671
5672 static void
5673 quiescePowerTreeCallback( void * target, void * param )
5674 {
5675 IOLockLock(gPMHaltLock);
5676 gPMQuiesced = true;
5677 thread_wakeup(param);
5678 IOLockUnlock(gPMHaltLock);
5679 }
5680
5681 void
5682 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5683 {
5684 AbsoluteTime startTime, elapsedTime;
5685 uint32_t deltaTime;
5686
5687 memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5688 gHaltRestartCtx.RootDomain = this;
5689
5690 clock_get_uptime(&startTime);
5691 switch (pe_type) {
5692 case kPEHaltCPU:
5693 case kPEUPSDelayHaltCPU:
5694 gHaltRestartCtx.PowerState = OFF_STATE;
5695 gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5696 gHaltRestartCtx.LogString = "PowerOff";
5697 break;
5698
5699 case kPERestartCPU:
5700 gHaltRestartCtx.PowerState = RESTART_STATE;
5701 gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5702 gHaltRestartCtx.LogString = "Restart";
5703 break;
5704
5705 case kPEPagingOff:
5706 gHaltRestartCtx.PowerState = ON_STATE;
5707 gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5708 gHaltRestartCtx.LogString = "PagingOff";
5709 IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5710 #if HIBERNATION
5711 IOHibernateSystemRestart();
5712 #endif
5713 break;
5714
5715 default:
5716 return;
5717 }
5718
5719 gHaltRestartCtx.phase = kNotifyPriorityClients;
5720 // Notify legacy clients
5721 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5722
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());
5729 }
5730 }
5731
5732 if (kPEPagingOff != pe_type) {
5733 gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5734 // Notify in power tree order
5735 notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5736 }
5737
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);
5744 }
5745 #endif /* !defined(XNU_TARGET_OS_OSX) */
5746
5747 // Wait for PM to quiesce
5748 if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5749 gHaltRestartCtx.phase = kQuiescePM;
5750 AbsoluteTime quiesceTime = mach_absolute_time();
5751
5752 IOLockLock(gPMHaltLock);
5753 gPMQuiesced = false;
5754 if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5755 kIOReturnSuccess) {
5756 while (!gPMQuiesced) {
5757 IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5758 }
5759 }
5760 IOLockUnlock(gPMHaltLock);
5761 deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5762 DLOG("PM quiesce took %u ms\n", deltaTime);
5763 halt_log_enter("Quiesce", NULL, elapsedTime);
5764 }
5765 gHaltRestartCtx.phase = kNotifyDone;
5766
5767 deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5768 LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5769
5770 halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5771
5772 deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5773 LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5774
5775 if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5776 printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5777 }
5778
5779 checkShutdownTimeout();
5780 }
5781
5782 bool
5783 IOPMrootDomain::checkShutdownTimeout()
5784 {
5785 AbsoluteTime elapsedTime;
5786 uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5787
5788 if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5789 return true;
5790 }
5791 return false;
5792 }
5793
5794 void
5795 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5796 {
5797 if (gHaltLog) {
5798 if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5799 halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5800 }
5801 panic("%s timed out in phase '%s'. Total %d ms:%s",
5802 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5803 } else {
5804 panic("%s timed out in phase \'%s\'. Total %d ms",
5805 gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5806 }
5807 }
5808
5809 //******************************************************************************
5810 // shutdownSystem
5811 //
5812 //******************************************************************************
5813
5814 IOReturn
5815 IOPMrootDomain::shutdownSystem( void )
5816 {
5817 return kIOReturnUnsupported;
5818 }
5819
5820 //******************************************************************************
5821 // restartSystem
5822 //
5823 //******************************************************************************
5824
5825 IOReturn
5826 IOPMrootDomain::restartSystem( void )
5827 {
5828 return kIOReturnUnsupported;
5829 }
5830
5831 // MARK: -
5832 // MARK: System Capability
5833
5834 //******************************************************************************
5835 // tagPowerPlaneService
5836 //
5837 // Running on PM work loop thread.
5838 //******************************************************************************
5839
5840 void
5841 IOPMrootDomain::tagPowerPlaneService(
5842 IOService * service,
5843 IOPMActions * actions,
5844 IOPMPowerStateIndex maxPowerState )
5845 {
5846 uint32_t flags = 0;
5847
5848 memset(actions, 0, sizeof(*actions));
5849 actions->target = this;
5850
5851 if (service == this) {
5852 actions->actionPowerChangeStart =
5853 OSMemberFunctionCast(
5854 IOPMActionPowerChangeStart, this,
5855 &IOPMrootDomain::handleOurPowerChangeStart);
5856
5857 actions->actionPowerChangeDone =
5858 OSMemberFunctionCast(
5859 IOPMActionPowerChangeDone, this,
5860 &IOPMrootDomain::handleOurPowerChangeDone);
5861
5862 actions->actionPowerChangeOverride =
5863 OSMemberFunctionCast(
5864 IOPMActionPowerChangeOverride, this,
5865 &IOPMrootDomain::overrideOurPowerChange);
5866 return;
5867 }
5868
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);
5875
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 );
5880 }
5881 flags |= kPMActionsFlagIsDisplayWrangler;
5882 }
5883 #endif /* DISPLAY_WRANGLER_PRESENT */
5884
5885 if (service->propertyExists("IOPMStrictTreeOrder")) {
5886 flags |= kPMActionsFlagIsGraphicsDriver;
5887 }
5888 if (service->propertyExists("IOPMUnattendedWakePowerState")) {
5889 flags |= kPMActionsFlagIsAudioDriver;
5890 }
5891
5892 OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
5893 if (prop) {
5894 OSNumber * num = OSDynamicCast(OSNumber, prop.get());
5895 if (num) {
5896 actions->darkWakePowerState = num->unsigned32BitValue();
5897 if (actions->darkWakePowerState < maxPowerState) {
5898 flags |= kPMActionsFlagHasDarkWakePowerState;
5899 }
5900 }
5901 }
5902
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.
5906
5907 if (flags) {
5908 IORegistryEntry * child = service;
5909 IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
5910
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);
5915 flags = 0;
5916 break;
5917 }
5918 if ((parent == pciHostBridgeDriver) ||
5919 (parent == this)) {
5920 if (OSDynamicCast(IOPowerConnection, child)) {
5921 IOPowerConnection * conn = (IOPowerConnection *) child;
5922 conn->delayChildNotification = true;
5923 DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
5924 }
5925 break;
5926 }
5927 child = parent;
5928 parent = child->getParentEntry(gIOPowerPlane);
5929 }
5930 }
5931
5932 if (flags) {
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);
5939
5940 if (flags & kPMActionsFlagIsDisplayWrangler) {
5941 actions->actionActivityTickle =
5942 OSMemberFunctionCast(
5943 IOPMActionActivityTickle, this,
5944 &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
5945
5946 actions->actionUpdatePowerClient =
5947 OSMemberFunctionCast(
5948 IOPMActionUpdatePowerClient, this,
5949 &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
5950 }
5951 return;
5952 }
5953
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());
5963 }
5964 }
5965
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 );
5974 if (bit >= 0) {
5975 // Save the assigned bit for fast lookup.
5976 actions->flags |= (bit & kPMActionsPCIBitNumberMask);
5977
5978 actions->actionPowerChangeStart =
5979 OSMemberFunctionCast(
5980 IOPMActionPowerChangeStart, this,
5981 &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
5982
5983 actions->actionPowerChangeDone =
5984 OSMemberFunctionCast(
5985 IOPMActionPowerChangeDone, this,
5986 &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
5987 }
5988 }
5989 }
5990 }
5991
5992 //******************************************************************************
5993 // PM actions for root domain
5994 //******************************************************************************
5995
5996 void
5997 IOPMrootDomain::overrideOurPowerChange(
5998 IOService * service,
5999 IOPMActions * actions,
6000 const IOPMRequest * request,
6001 IOPMPowerStateIndex * inOutPowerState,
6002 IOPMPowerChangeFlags * inOutChangeFlags )
6003 {
6004 uint32_t changeFlags = *inOutChangeFlags;
6005 uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6006 uint32_t currentPowerState = (uint32_t) getPowerState();
6007
6008 if (request->getTag() == 0) {
6009 // Set a tag for any request that originates from IOServicePM
6010 (const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6011 }
6012
6013 DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6014 getPowerStateString(currentPowerState),
6015 getPowerStateString(desiredPowerState),
6016 _currentCapability, changeFlags,
6017 request->getTag());
6018
6019
6020 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6021 /*
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
6030 */
6031 if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6032 if (!lowBatteryCondition) {
6033 DLOG("Duplicate lowBattery sleep");
6034 *inOutChangeFlags |= kIOPMNotDone;
6035 return;
6036 }
6037 }
6038 #endif
6039
6040 if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6041 // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6042 *inOutChangeFlags |= kIOPMNotDone;
6043 return;
6044 }
6045
6046 if (changeFlags & kIOPMParentInitiated) {
6047 // Root parent is permanently pegged at max power,
6048 // a parent initiated power change is unexpected.
6049 *inOutChangeFlags |= kIOPMNotDone;
6050 return;
6051 }
6052
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.
6059
6060 darkWakeToSleepASAP = true;
6061
6062 // Drop graphics and audio capability
6063 _desiredCapability &= ~(
6064 kIOPMSystemCapabilityGraphics |
6065 kIOPMSystemCapabilityAudio);
6066
6067 // Convert to capability change (ON->ON)
6068 *inOutPowerState = getRUN_STATE();
6069 *inOutChangeFlags |= kIOPMSynchronize;
6070
6071 // Revert device desire from SLEEP to ON
6072 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6073 } else {
6074 // System is already in dark wake, ok to drop power state.
6075 // Broadcast root power down to entire tree.
6076 *inOutChangeFlags |= kIOPMRootChangeDown;
6077 }
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;
6083 }
6084 }
6085 }
6086
6087 void
6088 IOPMrootDomain::handleOurPowerChangeStart(
6089 IOService * service,
6090 IOPMActions * actions,
6091 const IOPMRequest * request,
6092 IOPMPowerStateIndex newPowerState,
6093 IOPMPowerChangeFlags * inOutChangeFlags )
6094 {
6095 IOPMRequestTag requestTag = request->getTag();
6096 IOPMRequestTag sleepReason;
6097
6098 uint32_t changeFlags = *inOutChangeFlags;
6099 uint32_t currentPowerState = (uint32_t) getPowerState();
6100 bool publishSleepReason = false;
6101
6102 // Check if request has a valid sleep reason
6103 sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6104 if (sleepReason < kIOPMSleepReasonClamshell) {
6105 sleepReason = kIOPMSleepReasonIdle;
6106 }
6107
6108 _systemTransitionType = kSystemTransitionNone;
6109 _systemMessageClientMask = 0;
6110 capabilityLoss = false;
6111 toldPowerdCapWillChange = false;
6112
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;
6120 }
6121
6122 // 1. Explicit capability change.
6123 if (changeFlags & kIOPMSynchronize) {
6124 if (newPowerState == ON_STATE) {
6125 if (changeFlags & kIOPMSyncNoChildNotify) {
6126 _systemTransitionType = kSystemTransitionNewCapClient;
6127 } else {
6128 _systemTransitionType = kSystemTransitionCapability;
6129 }
6130 }
6131 }
6132 // 2. Going to sleep (cancellation still possible).
6133 else if (newPowerState < currentPowerState) {
6134 _systemTransitionType = kSystemTransitionSleep;
6135 }
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;
6142
6143 // Early exit from dark wake to full (e.g. LID open)
6144 if (kFullWakeReasonNone != fullWakeReason) {
6145 _desiredCapability |= (
6146 kIOPMSystemCapabilityGraphics |
6147 kIOPMSystemCapabilityAudio);
6148
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);
6155 }
6156 #endif
6157 }
6158 #if HIBERNATION
6159 IOHibernateSetWakeCapabilities(_desiredCapability);
6160 #endif
6161 }
6162
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.
6166
6167 if (kSystemTransitionSleep == _systemTransitionType) {
6168 _pendingCapability = 0;
6169 capabilityLoss = true;
6170 } else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6171 _pendingCapability = _desiredCapability |
6172 kIOPMSystemCapabilityCPU |
6173 kIOPMSystemCapabilityNetwork;
6174
6175 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6176 _pendingCapability |= kIOPMSystemCapabilityAudio;
6177 }
6178
6179 if ((kSystemTransitionCapability == _systemTransitionType) &&
6180 (_pendingCapability == _currentCapability)) {
6181 // Cancel the PM state change.
6182 _systemTransitionType = kSystemTransitionNone;
6183 *inOutChangeFlags |= kIOPMNotDone;
6184 }
6185 if (__builtin_popcount(_pendingCapability) <
6186 __builtin_popcount(_currentCapability)) {
6187 capabilityLoss = true;
6188 }
6189 }
6190
6191 // 1. Capability change.
6192 if (kSystemTransitionCapability == _systemTransitionType) {
6193 // Dark to Full transition.
6194 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6195 tracePoint( kIOPMTracePointDarkWakeExit );
6196
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);
6206 }
6207 #endif
6208
6209 willEnterFullWake();
6210 }
6211
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);
6218 }
6219 IOLockUnlock(pmStatsLock);
6220
6221 tracePoint( kIOPMTracePointDarkWakeEntry );
6222 *inOutChangeFlags |= kIOPMSyncTellPowerDown;
6223 _systemMessageClientMask = kSystemMessageClientPowerd |
6224 kSystemMessageClientLegacyApp;
6225
6226 // rdar://15971327
6227 // Prevent user active transitions before notifying clients
6228 // that system will sleep.
6229 preventTransitionToUserActive(true);
6230
6231 IOService::setAdvisoryTickleEnable( false );
6232
6233 // Publish the sleep reason for full to dark wake
6234 publishSleepReason = true;
6235 lastSleepReason = fullToDarkReason = sleepReason;
6236
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);
6242 }
6243
6244 darkWakeExit = false;
6245 }
6246 }
6247 // 2. System sleep.
6248 else if (kSystemTransitionSleep == _systemTransitionType) {
6249 // Beginning of a system sleep transition.
6250 // Cancellation is still possible.
6251 tracePoint( kIOPMTracePointSleepStarted );
6252
6253 _systemMessageClientMask = kSystemMessageClientAll;
6254 if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6255 _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6256 }
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;
6262 } else {
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;
6269 }
6270 }
6271 #if HIBERNATION
6272 gIOHibernateState = 0;
6273 #endif
6274
6275 // Record the reason for dark wake back to sleep
6276 // System may not have ever achieved full wake
6277
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);
6283 }
6284 }
6285 // 3. System wake.
6286 else if (kSystemTransitionWake == _systemTransitionType) {
6287 tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6288 // Clear stats about sleep
6289
6290 if (AOT_STATE == newPowerState) {
6291 _pendingCapability = 0;
6292 }
6293
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);
6299 }
6300
6301 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6302 willEnterFullWake();
6303 }
6304 }
6305
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.
6309
6310 if (publishSleepReason) {
6311 static const char * IOPMSleepReasons[] =
6312 {
6313 kIOPMClamshellSleepKey,
6314 kIOPMPowerButtonSleepKey,
6315 kIOPMSoftwareSleepKey,
6316 kIOPMOSSwitchHibernationKey,
6317 kIOPMIdleSleepKey,
6318 kIOPMLowPowerSleepKey,
6319 kIOPMThermalEmergencySleepKey,
6320 kIOPMMaintenanceSleepKey,
6321 kIOPMSleepServiceExitKey,
6322 kIOPMDarkWakeThermalEmergencyKey,
6323 kIOPMNotificationWakeExitKey
6324 };
6325
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]);
6331 }
6332 }
6333
6334 if ((kSystemTransitionNone != _systemTransitionType) &&
6335 (kSystemTransitionNewCapClient != _systemTransitionType)) {
6336 _systemStateGeneration++;
6337 systemDarkWake = false;
6338
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,
6344 requestTag);
6345 }
6346
6347 if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6348 panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6349 }
6350 if (_aotNow && (ON_STATE == newPowerState)) {
6351 WAKEEVENT_LOCK();
6352 aotShouldExit(false, true);
6353 WAKEEVENT_UNLOCK();
6354 aotExit(false);
6355 }
6356 }
6357
6358 void
6359 IOPMrootDomain::handleOurPowerChangeDone(
6360 IOService * service,
6361 IOPMActions * actions,
6362 const IOPMRequest * request,
6363 IOPMPowerStateIndex oldPowerState,
6364 IOPMPowerChangeFlags changeFlags )
6365 {
6366 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6367 _systemTransitionType = kSystemTransitionNone;
6368 return;
6369 }
6370
6371 if (_systemTransitionType != kSystemTransitionNone) {
6372 uint32_t currentPowerState = (uint32_t) getPowerState();
6373
6374 if (changeFlags & kIOPMNotDone) {
6375 // Power down was cancelled or vetoed.
6376 _pendingCapability = _currentCapability;
6377 lastSleepReason = 0;
6378
6379 // When sleep is cancelled or reverted, don't report
6380 // the target (lower) power state as the previous state.
6381 oldPowerState = currentPowerState;
6382
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) */
6399 }
6400
6401 // Revert device desire to max.
6402 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6403 } else {
6404 // Send message on dark wake to full wake promotion.
6405 // tellChangeUp() handles the normal SLEEP->ON case.
6406
6407 if (kSystemTransitionCapability == _systemTransitionType) {
6408 if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6409 lastSleepReason = 0; // stop logging wrangler tickles
6410 tellClients(kIOMessageSystemHasPoweredOn);
6411 }
6412 if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6413 // Going dark, reset full wake state
6414 // userIsActive will be cleared by wrangler powering down
6415 fullWakeReason = kFullWakeReasonNone;
6416
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);
6421 ts_sleepStart = 0;
6422 }
6423 }
6424 }
6425
6426 // Reset state after exiting from dark wake.
6427
6428 if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6429 CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6430 darkWakeMaintenance = false;
6431 darkWakeToSleepASAP = false;
6432 pciCantSleepValid = false;
6433 darkWakeSleepService = false;
6434
6435 if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6436 // Remove the influence of display power assertion
6437 // before next system wake.
6438 if (wrangler) {
6439 wrangler->changePowerStateForRootDomain(
6440 kWranglerPowerStateMin );
6441 }
6442 removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6443 }
6444 }
6445
6446 // Entered dark mode.
6447
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.
6453
6454 pmPowerStateQueue->submitPowerEvent(
6455 kPowerEventPolicyStimulus,
6456 (void *) kStimulusDarkWakeEntry,
6457 _systemStateGeneration );
6458 }
6459 }
6460
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,
6465 request->getTag());
6466
6467 if ((currentPowerState == ON_STATE) && pmAssertions) {
6468 pmAssertions->reportCPUBitAccounting();
6469 }
6470
6471 if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6472 displayWakeCnt++;
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);
6478 }
6479 #endif
6480 } else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6481 darkWakeCnt++;
6482 }
6483
6484 // Update current system capability.
6485 if (_currentCapability != _pendingCapability) {
6486 _currentCapability = _pendingCapability;
6487 }
6488
6489 // Update highest system capability.
6490
6491 _highestCapability |= _currentCapability;
6492
6493 if (darkWakePostTickle &&
6494 (kSystemTransitionWake == _systemTransitionType) &&
6495 (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6496 kDarkWakeFlagPromotionLate) {
6497 darkWakePostTickle = false;
6498 reportUserInput();
6499 } else if (darkWakeExit) {
6500 requestFullWake( kFullWakeReasonLocalUser );
6501 }
6502
6503 // Reset tracepoint at completion of capability change,
6504 // completion of wake transition, and aborted sleep transition.
6505
6506 if ((_systemTransitionType == kSystemTransitionCapability) ||
6507 (_systemTransitionType == kSystemTransitionWake) ||
6508 ((_systemTransitionType == kSystemTransitionSleep) &&
6509 (changeFlags & kIOPMNotDone))) {
6510 setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6511 tracePoint( kIOPMTracePointSystemUp );
6512 }
6513
6514 _systemTransitionType = kSystemTransitionNone;
6515 _systemMessageClientMask = 0;
6516 toldPowerdCapWillChange = false;
6517
6518 darkWakeLogClamp = false;
6519
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);
6528 }
6529
6530 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6531 pmPowerStateQueue->submitPowerEvent(
6532 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6533 }
6534 }
6535 }
6536
6537 //******************************************************************************
6538 // PM actions for graphics and audio.
6539 //******************************************************************************
6540
6541 void
6542 IOPMrootDomain::overridePowerChangeForService(
6543 IOService * service,
6544 IOPMActions * actions,
6545 const IOPMRequest * request,
6546 IOPMPowerStateIndex * inOutPowerState,
6547 IOPMPowerChangeFlags * inOutChangeFlags )
6548 {
6549 uint32_t powerState = (uint32_t) *inOutPowerState;
6550 uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6551 const uint32_t actionFlags = actions->flags;
6552
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;
6558
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)) {
6564 enableClamp = true;
6565 } else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6566 ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6567 ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6568 (changeFlags & kIOPMSynchronize)) {
6569 enableClamp = true;
6570 } else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6571 ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6572 (changeFlags & kIOPMSynchronize)) {
6573 enableClamp = true;
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.
6578 enableClamp = true;
6579 }
6580
6581 if (enableClamp) {
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);
6586 }
6587 } else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6588 bool disableClamp = false;
6589
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;
6601 }
6602
6603 if (disableClamp) {
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);
6608 }
6609 }
6610
6611 if (actions->state & kPMActionsStatePowerClamped) {
6612 uint32_t maxPowerState = 0;
6613
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)) {
6619 maxPowerState++;
6620
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.
6624
6625 if (changeFlags & kIOPMDomainDidChange) {
6626 *inOutChangeFlags |= kIOPMExpireIdleTimer;
6627 }
6628 } else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6629 maxPowerState++;
6630 } else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6631 maxPowerState = actions->darkWakePowerState;
6632 }
6633 } else {
6634 // Deny all self-initiated changes when power is limited.
6635 // Wrangler tickle should never defeat the limiter.
6636 maxPowerState = service->getPowerState();
6637 }
6638
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;
6644
6645 if (darkWakePostTickle &&
6646 (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6647 (changeFlags & kIOPMDomainWillChange) &&
6648 ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6649 kDarkWakeFlagPromotionEarly)) {
6650 darkWakePostTickle = false;
6651 reportUserInput();
6652 }
6653 }
6654
6655 if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6656 if (darkWakeLogClamp) {
6657 AbsoluteTime now;
6658 uint64_t nsec;
6659
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)));
6665 }
6666 darkWakePowerClamped = true;
6667 }
6668 }
6669 }
6670
6671 void
6672 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6673 IOService * service,
6674 IOPMActions * actions )
6675 {
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.
6680
6681 assert(service == wrangler);
6682
6683 clock_get_uptime(&userActivityTime);
6684 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6685 || (lastSleepReason == kIOPMSleepReasonMaintenance)
6686 || (lastSleepReason == kIOPMSleepReasonSoftware));
6687 if (aborting) {
6688 userActivityCount++;
6689 DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6690 userActivityCount, lastSleepReason);
6691 }
6692
6693 if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6694 DLOG("display wrangler tickled\n");
6695 if (kIOLogPMRootDomain & gIOKitDebug) {
6696 OSReportWithBacktrace("Dark wake display tickle");
6697 }
6698 if (pmPowerStateQueue) {
6699 pmPowerStateQueue->submitPowerEvent(
6700 kPowerEventPolicyStimulus,
6701 (void *) kStimulusDarkWakeActivityTickle,
6702 true /* set wake type */ );
6703 }
6704 }
6705 #endif /* DISPLAY_WRANGLER_PRESENT */
6706 }
6707
6708 void
6709 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6710 IOService * service,
6711 IOPMActions * actions,
6712 const OSSymbol * powerClient,
6713 IOPMPowerStateIndex oldPowerState,
6714 IOPMPowerStateIndex newPowerState )
6715 {
6716 #if DISPLAY_WRANGLER_PRESENT
6717 assert(service == wrangler);
6718
6719 // This function implements half of the user active detection
6720 // by monitoring changes to the display wrangler's device desire.
6721 //
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().
6727 //
6728 // 2. Power state change to max, and DeviceDesire is also at max.
6729 // Handled by displayWranglerNotification().
6730 //
6731 // User becomes inactive when DeviceDesire drops to sleep state or below.
6732
6733 DLOG("wrangler %s (ps %u, %u->%u)\n",
6734 powerClient->getCStringNoCopy(),
6735 (uint32_t) service->getPowerState(),
6736 (uint32_t) oldPowerState, (uint32_t) newPowerState);
6737
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 );
6746 }
6747 }
6748
6749 if (newPowerState <= kWranglerPowerStateSleep) {
6750 evaluatePolicy( kStimulusDisplayWranglerSleep );
6751 } else if (newPowerState == kWranglerPowerStateMax) {
6752 evaluatePolicy( kStimulusDisplayWranglerWake );
6753 }
6754 #endif /* DISPLAY_WRANGLER_PRESENT */
6755 }
6756
6757 //******************************************************************************
6758 // User active state management
6759 //******************************************************************************
6760
6761 void
6762 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6763 {
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.
6771
6772 if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6773 (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6774 kWranglerPowerStateMax)) {
6775 evaluatePolicy( kStimulusEnterUserActiveState );
6776 }
6777 }
6778 #endif /* DISPLAY_WRANGLER_PRESENT */
6779 }
6780
6781 //******************************************************************************
6782 // Approve usage of delayed child notification by PM.
6783 //******************************************************************************
6784
6785 bool
6786 IOPMrootDomain::shouldDelayChildNotification(
6787 IOService * service )
6788 {
6789 if ((kFullWakeReasonNone == fullWakeReason) &&
6790 (kSystemTransitionWake == _systemTransitionType)) {
6791 DLOG("%s: delay child notify\n", service->getName());
6792 return true;
6793 }
6794 return false;
6795 }
6796
6797 //******************************************************************************
6798 // PM actions for PCI device.
6799 //******************************************************************************
6800
6801 void
6802 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6803 IOService * service,
6804 IOPMActions * actions,
6805 const IOPMRequest * request,
6806 IOPMPowerStateIndex powerState,
6807 IOPMPowerChangeFlags * inOutChangeFlags )
6808 {
6809 pmTracer->tracePCIPowerChange(
6810 PMTraceWorker::kPowerChangeStart,
6811 service, *inOutChangeFlags,
6812 (actions->flags & kPMActionsPCIBitNumberMask));
6813 }
6814
6815 void
6816 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6817 IOService * service,
6818 IOPMActions * actions,
6819 const IOPMRequest * request,
6820 IOPMPowerStateIndex powerState,
6821 IOPMPowerChangeFlags changeFlags )
6822 {
6823 pmTracer->tracePCIPowerChange(
6824 PMTraceWorker::kPowerChangeCompleted,
6825 service, changeFlags,
6826 (actions->flags & kPMActionsPCIBitNumberMask));
6827 }
6828
6829 //******************************************************************************
6830 // registerInterest
6831 //
6832 // Override IOService::registerInterest() for root domain clients.
6833 //******************************************************************************
6834
6835 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
6836 {
6837 friend class IOPMrootDomain;
6838 OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
6839
6840 protected:
6841 uint32_t ackTimeoutCnt;
6842 uint32_t msgType; // Message pending ack
6843 uint32_t msgIndex;
6844 uint32_t maxMsgDelayMS;
6845 uint32_t maxAckDelayMS;
6846 uint64_t msgAbsTime;
6847 uint64_t uuid0;
6848 uint64_t uuid1;
6849 OSSharedPtr<const OSSymbol> identifier;
6850 OSSharedPtr<const OSSymbol> clientName;
6851 };
6852
6853 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
6854
6855 OSSharedPtr<IONotifier>
6856 IOPMrootDomain::registerInterest(
6857 const OSSymbol * typeOfInterest,
6858 IOServiceInterestHandler handler,
6859 void * target, void * ref )
6860 {
6861 IOPMServiceInterestNotifier* notifier;
6862 bool isSystemCapabilityClient;
6863 bool isKernelCapabilityClient;
6864 IOReturn rc = kIOReturnError;
6865
6866 isSystemCapabilityClient = typeOfInterest &&
6867 typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
6868
6869 isKernelCapabilityClient = typeOfInterest &&
6870 typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
6871
6872 if (isSystemCapabilityClient) {
6873 typeOfInterest = gIOAppPowerStateInterest;
6874 }
6875
6876 notifier = new IOPMServiceInterestNotifier;
6877 if (!notifier) {
6878 return NULL;
6879 }
6880
6881 if (notifier->init()) {
6882 rc = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
6883 }
6884 if (rc != kIOReturnSuccess) {
6885 return NULL;
6886 }
6887
6888 notifier->ackTimeoutCnt = 0;
6889
6890 if (pmPowerStateQueue) {
6891 if (isSystemCapabilityClient) {
6892 notifier->retain();
6893 if (pmPowerStateQueue->submitPowerEvent(
6894 kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
6895 notifier->release();
6896 }
6897 }
6898
6899 if (isKernelCapabilityClient) {
6900 notifier->retain();
6901 if (pmPowerStateQueue->submitPowerEvent(
6902 kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
6903 notifier->release();
6904 }
6905 }
6906 }
6907
6908 OSSharedPtr<OSData> data;
6909 uint8_t *uuid = NULL;
6910 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
6911 if (kext) {
6912 data = kext->copyUUID();
6913 }
6914 if (data && (data->getLength() == sizeof(uuid_t))) {
6915 uuid = (uint8_t *)(data->getBytesNoCopy());
6916
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]);
6923
6924 notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
6925 }
6926 return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
6927 }
6928
6929 //******************************************************************************
6930 // systemMessageFilter
6931 //
6932 //******************************************************************************
6933
6934 bool
6935 IOPMrootDomain::systemMessageFilter(
6936 void * object, void * arg1, void * arg2, void * arg3 )
6937 {
6938 const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
6939 bool isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
6940 bool isCapClient = false;
6941 bool allow = false;
6942 IOPMServiceInterestNotifier *notifier;
6943
6944 notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
6945
6946 do {
6947 if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
6948 (!isCapMsg || !_joinedCapabilityClients ||
6949 !_joinedCapabilityClients->containsObject((OSObject *) object))) {
6950 break;
6951 }
6952
6953 // Capability change message for app and kernel clients.
6954
6955 if (isCapMsg) {
6956 // Kernel clients
6957 if ((context->notifyType == kNotifyPriority) ||
6958 (context->notifyType == kNotifyCapabilityChangePriority)) {
6959 isCapClient = true;
6960 }
6961
6962 // powerd's systemCapabilityNotifier
6963 if ((context->notifyType == kNotifyCapabilityChangeApps) &&
6964 (object == (void *) systemCapabilityNotifier.get())) {
6965 isCapClient = true;
6966 }
6967 }
6968
6969 if (isCapClient) {
6970 IOPMSystemCapabilityChangeParameters * capArgs =
6971 (IOPMSystemCapabilityChangeParameters *) arg2;
6972
6973 if (kSystemTransitionNewCapClient == _systemTransitionType) {
6974 capArgs->fromCapabilities = 0;
6975 capArgs->toCapabilities = _currentCapability;
6976 capArgs->changeFlags = 0;
6977 } else {
6978 capArgs->fromCapabilities = _currentCapability;
6979 capArgs->toCapabilities = _pendingCapability;
6980
6981 if (context->isPreChange) {
6982 capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
6983 } else {
6984 capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
6985 }
6986
6987 if ((object == (void *) systemCapabilityNotifier.get()) &&
6988 context->isPreChange) {
6989 toldPowerdCapWillChange = true;
6990 }
6991 }
6992
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.
6996
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;
7002 }
7003
7004 allow = true;
7005 break;
7006 }
7007
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
7012
7013 if ((kIOMessageCanSystemSleep == context->messageType) ||
7014 (kIOMessageSystemWillNotSleep == context->messageType)) {
7015 if (object == (OSObject *) systemCapabilityNotifier.get()) {
7016 allow = true;
7017 break;
7018 }
7019
7020 // Not idle sleep, don't ask apps.
7021 if (context->changeFlags & kIOPMSkipAskPowerDown) {
7022 break;
7023 }
7024 }
7025
7026 if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7027 if ((object == (OSObject *) systemCapabilityNotifier.get()) &&
7028 CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7029 (fullToDarkReason == kIOPMSleepReasonIdle)) {
7030 allow = true;
7031 }
7032 break;
7033 }
7034
7035 // Reject capability change messages for legacy clients.
7036 // Reject legacy system sleep messages for capability client.
7037
7038 if (isCapMsg || (object == (OSObject *) systemCapabilityNotifier.get())) {
7039 break;
7040 }
7041
7042 // Filter system sleep messages.
7043
7044 if ((context->notifyType == kNotifyApps) &&
7045 (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7046 allow = true;
7047
7048 if (notifier) {
7049 if (arg3) {
7050 if (notifier->ackTimeoutCnt >= 3) {
7051 *((OSObject **) arg3) = kOSBooleanFalse;
7052 } else {
7053 *((OSObject **) arg3) = kOSBooleanTrue;
7054 }
7055 }
7056 }
7057 } else if ((context->notifyType == kNotifyPriority) &&
7058 (_systemMessageClientMask & kSystemMessageClientKernel)) {
7059 allow = true;
7060 }
7061 }while (false);
7062
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();
7069 }
7070 }
7071 if (notifier) {
7072 notifier->msgType = context->messageType;
7073 }
7074
7075 return allow;
7076 }
7077
7078 //******************************************************************************
7079 // setMaintenanceWakeCalendar
7080 //
7081 //******************************************************************************
7082
7083 IOReturn
7084 IOPMrootDomain::setMaintenanceWakeCalendar(
7085 const IOPMCalendarStruct * calendar )
7086 {
7087 OSSharedPtr<OSData> data;
7088 IOReturn ret = 0;
7089
7090 if (!calendar) {
7091 return kIOReturnBadArgument;
7092 }
7093
7094 data = OSData::withBytes((void *) calendar, sizeof(*calendar));
7095 if (!data) {
7096 return kIOReturnNoMemory;
7097 }
7098
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());
7103 }
7104
7105 return ret;
7106 }
7107
7108 // MARK: -
7109 // MARK: Display Wrangler
7110
7111 //******************************************************************************
7112 // displayWranglerNotification
7113 //
7114 // Handle the notification when the IODisplayWrangler changes power state.
7115 //******************************************************************************
7116
7117 IOReturn
7118 IOPMrootDomain::displayWranglerNotification(
7119 void * target, void * refCon,
7120 UInt32 messageType, IOService * service,
7121 void * messageArgument, vm_size_t argSize )
7122 {
7123 #if DISPLAY_WRANGLER_PRESENT
7124 IOPMPowerStateIndex displayPowerState;
7125 IOPowerStateChangeNotification * params =
7126 (IOPowerStateChangeNotification *) messageArgument;
7127
7128 if ((messageType != kIOMessageDeviceWillPowerOff) &&
7129 (messageType != kIOMessageDeviceHasPoweredOn)) {
7130 return kIOReturnUnsupported;
7131 }
7132
7133 ASSERT_GATED();
7134 if (!gRootDomain) {
7135 return kIOReturnUnsupported;
7136 }
7137
7138 displayPowerState = params->stateNumber;
7139 DLOG("wrangler %s ps %d\n",
7140 getIOMessageString(messageType), (uint32_t) displayPowerState);
7141
7142 switch (messageType) {
7143 case kIOMessageDeviceWillPowerOff:
7144 // Display wrangler has dropped power due to display idle
7145 // or force system sleep.
7146 //
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
7152
7153 if (displayPowerState <= kWranglerPowerStateSleep) {
7154 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7155 }
7156 break;
7157
7158 case kIOMessageDeviceHasPoweredOn:
7159 // Display wrangler has powered on due to user activity
7160 // or wake from sleep.
7161
7162 if (kWranglerPowerStateMax == displayPowerState) {
7163 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7164
7165 // See comment in handleUpdatePowerClientForDisplayWrangler
7166 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7167 kWranglerPowerStateMax) {
7168 gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7169 }
7170 }
7171 break;
7172 }
7173 #endif /* DISPLAY_WRANGLER_PRESENT */
7174 return kIOReturnUnsupported;
7175 }
7176
7177 //******************************************************************************
7178 // reportUserInput
7179 //
7180 //******************************************************************************
7181
7182 void
7183 IOPMrootDomain::updateUserActivity( void )
7184 {
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));
7190 if (aborting) {
7191 userActivityCount++;
7192 DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7193 }
7194 #endif
7195 }
7196 void
7197 IOPMrootDomain::reportUserInput( void )
7198 {
7199 if (wrangler) {
7200 wrangler->activityTickle(0, 0);
7201 }
7202 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7203 // Update user activity
7204 updateUserActivity();
7205
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 */ );
7213 }
7214 #endif
7215 }
7216
7217 void
7218 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7219 {
7220 #if DISPLAY_WRANGLER_PRESENT
7221 if (wrangler) {
7222 wrangler->activityTickle(0, 0);
7223 }
7224 #else
7225 if (!device) {
7226 DLOG("requestUserActive: device is null\n");
7227 return;
7228 }
7229 OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7230 uint64_t registryID = device->getRegistryEntryID();
7231
7232 if (!deviceName || !registryID) {
7233 DLOG("requestUserActive: no device name or registry entry\n");
7234 return;
7235 }
7236 const char *name = deviceName->getCStringNoCopy();
7237 char payload[128];
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));
7241 #endif
7242 }
7243
7244 //******************************************************************************
7245 // latchDisplayWranglerTickle
7246 //******************************************************************************
7247
7248 bool
7249 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7250 {
7251 #if DISPLAY_WRANGLER_PRESENT
7252 if (latch) {
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;
7260 } else {
7261 wranglerTickled = false;
7262 }
7263 } else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7264 wranglerTickled = false;
7265
7266 pmPowerStateQueue->submitPowerEvent(
7267 kPowerEventPolicyStimulus,
7268 (void *) kStimulusDarkWakeActivityTickle );
7269 }
7270
7271 return wranglerTickled;
7272 #else /* ! DISPLAY_WRANGLER_PRESENT */
7273 return false;
7274 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7275 }
7276
7277 //******************************************************************************
7278 // setDisplayPowerOn
7279 //
7280 // For root domain user client
7281 //******************************************************************************
7282
7283 void
7284 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7285 {
7286 pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7287 (void *) NULL, options );
7288 }
7289
7290 // MARK: -
7291 // MARK: System PM Policy
7292
7293 //******************************************************************************
7294 // checkSystemSleepAllowed
7295 //
7296 //******************************************************************************
7297
7298 bool
7299 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7300 uint32_t sleepReason )
7301 {
7302 uint32_t err = 0;
7303
7304 // Conditions that prevent idle and demand system sleep.
7305
7306 do {
7307 if (userDisabledAllSleep) {
7308 err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7309 break;
7310 }
7311
7312 if (systemBooting || systemShutdown || gWillShutdown) {
7313 err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7314 break;
7315 }
7316
7317 if (options == 0) {
7318 break;
7319 }
7320
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.
7324
7325 #if !CONFIG_SLEEP
7326 err = kPMConfigPreventSystemSleep; // 3. config does not support sleep
7327 break;
7328 #endif
7329
7330 if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7331 break; // always sleep on low battery or when in thermal warning/emergency state
7332 }
7333
7334 if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7335 break; // always sleep on dark wake thermal emergencies
7336 }
7337
7338 if (preventSystemSleepList->getCount() != 0) {
7339 err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7340 break;
7341 }
7342
7343 if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7344 kIOPMDriverAssertionLevelOn) {
7345 err = kPMCPUAssertion; // 5. CPU assertion
7346 break;
7347 }
7348
7349 if (pciCantSleepValid) {
7350 if (pciCantSleepFlag) {
7351 err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7352 }
7353 break;
7354 } else if (sleepSupportedPEFunction &&
7355 CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7356 IOReturn ret;
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;
7367 break;
7368 }
7369 }
7370 }while (false);
7371
7372 if (err) {
7373 DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7374 return false;
7375 }
7376 return true;
7377 }
7378
7379 bool
7380 IOPMrootDomain::checkSystemSleepEnabled( void )
7381 {
7382 return checkSystemSleepAllowed(0, 0);
7383 }
7384
7385 bool
7386 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7387 {
7388 ASSERT_GATED();
7389 return checkSystemSleepAllowed(1, sleepReason);
7390 }
7391
7392 //******************************************************************************
7393 // checkSystemCanSustainFullWake
7394 //******************************************************************************
7395
7396 bool
7397 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7398 {
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.
7403 return false;
7404 }
7405
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.
7410
7411 if (!acAdaptorConnected) {
7412 DLOG("full wake check: no AC\n");
7413 return false;
7414 }
7415 }
7416 return true;
7417 }
7418
7419 //******************************************************************************
7420 // mustHibernate
7421 //******************************************************************************
7422
7423 #if HIBERNATION
7424
7425 bool
7426 IOPMrootDomain::mustHibernate( void )
7427 {
7428 return lowBatteryCondition || thermalWarningState;
7429 }
7430
7431 #endif /* HIBERNATION */
7432
7433 //******************************************************************************
7434 // AOT
7435 //******************************************************************************
7436
7437 // Tables for accumulated days in year by month, latter used for leap years
7438
7439 static const unsigned int daysbymonth[] =
7440 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7441
7442 static const unsigned int lydaysbymonth[] =
7443 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7444
7445 static int __unused
7446 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7447 {
7448 const unsigned int * dbm = daysbymonth;
7449 clock_sec_t n, x, y, z;
7450
7451 // Calculate seconds, minutes and hours
7452
7453 n = secs % (24 * 3600);
7454 dt->second = n % 60;
7455 n /= 60;
7456 dt->minute = n % 60;
7457 dt->hour = (typeof(dt->hour))(n / 60);
7458
7459 // Calculate day of week
7460
7461 n = secs / (24 * 3600);
7462 // dt->dayWeek = (n + 4) % 7;
7463
7464 // Calculate year
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
7467 // on a leap year.
7468
7469 n += (366 + 365);
7470
7471 // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7472 // Valid before 2100, since 2100 is not a leap year.
7473
7474 x = n / 1461; // number of 4 year cycles
7475 y = n % 1461; // days into current 4 year cycle
7476 z = 1968 + (4 * x);
7477
7478 // Add in years in the current 4 year cycle
7479
7480 if (y >= 366) {
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
7484 } else {
7485 n = y;
7486 dbm = lydaysbymonth;
7487 }
7488 if (z > 2099) {
7489 return 0;
7490 }
7491
7492 dt->year = (typeof(dt->year))z;
7493
7494 // Adjust remaining days value to start at 1
7495
7496 n += 1;
7497
7498 // Calculate month
7499
7500 for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7501 continue;
7502 }
7503 dt->month = (typeof(dt->month))x;
7504
7505 // Calculate day of month
7506
7507 dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7508
7509 return 1;
7510 }
7511
7512 static clock_sec_t
7513 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7514 {
7515 const unsigned int * dbm = daysbymonth;
7516 long y, secs, days;
7517
7518 if (dt->year < 1970 || dt->month > 12) {
7519 return 0;
7520 }
7521
7522 // Seconds elapsed in the current day
7523
7524 secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7525
7526 // Number of days from 1/1/70 to beginning of current year
7527 // Account for extra day every 4 years starting at 1973
7528
7529 y = dt->year - 1970;
7530 days = (y * 365) + ((y + 1) / 4);
7531
7532 // Change table if current year is a leap year
7533
7534 if ((dt->year % 4) == 0) {
7535 dbm = lydaysbymonth;
7536 }
7537
7538 // Add in days elapsed in the current year
7539
7540 days += (dt->day - 1) + dbm[dt->month - 1];
7541
7542 // Add accumulated days to accumulated seconds
7543
7544 secs += 24 * 3600 * days;
7545
7546 return secs;
7547 }
7548
7549 unsigned long
7550 IOPMrootDomain::getRUN_STATE(void)
7551 {
7552 return _aotNow ? AOT_STATE : ON_STATE;
7553 }
7554
7555 bool
7556 IOPMrootDomain::isAOTMode()
7557 {
7558 return _aotNow;
7559 }
7560
7561 IOReturn
7562 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7563 {
7564 clock_sec_t nowsecs, wakesecs;
7565 clock_usec_t nowmicrosecs, wakemicrosecs;
7566 uint64_t nowAbs, wakeAbs;
7567
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);
7572 wakeAbs = nowAbs;
7573 }
7574 wakeAbs -= nowAbs;
7575 absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7576
7577 wakesecs += nowsecs;
7578 wakemicrosecs += nowmicrosecs;
7579 if (wakemicrosecs >= USEC_PER_SEC) {
7580 wakesecs++;
7581 wakemicrosecs -= USEC_PER_SEC;
7582 }
7583 if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7584 wakesecs++;
7585 }
7586
7587 IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7588
7589 if (_aotWakeTimeContinuous != wakeContinuousTime) {
7590 _aotWakeTimeContinuous = wakeContinuousTime;
7591 IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7592 }
7593 _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7594 _aotWakeTimeUTC = wakesecs;
7595
7596 return kIOReturnSuccess;
7597 }
7598
7599 // assumes WAKEEVENT_LOCK
7600 bool
7601 IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
7602 {
7603 bool exitNow;
7604 const char * reason = "";
7605
7606 if (software) {
7607 _aotExit = true;
7608 _aotMetrics->softwareRequestCount++;
7609 reason = "software request";
7610 } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7611 _aotExit = true;
7612 reason = gWakeReasonString;
7613 } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
7614 _aotExit = true;
7615 _aotMetrics->noTimeSetCount++;
7616 reason = "flipbook expired";
7617 } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7618 clock_sec_t sec;
7619 clock_usec_t usec;
7620 clock_get_calendar_microtime(&sec, &usec);
7621 if (_calendarWakeAlarmUTC <= sec) {
7622 _aotExit = true;
7623 _aotMetrics->rtcAlarmsCount++;
7624 reason = "user alarm";
7625 }
7626 }
7627 exitNow = (_aotNow && _aotExit);
7628 if (exitNow) {
7629 _aotNow = false;
7630 IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7631 reason,
7632 _aotMetrics->sleepCount,
7633 _aotMetrics->possibleCount,
7634 _aotMetrics->confirmedPossibleCount,
7635 _aotMetrics->rejectedPossibleCount,
7636 _aotMetrics->expiredPossibleCount,
7637 _aotMetrics->noTimeSetCount,
7638 _aotMetrics->rtcAlarmsCount);
7639 }
7640 return exitNow;
7641 }
7642
7643 void
7644 IOPMrootDomain::aotExit(bool cps)
7645 {
7646 uint32_t savedMessageMask;
7647
7648 ASSERT_GATED();
7649 _aotTasksSuspended = false;
7650 _aotReadyToFullWake = false;
7651 if (_aotTimerScheduled) {
7652 _aotTimerES->cancelTimeout();
7653 _aotTimerScheduled = false;
7654 }
7655 updateTasksSuspend();
7656
7657 _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7658 _aotLastWakeTime = 0;
7659 if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7660 WAKEEVENT_LOCK();
7661 strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7662 gWakeReasonString,
7663 sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7664 WAKEEVENT_UNLOCK();
7665 }
7666
7667 _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7668
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;
7675
7676 if (cps) {
7677 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7678 }
7679 }
7680
7681 void
7682 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7683 {
7684 bool exitNow;
7685
7686 IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7687
7688 WAKEEVENT_LOCK();
7689 exitNow = aotShouldExit(false, false);
7690 if (timer != NULL) {
7691 _aotTimerScheduled = false;
7692 }
7693 WAKEEVENT_UNLOCK();
7694 if (exitNow) {
7695 aotExit(true);
7696 } else {
7697 #if 0
7698 if (_aotLingerTime) {
7699 uint64_t deadline;
7700 IOLog("aot linger before sleep\n");
7701 clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7702 clock_delay_until(deadline);
7703 }
7704 #endif
7705 privateSleepSystem(kIOPMSleepReasonSoftware);
7706 }
7707 }
7708
7709 //******************************************************************************
7710 // adjustPowerState
7711 //
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
7716 // to SLEEP_STATE.
7717 //******************************************************************************
7718
7719 void
7720 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7721 {
7722 DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7723 getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7724
7725 ASSERT_GATED();
7726
7727 if (_aotNow) {
7728 bool exitNow;
7729
7730 if (AOT_STATE != getPowerState()) {
7731 return;
7732 }
7733 WAKEEVENT_LOCK();
7734 exitNow = aotShouldExit(true, false);
7735 if (!exitNow
7736 && !_aotTimerScheduled
7737 && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
7738 _aotTimerScheduled = true;
7739 if (_aotLingerTime) {
7740 _aotTimerES->setTimeout(_aotLingerTime);
7741 } else {
7742 _aotTimerES->setTimeout(800, kMillisecondScale);
7743 }
7744 }
7745 WAKEEVENT_UNLOCK();
7746 if (exitNow) {
7747 aotExit(true);
7748 } else {
7749 _aotReadyToFullWake = true;
7750 if (!_aotTimerScheduled) {
7751 privateSleepSystem(kIOPMSleepReasonSoftware);
7752 }
7753 }
7754 return;
7755 }
7756
7757 if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
7758 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
7759 } else if (sleepASAP) {
7760 changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
7761 }
7762 }
7763
7764 void
7765 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
7766 {
7767 if (powerOn) {
7768 if (!checkSystemCanSustainFullWake()) {
7769 DLOG("System cannot sustain full wake\n");
7770 return;
7771 }
7772
7773 // Force wrangler to max power state. If system is in dark wake
7774 // this alone won't raise the wrangler's power state.
7775 if (wrangler) {
7776 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
7777 }
7778
7779 // System in dark wake, always requesting full wake should
7780 // not have any bad side-effects, even if the request fails.
7781
7782 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7783 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
7784 requestFullWake( kFullWakeReasonDisplayOn );
7785 }
7786 } else {
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.
7791 if (wrangler) {
7792 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
7793 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
7794 }
7795 }
7796 }
7797
7798 //******************************************************************************
7799 // dispatchPowerEvent
7800 //
7801 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7802 //******************************************************************************
7803
7804 void
7805 IOPMrootDomain::dispatchPowerEvent(
7806 uint32_t event, void * arg0, uint64_t arg1 )
7807 {
7808 ASSERT_GATED();
7809
7810 switch (event) {
7811 case kPowerEventFeatureChanged:
7812 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7813 messageClients(kIOPMMessageFeatureChange, this);
7814 break;
7815
7816 case kPowerEventReceivedPowerNotification:
7817 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7818 handlePowerNotification((UInt32)(uintptr_t) arg0 );
7819 break;
7820
7821 case kPowerEventSystemBootCompleted:
7822 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7823 if (systemBooting) {
7824 systemBooting = false;
7825
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);
7834 }
7835 }
7836 if (lowBatteryCondition || thermalEmergencyState) {
7837 if (lowBatteryCondition) {
7838 privateSleepSystem(kIOPMSleepReasonLowPower);
7839 } else {
7840 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
7841 }
7842 // The rest is unnecessary since the system is expected
7843 // to sleep immediately. The following wake will update
7844 // everything.
7845 break;
7846 }
7847
7848 sleepWakeDebugMemAlloc();
7849 saveFailureData2File();
7850
7851 // If lid is closed, re-send lid closed notification
7852 // now that booting is complete.
7853 if (clamshellClosed) {
7854 handlePowerNotification(kLocalEvalClamshellCommand);
7855 }
7856 evaluatePolicy( kStimulusAllowSystemSleepChanged );
7857 }
7858 break;
7859
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.
7867 *
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.
7871 */
7872 systemShutdown = true;
7873 } else {
7874 /*
7875 * A shutdown was initiated, but then the shutdown
7876 * was cancelled, clearing systemShutdown to false here.
7877 */
7878 systemShutdown = false;
7879 }
7880 break;
7881
7882 case kPowerEventUserDisabledSleep:
7883 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7884 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
7885 break;
7886
7887 case kPowerEventRegisterSystemCapabilityClient:
7888 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7889
7890 // reset() handles the arg0 == nullptr case for us
7891 systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
7892 /* intentional fall-through */
7893 [[clang::fallthrough]];
7894
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);
7899 }
7900 if (arg0) {
7901 OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
7902 if (_joinedCapabilityClients) {
7903 _joinedCapabilityClients->setObject(notify.get());
7904 synchronizePowerTree( kIOPMSyncNoChildNotify );
7905 }
7906 }
7907 break;
7908
7909 case kPowerEventPolicyStimulus:
7910 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7911 if (arg0) {
7912 int stimulus = (int)(uintptr_t) arg0;
7913 evaluatePolicy(stimulus, (uint32_t) arg1);
7914 }
7915 break;
7916
7917 case kPowerEventAssertionCreate:
7918 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7919 if (pmAssertions) {
7920 pmAssertions->handleCreateAssertion((OSData *)arg0);
7921 }
7922 break;
7923
7924
7925 case kPowerEventAssertionRelease:
7926 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7927 if (pmAssertions) {
7928 pmAssertions->handleReleaseAssertion(arg1);
7929 }
7930 break;
7931
7932 case kPowerEventAssertionSetLevel:
7933 DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7934 if (pmAssertions) {
7935 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
7936 }
7937 break;
7938
7939 case kPowerEventQueueSleepWakeUUID:
7940 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7941 handleQueueSleepWakeUUID((OSObject *)arg0);
7942 break;
7943 case kPowerEventPublishSleepWakeUUID:
7944 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7945 handlePublishSleepWakeUUID((bool)arg0);
7946 break;
7947
7948 case kPowerEventSetDisplayPowerOn:
7949 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7950 if (arg1 != 0) {
7951 displayPowerOnRequested = true;
7952 } else {
7953 displayPowerOnRequested = false;
7954 }
7955 handleSetDisplayPowerOn(displayPowerOnRequested);
7956 break;
7957
7958 case kPowerEventPublishWakeType:
7959 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7960
7961 // Don't replace wake type property if already set
7962 if ((arg0 == gIOPMWakeTypeUserKey) ||
7963 !propertyExists(kIOPMRootDomainWakeTypeKey)) {
7964 const char * wakeType = NULL;
7965
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;
7977 }
7978
7979 if (wakeType) {
7980 setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
7981 }
7982 }
7983 break;
7984
7985 case kPowerEventAOTEvaluate:
7986 DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
7987 if (_aotReadyToFullWake) {
7988 aotEvaluate(NULL);
7989 }
7990 break;
7991 }
7992 }
7993
7994 //******************************************************************************
7995 // systemPowerEventOccurred
7996 //
7997 // The power controller is notifying us of a hardware-related power management
7998 // event that we must handle.
7999 //
8000 // systemPowerEventOccurred covers the same functionality that
8001 // receivePowerNotification does; it simply provides a richer API for conveying
8002 // more information.
8003 //******************************************************************************
8004
8005 IOReturn
8006 IOPMrootDomain::systemPowerEventOccurred(
8007 const OSSymbol *event,
8008 uint32_t intValue)
8009 {
8010 IOReturn attempt = kIOReturnSuccess;
8011 OSSharedPtr<OSNumber> newNumber;
8012
8013 if (!event) {
8014 return kIOReturnBadArgument;
8015 }
8016
8017 newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8018 if (!newNumber) {
8019 return kIOReturnInternalError;
8020 }
8021
8022 attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8023
8024 return attempt;
8025 }
8026
8027 void
8028 IOPMrootDomain::setThermalState(OSObject *value)
8029 {
8030 OSNumber * num;
8031
8032 if (gIOPMWorkLoop->inGate() == false) {
8033 gIOPMWorkLoop->runAction(
8034 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8035 (OSObject *)this,
8036 (void *)value);
8037
8038 return;
8039 }
8040 if (value && (num = OSDynamicCast(OSNumber, value))) {
8041 thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8042 (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8043 }
8044 }
8045
8046 IOReturn
8047 IOPMrootDomain::systemPowerEventOccurred(
8048 const OSSymbol *event,
8049 OSObject *value)
8050 {
8051 OSSharedPtr<OSDictionary> thermalsDict;
8052 bool shouldUpdate = true;
8053
8054 if (!event || !value) {
8055 return kIOReturnBadArgument;
8056 }
8057
8058 // LOCK
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);
8064 }
8065
8066 OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8067 OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8068
8069 if (origThermalsDict) {
8070 thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8071 } else {
8072 thermalsDict = OSDictionary::withCapacity(1);
8073 }
8074
8075 if (!thermalsDict) {
8076 shouldUpdate = false;
8077 goto exit;
8078 }
8079
8080 thermalsDict->setObject(event, value);
8081
8082 setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8083
8084 exit:
8085 // UNLOCK
8086 if (featuresDictLock) {
8087 IOLockUnlock(featuresDictLock);
8088 }
8089
8090 if (shouldUpdate) {
8091 if (event &&
8092 event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8093 setThermalState(value);
8094 }
8095 messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8096 }
8097
8098 return kIOReturnSuccess;
8099 }
8100
8101 //******************************************************************************
8102 // receivePowerNotification
8103 //
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 //******************************************************************************
8108
8109 IOReturn
8110 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8111 {
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);
8118 } else {
8119 DEBUG_LOG("power button pressed when system is up\n");
8120 }
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);
8125 }
8126 } else {
8127 pmPowerStateQueue->submitPowerEvent(
8128 kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8129 }
8130 return kIOReturnSuccess;
8131 }
8132
8133 void
8134 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8135 {
8136 bool eval_clamshell = false;
8137 bool eval_clamshell_alarm = false;
8138
8139 ASSERT_GATED();
8140
8141 /*
8142 * Local (IOPMrootDomain only) eval clamshell command
8143 */
8144 if (msg & kLocalEvalClamshellCommand) {
8145 if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8146 eval_clamshell_alarm = true;
8147
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;
8152 } else {
8153 eval_clamshell = true;
8154 }
8155 }
8156
8157 /*
8158 * Overtemp
8159 */
8160 if (msg & kIOPMOverTemp) {
8161 DLOG("Thermal overtemp message received!\n");
8162 thermalEmergencyState = true;
8163 privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8164 }
8165
8166 /*
8167 * Forward DW thermal notification to client, if system is not going to sleep
8168 */
8169 if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8170 DLOG("DarkWake thermal limits message received!\n");
8171 messageClients(kIOPMMessageDarkWakeThermalEmergency);
8172 }
8173
8174 /*
8175 * Sleep Now!
8176 */
8177 if (msg & kIOPMSleepNow) {
8178 privateSleepSystem(kIOPMSleepReasonSoftware);
8179 }
8180
8181 /*
8182 * Power Emergency
8183 */
8184 if (msg & kIOPMPowerEmergency) {
8185 DLOG("Received kIOPMPowerEmergency");
8186 lowBatteryCondition = true;
8187 privateSleepSystem(kIOPMSleepReasonLowPower);
8188 }
8189
8190 /*
8191 * Clamshell OPEN
8192 */
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;
8199
8200 // Don't issue a hid tickle when lid is open and polled on wake
8201 if (msg & kIOPMSetValue) {
8202 setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8203 reportUserInput();
8204 }
8205
8206 // Tell PMCPU
8207 informCPUStateChange(kInformLid, 0);
8208
8209 // Tell general interest clients
8210 sendClientClamshellNotification();
8211
8212 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
8213 || (lastSleepReason == kIOPMSleepReasonIdle)
8214 || (lastSleepReason == kIOPMSleepReasonMaintenance));
8215 if (aborting) {
8216 userActivityCount++;
8217 }
8218 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8219 }
8220
8221 /*
8222 * Clamshell CLOSED
8223 * Send the clamshell interest notification since the lid is closing.
8224 */
8225 if (msg & kIOPMClamshellClosed) {
8226 if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8227 clamshellClosed && clamshellExists) {
8228 DLOG("Ignoring redundant Clamshell close event\n");
8229 } else {
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;
8235
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;
8242
8243 // Tell PMCPU
8244 informCPUStateChange(kInformLid, 1);
8245
8246 // Tell general interest clients
8247 sendClientClamshellNotification();
8248
8249 // And set eval_clamshell = so we can attempt
8250 eval_clamshell = true;
8251 }
8252 }
8253
8254 /*
8255 * Set Desktop mode (sent from graphics)
8256 *
8257 * -> reevaluate lid state
8258 */
8259 if (msg & kIOPMSetDesktopMode) {
8260 desktopMode = (0 != (msg & kIOPMSetValue));
8261 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8262 DLOG("Desktop mode %d\n", desktopMode);
8263
8264 sendClientClamshellNotification();
8265
8266 // Re-evaluate the lid state
8267 eval_clamshell = true;
8268 }
8269
8270 /*
8271 * AC Adaptor connected
8272 *
8273 * -> reevaluate lid state
8274 */
8275 if (msg & kIOPMSetACAdaptorConnected) {
8276 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8277 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8278
8279 // Tell CPU PM
8280 informCPUStateChange(kInformAC, !acAdaptorConnected);
8281
8282 // Tell BSD if AC is connected
8283 // 0 == external power source; 1 == on battery
8284 post_sys_powersource(acAdaptorConnected ? 0:1);
8285
8286 sendClientClamshellNotification();
8287
8288 // Re-evaluate the lid state
8289 eval_clamshell = true;
8290
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 );
8295
8296 #if HIBERNATION
8297 // AC presence will reset the standy timer delay adjustment.
8298 _standbyTimerResetSeconds = 0;
8299 #endif
8300 if (!userIsActive) {
8301 // Reset userActivityTime when power supply is changed(rdr 13789330)
8302 clock_get_uptime(&userActivityTime);
8303 }
8304 }
8305
8306 /*
8307 * Enable Clamshell (external display disappear)
8308 *
8309 * -> reevaluate lid state
8310 */
8311 if (msg & kIOPMEnableClamshell) {
8312 DLOG("Clamshell enabled\n");
8313
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;
8319
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);
8329
8330 // Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8331 // when timer expires which is harmless but useless.
8332 thread_call_cancel(fullWakeThreadCall);
8333 }
8334 #endif
8335 }
8336
8337 clamshellDisabled = false;
8338 sendClientClamshellNotification();
8339 }
8340
8341 /*
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.
8345 */
8346 if (msg & kIOPMDisableClamshell) {
8347 DLOG("Clamshell disabled\n");
8348 clamshellDisabled = true;
8349 sendClientClamshellNotification();
8350 }
8351
8352 /*
8353 * Evaluate clamshell and SLEEP if appropriate
8354 */
8355 if (eval_clamshell_alarm && clamshellClosed) {
8356 if (shouldSleepOnRTCAlarmWake()) {
8357 privateSleepSystem(kIOPMSleepReasonClamshell);
8358 }
8359 } else if (eval_clamshell && clamshellClosed) {
8360 if (shouldSleepOnClamshellClosed()) {
8361 privateSleepSystem(kIOPMSleepReasonClamshell);
8362 } else {
8363 evaluatePolicy( kStimulusDarkWakeEvaluate );
8364 }
8365 }
8366
8367 if (msg & kIOPMProModeEngaged) {
8368 int newState = 1;
8369 DLOG("ProModeEngaged\n");
8370 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8371 }
8372
8373 if (msg & kIOPMProModeDisengaged) {
8374 int newState = 0;
8375 DLOG("ProModeDisengaged\n");
8376 messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8377 }
8378 }
8379
8380 //******************************************************************************
8381 // evaluatePolicy
8382 //
8383 // Evaluate root-domain policy in response to external changes.
8384 //******************************************************************************
8385
8386 void
8387 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8388 {
8389 union {
8390 struct {
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;
8399 } bit;
8400 uint32_t u32;
8401 } flags;
8402
8403
8404 ASSERT_GATED();
8405 flags.u32 = 0;
8406
8407 switch (stimulus) {
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;
8413 }
8414 if (!wranglerAsleep) {
8415 // transition from wrangler wake to wrangler sleep
8416 flags.bit.displaySleepEntry = true;
8417 wranglerAsleep = true;
8418 }
8419 break;
8420
8421 case kStimulusDisplayWranglerWake:
8422 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8423 displayIdleForDemandSleep = false;
8424 wranglerPowerOff = false;
8425 wranglerAsleep = false;
8426 break;
8427
8428 case kStimulusEnterUserActiveState:
8429 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8430 if (_preventUserActive) {
8431 DLOG("user active dropped\n");
8432 break;
8433 }
8434 if (!userIsActive) {
8435 userIsActive = true;
8436 userWasActive = true;
8437 clock_get_uptime(&gUserActiveAbsTime);
8438
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);
8444 }
8445
8446 kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8447 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8448 messageClients(kIOPMMessageUserIsActiveChanged);
8449 }
8450 flags.bit.idleSleepDisabled = true;
8451 break;
8452
8453 case kStimulusLeaveUserActiveState:
8454 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8455 if (userIsActive) {
8456 clock_get_uptime(&gUserInactiveAbsTime);
8457 userIsActive = false;
8458 clock_get_uptime(&userBecameInactiveTime);
8459 flags.bit.userBecameInactive = true;
8460
8461 kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8462 setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8463 messageClients(kIOPMMessageUserIsActiveChanged);
8464 }
8465 break;
8466
8467 case kStimulusAggressivenessChanged:
8468 {
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;
8474
8475 // Fetch latest display and system sleep slider values.
8476 aggressiveValue = 0;
8477 getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8478 minutesToIdleSleep = (uint32_t) aggressiveValue;
8479
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);
8485
8486 DLOG("idle time -> %d secs (ena %d)\n",
8487 idleSeconds, (minutesToIdleSleep != 0));
8488
8489 // How long to wait before sleeping the system once
8490 // the displays turns off is indicated by 'extraSleepDelay'.
8491
8492 if (minutesToIdleSleep > minutesToDisplayDim) {
8493 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8494 } else if (minutesToIdleSleep == minutesToDisplayDim) {
8495 minutesDelta = 1;
8496 }
8497
8498 if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8499 idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8500 }
8501
8502 if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8503 flags.bit.idleSleepDisabled = true;
8504 idleSleepEnabled = false;
8505 }
8506 #if !defined(XNU_TARGET_OS_OSX)
8507 if (0x7fffffff == minutesToIdleSleep) {
8508 minutesToIdleSleep = idleSeconds;
8509 }
8510 #endif /* !defined(XNU_TARGET_OS_OSX) */
8511
8512 if (((minutesDelta != extraSleepDelay) ||
8513 (userActivityTime != userActivityTime_prev)) &&
8514 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8515 flags.bit.sleepDelayChanged = true;
8516 }
8517
8518 if (systemDarkWake && !darkWakeToSleepASAP &&
8519 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8520 // Reconsider decision to remain in dark wake
8521 flags.bit.evaluateDarkWake = true;
8522 }
8523
8524 sleepSlider = minutesToIdleSleep;
8525 extraSleepDelay = minutesDelta;
8526 userActivityTime_prev = userActivityTime;
8527 } break;
8528
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
8534 // from full wake.
8535 if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8536 wrangler->setProperties(wranglerIdleSettings.get());
8537 DLOG("Requested wrangler idle\n");
8538 }
8539 }
8540 // arg = sleepReason
8541 changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8542 break;
8543
8544 case kStimulusAllowSystemSleepChanged:
8545 DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8546 flags.bit.adjustPowerState = true;
8547 break;
8548
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.
8555 if (arg == true) {
8556 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8557 }
8558
8559 if (!darkWakeExit) {
8560 if (latchDisplayWranglerTickle(true)) {
8561 DLOG("latched tickle\n");
8562 break;
8563 }
8564
8565 darkWakeExit = true;
8566 DLOG("Requesting full wake due to dark wake activity tickle\n");
8567 requestFullWake( kFullWakeReasonLocalUser );
8568 }
8569 break;
8570
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.
8576
8577 if (arg == _systemStateGeneration) {
8578 DLOG("dark wake entry\n");
8579 systemDarkWake = true;
8580
8581 // Keep wranglerPowerOff an invariant when wrangler is absent
8582 if (wrangler) {
8583 wranglerPowerOff = true;
8584 }
8585
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");
8591 reportUserInput();
8592 }
8593 }
8594
8595 // Always accelerate disk spindown while in dark wake,
8596 // even if system does not support/allow sleep.
8597
8598 cancelIdleSleepTimer();
8599 setQuickSpinDownTimeout();
8600 }
8601 break;
8602
8603 case kStimulusDarkWakeEvaluate:
8604 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8605 if (systemDarkWake) {
8606 flags.bit.evaluateDarkWake = true;
8607 }
8608 break;
8609
8610 case kStimulusNoIdleSleepPreventers:
8611 DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8612 flags.bit.adjustPowerState = true;
8613 break;
8614 } /* switch(stimulus) */
8615
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;
8622
8623 if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8624 // System was previously in full wake. Sleep reason from
8625 // full to dark already recorded in fullToDarkReason.
8626
8627 if (lowBatteryCondition) {
8628 newSleepReason = kIOPMSleepReasonLowPower;
8629 } else if (thermalEmergencyState) {
8630 newSleepReason = kIOPMSleepReasonThermalEmergency;
8631 } else {
8632 newSleepReason = fullToDarkReason;
8633 }
8634 } else {
8635 // In dark wake from system sleep.
8636
8637 if (darkWakeSleepService) {
8638 newSleepReason = kIOPMSleepReasonSleepServiceExit;
8639 } else {
8640 newSleepReason = kIOPMSleepReasonMaintenance;
8641 }
8642 }
8643
8644 if (checkSystemCanSleep(newSleepReason)) {
8645 privateSleepSystem(newSleepReason);
8646 }
8647 } else { // non-maintenance (network) dark wake
8648 if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8649 // Release power clamp, and wait for children idle.
8650 adjustPowerState(true);
8651 } else {
8652 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8653 }
8654 }
8655 }
8656
8657 if (systemDarkWake) {
8658 // The rest are irrelevant while system is in dark wake.
8659 flags.u32 = 0;
8660 }
8661
8662 if ((flags.bit.displaySleepEntry) &&
8663 (kFullWakeReasonDisplayOn == fullWakeReason)) {
8664 // kIOPMSleepReasonNotificationWakeExit
8665 DLOG("Display sleep while in notification wake\n");
8666 changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8667 }
8668
8669 if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8670 bool cancelQuickSpindown = false;
8671
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.
8676
8677 DLOG("extra sleep timer changed\n");
8678 cancelIdleSleepTimer();
8679 cancelQuickSpindown = true;
8680 } else {
8681 DLOG("user inactive\n");
8682 }
8683
8684 if (!userIsActive && idleSleepEnabled) {
8685 startIdleSleepTimer(getTimeToIdleSleep());
8686 }
8687
8688 if (cancelQuickSpindown) {
8689 restoreUserSpinDownTimeout();
8690 }
8691 }
8692
8693 if (flags.bit.idleSleepEnabled) {
8694 DLOG("idle sleep timer enabled\n");
8695 if (!wrangler) {
8696 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8697 startIdleSleepTimer(getTimeToIdleSleep());
8698 #else
8699 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8700 startIdleSleepTimer( idleSeconds );
8701 #endif
8702 } else {
8703 // Start idle timer if prefs now allow system sleep
8704 // and user is already inactive. Disk spindown is
8705 // accelerated upon timer expiration.
8706
8707 if (!userIsActive) {
8708 startIdleSleepTimer(getTimeToIdleSleep());
8709 }
8710 }
8711 }
8712
8713 if (flags.bit.idleSleepDisabled) {
8714 DLOG("idle sleep timer disabled\n");
8715 cancelIdleSleepTimer();
8716 restoreUserSpinDownTimeout();
8717 adjustPowerState();
8718 }
8719
8720 if (flags.bit.adjustPowerState) {
8721 bool sleepASAP = false;
8722
8723 if (!systemBooting && (0 == idleSleepPreventersCount())) {
8724 if (!wrangler) {
8725 changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
8726 if (idleSleepEnabled) {
8727 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8728 if (!extraSleepDelay && !idleSleepTimerPending) {
8729 sleepASAP = true;
8730 }
8731 #else
8732 // stay awake for at least idleSeconds
8733 startIdleSleepTimer(idleSeconds);
8734 #endif
8735 }
8736 } else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake) {
8737 sleepASAP = true;
8738 }
8739 }
8740
8741 adjustPowerState(sleepASAP);
8742 }
8743 }
8744
8745 //******************************************************************************
8746
8747 unsigned int
8748 IOPMrootDomain::idleSleepPreventersCount()
8749 {
8750 if (_aotMode) {
8751 unsigned int count __block;
8752 count = 0;
8753 preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
8754 {
8755 count += (NULL == obj->metaCast("AppleARMBacklight"));
8756 return false;
8757 });
8758 return count;
8759 }
8760
8761 return preventIdleSleepList->getCount();
8762 }
8763
8764
8765 //******************************************************************************
8766 // requestFullWake
8767 //
8768 // Request transition from dark wake to full wake
8769 //******************************************************************************
8770
8771 void
8772 IOPMrootDomain::requestFullWake( FullWakeReason reason )
8773 {
8774 uint32_t options = 0;
8775 IOService * pciRoot = NULL;
8776 bool promotion = false;
8777
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))) {
8782 return;
8783 }
8784
8785 // Will clear reason upon exit from full wake
8786 fullWakeReason = reason;
8787
8788 _desiredCapability |= (kIOPMSystemCapabilityGraphics |
8789 kIOPMSystemCapabilityAudio);
8790
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);
8803
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();
8808 promotion = true;
8809 }
8810
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;
8819 }
8820
8821 synchronizePowerTree(options, pciRoot);
8822
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
8827 if (wrangler) {
8828 wrangler->activityTickle(0, 0);
8829 }
8830 }
8831
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)) {
8835 AbsoluteTime now;
8836 uint64_t nsec;
8837
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)));
8844 }
8845 }
8846
8847 //******************************************************************************
8848 // willEnterFullWake
8849 //
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.
8853 //
8854 // Assumptions: fullWakeReason was updated
8855 //******************************************************************************
8856
8857 void
8858 IOPMrootDomain::willEnterFullWake( void )
8859 {
8860 hibernateRetry = false;
8861 sleepToStandby = false;
8862 standbyNixed = false;
8863 resetTimers = false;
8864 sleepTimerMaintenance = false;
8865
8866 assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
8867
8868 _systemMessageClientMask = kSystemMessageClientPowerd |
8869 kSystemMessageClientLegacyApp;
8870
8871 if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
8872 // First time to attain full wake capability since the last wake
8873 _systemMessageClientMask |= kSystemMessageClientKernel;
8874
8875 // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
8876 setProperty(gIOPMUserTriggeredFullWakeKey.get(),
8877 (kFullWakeReasonLocalUser == fullWakeReason) ?
8878 kOSBooleanTrue : kOSBooleanFalse);
8879 }
8880 #if HIBERNATION
8881 IOHibernateSetWakeCapabilities(_pendingCapability);
8882 #endif
8883
8884 IOService::setAdvisoryTickleEnable( true );
8885 tellClients(kIOMessageSystemWillPowerOn);
8886 preventTransitionToUserActive(false);
8887 }
8888
8889 //******************************************************************************
8890 // fullWakeDelayedWork
8891 //
8892 // System has already entered full wake. Invoked by a delayed thread call.
8893 //******************************************************************************
8894
8895 void
8896 IOPMrootDomain::fullWakeDelayedWork( void )
8897 {
8898 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8899 if (!gIOPMWorkLoop->inGate()) {
8900 gIOPMWorkLoop->runAction(
8901 OSMemberFunctionCast(IOWorkLoop::Action, this,
8902 &IOPMrootDomain::fullWakeDelayedWork), this);
8903 return;
8904 }
8905
8906 DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
8907 _currentCapability, _pendingCapability, _highestCapability,
8908 clamshellDisabled, clamshellSleepDisableMask);
8909
8910 if (clamshellExists &&
8911 CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
8912 !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
8913 if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
8914 setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8915 } else {
8916 // Not the initial full wake after waking from sleep.
8917 // Evaluate the clamshell for rdar://problem/9157444.
8918 receivePowerNotification(kLocalEvalClamshellCommand);
8919 }
8920 }
8921 #endif
8922 }
8923
8924 //******************************************************************************
8925 // evaluateAssertions
8926 //
8927 //******************************************************************************
8928
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)
8934
8935 void
8936 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
8937 {
8938 IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
8939
8940 messageClients(kIOPMMessageDriverAssertionsChanged);
8941
8942 if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
8943 if (wrangler) {
8944 bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
8945
8946 DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
8947 wrangler->setIgnoreIdleTimer( value );
8948 }
8949 }
8950
8951 if (changedBits & kIOPMDriverAssertionCPUBit) {
8952 if (_aotNow) {
8953 IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
8954 }
8955 evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
8956 if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
8957 AbsoluteTime now;
8958 clock_usec_t microsecs;
8959 clock_get_uptime(&now);
8960 SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
8961 absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
8962 if (assertOnWakeReport) {
8963 HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
8964 DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
8965 }
8966 }
8967 }
8968
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);
8977 }
8978 }
8979 } else {
8980 DLOG("PreventIdleSleep driver assertion dropped\n");
8981 updatePreventIdleSleepList(this, false);
8982 }
8983 }
8984 }
8985
8986 // MARK: -
8987 // MARK: Statistics
8988
8989 //******************************************************************************
8990 // pmStats
8991 //
8992 //******************************************************************************
8993
8994 void
8995 IOPMrootDomain::pmStatsRecordEvent(
8996 int eventIndex,
8997 AbsoluteTime timestamp)
8998 {
8999 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9000 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9001 uint64_t delta;
9002 uint64_t nsec;
9003 OSSharedPtr<OSData> publishPMStats;
9004
9005 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9006
9007 absolutetime_to_nanoseconds(timestamp, &nsec);
9008
9009 switch (eventIndex) {
9010 case kIOPMStatsHibernateImageWrite:
9011 if (starting) {
9012 gPMStats.hibWrite.start = nsec;
9013 } else if (stopping) {
9014 gPMStats.hibWrite.stop = nsec;
9015 }
9016
9017 if (stopping) {
9018 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9019 IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9020 }
9021 break;
9022 case kIOPMStatsHibernateImageRead:
9023 if (starting) {
9024 gPMStats.hibRead.start = nsec;
9025 } else if (stopping) {
9026 gPMStats.hibRead.stop = nsec;
9027 }
9028
9029 if (stopping) {
9030 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9031 IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9032
9033 publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats));
9034 setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9035 bzero(&gPMStats, sizeof(gPMStats));
9036 }
9037 break;
9038 }
9039 }
9040
9041 /*
9042 * Appends a record of the application response to
9043 * IOPMrootDomain::pmStatsAppResponses
9044 */
9045 void
9046 IOPMrootDomain::pmStatsRecordApplicationResponse(
9047 const OSSymbol *response,
9048 const char *name,
9049 int messageType,
9050 uint32_t delay_ms,
9051 uint64_t id,
9052 OSObject *object,
9053 IOPMPowerStateIndex powerState,
9054 bool async)
9055 {
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;
9065
9066 if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9067 if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9068 notify->ackTimeoutCnt++;
9069 } else {
9070 notify->ackTimeoutCnt = 0;
9071 }
9072 }
9073
9074 if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9075 (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9076 return;
9077 }
9078
9079
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
9084 if (id) {
9085 kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9086 } else {
9087 kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9088 }
9089 notify->msgType = 0;
9090 }
9091
9092 responseDescription = OSDictionary::withCapacity(5);
9093 if (responseDescription) {
9094 if (response) {
9095 responseDescription->setObject(_statsResponseTypeKey.get(), response);
9096 }
9097
9098 msgNum = OSNumber::withNumber(messageType, 32);
9099 if (msgNum) {
9100 responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9101 }
9102
9103 if (!name && notify && notify->identifier) {
9104 name = notify->identifier->getCStringNoCopy();
9105 }
9106
9107 if (name && (strlen(name) > 0)) {
9108 appname = OSSymbol::withCString(name);
9109 if (appname) {
9110 responseDescription->setObject(_statsNameKey.get(), appname.get());
9111 }
9112 }
9113
9114 if (!id && notify) {
9115 id = notify->uuid0;
9116 }
9117 if (id != 0) {
9118 pidNum = OSNumber::withNumber(id, 64);
9119 if (pidNum) {
9120 responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9121 }
9122 }
9123
9124 delayNum = OSNumber::withNumber(delay_ms, 32);
9125 if (delayNum) {
9126 responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9127 }
9128
9129 if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9130 powerCaps = OSNumber::withNumber(powerState, 32);
9131
9132 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9133 static const char * driverCallTypes[] = {
9134 [kDriverCallInformPreChange] = "powerStateWillChangeTo",
9135 [kDriverCallInformPostChange] = "powerStateDidChangeTo",
9136 [kDriverCallSetPowerState] = "setPowerState"
9137 };
9138
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);
9143 }
9144 #endif
9145 } else {
9146 powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9147 }
9148 if (powerCaps) {
9149 responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9150 }
9151
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());
9163 }
9164 }
9165
9166 IOLockLock(pmStatsLock);
9167 if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9168 pmStatsAppResponses->setObject(responseDescription.get());
9169 }
9170 IOLockUnlock(pmStatsLock);
9171 }
9172
9173 return;
9174 }
9175
9176 // MARK: -
9177 // MARK: PMTraceWorker
9178
9179 //******************************************************************************
9180 // TracePoint support
9181 //
9182 //******************************************************************************
9183
9184 #define kIOPMRegisterNVRAMTracePointHandlerKey \
9185 "IOPMRegisterNVRAMTracePointHandler"
9186
9187 IOReturn
9188 IOPMrootDomain::callPlatformFunction(
9189 const OSSymbol * functionName,
9190 bool waitForFunction,
9191 void * param1, void * param2,
9192 void * param3, void * param4 )
9193 {
9194 if (pmTracer && functionName &&
9195 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9196 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9197 uint32_t tracePointPhases, tracePointPCI;
9198 uint64_t statusCode;
9199
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 );
9206 if (node) {
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);
9215 }
9216 }
9217 }
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);
9222 }
9223 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9224 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9225
9226 return kIOReturnSuccess;
9227 }
9228 #if HIBERNATION
9229 else if (functionName &&
9230 functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9231 if (gSleepPolicyHandler) {
9232 return kIOReturnExclusiveAccess;
9233 }
9234 if (!param1) {
9235 return kIOReturnBadArgument;
9236 }
9237 gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9238 gSleepPolicyTarget = (void *) param2;
9239 setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9240 return kIOReturnSuccess;
9241 }
9242 #endif
9243
9244 return super::callPlatformFunction(
9245 functionName, waitForFunction, param1, param2, param3, param4);
9246 }
9247
9248 void
9249 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9250 uintptr_t param1, uintptr_t param2, uintptr_t param3)
9251 {
9252 uint32_t code = IODBG_POWER(event);
9253 uint64_t regId = id;
9254 if (regId == 0) {
9255 regId = getRegistryEntryID();
9256 }
9257 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9258 }
9259
9260 void
9261 IOPMrootDomain::tracePoint( uint8_t point )
9262 {
9263 if (systemBooting) {
9264 return;
9265 }
9266
9267 if (kIOPMTracePointWakeCapabilityClients == point) {
9268 acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9269 }
9270
9271 kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9272 pmTracer->tracePoint(point);
9273 }
9274
9275 static void
9276 kext_log_putc(char c)
9277 {
9278 if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9279 return;
9280 }
9281 if (c == '(' || c == '[' || c == ' ') {
9282 c = 0;
9283 gKextNameEnd = true;
9284 }
9285
9286 gKextNameBuf[gKextNamePos++] = c;
9287 }
9288
9289 static int
9290 kext_log(const char *fmt, ...)
9291 {
9292 va_list listp;
9293
9294 va_start(listp, fmt);
9295 _doprnt(fmt, &listp, &kext_log_putc, 16);
9296 va_end(listp);
9297
9298 return 0;
9299 }
9300
9301 static OSPtr<const OSSymbol>
9302 copyKextIdentifierWithAddress(vm_address_t address)
9303 {
9304 OSSharedPtr<const OSSymbol> identifer;
9305
9306 IOLockLock(gHaltLogLock);
9307
9308 gKextNameEnd = false;
9309 gKextNamePos = 0;
9310 gKextNameBuf[0] = 0;
9311
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);
9315
9316 IOLockUnlock(gHaltLogLock);
9317
9318 return identifer;
9319 }
9320
9321 // Caller serialized using PM workloop
9322 const char *
9323 IOPMrootDomain::getNotificationClientName(OSObject *object)
9324 {
9325 IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9326 const char *clientName = "UNKNOWN";
9327
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);
9333 if (clientID) {
9334 OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9335 if (string) {
9336 notifier->clientName = OSSymbol::withString(string.get());
9337 }
9338 clientID->release();
9339 }
9340 } else if (notifier->identifier) {
9341 notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9342 }
9343 }
9344
9345 if (notifier->clientName) {
9346 clientName = notifier->clientName->getCStringNoCopy();
9347 }
9348
9349 return clientName;
9350 }
9351
9352 void
9353 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9354 {
9355 IOPMServiceInterestNotifier *notifier;
9356
9357 if (systemBooting) {
9358 return;
9359 }
9360 notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9361 if (!notifier) {
9362 return;
9363 }
9364
9365 if (start) {
9366 pmTracer->traceDetail(notifier->uuid0 >> 32);
9367 kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9368 (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9369
9370 // Update notifier state used for response/ack logging
9371 notifier->msgIndex = msgIndex;
9372 notifier->msgAbsTime = timestamp;
9373
9374 if (msgIndex != UINT_MAX) {
9375 DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9376 } else {
9377 DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9378 }
9379
9380 assert(notifierObject == NULL);
9381 notifierThread = current_thread();
9382 notifierObject.reset(notifier, OSRetain);
9383 } else {
9384 uint64_t nsec;
9385 uint32_t delayMS;
9386
9387 SUB_ABSOLUTETIME(&timestamp, &notifier->msgAbsTime);
9388 absolutetime_to_nanoseconds(timestamp, &nsec);
9389 delayMS = (uint32_t)(nsec / 1000000ULL);
9390 if (delayMS > notifier->maxMsgDelayMS) {
9391 notifier->maxMsgDelayMS = delayMS;
9392 }
9393
9394 assert(notifierObject == notifier);
9395 notifierObject.reset();
9396 notifierThread = NULL;
9397 }
9398 }
9399
9400 void
9401 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9402 {
9403 if (systemBooting) {
9404 return;
9405 }
9406 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9407 if (!notifier) {
9408 return;
9409 }
9410
9411 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9412 (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9413
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;
9418 }
9419 }
9420
9421 void
9422 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9423 {
9424 if (systemBooting) {
9425 return;
9426 }
9427 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9428 if (!notifier) {
9429 return;
9430 }
9431
9432 kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9433 (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9434
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);
9439 } else {
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);
9443 }
9444 }
9445
9446 void
9447 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9448 {
9449 if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9450 return;
9451 }
9452 if (systemBooting) {
9453 return;
9454 }
9455 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9456 if (!notifier) {
9457 return;
9458 }
9459
9460 DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9461 }
9462
9463 void
9464 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9465 {
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);
9471 }
9472 }
9473
9474 void
9475 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9476 {
9477 size_t reportSize;
9478 void **report = NULL;
9479 uint32_t bktCnt;
9480 uint32_t bktSize;
9481 uint32_t *clientCnt;
9482
9483 ASSERT_GATED();
9484
9485 report = NULL;
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;
9496 } else {
9497 assert(false);
9498 return;
9499 }
9500
9501 switch (action) {
9502 case kIOReportEnable:
9503
9504 if (*report) {
9505 (*clientCnt)++;
9506 break;
9507 }
9508
9509 reportSize = HISTREPORT_BUFSIZE(bktCnt);
9510 *report = IOMalloc(reportSize);
9511 if (*report == NULL) {
9512 break;
9513 }
9514 bzero(*report, reportSize);
9515 HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9516 getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9517
9518 if (channel_id == kAssertDelayChID) {
9519 assertOnWakeSecs = 0;
9520 }
9521
9522 break;
9523
9524 case kIOReportDisable:
9525 if (*clientCnt == 0) {
9526 break;
9527 }
9528 if (*clientCnt == 1) {
9529 IOFree(*report, HISTREPORT_BUFSIZE(bktCnt));
9530 *report = NULL;
9531 }
9532 (*clientCnt)--;
9533
9534 if (channel_id == kAssertDelayChID) {
9535 assertOnWakeSecs = -1; // Invalid value to prevent updates
9536 }
9537 break;
9538
9539 case kIOReportGetDimensions:
9540 if (*report) {
9541 HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9542 }
9543 break;
9544 }
9545
9546 return;
9547 }
9548
9549 IOReturn
9550 IOPMrootDomain::configureReport(IOReportChannelList *channelList,
9551 IOReportConfigureAction action,
9552 void *result,
9553 void *destination)
9554 {
9555 unsigned cnt;
9556 uint64_t configAction = (uint64_t)action;
9557
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) {
9563 continue;
9564 }
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);
9572 }
9573 }
9574
9575 return super::configureReport(channelList, action, result, destination);
9576 }
9577
9578 IOReturn
9579 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9580 {
9581 uint32_t size2cpy;
9582 void *data2cpy;
9583 void **report;
9584
9585 ASSERT_GATED();
9586
9587 report = NULL;
9588 if (ch_id == kAssertDelayChID) {
9589 report = &assertOnWakeReport;
9590 } else if (ch_id == kSleepDelaysChID) {
9591 report = &sleepDelaysReport;
9592 } else {
9593 assert(false);
9594 return kIOReturnBadArgument;
9595 }
9596
9597 if (*report == NULL) {
9598 return kIOReturnNotOpen;
9599 }
9600
9601 HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9602 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9603 return kIOReturnOverrun;
9604 }
9605
9606 HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9607 dest->appendBytes(data2cpy, size2cpy);
9608
9609 return kIOReturnSuccess;
9610 }
9611
9612 IOReturn
9613 IOPMrootDomain::updateReport(IOReportChannelList *channelList,
9614 IOReportUpdateAction action,
9615 void *result,
9616 void *destination)
9617 {
9618 uint32_t size2cpy;
9619 void *data2cpy;
9620 uint8_t buf[SIMPLEREPORT_BUFSIZE];
9621 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9622 unsigned cnt;
9623 uint64_t ch_id;
9624
9625 if (action != kIOReportCopyChannelData) {
9626 goto exit;
9627 }
9628
9629 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9630 ch_id = channelList->channels[cnt].channel_id;
9631
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);
9637 continue;
9638 } else if ((ch_id == kSleepCntChID) ||
9639 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9640 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9641 } else {
9642 continue;
9643 }
9644
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);
9651 }
9652
9653 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9654 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9655 dest->appendBytes(data2cpy, size2cpy);
9656 }
9657
9658 exit:
9659 return super::updateReport(channelList, action, result, destination);
9660 }
9661
9662
9663 //******************************************************************************
9664 // PMTraceWorker Class
9665 //
9666 //******************************************************************************
9667
9668 #undef super
9669 #define super OSObject
9670 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9671
9672 #define kPMBestGuessPCIDevicesCount 25
9673 #define kPMMaxRTCBitfieldSize 32
9674
9675 OSPtr<PMTraceWorker>
9676 PMTraceWorker::tracer(IOPMrootDomain * owner)
9677 {
9678 OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9679 if (!me || !me->init()) {
9680 return NULL;
9681 }
9682
9683 DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9684
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.
9688 me->owner = owner;
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;
9696 return me;
9697 }
9698
9699 void
9700 PMTraceWorker::RTC_TRACE(void)
9701 {
9702 if (tracePointHandler && tracePointTarget) {
9703 uint32_t wordA;
9704
9705 IOLockLock(pmTraceWorkerLock);
9706 wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9707 (coreGraphicsData << 8) | tracePhase;
9708 IOLockUnlock(pmTraceWorkerLock);
9709
9710 tracePointHandler( tracePointTarget, traceData32, wordA );
9711 _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
9712 }
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();
9717 IOLockLock(l);
9718 IOLockLock(l);
9719 }
9720 #endif
9721 }
9722
9723 int
9724 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
9725 {
9726 OSSharedPtr<const OSSymbol> deviceName;
9727 int index = -1;
9728
9729 IOLockLock(pmTraceWorkerLock);
9730
9731 if (!pciDeviceBitMappings) {
9732 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
9733 if (!pciDeviceBitMappings) {
9734 goto exit;
9735 }
9736 }
9737
9738 // Check for bitmask overflow.
9739 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
9740 goto exit;
9741 }
9742
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);
9749 }
9750
9751 if (!addedToRegistry && (index >= 0)) {
9752 addedToRegistry = owner->setProperty("PCITopLevel", this);
9753 }
9754
9755 exit:
9756 IOLockUnlock(pmTraceWorkerLock);
9757 return index;
9758 }
9759
9760 bool
9761 PMTraceWorker::serialize(OSSerialize *s) const
9762 {
9763 bool ok = false;
9764 if (pciDeviceBitMappings) {
9765 IOLockLock(pmTraceWorkerLock);
9766 ok = pciDeviceBitMappings->serialize(s);
9767 IOLockUnlock(pmTraceWorkerLock);
9768 }
9769 return ok;
9770 }
9771
9772 void
9773 PMTraceWorker::tracePoint(uint8_t phase)
9774 {
9775 // clear trace detail when phase begins
9776 if (tracePhase != phase) {
9777 traceData32 = 0;
9778 }
9779
9780 tracePhase = phase;
9781
9782 DLOG("trace point 0x%02x\n", tracePhase);
9783 RTC_TRACE();
9784 }
9785
9786 void
9787 PMTraceWorker::traceDetail(uint32_t detail)
9788 {
9789 if (detail == traceData32) {
9790 return;
9791 }
9792 traceData32 = detail;
9793 RTC_TRACE();
9794 }
9795
9796 void
9797 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
9798 {
9799 switch (component) {
9800 case kIOPMLoginWindowProgress:
9801 loginWindowData = data & kIOPMLoginWindowProgressMask;
9802 break;
9803 case kIOPMCoreDisplayProgress:
9804 coreDisplayData = data & kIOPMCoreDisplayProgressMask;
9805 break;
9806 case kIOPMCoreGraphicsProgress:
9807 coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
9808 break;
9809 default:
9810 return;
9811 }
9812
9813 DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
9814 RTC_TRACE();
9815 }
9816
9817 void
9818 PMTraceWorker::tracePCIPowerChange(
9819 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
9820 {
9821 uint32_t bitMask;
9822 uint32_t expectedFlag;
9823
9824 // Ignore PCI changes outside of system sleep/wake.
9825 if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
9826 (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
9827 return;
9828 }
9829
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) {
9836 return;
9837 }
9838
9839 // Mark this device off in our bitfield
9840 if (bitNum < kPMMaxRTCBitfieldSize) {
9841 bitMask = (1 << bitNum);
9842
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);
9848 } else {
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);
9853 }
9854
9855 DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
9856 RTC_TRACE();
9857 }
9858 }
9859
9860 uint64_t
9861 PMTraceWorker::getPMStatusCode()
9862 {
9863 return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
9864 }
9865
9866 uint8_t
9867 PMTraceWorker::getTracePhase()
9868 {
9869 return tracePhase;
9870 }
9871
9872 uint32_t
9873 PMTraceWorker::getTraceData()
9874 {
9875 return traceData32;
9876 }
9877
9878 // MARK: -
9879 // MARK: PMHaltWorker
9880
9881 //******************************************************************************
9882 // PMHaltWorker Class
9883 //
9884 //******************************************************************************
9885
9886 PMHaltWorker *
9887 PMHaltWorker::worker( void )
9888 {
9889 PMHaltWorker * me;
9890 IOThread thread;
9891
9892 do {
9893 me = OSTypeAlloc( PMHaltWorker );
9894 if (!me || !me->init()) {
9895 break;
9896 }
9897
9898 me->lock = IOLockAlloc();
9899 if (!me->lock) {
9900 break;
9901 }
9902
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)) {
9906 me->release();
9907 break;
9908 }
9909 thread_deallocate(thread);
9910 return me;
9911 } while (false);
9912
9913 if (me) {
9914 me->release();
9915 }
9916 return NULL;
9917 }
9918
9919 void
9920 PMHaltWorker::free( void )
9921 {
9922 DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
9923 if (lock) {
9924 IOLockFree(lock);
9925 lock = NULL;
9926 }
9927 return OSObject::free();
9928 }
9929
9930 void
9931 PMHaltWorker::main( void * arg, wait_result_t waitResult )
9932 {
9933 PMHaltWorker * me = (PMHaltWorker *) arg;
9934
9935 IOLockLock( gPMHaltLock );
9936 gPMHaltBusyCount++;
9937 me->depth = gPMHaltDepth;
9938 IOLockUnlock( gPMHaltLock );
9939
9940 while (me->depth >= 0) {
9941 PMHaltWorker::work( me );
9942
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.
9947 gPMHaltDepth--;
9948 me->depth = gPMHaltDepth;
9949 gPMHaltIdleCount = 0;
9950 thread_wakeup((event_t) &gPMHaltIdleCount);
9951 } else {
9952 // One or more threads are still working on this level,
9953 // this thread must wait.
9954 me->depth = gPMHaltDepth - 1;
9955 do {
9956 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
9957 } while (me->depth != gPMHaltDepth);
9958 }
9959 IOLockUnlock( gPMHaltLock );
9960 }
9961
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 );
9965 me->release();
9966 }
9967
9968 void
9969 PMHaltWorker::work( PMHaltWorker * me )
9970 {
9971 OSSharedPtr<IOService> service;
9972 OSSet * inner;
9973 AbsoluteTime startTime, elapsedTime;
9974 UInt32 deltaTime;
9975 bool timeout;
9976
9977 while (true) {
9978 timeout = false;
9979
9980 // Claim an unit of work from the shared pool
9981 IOLockLock( gPMHaltLock );
9982 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
9983 if (inner) {
9984 service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
9985 if (service) {
9986 inner->removeObject(service.get());
9987 }
9988 }
9989 IOLockUnlock( gPMHaltLock );
9990 if (!service) {
9991 break; // no more work at this depth
9992 }
9993 clock_get_uptime(&startTime);
9994
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);
10002
10003 service->systemWillShutdown( gPMHaltMessageType);
10004
10005 // Wait for driver acknowledgement
10006 IOLockLock(me->lock);
10007 while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10008 IOLockSleep(me->lock, me, THREAD_UNINT);
10009 }
10010 me->service = NULL;
10011 timeout = me->timeout;
10012 IOLockUnlock(me->lock);
10013 }
10014
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),
10024 elapsedTime);
10025 }
10026
10027 me->visits++;
10028 }
10029 }
10030
10031 void
10032 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10033 {
10034 UInt64 nano;
10035 AbsoluteTime startTime;
10036 AbsoluteTime endTime;
10037
10038 endTime = *now;
10039
10040 IOLockLock(me->lock);
10041 if (me->service && !me->timeout) {
10042 startTime = me->startTime;
10043 nano = 0;
10044 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10045 SUB_ABSOLUTETIME(&endTime, &startTime);
10046 absolutetime_to_nanoseconds(endTime, &nano);
10047 }
10048 if (nano > 3000000000ULL) {
10049 me->timeout = true;
10050
10051 halt_log_enter("PowerOff/Restart still waiting on handler",
10052 OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10053 endTime);
10054 MSG("%s still waiting on %s\n",
10055 (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" : "Restart",
10056 me->service->getName());
10057 }
10058 }
10059 IOLockUnlock(me->lock);
10060 }
10061
10062 //******************************************************************************
10063 // acknowledgeSystemWillShutdown
10064 //
10065 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10066 //******************************************************************************
10067
10068 void
10069 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10070 {
10071 PMHaltWorker * worker;
10072 OSSharedPtr<OSObject> prop;
10073
10074 if (!from) {
10075 return;
10076 }
10077
10078 //DLOG("%s acknowledged\n", from->getName());
10079 prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10080 if (prop) {
10081 worker = (PMHaltWorker *) prop.get();
10082 IOLockLock(worker->lock);
10083 from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10084 thread_wakeup((event_t) worker);
10085 IOLockUnlock(worker->lock);
10086 } else {
10087 DLOG("%s acknowledged without worker property\n",
10088 from->getName());
10089 }
10090 }
10091
10092
10093 //******************************************************************************
10094 // notifySystemShutdown
10095 //
10096 // Notify all objects in PM tree that system will shutdown or restart
10097 //******************************************************************************
10098
10099 static void
10100 notifySystemShutdown( IOService * root, uint32_t messageType )
10101 {
10102 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10103 OSSharedPtr<IORegistryIterator> iter;
10104 IORegistryEntry * entry;
10105 IOService * node;
10106 OSSet * inner;
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;
10115 int waitResult;
10116 void * baseFunc;
10117 bool ok;
10118
10119 DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10120
10121 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10122
10123 // Iterate the entire PM tree starting from root
10124
10125 rootDepth = root->getDepth( gIOPowerPlane );
10126 if (!rootDepth) {
10127 goto done;
10128 }
10129
10130 // debug - for repeated test runs
10131 while (PMHaltWorker::metaClass->getInstanceCount()) {
10132 IOSleep(1);
10133 }
10134
10135 if (!gPMHaltArray) {
10136 gPMHaltArray = OSArray::withCapacity(40);
10137 if (!gPMHaltArray) {
10138 goto done;
10139 }
10140 } else { // debug
10141 gPMHaltArray->flushCollection();
10142 }
10143
10144 if (!gPMHaltLock) {
10145 gPMHaltLock = IOLockAlloc();
10146 if (!gPMHaltLock) {
10147 goto done;
10148 }
10149 }
10150
10151 if (!gPMHaltClientAcknowledgeKey) {
10152 gPMHaltClientAcknowledgeKey =
10153 OSSymbol::withCStringNoCopy("PMShutdown");
10154 if (!gPMHaltClientAcknowledgeKey) {
10155 goto done;
10156 }
10157 }
10158
10159 gPMHaltMessageType = messageType;
10160
10161 // Depth-first walk of PM plane
10162
10163 iter = IORegistryIterator::iterateOver(
10164 root, gIOPowerPlane, kIORegistryIterateRecursively);
10165
10166 if (iter) {
10167 while ((entry = iter->getNextObject())) {
10168 node = OSDynamicCast(IOService, entry);
10169 if (!node) {
10170 continue;
10171 }
10172
10173 if (baseFunc ==
10174 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10175 continue;
10176 }
10177
10178 depth = node->getDepth( gIOPowerPlane );
10179 if (depth <= rootDepth) {
10180 continue;
10181 }
10182
10183 ok = false;
10184
10185 // adjust to zero based depth
10186 depth -= (rootDepth + 1);
10187
10188 // gPMHaltArray is an array of containers, each container
10189 // refers to nodes with the same depth.
10190
10191 count = gPMHaltArray->getCount();
10192 while (depth >= count) {
10193 // expand array and insert placeholders
10194 gPMHaltArray->setObject(PLACEHOLDER);
10195 count++;
10196 }
10197 count = gPMHaltArray->getCount();
10198 if (depth < count) {
10199 inner = (OSSet *)gPMHaltArray->getObject(depth);
10200 if (inner == PLACEHOLDER) {
10201 newInner = OSSet::withCapacity(40);
10202 if (newInner) {
10203 gPMHaltArray->replaceObject(depth, newInner.get());
10204 inner = newInner.get();
10205 }
10206 }
10207
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.
10210 if (inner) {
10211 ok = inner->setObject(node);
10212 }
10213 }
10214 if (!ok) {
10215 DLOG("Skipped PM node %s\n", node->getName());
10216 }
10217 }
10218 }
10219
10220 // debug only
10221 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10222 count = 0;
10223 if (inner != PLACEHOLDER) {
10224 count = inner->getCount();
10225 }
10226 DLOG("Nodes at depth %u = %u\n", i, count);
10227 }
10228
10229 // strip placeholders (not all depths are populated)
10230 numWorkers = 0;
10231 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10232 if (inner == PLACEHOLDER) {
10233 gPMHaltArray->removeObject(i);
10234 continue;
10235 }
10236 count = inner->getCount();
10237 if (count > numWorkers) {
10238 numWorkers = count;
10239 }
10240 totalNodes += count;
10241 i++;
10242 }
10243
10244 if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10245 goto done;
10246 }
10247
10248 gPMHaltBusyCount = 0;
10249 gPMHaltIdleCount = 0;
10250 gPMHaltDepth = gPMHaltArray->getCount() - 1;
10251
10252 // Create multiple workers (and threads)
10253
10254 if (numWorkers > kPMHaltMaxWorkers) {
10255 numWorkers = kPMHaltMaxWorkers;
10256 }
10257
10258 DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10259 totalNodes, gPMHaltArray->getCount(), numWorkers);
10260
10261 for (unsigned int i = 0; i < numWorkers; i++) {
10262 workers[i] = PMHaltWorker::worker();
10263 }
10264
10265 // Wait for workers to exhaust all available work
10266
10267 IOLockLock(gPMHaltLock);
10268 while (gPMHaltDepth >= 0) {
10269 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10270
10271 waitResult = IOLockSleepDeadline(
10272 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10273 if (THREAD_TIMED_OUT == waitResult) {
10274 AbsoluteTime now;
10275 clock_get_uptime(&now);
10276
10277 IOLockUnlock(gPMHaltLock);
10278 for (unsigned int i = 0; i < numWorkers; i++) {
10279 if (workers[i]) {
10280 PMHaltWorker::checkTimeout(workers[i], &now);
10281 }
10282 }
10283 IOLockLock(gPMHaltLock);
10284 }
10285 }
10286 IOLockUnlock(gPMHaltLock);
10287
10288 // Release all workers
10289
10290 for (unsigned int i = 0; i < numWorkers; i++) {
10291 if (workers[i]) {
10292 workers[i]->release();
10293 }
10294 // worker also retained by it's own thread
10295 }
10296
10297 done:
10298 DLOG("%s done\n", __FUNCTION__);
10299 return;
10300 }
10301
10302 // MARK: -
10303 // MARK: Kernel Assertion
10304
10305 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10306
10307 IOPMDriverAssertionID
10308 IOPMrootDomain::createPMAssertion(
10309 IOPMDriverAssertionType whichAssertionBits,
10310 IOPMDriverAssertionLevel assertionLevel,
10311 IOService *ownerService,
10312 const char *ownerDescription)
10313 {
10314 IOReturn ret;
10315 IOPMDriverAssertionID newAssertion;
10316
10317 if (!pmAssertions) {
10318 return 0;
10319 }
10320
10321 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10322
10323 if (kIOReturnSuccess == ret) {
10324 return newAssertion;
10325 } else {
10326 return 0;
10327 }
10328 }
10329
10330 IOReturn
10331 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10332 {
10333 if (!pmAssertions) {
10334 return kIOReturnInternalError;
10335 }
10336
10337 return pmAssertions->releaseAssertion(releaseAssertion);
10338 }
10339
10340
10341 IOReturn
10342 IOPMrootDomain::setPMAssertionLevel(
10343 IOPMDriverAssertionID assertionID,
10344 IOPMDriverAssertionLevel assertionLevel)
10345 {
10346 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10347 }
10348
10349 IOPMDriverAssertionLevel
10350 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10351 {
10352 IOPMDriverAssertionType sysLevels;
10353
10354 if (!pmAssertions || whichAssertion == 0) {
10355 return kIOPMDriverAssertionLevelOff;
10356 }
10357
10358 sysLevels = pmAssertions->getActivatedAssertions();
10359
10360 // Check that every bit set in argument 'whichAssertion' is asserted
10361 // in the aggregate bits.
10362 if ((sysLevels & whichAssertion) == whichAssertion) {
10363 return kIOPMDriverAssertionLevelOn;
10364 } else {
10365 return kIOPMDriverAssertionLevelOff;
10366 }
10367 }
10368
10369 IOReturn
10370 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10371 {
10372 if (!pmAssertions) {
10373 return kIOReturnNotFound;
10374 }
10375
10376 return pmAssertions->setUserAssertionLevels(inLevels);
10377 }
10378
10379 bool
10380 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10381 {
10382 if (pmAssertions) {
10383 pmAssertions->publishProperties();
10384 }
10385 return IOService::serializeProperties(s);
10386 }
10387
10388 OSSharedPtr<OSObject>
10389 IOPMrootDomain::copyProperty( const char * aKey) const
10390 {
10391 OSSharedPtr<OSObject> obj;
10392 obj = IOService::copyProperty(aKey);
10393
10394 if (obj) {
10395 return obj;
10396 }
10397
10398 if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10399 sizeof(kIOPMSleepWakeWdogRebootKey))) {
10400 if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10401 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10402 } else {
10403 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10404 }
10405 }
10406
10407 if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10408 sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10409 if (swd_flags & SWD_VALID_LOGS) {
10410 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10411 } else {
10412 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10413 }
10414 }
10415
10416 /*
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.
10420 */
10421 if (!strcmp(aKey, "DesktopMode")) {
10422 if (desktopMode) {
10423 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10424 } else {
10425 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10426 }
10427 }
10428 if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10429 if (displayIdleForDemandSleep) {
10430 return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10431 } else {
10432 return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10433 }
10434 }
10435
10436 if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10437 OSSharedPtr<OSArray> array;
10438 WAKEEVENT_LOCK();
10439 if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10440 OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10441 if (collection) {
10442 array = OSDynamicPtrCast<OSArray>(collection);
10443 }
10444 }
10445 WAKEEVENT_UNLOCK();
10446 return os::move(array);
10447 }
10448
10449 if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10450 OSSharedPtr<OSArray> array;
10451 IOLockLock(pmStatsLock);
10452 if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10453 OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10454 if (collection) {
10455 array = OSDynamicPtrCast<OSArray>(collection);
10456 }
10457 }
10458 IOLockUnlock(pmStatsLock);
10459 return os::move(array);
10460 }
10461
10462 if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10463 OSArray *idleSleepList = NULL;
10464 gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10465 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10466 }
10467
10468 if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10469 OSArray *systemSleepList = NULL;
10470 gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10471 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10472 }
10473
10474 if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10475 OSArray *idleSleepList = NULL;
10476 gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10477 return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10478 }
10479
10480 if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10481 OSArray *systemSleepList = NULL;
10482 gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10483 return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10484 }
10485 return NULL;
10486 }
10487
10488 // MARK: -
10489 // MARK: Wake Event Reporting
10490
10491 void
10492 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10493 {
10494 WAKEEVENT_LOCK();
10495 strlcpy(outBuf, gWakeReasonString, bufSize);
10496 WAKEEVENT_UNLOCK();
10497 }
10498
10499 void
10500 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10501 {
10502 WAKEEVENT_LOCK();
10503 strlcpy(outBuf, gShutdownReasonString, bufSize);
10504 WAKEEVENT_UNLOCK();
10505 }
10506
10507 //******************************************************************************
10508 // acceptSystemWakeEvents
10509 //
10510 // Private control for the acceptance of driver wake event claims.
10511 //******************************************************************************
10512
10513 void
10514 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10515 {
10516 bool logWakeReason = false;
10517
10518 WAKEEVENT_LOCK();
10519 switch (control) {
10520 case kAcceptSystemWakeEvents_Enable:
10521 assert(_acceptSystemWakeEvents == false);
10522 if (!_systemWakeEventsArray) {
10523 _systemWakeEventsArray = OSArray::withCapacity(4);
10524 }
10525 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10526 if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10527 gWakeReasonString[0] = '\0';
10528 if (_systemWakeEventsArray) {
10529 _systemWakeEventsArray->flushCollection();
10530 }
10531 }
10532
10533 // Remove stale WakeType property before system sleep
10534 removeProperty(kIOPMRootDomainWakeTypeKey);
10535 removeProperty(kIOPMRootDomainWakeReasonKey);
10536 break;
10537
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;
10544 #if DEVELOPMENT
10545 static int panic_allowed = -1;
10546
10547 if ((panic_allowed == -1) &&
10548 (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10549 panic_allowed = 0;
10550 }
10551
10552 if (panic_allowed) {
10553 size_t i = 0;
10554 // Panic if wake reason is null or empty
10555 for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10556 if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10557 break;
10558 }
10559 }
10560 if (i >= strlen(gWakeReasonString)) {
10561 panic("Wake reason is empty\n");
10562 }
10563 }
10564 #endif /* DEVELOPMENT */
10565 #endif /* !defined(XNU_TARGET_OS_OSX) */
10566
10567 // publish kIOPMRootDomainWakeReasonKey if not already set
10568 if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10569 setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10570 }
10571 break;
10572
10573 case kAcceptSystemWakeEvents_Reenable:
10574 assert(_acceptSystemWakeEvents == false);
10575 _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10576 removeProperty(kIOPMRootDomainWakeReasonKey);
10577 break;
10578 }
10579 WAKEEVENT_UNLOCK();
10580
10581 if (logWakeReason) {
10582 MSG("system wake events: %s\n", gWakeReasonString);
10583 }
10584 }
10585
10586 //******************************************************************************
10587 // claimSystemWakeEvent
10588 //
10589 // For a driver to claim a device is the source/conduit of a system wake event.
10590 //******************************************************************************
10591
10592 void
10593 IOPMrootDomain::claimSystemWakeEvent(
10594 IOService * device,
10595 IOOptionBits flags,
10596 const char * reason,
10597 OSObject * details )
10598 {
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;
10607
10608 if (!device || !reason) {
10609 return;
10610 }
10611
10612 pmEventTimeStamp(&timestamp);
10613
10614 IOOptionBits aotFlags = 0;
10615 bool needAOTEvaluate = FALSE;
10616
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;
10629 }
10630 }
10631
10632 #if DEVELOPMENT || DEBUG
10633 if (_aotLingerTime && !strcmp("rtc", reason)) {
10634 flags |= kIOPMWakeEventAOTPossibleExit;
10635 }
10636 #endif /* DEVELOPMENT || DEBUG */
10637
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());
10643 }
10644
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());
10650 }
10651 }
10652 #endif
10653
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) {
10661 goto done;
10662 }
10663
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());
10669 if (details) {
10670 dict->setObject(kIOPMWakeEventDetailsKey, details);
10671 }
10672
10673 WAKEEVENT_LOCK();
10674 addWakeReason = _acceptSystemWakeEvents;
10675 if (_aotMode) {
10676 IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
10677 }
10678 aotFlags = (kIOPMWakeEventAOTFlags & flags);
10679 aotFlags = (aotFlags & ~_aotPendingFlags);
10680 needAOTEvaluate = false;
10681 if (_aotNow && aotFlags) {
10682 if (kIOPMWakeEventAOTPossibleExit & flags) {
10683 _aotMetrics->possibleCount++;
10684 }
10685 if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
10686 _aotMetrics->confirmedPossibleCount++;
10687 }
10688 if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
10689 _aotMetrics->rejectedPossibleCount++;
10690 }
10691 if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
10692 _aotMetrics->expiredPossibleCount++;
10693 }
10694
10695 _aotPendingFlags |= aotFlags;
10696 addWakeReason = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
10697 needAOTEvaluate = _aotReadyToFullWake;
10698 }
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);
10702
10703 if (!gWakeReasonSysctlRegistered) {
10704 // Lazy registration until the platform driver stops registering
10705 // the same name.
10706 gWakeReasonSysctlRegistered = true;
10707 }
10708 if (addWakeReason) {
10709 _systemWakeEventsArray->setObject(dict.get());
10710 if (gWakeReasonString[0] != '\0') {
10711 strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
10712 }
10713 strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
10714 }
10715
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);
10721 }
10722
10723 done:
10724 return;
10725 }
10726
10727 //******************************************************************************
10728 // claimSystemBootEvent
10729 //
10730 // For a driver to claim a device is the source/conduit of a system boot event.
10731 //******************************************************************************
10732
10733 void
10734 IOPMrootDomain::claimSystemBootEvent(
10735 IOService * device,
10736 IOOptionBits flags,
10737 const char * reason,
10738 __unused OSObject * details )
10739 {
10740 if (!device || !reason) {
10741 return;
10742 }
10743
10744 DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
10745 WAKEEVENT_LOCK();
10746 if (!gBootReasonSysctlRegistered) {
10747 // Lazy sysctl registration after setting gBootReasonString
10748 strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
10749 os_atomic_store(&gBootReasonSysctlRegistered, true, release);
10750 }
10751 WAKEEVENT_UNLOCK();
10752 }
10753
10754 //******************************************************************************
10755 // claimSystemShutdownEvent
10756 //
10757 // For drivers to claim a system shutdown event on the ensuing boot.
10758 //******************************************************************************
10759
10760 void
10761 IOPMrootDomain::claimSystemShutdownEvent(
10762 IOService * device,
10763 IOOptionBits flags,
10764 const char * reason,
10765 __unused OSObject * details )
10766 {
10767 if (!device || !reason) {
10768 return;
10769 }
10770
10771 DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
10772 WAKEEVENT_LOCK();
10773 if (gShutdownReasonString[0] != '\0') {
10774 strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
10775 }
10776 strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
10777
10778 gShutdownReasonSysctlRegistered = true;
10779 WAKEEVENT_UNLOCK();
10780 }
10781
10782 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10783
10784 // MARK: -
10785 // MARK: PMSettingHandle
10786
10787 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
10788
10789 void
10790 PMSettingHandle::free( void )
10791 {
10792 if (pmso) {
10793 pmso->clientHandleFreed();
10794 pmso->release();
10795 pmso = NULL;
10796 }
10797
10798 OSObject::free();
10799 }
10800
10801 // MARK: -
10802 // MARK: PMSettingObject
10803
10804 #undef super
10805 #define super OSObject
10806 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
10807
10808 /*
10809 * Static constructor/initializer for PMSettingObject
10810 */
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)
10819 {
10820 uint32_t settingCount = 0;
10821 PMSettingObject *pmso = NULL;
10822 PMSettingHandle *pmsh = NULL;
10823
10824 if (!parent_arg || !handler_arg || !settings || !handle_obj) {
10825 return NULL;
10826 }
10827
10828 // count OSSymbol entries in NULL terminated settings array
10829 while (settings[settingCount]) {
10830 settingCount++;
10831 }
10832 if (0 == settingCount) {
10833 return NULL;
10834 }
10835
10836 pmso = new PMSettingObject;
10837 if (!pmso || !pmso->init()) {
10838 goto fail;
10839 }
10840
10841 pmsh = new PMSettingHandle;
10842 if (!pmsh || !pmsh->init()) {
10843 goto fail;
10844 }
10845
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;
10852
10853 pmso->retain(); // handle holds a retain on pmso
10854 pmsh->pmso = pmso;
10855 pmso->pmsh = pmsh;
10856
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] );
10864 }
10865 }
10866
10867 *handle_obj = pmsh;
10868 return pmso;
10869
10870 fail:
10871 if (pmso) {
10872 pmso->release();
10873 }
10874 if (pmsh) {
10875 pmsh->release();
10876 }
10877 return NULL;
10878 }
10879
10880 void
10881 PMSettingObject::free( void )
10882 {
10883 if (publishedFeatureID) {
10884 for (uint32_t i = 0; i < settingCount; i++) {
10885 if (publishedFeatureID[i]) {
10886 parent->removePublishedFeature( publishedFeatureID[i] );
10887 }
10888 }
10889
10890 IOFree(publishedFeatureID, sizeof(uint32_t) * settingCount);
10891 }
10892
10893 super::free();
10894 }
10895
10896 IOReturn
10897 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
10898 {
10899 return (*func)(target, type, object, refcon);
10900 }
10901
10902 void
10903 PMSettingObject::clientHandleFreed( void )
10904 {
10905 parent->deregisterPMSettingObject(this);
10906 }
10907
10908 // MARK: -
10909 // MARK: PMAssertionsTracker
10910
10911 //*********************************************************************************
10912 //*********************************************************************************
10913 //*********************************************************************************
10914 // class PMAssertionsTracker Implementation
10915
10916 #define kAssertUniqueIDStart 500
10917
10918 PMAssertionsTracker *
10919 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
10920 {
10921 PMAssertionsTracker *me;
10922
10923 me = new PMAssertionsTracker;
10924 if (!me || !me->init()) {
10925 if (me) {
10926 me->release();
10927 }
10928 return NULL;
10929 }
10930
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;
10939
10940 assert(me->assertionsArray);
10941 assert(me->assertionsArrayLock);
10942
10943 return me;
10944 }
10945
10946 /* tabulate
10947 * - Update assertionsKernel to reflect the state of all
10948 * assertions in the kernel.
10949 * - Update assertionsCombined to reflect both kernel & user space.
10950 */
10951 void
10952 PMAssertionsTracker::tabulate(void)
10953 {
10954 int i;
10955 int count;
10956 PMAssertStruct *_a = NULL;
10957 OSData *_d = NULL;
10958
10959 IOPMDriverAssertionType oldKernel = assertionsKernel;
10960 IOPMDriverAssertionType oldCombined = assertionsCombined;
10961
10962 ASSERT_GATED();
10963
10964 assertionsKernel = 0;
10965 assertionsCombined = 0;
10966
10967 if (!assertionsArray) {
10968 return;
10969 }
10970
10971 if ((count = assertionsArray->getCount())) {
10972 for (i = 0; i < count; i++) {
10973 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
10974 if (_d) {
10975 _a = (PMAssertStruct *)_d->getBytesNoCopy();
10976 if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
10977 assertionsKernel |= _a->assertionBits;
10978 }
10979 }
10980 }
10981 }
10982
10983 tabulateProducerCount++;
10984 assertionsCombined = assertionsKernel | assertionsUser;
10985
10986 if ((assertionsKernel != oldKernel) ||
10987 (assertionsCombined != oldCombined)) {
10988 owner->evaluateAssertions(assertionsCombined, oldCombined);
10989 }
10990 }
10991
10992 void
10993 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
10994 {
10995 AbsoluteTime now;
10996 uint64_t nsec;
10997
10998 if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
10999 (assertStruct->assertCPUStartTime == 0)) {
11000 return;
11001 }
11002
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;
11008
11009 if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11010 maxAssertCPUDuration = assertStruct->assertCPUDuration;
11011 maxAssertCPUEntryId = assertStruct->registryEntryID;
11012 }
11013 }
11014
11015 void
11016 PMAssertionsTracker::reportCPUBitAccounting( void )
11017 {
11018 PMAssertStruct *_a;
11019 OSData *_d;
11020 int i, count;
11021 AbsoluteTime now;
11022 uint64_t nsec;
11023
11024 ASSERT_GATED();
11025
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));
11032 if (_d) {
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;
11045 }
11046 }
11047 }
11048 }
11049 }
11050 }
11051
11052 if (maxAssertCPUDuration) {
11053 DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11054 (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11055 }
11056
11057 maxAssertCPUDuration = 0;
11058 maxAssertCPUEntryId = 0;
11059 }
11060
11061 void
11062 PMAssertionsTracker::publishProperties( void )
11063 {
11064 OSSharedPtr<OSArray> assertionsSummary;
11065
11066 if (tabulateConsumerCount != tabulateProducerCount) {
11067 IOLockLock(assertionsArrayLock);
11068
11069 tabulateConsumerCount = tabulateProducerCount;
11070
11071 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11072 */
11073 assertionsSummary = copyAssertionsArray();
11074 if (assertionsSummary) {
11075 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11076 } else {
11077 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11078 }
11079
11080 /* Publish the IOPMrootDomain property "DriverPMAssertions"
11081 */
11082 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11083
11084 IOLockUnlock(assertionsArrayLock);
11085 }
11086 }
11087
11088 PMAssertionsTracker::PMAssertStruct *
11089 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11090 {
11091 PMAssertStruct *_a = NULL;
11092 OSData *_d = NULL;
11093 int found = -1;
11094 int count = 0;
11095 int i = 0;
11096
11097 if (assertionsArray
11098 && (count = assertionsArray->getCount())) {
11099 for (i = 0; i < count; i++) {
11100 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
11101 if (_d) {
11102 _a = (PMAssertStruct *)_d->getBytesNoCopy();
11103 if (_a && (_id == _a->id)) {
11104 found = i;
11105 break;
11106 }
11107 }
11108 }
11109 }
11110
11111 if (-1 == found) {
11112 return NULL;
11113 } else {
11114 if (index) {
11115 *index = found;
11116 }
11117 return _a;
11118 }
11119 }
11120
11121 /* PMAssertionsTracker::handleCreateAssertion
11122 * Perform assertion work on the PM workloop. Do not call directly.
11123 */
11124 IOReturn
11125 PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion)
11126 {
11127 PMAssertStruct *assertStruct;
11128
11129 ASSERT_GATED();
11130
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();
11137 }
11138 assertionsArray->setObject(newAssertion);
11139 IOLockUnlock(assertionsArrayLock);
11140 newAssertion->release();
11141
11142 tabulate();
11143 }
11144 return kIOReturnSuccess;
11145 }
11146
11147 /* PMAssertionsTracker::createAssertion
11148 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11149 * appropiate.
11150 */
11151 IOReturn
11152 PMAssertionsTracker::createAssertion(
11153 IOPMDriverAssertionType which,
11154 IOPMDriverAssertionLevel level,
11155 IOService *serviceID,
11156 const char *whoItIs,
11157 IOPMDriverAssertionID *outID)
11158 {
11159 OSSharedPtr<OSData> dataStore;
11160 PMAssertStruct track;
11161
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;
11166
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;
11176
11177 dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct));
11178 if (!dataStore) {
11179 if (track.ownerString) {
11180 track.ownerString->release();
11181 track.ownerString = NULL;
11182 }
11183 return kIOReturnNoMemory;
11184 }
11185
11186 *outID = track.id;
11187
11188 if (owner && owner->pmPowerStateQueue) {
11189 // queue action is responsible for releasing dataStore
11190 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11191 }
11192
11193 return kIOReturnSuccess;
11194 }
11195
11196 /* PMAssertionsTracker::handleReleaseAssertion
11197 * Runs in PM workloop. Do not call directly.
11198 */
11199 IOReturn
11200 PMAssertionsTracker::handleReleaseAssertion(
11201 IOPMDriverAssertionID _id)
11202 {
11203 ASSERT_GATED();
11204
11205 int index;
11206 PMAssertStruct *assertStruct = detailsForID(_id, &index);
11207
11208 if (!assertStruct) {
11209 return kIOReturnNotFound;
11210 }
11211
11212 IOLockLock(assertionsArrayLock);
11213
11214 if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11215 (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11216 updateCPUBitAccounting(assertStruct);
11217 }
11218
11219 if (assertStruct->ownerString) {
11220 assertStruct->ownerString->release();
11221 assertStruct->ownerString = NULL;
11222 }
11223
11224 assertionsArray->removeObject(index);
11225 IOLockUnlock(assertionsArrayLock);
11226
11227 tabulate();
11228 return kIOReturnSuccess;
11229 }
11230
11231 /* PMAssertionsTracker::releaseAssertion
11232 * Releases an assertion and affects system behavior if appropiate.
11233 * Actual work happens on PM workloop.
11234 */
11235 IOReturn
11236 PMAssertionsTracker::releaseAssertion(
11237 IOPMDriverAssertionID _id)
11238 {
11239 if (owner && owner->pmPowerStateQueue) {
11240 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11241 }
11242 return kIOReturnSuccess;
11243 }
11244
11245 /* PMAssertionsTracker::handleSetAssertionLevel
11246 * Runs in PM workloop. Do not call directly.
11247 */
11248 IOReturn
11249 PMAssertionsTracker::handleSetAssertionLevel(
11250 IOPMDriverAssertionID _id,
11251 IOPMDriverAssertionLevel _level)
11252 {
11253 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
11254
11255 ASSERT_GATED();
11256
11257 if (!assertStruct) {
11258 return kIOReturnNotFound;
11259 }
11260
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();
11267 } else {
11268 updateCPUBitAccounting(assertStruct);
11269 }
11270 }
11271 assertStruct->level = _level;
11272 IOLockUnlock(assertionsArrayLock);
11273
11274 tabulate();
11275 return kIOReturnSuccess;
11276 }
11277
11278 /* PMAssertionsTracker::setAssertionLevel
11279 */
11280 IOReturn
11281 PMAssertionsTracker::setAssertionLevel(
11282 IOPMDriverAssertionID _id,
11283 IOPMDriverAssertionLevel _level)
11284 {
11285 if (owner && owner->pmPowerStateQueue) {
11286 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11287 (void *)(uintptr_t)_level, _id);
11288 }
11289
11290 return kIOReturnSuccess;
11291 }
11292
11293 IOReturn
11294 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11295 {
11296 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11297
11298 ASSERT_GATED();
11299
11300 if (new_user_levels != assertionsUser) {
11301 DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11302 assertionsUser = new_user_levels;
11303 }
11304
11305 tabulate();
11306 return kIOReturnSuccess;
11307 }
11308
11309 IOReturn
11310 PMAssertionsTracker::setUserAssertionLevels(
11311 IOPMDriverAssertionType new_user_levels)
11312 {
11313 if (gIOPMWorkLoop) {
11314 gIOPMWorkLoop->runAction(
11315 OSMemberFunctionCast(
11316 IOWorkLoop::Action,
11317 this,
11318 &PMAssertionsTracker::handleSetUserAssertionLevels),
11319 this,
11320 (void *) &new_user_levels, NULL, NULL, NULL);
11321 }
11322
11323 return kIOReturnSuccess;
11324 }
11325
11326
11327 OSSharedPtr<OSArray>
11328 PMAssertionsTracker::copyAssertionsArray(void)
11329 {
11330 int count;
11331 int i;
11332 OSSharedPtr<OSArray> outArray = NULL;
11333
11334 if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11335 goto exit;
11336 }
11337 outArray = OSArray::withCapacity(count);
11338 if (!outArray) {
11339 goto exit;
11340 }
11341
11342 for (i = 0; i < count; i++) {
11343 PMAssertStruct *_a = NULL;
11344 OSData *_d = NULL;
11345 OSSharedPtr<OSDictionary> details;
11346
11347 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
11348 if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy())) {
11349 OSSharedPtr<OSNumber> _n;
11350
11351 details = OSDictionary::withCapacity(7);
11352 if (!details) {
11353 continue;
11354 }
11355
11356 outArray->setObject(details.get());
11357
11358 _n = OSNumber::withNumber(_a->id, 64);
11359 if (_n) {
11360 details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11361 }
11362 _n = OSNumber::withNumber(_a->createdTime, 64);
11363 if (_n) {
11364 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11365 }
11366 _n = OSNumber::withNumber(_a->modifiedTime, 64);
11367 if (_n) {
11368 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11369 }
11370 _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11371 if (_n) {
11372 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11373 }
11374 _n = OSNumber::withNumber(_a->level, 64);
11375 if (_n) {
11376 details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11377 }
11378 _n = OSNumber::withNumber(_a->assertionBits, 64);
11379 if (_n) {
11380 details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11381 }
11382
11383 if (_a->ownerString) {
11384 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11385 }
11386 }
11387 }
11388
11389 exit:
11390 return os::move(outArray);
11391 }
11392
11393 IOPMDriverAssertionType
11394 PMAssertionsTracker::getActivatedAssertions(void)
11395 {
11396 return assertionsCombined;
11397 }
11398
11399 IOPMDriverAssertionLevel
11400 PMAssertionsTracker::getAssertionLevel(
11401 IOPMDriverAssertionType type)
11402 {
11403 // FIXME: unused and also wrong
11404 if (type && ((type & assertionsKernel) == assertionsKernel)) {
11405 return kIOPMDriverAssertionLevelOn;
11406 } else {
11407 return kIOPMDriverAssertionLevelOff;
11408 }
11409 }
11410
11411 //*********************************************************************************
11412 //*********************************************************************************
11413 //*********************************************************************************
11414
11415
11416 static void
11417 pmEventTimeStamp(uint64_t *recordTS)
11418 {
11419 clock_sec_t tsec;
11420 clock_usec_t tusec;
11421
11422 if (!recordTS) {
11423 return;
11424 }
11425
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);
11429
11430
11431 // Pack the sec & microsec calendar time into a uint64_t, for fun.
11432 *recordTS = 0;
11433 *recordTS |= (uint32_t)tusec;
11434 *recordTS |= ((uint64_t)tsec << 32);
11435
11436 return;
11437 }
11438
11439 // MARK: -
11440 // MARK: IORootParent
11441
11442 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11443
11444 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11445
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.
11448 //
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.
11452
11453
11454 static IOPMPowerState patriarchPowerStates[2] =
11455 {
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},
11458 };
11459
11460 void
11461 IORootParent::initialize( void )
11462 {
11463
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);
11508 }
11509
11510 bool
11511 IORootParent::start( IOService * nub )
11512 {
11513 IOService::start(nub);
11514 attachToParent( getRegistryRoot(), gIOPowerPlane );
11515 PMinit();
11516 registerPowerDriver(this, patriarchPowerStates, 2);
11517 makeUsable();
11518 return true;
11519 }
11520
11521 void
11522 IORootParent::shutDownSystem( void )
11523 {
11524 }
11525
11526 void
11527 IORootParent::restartSystem( void )
11528 {
11529 }
11530
11531 void
11532 IORootParent::sleepSystem( void )
11533 {
11534 }
11535
11536 void
11537 IORootParent::dozeSystem( void )
11538 {
11539 }
11540
11541 void
11542 IORootParent::sleepToDoze( void )
11543 {
11544 }
11545
11546 void
11547 IORootParent::wakeSystem( void )
11548 {
11549 }
11550
11551 OSSharedPtr<OSObject>
11552 IORootParent::copyProperty( const char * aKey) const
11553 {
11554 return IOService::copyProperty(aKey);
11555 }
11556
11557 uint32_t
11558 IOPMrootDomain::getWatchdogTimeout()
11559 {
11560 if (gSwdSleepWakeTimeout) {
11561 gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11562 }
11563 if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11564 (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11565 return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11566 } else {
11567 return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11568 }
11569 }
11570
11571
11572 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11573 IOReturn
11574 IOPMrootDomain::restartWithStackshot()
11575 {
11576 takeStackshot(true);
11577
11578 return kIOReturnSuccess;
11579 }
11580
11581 void
11582 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11583 {
11584 takeStackshot(wdogTrigger);
11585 }
11586
11587 void
11588 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11589 {
11590 switch (tracePhase) {
11591 case kIOPMTracePointSleepStarted:
11592 *phaseString = "kIOPMTracePointSleepStarted";
11593 *description = "starting sleep";
11594 break;
11595
11596 case kIOPMTracePointSleepApplications:
11597 *phaseString = "kIOPMTracePointSleepApplications";
11598 *description = "notifying applications";
11599 break;
11600
11601 case kIOPMTracePointSleepPriorityClients:
11602 *phaseString = "kIOPMTracePointSleepPriorityClients";
11603 *description = "notifying clients about upcoming system capability changes";
11604 break;
11605
11606 case kIOPMTracePointSleepWillChangeInterests:
11607 *phaseString = "kIOPMTracePointSleepWillChangeInterests";
11608 *description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11609 break;
11610
11611 case kIOPMTracePointSleepPowerPlaneDrivers:
11612 *phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11613 *description = "calling power state change callbacks";
11614 break;
11615
11616 case kIOPMTracePointSleepDidChangeInterests:
11617 *phaseString = "kIOPMTracePointSleepDidChangeInterests";
11618 *description = "calling rootDomain's clients about rootDomain's state changes";
11619 break;
11620
11621 case kIOPMTracePointSleepCapabilityClients:
11622 *phaseString = "kIOPMTracePointSleepCapabilityClients";
11623 *description = "notifying clients about current system capabilities";
11624 break;
11625
11626 case kIOPMTracePointSleepPlatformActions:
11627 *phaseString = "kIOPMTracePointSleepPlatformActions";
11628 *description = "calling Quiesce/Sleep action callbacks";
11629 break;
11630
11631 case kIOPMTracePointSleepCPUs:
11632 {
11633 *phaseString = "kIOPMTracePointSleepCPUs";
11634 #if defined(__i386__) || defined(__x86_64__)
11635 /*
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.
11643 */
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;
11649 } else {
11650 *description = "halting all non-boot CPUs";
11651 }
11652 #else
11653 *description = "halting all non-boot CPUs";
11654 #endif
11655 break;
11656 }
11657 case kIOPMTracePointSleepPlatformDriver:
11658 *phaseString = "kIOPMTracePointSleepPlatformDriver";
11659 *description = "executing platform specific code";
11660 break;
11661
11662 case kIOPMTracePointHibernate:
11663 *phaseString = "kIOPMTracePointHibernate";
11664 *description = "writing the hibernation image";
11665 break;
11666
11667 case kIOPMTracePointSystemSleep:
11668 *phaseString = "kIOPMTracePointSystemSleep";
11669 *description = "in EFI/Bootrom after last point of entry to sleep";
11670 break;
11671
11672 case kIOPMTracePointWakePlatformDriver:
11673 *phaseString = "kIOPMTracePointWakePlatformDriver";
11674 *description = "executing platform specific code";
11675 break;
11676
11677
11678 case kIOPMTracePointWakePlatformActions:
11679 *phaseString = "kIOPMTracePointWakePlatformActions";
11680 *description = "calling Wake action callbacks";
11681 break;
11682
11683 case kIOPMTracePointWakeCPUs:
11684 *phaseString = "kIOPMTracePointWakeCPUs";
11685 *description = "starting non-boot CPUs";
11686 break;
11687
11688 case kIOPMTracePointWakeWillPowerOnClients:
11689 *phaseString = "kIOPMTracePointWakeWillPowerOnClients";
11690 *description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
11691 break;
11692
11693 case kIOPMTracePointWakeWillChangeInterests:
11694 *phaseString = "kIOPMTracePointWakeWillChangeInterests";
11695 *description = "calling rootDomain's clients about upcoming rootDomain's state changes";
11696 break;
11697
11698 case kIOPMTracePointWakeDidChangeInterests:
11699 *phaseString = "kIOPMTracePointWakeDidChangeInterests";
11700 *description = "calling rootDomain's clients about completed rootDomain's state changes";
11701 break;
11702
11703 case kIOPMTracePointWakePowerPlaneDrivers:
11704 *phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
11705 *description = "calling power state change callbacks";
11706 break;
11707
11708 case kIOPMTracePointWakeCapabilityClients:
11709 *phaseString = "kIOPMTracePointWakeCapabilityClients";
11710 *description = "informing clients about current system capabilities";
11711 break;
11712
11713 case kIOPMTracePointWakeApplications:
11714 *phaseString = "kIOPMTracePointWakeApplications";
11715 *description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
11716 break;
11717
11718 case kIOPMTracePointDarkWakeEntry:
11719 *phaseString = "kIOPMTracePointDarkWakeEntry";
11720 *description = "entering darkwake on way to sleep";
11721 break;
11722
11723 case kIOPMTracePointDarkWakeExit:
11724 *phaseString = "kIOPMTracePointDarkWakeExit";
11725 *description = "entering fullwake from darkwake";
11726 break;
11727
11728 default:
11729 *phaseString = NULL;
11730 *description = NULL;
11731 }
11732 }
11733
11734 void
11735 IOPMrootDomain::saveFailureData2File()
11736 {
11737 unsigned int len = 0;
11738 char failureStr[512];
11739 errno_t error;
11740 char *outbuf;
11741 OSNumber *statusCode;
11742 uint64_t pmStatusCode = 0;
11743 uint32_t phaseData = 0;
11744 uint32_t phaseDetail = 0;
11745 bool efiFailure = false;
11746
11747 OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
11748 statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
11749 if (statusCode) {
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");
11755 efiFailure = true;
11756 failureStr[0] = 0;
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));
11759 }
11760 }
11761
11762 if (!efiFailure) {
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
11767 return;
11768 }
11769
11770 /* Keeping this around for capturing data during power
11771 * button press */
11772
11773 if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
11774 DLOG("No sleep wake failure string\n");
11775 return;
11776 }
11777 if (len == 0) {
11778 DLOG("Ignoring zero byte SleepWake failure string\n");
11779 goto exit;
11780 }
11781
11782 // if PMStatus code is zero, delete stackshot and return
11783 if (statusCode) {
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");
11790 deleteStackshot();
11791 return;
11792 }
11793 }
11794
11795 if (len > sizeof(failureStr)) {
11796 len = sizeof(failureStr);
11797 }
11798 failureStr[0] = 0;
11799 PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
11800 }
11801 if (failureStr[0] != 0) {
11802 error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
11803 if (error) {
11804 DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
11805 } else {
11806 DLOG("Saved SleepWake failure string to file.\n");
11807 }
11808 }
11809
11810 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
11811 goto exit;
11812 }
11813
11814 if (swd_buffer) {
11815 unsigned int len = 0;
11816 errno_t error;
11817 char nvram_var_name_buffer[20];
11818 unsigned int concat_len = 0;
11819 swd_hdr *hdr = NULL;
11820
11821
11822 hdr = (swd_hdr *)swd_buffer;
11823 outbuf = (char *)hdr + hdr->spindump_offset;
11824 OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
11825
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);
11830 break;
11831 }
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");
11835 break;
11836 }
11837 PERemoveNVRAMProperty(nvram_var_name_buffer);
11838 concat_len += len;
11839 }
11840 LOG("Concatenated length for the SWD blob %d\n", concat_len);
11841
11842 if (concat_len) {
11843 error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
11844 if (error) {
11845 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
11846 } else {
11847 LOG("Saved SleepWake zipped data to file.\n");
11848 }
11849 } else {
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);
11854 if (error) {
11855 LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
11856 } else {
11857 LOG("Saved SleepWake zipped data to file.\n");
11858 }
11859 }
11860 } else {
11861 LOG("No buffer allocated to save failure stackshot\n");
11862 }
11863
11864
11865 gRootDomain->swd_lock = 0;
11866 exit:
11867 PERemoveNVRAMProperty(kIOSleepWakeFailureString);
11868 return;
11869 }
11870
11871
11872 void
11873 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
11874 {
11875 OSSharedPtr<IORegistryIterator> iter;
11876 OSSharedPtr<const OSSymbol> kextName = NULL;
11877 IORegistryEntry * entry;
11878 IOService * node;
11879 bool nodeFound = false;
11880
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;
11886
11887 IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
11888 uint32_t tracePhase = pmTracer->getTracePhase();
11889
11890 *thread = NULL;
11891 if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
11892 snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
11893 } else {
11894 snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
11895 }
11896 tracePhase2String(tracePhase, &phaseString, &phaseDescription);
11897
11898 if (notifierThread) {
11899 if (notifier && (notifier->identifier)) {
11900 objectName = notifier->identifier->getCStringNoCopy();
11901 }
11902 *thread = notifierThread;
11903 } else {
11904 iter = IORegistryIterator::iterateOver(
11905 getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
11906
11907 if (iter) {
11908 while ((entry = iter->getNextObject())) {
11909 node = OSDynamicCast(IOService, entry);
11910 if (!node) {
11911 continue;
11912 }
11913 if (OSDynamicCast(IOPowerConnection, node)) {
11914 continue;
11915 }
11916
11917 if (node->getBlockingDriverCall(thread, &callMethod)) {
11918 nodeFound = true;
11919 break;
11920 }
11921 }
11922 }
11923 if (nodeFound) {
11924 kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
11925 if (kextName) {
11926 objectName = kextName->getCStringNoCopy();
11927 }
11928 }
11929 }
11930 if (phaseDescription) {
11931 strlcat(failureStr, " while ", strLen);
11932 strlcat(failureStr, phaseDescription, strLen);
11933 strlcat(failureStr, ".", strLen);
11934 }
11935 if (objectName) {
11936 strlcat(failureStr, " Suspected bundle: ", strLen);
11937 strlcat(failureStr, objectName, strLen);
11938 strlcat(failureStr, ".", strLen);
11939 }
11940 if (*thread) {
11941 char threadName[40];
11942 snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
11943 strlcat(failureStr, threadName, strLen);
11944 }
11945
11946 DLOG("%s\n", failureStr);
11947 }
11948
11949 struct swd_stackshot_compressed_data {
11950 z_output_func zoutput;
11951 size_t zipped;
11952 uint64_t totalbytes;
11953 uint64_t lastpercent;
11954 IOReturn error;
11955 unsigned outremain;
11956 unsigned outlen;
11957 unsigned writes;
11958 Bytef * outbuf;
11959 };
11960 struct swd_stackshot_compressed_data swd_zip_var = { };
11961
11962 static void *
11963 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
11964 {
11965 void *result;
11966 LOG("Alloc in zipping %d items of size %d\n", items, size);
11967
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);
11971 return result;
11972 }
11973
11974 static int
11975 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
11976 {
11977 unsigned len;
11978
11979 len = strm->avail_in;
11980
11981 if (len > size) {
11982 len = size;
11983 }
11984 if (len == 0) {
11985 return 0;
11986 }
11987
11988 if (strm->next_in != (Bytef *) strm) {
11989 memcpy(buf, strm->next_in, len);
11990 } else {
11991 bzero(buf, len);
11992 }
11993
11994 strm->adler = z_crc32(strm->adler, buf, len);
11995
11996 strm->avail_in -= len;
11997 strm->next_in += len;
11998 strm->total_in += len;
11999
12000 return (int)len;
12001 }
12002
12003 static int
12004 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12005 {
12006 unsigned int i = 0;
12007 // if outlen > max size don't add to the buffer
12008 assert(buf != NULL);
12009 if (strm && buf) {
12010 if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12011 LOG("No space to GZIP... not writing to NVRAM\n");
12012 return len;
12013 }
12014 }
12015 for (i = 0; i < len; i++) {
12016 *(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12017 }
12018 swd_zip_var.outlen += len;
12019 return len;
12020 }
12021
12022 static void
12023 swd_zs_free(void * __unused ref, void * __unused ptr)
12024 {
12025 }
12026
12027 static int
12028 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12029 {
12030 int wbits = 12;
12031 int memlevel = 3;
12032
12033 if (((unsigned int) numBytes) != numBytes) {
12034 return 0;
12035 }
12036
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;
12044 } else {
12045 LOG("PMRD inited the zlib allocation routines\n");
12046 }
12047 }
12048
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;
12057
12058 swd_zip_var.totalbytes = numBytes;
12059
12060 swd_zs.avail_in = 0;
12061 swd_zs.next_in = NULL;
12062 swd_zs.avail_out = 0;
12063 swd_zs.next_out = NULL;
12064
12065 deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12066
12067 z_stream *zs;
12068 int zr;
12069 zs = &swd_zs;
12070
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;
12075 }
12076 if (!zs->avail_out) {
12077 zs->next_out = (Bytef *)zs;
12078 zs->avail_out = UINT32_MAX;
12079 }
12080 zr = deflate(zs, Z_NO_FLUSH);
12081 if (Z_STREAM_END == zr) {
12082 break;
12083 }
12084 if (zr != Z_OK) {
12085 LOG("ZERR %d\n", zr);
12086 swd_zip_var.error = zr;
12087 } else {
12088 if (zs->total_in == numBytes) {
12089 break;
12090 }
12091 }
12092 }
12093
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;
12099 }
12100 zr = deflate(zs, Z_FINISH);
12101 if (Z_STREAM_END == zr) {
12102 break;
12103 }
12104 if (zr != Z_OK) {
12105 LOG("ZERR %d\n", zr);
12106 swd_zip_var.error = zr;
12107 } else {
12108 if (zs->total_in == numBytes) {
12109 LOG("Total output size %d\n", swd_zip_var.outlen);
12110 break;
12111 }
12112 }
12113 }
12114
12115 return swd_zip_var.outlen;
12116 }
12117
12118 void
12119 IOPMrootDomain::deleteStackshot()
12120 {
12121 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12122 // takeStackshot hasn't completed
12123 return;
12124 }
12125 LOG("Deleting any sleepwake failure data in nvram\n");
12126
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);
12133 }
12134 }
12135 // force NVRAM sync
12136 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12137 DLOG("Failed to force nvram sync\n");
12138 }
12139 gRootDomain->swd_lock = 0;
12140 }
12141
12142 void
12143 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12144 {
12145 swd_hdr * hdr = NULL;
12146 int cnt = 0;
12147 int max_cnt = 2;
12148 pid_t pid = 0;
12149 kern_return_t kr = KERN_SUCCESS;
12150 uint64_t flags;
12151
12152 char * dstAddr;
12153 uint32_t size;
12154 uint32_t bytesRemaining;
12155 unsigned bytesWritten = 0;
12156
12157 char failureStr[512];
12158 thread_t thread = NULL;
12159 const char * swfPanic = "swfPanic";
12160
12161 uint32_t bufSize;
12162 int success = 0;
12163
12164 #if defined(__i386__) || defined(__x86_64__)
12165 const bool concise = false;
12166 #else
12167 const bool concise = true;
12168 #endif
12169
12170 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12171 return;
12172 }
12173
12174 failureStr[0] = 0;
12175 if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12176 return;
12177 }
12178
12179 if (wdogTrigger) {
12180 getFailureData(&thread, failureStr, sizeof(failureStr));
12181
12182 if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12183 goto skip_stackshot;
12184 }
12185 } else {
12186 AbsoluteTime now;
12187 uint64_t nsec;
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)));
12192 }
12193
12194 if (swd_buffer == NULL) {
12195 sleepWakeDebugMemAlloc();
12196 if (swd_buffer == NULL) {
12197 return;
12198 }
12199 }
12200 hdr = (swd_hdr *)swd_buffer;
12201 bufSize = hdr->alloc_size;
12202
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
12206 */
12207 if (wdogTrigger) {
12208 pid = -1;
12209 } else {
12210 pid = 0;
12211 }
12212
12213 /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12214 * If we run out of space, take stackshot with only kernel task
12215 */
12216 while (success == 0 && cnt < max_cnt) {
12217 bytesRemaining = bufSize - hdr->spindump_offset;
12218 cnt++;
12219 DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12220
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) {
12226 if (pid == -1) {
12227 pid = 0;
12228 } else {
12229 LOG("Insufficient buffer size for only kernel task\n");
12230 break;
12231 }
12232 }
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);
12236 continue;
12237 }
12238 bytesRemaining -= bytesWritten;
12239 hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12240
12241 memset(hdr->reason, 0x20, sizeof(hdr->reason));
12242
12243 // Compress stackshot and save to NVRAM
12244 {
12245 char *outbuf = (char *)swd_compressed_buffer;
12246 int outlen = 0;
12247 int num_chunks = 0;
12248 int max_chunks = 0;
12249 int leftover = 0;
12250 char nvram_var_name_buffer[20];
12251
12252 outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12253
12254 if (outlen) {
12255 max_chunks = outlen / (2096 - 200);
12256 leftover = outlen % (2096 - 200);
12257
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);
12263 break;
12264 }
12265 }
12266 if (leftover) {
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");
12270 }
12271 }
12272 success = 1;
12273 LOG("Successfully saved stackshot to NVRAM\n");
12274 } else {
12275 LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12276 if (pid == -1) {
12277 pid = 0;
12278 } else {
12279 LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12280 break;
12281 }
12282 }
12283 }
12284 }
12285 }
12286 }
12287
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");
12296 }
12297 }
12298
12299 // force NVRAM sync
12300 if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12301 DLOG("Failed to force nvram sync\n");
12302 }
12303
12304 skip_stackshot:
12305 if (wdogTrigger) {
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();
12315 }
12316 PEHaltRestart(kPEHaltCPU);
12317 return;
12318 }
12319 }
12320 if (gSwdPanic == 0) {
12321 LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12322 if (!tasksSuspended) {
12323 tasksSuspended = TRUE;
12324 updateTasksSuspend();
12325 }
12326 PEHaltRestart(kPERestartCPU);
12327 }
12328 }
12329 if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12330 DLOG("Failed to write SleepWake failure panic key\n");
12331 }
12332 #if defined(__x86_64__)
12333 if (thread) {
12334 panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12335 } else
12336 #endif /* defined(__x86_64__) */
12337 {
12338 panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12339 }
12340 } else {
12341 gRootDomain->swd_lock = 0;
12342 return;
12343 }
12344 }
12345
12346 void
12347 IOPMrootDomain::sleepWakeDebugMemAlloc()
12348 {
12349 vm_size_t size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12350
12351 swd_hdr *hdr = NULL;
12352 void *bufPtr = NULL;
12353
12354 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12355
12356
12357 if (kIOSleepWakeWdogOff & gIOKitDebug) {
12358 return;
12359 }
12360
12361 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12362 return;
12363 }
12364
12365 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12366 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12367 size);
12368 if (memDesc == NULL) {
12369 DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12370 goto exit;
12371 }
12372
12373 bufPtr = memDesc->getBytesNoCopy();
12374
12375 // Carve out memory for zlib routines
12376 swd_zs_zmem = (vm_offset_t)bufPtr;
12377 bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12378
12379 // Carve out memory for compressed stackshots
12380 swd_compressed_buffer = bufPtr;
12381 bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12382
12383 // Remaining is used for holding stackshot
12384 hdr = (swd_hdr *)bufPtr;
12385 memset(hdr, 0, sizeof(swd_hdr));
12386
12387 hdr->signature = SWD_HDR_SIGNATURE;
12388 hdr->alloc_size = SWD_STACKSHOT_SIZE;
12389
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);
12394
12395 exit:
12396 gRootDomain->swd_lock = 0;
12397 }
12398
12399 void
12400 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12401 {
12402 #if UNUSED
12403 vm_size_t size = SWD_SPINDUMP_SIZE;
12404
12405 swd_hdr *hdr = NULL;
12406
12407 OSSharedPtr<IOBufferMemoryDescriptor> memDesc;
12408
12409 if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12410 return;
12411 }
12412
12413 memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12414 kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12415 SWD_SPINDUMP_SIZE);
12416
12417 if (memDesc == NULL) {
12418 DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12419 goto exit;
12420 }
12421
12422
12423 hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12424 memset(hdr, 0, sizeof(swd_hdr));
12425
12426 hdr->signature = SWD_HDR_SIGNATURE;
12427 hdr->alloc_size = size;
12428
12429 hdr->spindump_offset = sizeof(swd_hdr);
12430 swd_spindump_buffer = (void *)hdr;
12431 swd_spindump_memDesc = os::move(memDesc);
12432
12433 exit:
12434 gRootDomain->swd_lock = 0;
12435 #endif /* UNUSED */
12436 }
12437
12438 void
12439 IOPMrootDomain::sleepWakeDebugEnableWdog()
12440 {
12441 }
12442
12443 bool
12444 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12445 {
12446 return !systemBooting && !systemShutdown && !gWillShutdown;
12447 }
12448
12449 void
12450 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12451 {
12452 swd_hdr *hdr = NULL;
12453 errno_t error = EIO;
12454
12455 if (swd_spindump_buffer && gSpinDumpBufferFull) {
12456 hdr = (swd_hdr *)swd_spindump_buffer;
12457
12458 error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12459 (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12460
12461 if (error) {
12462 return;
12463 }
12464
12465 sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12466 (char*)hdr + offsetof(swd_hdr, UUID),
12467 sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12468
12469 gSpinDumpBufferFull = false;
12470 }
12471 }
12472
12473 errno_t
12474 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12475 {
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;
12481
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;
12486 goto exit;
12487 }
12488 VATTR_INIT(&va);
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;
12495 goto exit;
12496 }
12497 VATTR_INIT(&va);
12498 VATTR_SET(&va, va_data_size, 0);
12499 vnode_setattr(vp, &va, ctx);
12500
12501
12502 if (buf != NULL) {
12503 error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12504 UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12505 if (error != 0) {
12506 LOG("Failed to save sleep wake log. err 0x%x\n", error);
12507 swd_flags |= SWD_FILEOP_ERROR;
12508 } else {
12509 DLOG("Saved %d bytes to file %s\n", len, name);
12510 }
12511 }
12512
12513 exit:
12514 if (vp) {
12515 vnode_close(vp, FWRITE, ctx);
12516 }
12517 if (ctx) {
12518 vfs_context_rele(ctx);
12519 }
12520
12521 return error;
12522 }
12523
12524 #else /* defined(__i386__) || defined(__x86_64__) */
12525
12526 void
12527 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12528 {
12529 if (restart) {
12530 if (gSwdPanic == 0) {
12531 return;
12532 }
12533 panic("Sleep/Wake hang detected");
12534 return;
12535 }
12536 }
12537
12538 void
12539 IOPMrootDomain::takeStackshot(bool restart)
12540 {
12541 #pragma unused(restart)
12542 }
12543
12544 void
12545 IOPMrootDomain::deleteStackshot()
12546 {
12547 }
12548
12549 void
12550 IOPMrootDomain::sleepWakeDebugMemAlloc()
12551 {
12552 }
12553
12554 void
12555 IOPMrootDomain::saveFailureData2File()
12556 {
12557 }
12558
12559 void
12560 IOPMrootDomain::sleepWakeDebugEnableWdog()
12561 {
12562 }
12563
12564 bool
12565 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12566 {
12567 return false;
12568 }
12569
12570 void
12571 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12572 {
12573 }
12574
12575 errno_t
12576 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12577 {
12578 return 0;
12579 }
12580
12581 #endif /* defined(__i386__) || defined(__x86_64__) */
12582